Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in
It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

How to create a custom script JQL function with two parameters?

Edited

I want to create a custom script JQL function with two parameters

name of function: childFeaturesOf

first parameter: JQL subquery

second parameter: a list of issuetypes

and I want that the 2nd parameter is not mandatory. If we just give the first parameter, it should return issues of all issuetypes

I want to use it as below:

issueFunction in childFeaturesOf("'parent business idea' = ABC-1 and issuetype = Package", (Feature, 'Package Unit'))

Kindly help me how to achieve this. This is the existing script:

Main script: 

package com.onresolve.jira.groovy.jql

import com.atlassian.jira.jql.query.QueryCreationContext
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.util.MessageSet
import com.atlassian.query.clause.TerminalClause
import com.atlassian.query.operand.FunctionOperand
import groovy.util.logging.Log4j
import org.apache.lucene.search.Query

@Log4j
class P3_ChildFeaturesOfJqlFunction extends AbstractScriptedJqlFunction implements JqlQueryFunction {

    P3_ChildIssueJqlFunctionHelper jqlFunctionHelper = new P3_ChildIssueJqlFunctionHelper(log)

    public static final String TEMPLATE_QUERY =
        "\"Parent Package Picker\" in ({0}) and issuetype in ({1})"

    @Override
    String getDescription() {
        "Returns the Features that have the issue(s) returned by the provided JQL-query in field 'Parent Package Picker'"
    }

    @Override
    MessageSet validate(ApplicationUser user, FunctionOperand operand, TerminalClause terminalClause) {
        log.error("Validating the JQL-function 'childFeaturesOf()' with input parameter(s) '" + operand.args + "'")
        jqlFunctionHelper.validate(user, operand, terminalClause, TEMPLATE_QUERY, getI18n())
    }

    @Override
    List<Map> getArguments() {
        [
            [
                description: "JQL-query for which the child Features should be returned",
                optional   : false,
            ],
            [
                description: "Issuetype which should be returned",
                optional   : false,
            ]
        ]
    }

    @Override
    String getFunctionName() {
        "childFeaturesOf"
    }

    @Override
    Query getQuery(QueryCreationContext queryCreationContext, FunctionOperand operand, TerminalClause terminalClause) {
        log.debug("Expanding the JQL-function 'childFeaturesOf()' with input parameter(s) '" + operand.args + "'")
        jqlFunctionHelper.getQuery(queryCreationContext, operand, terminalClause, TEMPLATE_QUERY)
    }
}
Script for file P3_ChildIssueJQLFunctionHelper.groovy:
package com.onresolve.jira.groovy.jql

import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.jql.query.LuceneQueryBuilder
import com.atlassian.jira.jql.query.QueryCreationContext
import com.atlassian.jira.jql.validator.NumberOfArgumentsValidator
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.util.I18nHelper
import com.atlassian.jira.util.MessageSet
import com.atlassian.jira.util.MessageSetImpl
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.query.clause.TerminalClause
import com.atlassian.query.operand.FunctionOperand
import org.apache.log4j.Category
import org.apache.lucene.search.Query

import java.text.MessageFormat

class P3_ChildIssueJqlFunctionHelper {

    Category log

    P3_ChildIssueJqlFunctionHelper(Category log) {
        this.log = log
    }

    JqlQueryParser queryParser = ComponentAccessor.getComponent(JqlQueryParser)
    LuceneQueryBuilder luceneQueryBuilder = ComponentAccessor.getComponent(LuceneQueryBuilder)
    SearchService searchService = ComponentAccessor.getComponent(SearchService)

    MessageSet validate(ApplicationUser user, FunctionOperand operand, TerminalClause terminalClause, String templateQuery, I18nHelper i18Helper) {
        def messageSet = new NumberOfArgumentsValidator(1, 1, i18Helper).validate(operand)
        if (messageSet.hasAnyErrors()) {
            return messageSet
        }

        def subqueryStr = operand.args.first()
        log.error "subster :"+subqueryStr
        def issueTypeList = operand.args.second()
        log.error "issueTypeList = "+issueTypeList

        if (! subqueryStr.trim()) {
            messageSet.addErrorMessage("Error in subquery: Query may not be empty")
            return messageSet
        }
        log.error "111"
        SearchService.ParseResult subQueryParseResult = searchService.parseQuery(user, subqueryStr)
        log.error "subQueryParseResult---"+subQueryParseResult
        def resultString
        if ( subQueryParseResult.isValid( ) ) {
            messageSet = searchService.validateQuery(user, subQueryParseResult.getQuery())
            log.error "messageSet---"+messageSet
            if (!messageSet.hasAnyErrors()) {
                resultString = executeSubquery(subQueryParseResult.getQuery(), user)
                log.error "resultString----"+resultString
            }
        } else {
            messageSet = subQueryParseResult.getErrors()
        }
        if (messageSet.hasAnyErrors()) {
            log.error "message set has errors"
            Set<String> errorSet = messageSet.getErrorMessages()
            MessageSet newMessageSet =  new MessageSetImpl()
            errorSet.each( { newMessageSet.addErrorMessage("Error in subquery: " + it)})
            log.debug("Error in subquery '" + subqueryStr + "': " + errorSet)
            return newMessageSet
        }

        def mainQuery = MessageFormat.format(templateQuery, resultString)
        log.error "mainQuery----"+mainQuery
        SearchService.ParseResult mainQueryParseResult = searchService.parseQuery(user, mainQuery)
        log.error "mainQueryParseResult--"+mainQueryParseResult
        if ( ! mainQueryParseResult.isValid( ) ) {
            messageSet = mainQueryParseResult.getErrors()
            log.debug("Error in subquery '" + subqueryStr + "': " + messageSet.getErrorMessages())
        }
        return messageSet
    }

    Query getQuery(QueryCreationContext queryCreationContext, FunctionOperand operand, TerminalClause terminalClause, String templateQuery) {
        def subquery = queryParser.parseQuery(operand.args.first())
        def resultStr = executeSubquery(subquery, queryCreationContext.getApplicationUser())
        if (resultStr == "0-0"){
            log.debug("Replaced empty list of results by '0-0' to produce a valid query")
        }
        def queryStr = MessageFormat.format(templateQuery, resultStr)
        log.debug("Final query: " + queryStr)
        log.error("Final query: " + queryStr)
        def query = queryParser.parseQuery(queryStr)
        luceneQueryBuilder.createLuceneQuery(queryCreationContext, query.whereClause)
    }

    String executeSubquery(com.atlassian.query.Query subquery, ApplicationUser user) {
        def searchResult = searchService.search(user, subquery, PagerFilter.getUnlimitedFilter())
        List<Issue> issuesFromQuery = searchResult.results
        if (! issuesFromQuery) {
            return "0-0"
        } else {
            log.error "issuesFromQuery----"+issuesFromQuery.collect({ it.getKey()}).join(",")
            return issuesFromQuery.collect({ it.getKey()}).join(",")
        }
    }
}

1 answer

Hi @SWAPNIL SRIVASTAV

To clarify, are you trying to get only all the child issues of a Feature issue type?

For example, if the Feature issue has multiple Epics, do you want all the issues that are in the Epics also to be returned?

Thank you and Kind Regards,
Ram

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Published in Jira Software

👋 Looking for 15-20 volunteers to test Atlassian training content

Hi everyone! Are you interested in beta testing Atlassian University’s newest (unreleased!) training course? We’re looking for 15-20 volunteers to test our newest training course, Basic reporting...

806 views 24 28
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you