Custom JQL Function Not Accepting Null Operand

Overview
Hello Atlassian Community! I’m trying to build a custom JQL function that’ll allow the subquery to pass as empty OR run the subquery (operand) that is defined by the user.

Example:

issueFunction in ademoTest()

issueFunction in ademoTest("reporter = name")

So far I got the script to work where users do not have to enter a subquery.

private com.atlassian.query.Query mergeQuery(FunctionOperand operand) {

def queryStr = MessageFormat.format(TEMPLATE_QUERY, "")

 queryParser.parseQuery(queryStr)

Problem
However, if I add an if/else statement to allow the subquery to pass as empty OR run a subquery, it does not work. By not work, I mean that it’ll require users to query

issueFunction in admoTest("") 

//Instead of querying the below, which is a better user experience 

issueFunction in ademoTest()
My If/Else Statement is below.

Any help is appreciated :slight_smile:

private com.atlassian.query.Query mergeQuery(FunctionOperand operand) {
    def queryStr = MessageFormat.format(TEMPLATE_QUERY, operand.args.first())
    def queryStrEmpty = MessageFormat.format(TEMPLATE_QUERY, "")
    if (operand != null) {
      queryParser.parseQuery(queryStr)
    } else {
      queryParser.parseQuery(queryStrEmpty)
    }

Code

import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.component.ComponentAccessor
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.MessageSet
import com.atlassian.query.clause.TerminalClause
import com.atlassian.query.operand.FunctionOperand
import org.apache.lucene.search.Query
import java.text.MessageFormat

class JqlAliasFunction extends AbstractScriptedJqlFunction implements JqlQueryFunction {
    /**
     * Modify this query as appropriate.
     *
     * See {@link java.text.MessageFormat} for details
     */
    public static final String TEMPLATE_QUERY =
        "project = ADEMO OR project = AWOLBP AND type = Task" // the scope of the query. To use a variable, pass it as {0}
    def queryParser = ComponentAccessor.getComponent(JqlQueryParser)
    def luceneQueryBuilder = ComponentAccessor.getComponent(LuceneQueryBuilder)
    def searchService = ComponentAccessor.getComponent(SearchService)
    @Override
    String getDescription() {
        "Pull in ADEMO and AWOLBP Tasks" // The text that appears next to the value defined in getFunctionName()
    }
    @Override
    MessageSet validate(ApplicationUser user, FunctionOperand operand, TerminalClause terminalClause) {
        def messageSet = new NumberOfArgumentsValidator(0, 1, getI18n()).validate(operand)
        if (messageSet.hasAnyErrors()) {
            return messageSet
        }
        def query = mergeQuery(operand)
        messageSet = searchService.validateQuery(user, query)
        messageSet
    }
    @Override
    List < Map > getArguments() {
        [
            [
                description: "Enter Subquery Here",
                optional: true,
            ]
        ]
    }
    @Override
    String getFunctionName() {
        "ademoTest" // this is the named function in the query
    }
    @Override
    Query getQuery(QueryCreationContext queryCreationContext, FunctionOperand operand, TerminalClause terminalClause) {
        def query = mergeQuery(operand)
        luceneQueryBuilder.createLuceneQuery(queryCreationContext, query.whereClause)
    }
    private com.atlassian.query.Query mergeQuery(FunctionOperand operand) {
        def queryStr = MessageFormat.format(TEMPLATE_QUERY, operand.args.first())
        def queryStrEmpty = MessageFormat.format(TEMPLATE_QUERY, "")
        if (operand != null) {
            queryParser.parseQuery(queryStr)
        } else {
            queryParser.parseQuery(queryStrEmpty)
        }
    }
}