实现这一点的最简单方法是确保问题列表缓存在您的某个应用程序组件中的某个位置。每个单独的问题列表都应由您自己定义的唯一 ID(下面的 magicKey)标识。
然后,您将编写自己的 JQL 函数,通过该魔术键查找预先计算的问题列表,然后将问题列表转换为问题导航器所需的格式。
buildUriEncodedJqlQuery() 方法可用于动态创建此类示例 JQL 查询。例如,如果魔术键是 1234,它将产生以下 JQL 查询:issue in myJqlFunction(1234)。
然后,您将向用户提供如下所示的 URL:
String url = "/secure/IssueNavigator.jspa?mode=hide&reset=true&jqlQuery=" + MyJqlFunction.buildUriEncodedJqlQuery(magicKey);
最终结果是用户将被放置在问题导航器中,查看您的代码提供的问题列表。
此代码还专门防止用户将您的 JQL 函数保存为已保存过滤器的一部分,因为它假定您的应用程序中的问题缓存不是永久性的。如果这不正确,您将需要清空 sanitiseOperand 部分。
在 atlassian-plugins.xml 中:
<jql-function key="myJqlFunction" name="My JQL Function"
class="com.mycompany.MyJqlFunction">
</jql-function>
JQL 函数:
import com.atlassian.crowd.embedded.api.User;
import com.atlassian.jira.JiraDataType;
import com.atlassian.jira.JiraDataTypes;
import com.atlassian.jira.jql.operand.QueryLiteral;
import com.atlassian.jira.jql.query.QueryCreationContext;
import com.atlassian.jira.plugin.jql.function.ClauseSanitisingJqlFunction;
import com.atlassian.jira.plugin.jql.function.JqlFunction;
import com.atlassian.jira.plugin.jql.function.JqlFunctionModuleDescriptor;
import com.atlassian.jira.util.MessageSet;
import com.atlassian.jira.util.MessageSetImpl;
import com.atlassian.jira.util.NotNull;
import com.atlassian.query.clause.TerminalClause;
import com.atlassian.query.operand.FunctionOperand;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MyJqlFunction implements JqlFunction, ClauseSanitisingJqlFunction
{
private static final String JQL_FUNCTION_NAME = "myJqlFunctionName";
private static final int JQL_FUNCTION_MIN_ARG_COUNT = 1;
private static final int JQL_FUNCTION_MAGIC_KEY_INDEX = 0;
public MyJqlFunction()
{
// inject your app's other components here
}
@Override
public void init(@NotNull JqlFunctionModuleDescriptor moduleDescriptor)
{
}
@Override
public JiraDataType getDataType()
{
return JiraDataTypes.ISSUE;
}
@Override
public String getFunctionName()
{
return JQL_FUNCTION_NAME;
}
@Override
public int getMinimumNumberOfExpectedArguments()
{
return JQL_FUNCTION_MIN_ARG_COUNT;
}
@Override
public boolean isList()
{
return true;
}
/**
* This function generates a URL-escaped JQL query that corresponds to the supplied magic key.
*
* @param magicKey
* @return
*/
public static String buildUriEncodedJqlQuery(String magicKey)
{
return "issue%20in%20" + JQL_FUNCTION_NAME + "(%22"
+ magicKey + "%22%)";
}
@Override
public List<QueryLiteral> getValues(@NotNull QueryCreationContext queryCreationContext,
@NotNull FunctionOperand operand,
@NotNull TerminalClause terminalClause)
{
User searchUser = queryCreationContext.getUser();
MessageSet messages = new MessageSetImpl();
List<QueryLiteral> values = internalGetValues(searchUser,
operand,
terminalClause,
messages,
!queryCreationContext.isSecurityOverriden());
return values;
}
private List<QueryLiteral> internalGetValues(@NotNull User searchUser,
@NotNull FunctionOperand operand,
@NotNull TerminalClause terminalClause,
@NotNull MessageSet messages,
@NotNull Boolean checkSecurity)
{
List<QueryLiteral> result = new ArrayList<QueryLiteral>();
if (searchUser==null)
{
// handle anon user
}
List<String> args = operand.getArgs();
if (wasSanitised(args))
{
messages.addErrorMessage("this function can't be used as part of a saved filter etc");
return result;
}
if (args.size() < getMinimumNumberOfExpectedArguments())
{
messages.addErrorMessage("too few arguments, etc");
return result;
}
final String magicKey = args.get(JQL_FUNCTION_MAGIC_KEY_INDEX);
// You need to implement this part yourself! This is where you use the supplied
// magicKey to fetch a list of issues from your own internal data source.
List<String> myIssueKeys = myCache.get(magicKey);
for (String id : myIssueKeys)
{
result.add(new QueryLiteral(operand, id));
}
return result;
}
@Override
public MessageSet validate(User searcher, @NotNull FunctionOperand operand, @NotNull TerminalClause terminalClause)
{
MessageSet messages = new MessageSetImpl();
internalGetValues(searcher, operand, terminalClause, messages, true);
return messages;
}
@Override
public FunctionOperand sanitiseOperand(User paramUser, @NotNull FunctionOperand operand)
{
// prevent the user from saving this as a filter, since the results are presumed to be dynamic
return new FunctionOperand(operand.getName(), Arrays.asList(""));
}
private boolean wasSanitised(List<String> args)
{
return (args.size() == 0 || args.get(JQL_FUNCTION_MAGIC_KEY_INDEX).isEmpty());
}
}