com.almworks.jira.structure.api.query.QueryContext Maven / Gradle / Ivy
Show all versions of structure-api Show documentation
package com.almworks.jira.structure.api.query;
import com.almworks.integers.*;
import com.almworks.integers.func.LongLongProcedure;
import com.almworks.jira.structure.api.forest.raw.Forest;
import com.almworks.jira.structure.api.row.RowManager;
import com.almworks.jira.structure.api.row.StructureRow;
import com.atlassian.annotations.PublicApi;
import com.atlassian.query.Query;
/**
* This interface represents the environment of the {@code StructureQuery} being executed. This interface is
* consumed by {@link StructureQueryConstraint} implementations.
*
* It consists mostly of accessors to the forest being searched. Some of them are backed by a per-execution cache and
* have better amortized time compared to their counterparts from {@code Forest}.
*
* There are also methods that help in mapping row ID to issue ID and vice versa.
* */
@PublicApi
public interface QueryContext {
/**
* Returns row ID at the specified index in the forest being searched.
* Basically, a shorthand for {@code getForest().getRow(idx)}.
* @param idx index into the forest being searched, must be not less than 0 and less than {@link #size()}
* @return row ID
* @throws IndexOutOfBoundsException if {@code idx} is not within range {@code [0 .. size())}.
* @see Forest#getRow(int)
* */
long rowId(int idx);
/**
* Returns a row object at the specified index in the forest being searched.
* Basically, a shorthand for {@code RowManager rm = ...; rm.getRow(getForest().getRow(idx))}.
* @param idx index into the forest being searched, must be not less than 0 and less than {@link #size()}
* @return row object
* @throws IndexOutOfBoundsException if {@code idx} is not within range {@code [0 .. size())}.
* @see Forest#getRow(int)
* @see RowManager#getRow(long)
* */
StructureRow row(int idx);
/**
* Given indices into the forest being searched, returns the corresponding rows.
* This behaves like {@code getForest().getRows().get(indices)}, but the result is computed on-demand (lazily).
* @param indices an iterator over indices into the forest being searched;
* each index must be not less than 0 and less than {@link #size()}
* @return row IDs
* @throws IndexOutOfBoundsException if any of {@code indices} is not within range {@code [0 .. size())}.
* @see Forest#getRow(int)
* */
LongIterator rows(IntIterator indices);
/**
* Returns {@code true} if the row at the specified index into the forest being searched represents an issue.
* The result is cached, so subsequent calls of this method during the computation of this query should be faster.
* @param idx index into the forest being searched, must be not less than 0 and less than {@link #size()}
* @return true iff the row is an issue
* @throws IndexOutOfBoundsException if {@code idx} is not within range {@code [0 .. size())}.
* */
boolean isIssue(int idx);
/**
* If the row at the specified index into the forest being searched represents an issue, returns that issues' ID;
* otherwise, returns 0.
* The result is cached, so subsequent calls of this method during the computation of this query should be faster.
* @param idx index into the forest being searched, must be not less than 0 and less than {@link #size()}
* @return issue ID if the row is an issue, 0 otherwise
* @throws IndexOutOfBoundsException if {@code idx} is not within range {@code [0 .. size())}.
* */
long issueId(int idx);
/**
* A shorthand for {@code getForest().getDepth(idx)}.
* @param idx index into the forest being searched, must be not less than 0 and less than {@link #size()}
* @return row depth
* @throws IndexOutOfBoundsException if {@code idx} is not within range {@code [0 .. size())}.
* @see Forest#getDepth(int)
* */
int depth(int idx);
/**
* A shorthand for {@code getForest().size()}.
* @return size of the forest being searched
* @see Forest#size()
* */
int size();
/**
* Behaves as {@code getForest().getParentIndex(idx)}, but for many calls the amortized time is much less because
* of caching; for O(N) calls the amortized time is O(N) with N = size().
*
* Not only the result for the requested index is cached, but also the results of all indices between the requested
* index and the returned index.
* @param idx index into the forest being searched, must be not less than 0 and less than {@link #size()}
* @return index of the parent row for the specified row
* @throws IndexOutOfBoundsException if {@code idx} is not within range {@code [0 .. size())}.
* @see Forest#getParentIndex(int)
* */
int parent(int idx);
/**
* Behaves as {@code getForest().getSubtreeEnd(idx)}, but for many calls the amortized time is much less because
* of caching; for O(N) calls the amortized time is O(N) with N = size().
*
* Not only the result for the requested index is cached, but also the results of all indices between the requested
* index and the returned index.
* @param idx index into the forest being searched, must be not less than 0 and less than {@link #size()}
* @return next index after the end of this row's subtree
* @throws IndexOutOfBoundsException if {@code idx} is not within range {@code [0 .. size())}.
* @see Forest#getSubtreeEnd(int)
* */
int subtreeEnd(int idx);
/**
* Returns the forest being searched.
* @return the forest being searched
* */
Forest getForest();
/**
* Looks up the specified rows, and for each issue among them calls {@code rowIssueCollector} with row ID and issue ID,
* respectively.
*
* This method reuses the same cache used by {@link #isIssue(int)} and {@link #issueId(int)}. Also, it uses a faster
* bulk row lookup method in {@code RowManager}.
*
* There are no guarantees on the order of calls to {@code rowIssueCollector} regardless of {@code sorted} parameter.
*
* @param rows row IDs to resolve
* @param sorted specify {@code true} if you can guarantee that the iterator produces strictly increasing values.
* Mind that here we talk about values ordered by row ID, not index into the forest being searched.
* @param rowIssueCollector callback to receive {@code (row ID, issue ID)} for all rows among {@code rows} that represent
* issues. The order of calls may not correspond to the order in {@code rows}.
* */
void resolveRowIdsToIssues(LongIterator rows, boolean sorted, LongLongProcedure rowIssueCollector);
/**
* Given the specified issue IDs (sorted in increasing order), returns those of them that match the specified JQL.
*
* The order of elements in the returned {@oode LongArray} is not specified.
*
* @param query the JQL query object
* @param sortedIssues issue ID list, sorted in increasing order
* @return ID list of issues matching the JQL, in unspecified order
* */
LongArray filterIssues(Query query, LongList sortedIssues);
/**
* Returns row IDs for rows in the forest being searched that represent issue with the specified ID.
* @param issueId ID of the issue (e.g., 10210)
* @return row IDs for rows in the forest being searched that represent the issue
* */
LongIterable resolveIssueIdToRows(long issueId);
/**
* Returns row IDs for rows in the forest being searched that represent issues with the specified issue key.
* @param issueKey key of the issue (e.g., FOO-123)
* @return row IDs for rows in the forest being searched that represent the issue
* */
LongIterable resolveIssueKeyToRows(String issueKey);
}