All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.almworks.jira.structure.api.query.StructureQuery Maven / Gradle / Ivy

There is a newer version: 17.25.3
Show newest version
package com.almworks.jira.structure.api.query;

import com.almworks.integers.*;
import com.almworks.jira.structure.api.forest.raw.Forest;
import com.almworks.jira.structure.api.settings.StructureConfiguration;
import com.atlassian.annotations.PublicApi;
import com.atlassian.jira.user.ApplicationUser;
import com.atlassian.jira.util.MessageSet;
import com.atlassian.query.Query;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;

/**
 * 

A structure query is a condition on rows and their relationships in a {@link Forest}, such as * rows that are children of issues satisfying JQL 'type = Epic' or * rows at the top level of the forest. * An object of class {@code StructureQuery} lets you search for matching rows in a given {@code Forest}. * It also lets you validate the structure query it represents, returning error messages that you can display * to the user.

* *

This class is the API counterpart of the {@code structure()} JQL function bundled with the Structure plugin, * along with the ability to retrieve {@code Structure} objects from {@code StructureManager} and * structure's {@code Forest} from {@code Structure}.

* *

{@code StructureQuery} is obtained by either {@link StructureQueryParser parsing} the query * expressed in the StructuredJQL language, or by building it with {@link StructureQueryBuilder}. * If you have obtained this {@code StructureQuery} by parsing a String, you can get this string back * via {@link #getQueryString()}. Otherwise, you can use {@code toString()}, which either returns the parsed * query string or generates a query string if this query was built.

* *

{@code StructureQuery}'s {@code equals()} and {@code hashCode()} provide structural equality: * if you have a query built by {@code StructureQueryBuilder} and a similar-looking query built by * {@code StructureQueryParser}, they are equal, if they happen to have equal JQL constraints. * That is, if you use {@code JqlQueryParser} instead of {@code JqlQueryBuilder} to create JQL {@code Query} * that you put into {@code StructureQueryBuilder}, the resulting Structure query will be equal to the * parsed one; this is due to the way Atlassian's {@code Query.equals()} and {@code Query.hashCode()} work.

* *

Note: this class is not thread-safe.

* * @see StructureQueryParser * @see StructureQueryBuilder * * @since 8.1.0 (Structure 2.4) * * @author Igor Baltiyskiy * */ @PublicApi public abstract class StructureQuery { /** *

Validates this {@code StructureQuery} in the current authentication context. The following things are checked: *

    *
  1. Whether all nested JQL constraints are valid, as per {@code SearchService.validateQuery(User, Query).} *
  2. Whether referenced items exist and are accessible to the current user.
  3. *
  4. Whether all nested constraints have valid arguments, as per {@link StructureQueryConstraint#validate(List)}.
  5. *
  6. Whether all saved filters (aka search requests) referenced in the nested JQL constraints don't * reference themselves through the {@code structure()} JQL function.
  7. *
*

The resulting human-readable errors and warnings are reported in the returned {@code MessageSet}. * *

The result of the validation is remembered, so that validation is not repeated at the execution time. * * @return human-readable validation error messages and warnings in the current user's locale; * if there are no error messages, this query has passed the validation * @see com.atlassian.jira.bc.issue.search.SearchService#validateQuery(ApplicationUser, Query) * @see StructureQueryConstraint#validate(List) * */ @NotNull public abstract MessageSet validate(); /** * Returns a string representation of this query, with all the potential "information leaks" removed, * with regards to the current user. * @return sanitized string representation of this query * @see com.atlassian.jira.bc.issue.search.SearchService#sanitiseSearchQuery * @since 8.5.0 (Structure 2.8) */ @NotNull public abstract String getSanitizedQueryString(); /** *

Executes this query against the specified {@link Forest}, returning IDs of all matching rows * in the forest order.

* *

This method observes JIRA and Structure permissions in the following ways: *

    *
  1. Only rows visible to the current user are returned.
  2. *
  3. All JIRA searches for nested JQL constraints are executed under the current user. *
  4. If the current user * {@link StructureConfiguration#getEnabledPermissionSubjects() cannot use Structure}, * an empty list is returned. *
* *

Prior to execution, validation status is checked. If {@link #validate()} hasn't been called on this * object before, validation is carried out. If validation fails, returns an empty list. *

If you are doing administrative tasks under a trusted account, and you need to ensure that you know * all certain rows in a forest, override security in the current authentication context * to skip validation and permission checks. * In this case, this method will not require you to call nor call itself {@link #validate()}, * and all JIRA searches for nested JQL constraints will be executed without permission checks. * * @param forest the forest in which to search the rows * @return the list of IDs of rows matching this query in {@code forest} in the forest order, * subject to permission restrictions unless security is overridden * */ @NotNull public abstract LongArray execute(@NotNull Forest forest); /** *

Executes this query against the specified {@link Forest}, returning an iterator over all matching row IDs * in the forest order.

* *

Behaves the same as {@link #execute(Forest)} with respect to validation and permission checks.

* @param forest the forest in which to search the rows * @return an iterator over matching row IDs in the forest order, * subject to permission restrictions unless security is overridden * */ public abstract LongIterator executeUnbuffered(@NotNull Forest forest); /** *

Executes this query against the specified {@link Forest}, returning {@link Forest#indexOf indices} * of all matching rows in the forest order (i.e., the sequence of indices strictly increases.)

* *

Behaves the same as {@link #execute(Forest)} with respect to validation and permission * checks.

* * @param forest the forest in which to search the rows * @return increasing positions of rows in {@code forest} matching this query * */ @NotNull public abstract IntArray executeIndices(@NotNull Forest forest); /** *

Executes this query against the specified {@link Forest}, returning an iterator over {@link Forest#indexOf indices} * of all matching rows in the forest order (i.e., iterator values strictly increase.)

* *

Behaves the same as {@link #execute(Forest)} with respect to validation and permission * checks.

* * @param forest the forest in which to search the rows * @return an iterator over increasing positions of rows in {@code forest} matching this query * */ public abstract IntIterator executeIndicesUnbuffered(@NotNull Forest forest); /** *

Checks if the specified row matches the query against the specified {@link Forest}.

* *

If {@code rowId} is {@code null} or the forest does not contain the row, {@code false} is returned.

* *

Because of possible implementation optimizations, it's better to use this method rather than calling * {@link #execute(Forest)} and checking if the row ID is contained in the result.

* *

Behaves the same as {@link #execute(Forest)} with respect to validation and permission checks.

* @param rowId ID of the row to check * @param forest the forest against which the row should be checked * @return {@code true} if the row matches the query, otherwise {@code false} */ public abstract boolean checkRow(Long rowId, @NotNull Forest forest); /** *

Checks if the row at the given {@link Forest#indexOf index} in the {@link Forest} matches the query.

* *

If {@code index} is out of the forest bounds, {@code false} is returned.

* *

Because of possible implementation optimizations, it's better to use this method rather than calling * {@link #executeIndices} and checking if the index is contained in the result.

* *

Behaves the same as {@link #execute(Forest)} with respect to validation and permission checks.

* @param index index in the forest * @param forest the forest for which to check the row at the specified index * @return {@code true} if the row at the specified index matches the query, otherwise {@code false} */ public abstract boolean checkIndex(int index, Forest forest); /** * @return If this query was created by {@link StructureQueryParser#parse parsing} a String, returns that String. * Otherwise, returns {@code null}. * */ @Nullable public abstract String getQueryString(); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy