CQL Function Module

Available:

Confluence 5.9 and later

Purpose of this module

The CQL Function Module allows plugins to add additional functions to CQL. 

Functions provide a way for values within a CQL query to be calculated at runtime. Consider the space keyword in CQL, which can be used to query content that exists in a particular space. This in itself may not seem powerful, but when combined with the favouriteSpaces function, "space = favouriteSpaces()", it provides a way to find all of the content that exists in a user's favourite spaces. 

It's important to note that CQL functions can only provide values to a query; most importantly, they can't be used to process the results

CQL functions can take arguments. These arguments must take the form of simple string values.

Your plugin must depend on the CQL SPI in order to declare CQL fields or functions. Please see the guide Adding a field to CQL for a detailed walkthrough

CQL Function declaration

Here is an example atlassian-plugin.xml declaring a new CQL function:

<atlassian-plugin name="Sample" key="confluence.cql.sample.function">
    ...
	<cql-query-function key="favourite-spaces-query-function" name="favouriteSpaces() CQL Function"
                  class="com.atlassian.confluence.plugins.cql.functions.FavouriteSpacesQueryFunction"/>
    ...
</atlassian-plugin>

The class attribute defines the function implementation class. This class must implement: 

  • com.atlassian.confluence.plugins.cql.spi.functions.CQLSingleValueQueryFunction or 
  • com.atlassian.confluence.plugins.cql.spi.functions.CQLMultiValueQueryFunction

CQL Function types

CQL works by first expanding functions and then evaluating the expanded statement to return a set of results. For this reason, there are two types of CQL functions which can be implemented.

Single value query functions

Single value query functions return a single String value upon being expanded. So 

 space = currentSpace()

becomes 

 space = "MYSPACE"

Single value query function implementations should extend from the CQLSingleValueQueryFunction class. 

Multi value query functions

Multi value query functions return a number of String values upon being expanded. So

 space IN favouriteSpaces()

becomes 

 space IN ("SPACE1", "SPACE2", "SPACE3")

Multi value query function implementations should extend from the CQLMultiValueQueryFunction class. 

An example CQL Function implementation

package com.atlassian.confluence.plugins.cql.functions;
import java.util.ArrayList;
import java.util.List;
import com.atlassian.confluence.labels.LabelManager;
import com.atlassian.confluence.plugins.cql.spi.functions.CQLEvaluationContext;
import com.atlassian.confluence.plugins.cql.spi.functions.CQLMultiValueQueryFunction;
import com.atlassian.confluence.spaces.Space;
/**
 * A function that returns provides a user's favourite spaces
 * <p>
 * For example :
 * {@code}
 *  space in favouriteSpaces()
 * {@code}
 * </p>
 */ 
public class FavouriteSpacesQueryFunction extends CQLMultiValueQueryFunction
{   
    private LabelManager labelManager;
        
    public FavouriteSpacesQueryFunction(LabelManager labelManager)
    {
        super("favouriteSpaces");
        this.labelManager = labelManager;
    }
    @Override
    public int paramCount()
    {
        return 0;
    }
    @Override
    public Iterable<String> invoke(List<String> params, CQLEvaluationContext context)
    {
        List<String> favouriteSpaceKeys = new ArrayList<String>();
        if (context.getCurrentUser().isEmpty())
            return favouriteSpaceKeys;
        List<Space> favouriteSpaces = labelManager.getFavouriteSpaces(context.getCurrentUser().get());
        for (Space space : favouriteSpaces)
        {
            favouriteSpaceKeys.add(space.getKey());
        }
        return favouriteSpaceKeys;
    }
} 

QueryFunction.paramCount Method

Returns the number of arguments accepted by the Query Function. For example, the NowFunction has a paramCount of 1, and it accepts a single argument, "created = now('-1w')" : 

@Override
public final int paramCount()
{
    return 1;
}

@Override
public final String invoke(List<String> params, EvaluationContext e)
{
    String relativeDate = params.get(0);
    ReadablePeriod period = DateLiteralHelper.toDateTime(relativeDate);
    return DateLiteralHelper.toDateTimeString(new DateTime().plus(period));
}

MultiValueQueryFunction.invoke Method

The invoke method of a given Query Function class is called when a CQL statement is executed containing that Query Function.

Accepts as arguments a List of String objects params, which are the parameters passed into the Query Function in the CQL statement being executed, as well as an EvaluationContext object context. The method should return an Iterable of String values which will be the values that the Query Function will be transformed into, appearing within the parenthesis following the IN clause in the CQL statement being executed.

SingleValueQueryFunction.invoke Method

As above, accepts as arguments a list of params and a context object. The method should return a single String value which will be the value that the Query Function will be tranformed into, appearing as a single quoted value following the = operator in the CQL statement being executed.

CQLEvaluationContext Class

The class definition of the object that is passed as the context argument to the invoke method of a Query Function.

Provides Confluence specific contextual information to a Query Function. Contains a method to optionally provide the space, contentId and contentType context that the CQL search is being executed in. If the function relies on a piece of contextual information that is not present, it should throw an InvalidFunctionQueryException. For example the invoke method of the currentSpace() function requires that the current space be present in the evaluation context. 

@Override
public String invoke(List<String> params, CQLEvaluationContext context)
{
    if (context.getCurrentSpaceKey().isEmpty()) // the evaluation context does not have a current space
        throw InvalidFunctionQueryException.invalidFunctionContext(name(), "space");

    return context.getCurrentSpaceKey().get();
}
Was this page helpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport