edu.byu.hbll.box.BoxQuery Maven / Gradle / Ivy
package edu.byu.hbll.box;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Query for requesting documents from Box.
*
* There are two ways of querying box. The first is to request documents by id. When requesting
* by id, the limit is ignored. There will be a 1:1 representation of documents according to the
* ids. If a document is not processed for a given id, a placeholder will still appear for that id.
* Documents are always returned in the same order as the requested ids.
*
*
The second query type harvests documents by requesting and filtering all documents according
* to the cursor, facets and limit instructions. Documents are always returned in cursor order. Only
* processed documents are returned. For this query type, the ids, process and wait clauses are
* ignored.
*
*
If there are ids in the query, then the id query type is used.
*/
public class BoxQuery {
/** The default limit. */
public static final long DEFAULT_LIMIT = 10;
/** The default cursor. */
public static final long DEFAULT_CURSOR = 0;
/** The default cursor when descending order. */
public static final long DEFAULT_CURSOR_DESC = Long.MAX_VALUE;
/** The default process flag. */
public static final boolean DEFAULT_PROCESS = false;
/** The default wait flag. */
public static final boolean DEFAULT_WAIT = false;
/** The default order. */
public static final Order DEFAULT_ORDER = Order.ASC;
/** The default statuses. */
// use linkedhashset to maintain order
public static final Set DEFAULT_STATUSES =
Collections.unmodifiableSet(
new LinkedHashSet<>(Arrays.asList(BoxDocument.Status.READY, BoxDocument.Status.DELETED)));
/** The default statuses. */
// use linkedhashset to maintain order
public static final Set ALL_STATUSES =
Collections.unmodifiableSet(
new LinkedHashSet<>(
Arrays.asList(
BoxDocument.Status.READY,
BoxDocument.Status.DELETED,
BoxDocument.Status.ERROR,
BoxDocument.Status.UNPROCESSED)));
/** Value used for limit to indicated unlimited. */
public static final long UNLIMITED = -1;
/** Special field to return the document. */
public static final String DOCUMENT_FIELD = "@doc";
/** Special field to return box metadata. */
public static final String METADATA_FIELD = "@box";
/** Special field to return document id. */
public static final String METADATA_FIELD_ID = "@box.id";
/** Special field to return document status. */
public static final String METADATA_FIELD_STATUS = "@box.status";
/** Special field to return document cursor. */
public static final String METADATA_FIELD_CURSOR = "@box.cursor";
/** Special field to return the document processed date. */
public static final String METADATA_FIELD_PROCESSED = "@box.processed";
/** Special field to return the document modified date. */
public static final String METADATA_FIELD_MODIFIED = "@box.modified";
/** Special field to return the document's facets. */
public static final String METADATA_FIELD_FACETS = "@box.facets";
/** Special field to return the document's dependencies. */
public static final String METADATA_FIELD_DEPENDENCIES = "@box.dependencies";
/** Special field to return the document group. */
public static final String METADATA_FIELD_GROUP_ID = "@box.groupId";
private List ids = new ArrayList<>();
private Optional process = Optional.empty();
private Optional wait = Optional.empty();
private Optional cursor = Optional.empty();
private Optional limit = Optional.empty();
private Optional offset = Optional.empty();
private Optional order = Optional.empty();
private Set statuses = new LinkedHashSet<>();
private Set fields = new LinkedHashSet<>();
private Set facets = new LinkedHashSet<>();
/** Creates a new empty query. */
public BoxQuery() {}
/**
* Copy constructor.
*
* @param query query to copy
*/
public BoxQuery(BoxQuery query) {
this.ids.addAll(query.ids);
this.process = query.process;
this.wait = query.wait;
this.cursor = query.cursor;
this.limit = query.limit;
this.offset = query.offset;
this.order = query.order;
this.statuses.addAll(query.statuses);
this.fields.addAll(query.fields);
this.facets.addAll(query.facets);
}
/**
* Creates a new query with the given ids.
*
* @param ids the ids
*/
public BoxQuery(Collection ids) {
this.ids.addAll(ids);
}
/**
* Creates a new query with the given ids.
*
* @param ids the ids
*/
public BoxQuery(String... ids) {
this.ids.addAll(Arrays.asList(ids));
}
/**
* Adds a filter facet. Facets across facet groups are ANDed. Facets within a facet group are
* ORed. Applicable only for harvest queries.
*
* @param name name of the facet group
* @param value value of the facet
* @return this
*/
public BoxQuery addFacet(String name, String value) {
this.facets.addAll(Arrays.asList(new Facet(name, value)));
return this;
}
/**
* Adds filter facets. Facets across facet groups are ANDed. Facets within a facet group are ORed.
* Applicable only for harvest queries.
*
* @param facet the facet to add
* @return this
*/
public BoxQuery addFacet(Facet facet) {
return addFacets(facet);
}
/**
* Adds filter facets. Facets across facet groups are ANDed. Facets within a facet group are ORed.
* Applicable only for harvest queries.
*
* @param facets the facets to add
* @return this
*/
public BoxQuery addFacets(Facet... facets) {
this.facets.addAll(Arrays.asList(facets));
return this;
}
/**
* Adds filter facets. Facets across facet groups are ANDed. Facets within a facet group are ORed.
* Applicable only for harvest queries.
*
* @param facets the facets to add
* @return this
*/
public BoxQuery addFacets(Collection extends Facet> facets) {
this.facets.addAll(facets);
return this;
}
/**
* Limit the document to only these fields. Dot notation.
*
* @param field the field to add
* @return this
*/
public BoxQuery addField(String field) {
return addFields(field);
}
/**
* Limit the document to only these fields. Dot notation.
*
* @param fields the fields to add
* @return this
*/
public BoxQuery addFields(Collection fields) {
this.fields.addAll(fields);
return this;
}
/**
* Limit the document to only these fields. Dot notation.
*
* @param fields the fields to add
* @return this
*/
public BoxQuery addFields(String... fields) {
this.fields.addAll(Arrays.asList(fields));
return this;
}
/**
* Adds an id to this query.
*
* @param id the id to add
* @return this
*/
public BoxQuery addId(String id) {
return addIds(id);
}
/**
* Adds ids to this query.
*
* @param ids the ids to add
* @return this
*/
public BoxQuery addIds(Collection ids) {
this.ids.addAll(ids);
return this;
}
/**
* Adds ids to this query.
*
* @param ids the ids to add
* @return this
*/
public BoxQuery addIds(String... ids) {
return addIds(Arrays.asList(ids));
}
/**
* Queries by these document statuses.
*
* @param status the status to add
* @return this
*/
public BoxQuery addStatus(BoxDocument.Status status) {
return addStatuses(status);
}
/**
* Queries by these document statuses.
*
* @param statuses the statuses to set
* @return this
*/
public BoxQuery addStatuses(BoxDocument.Status... statuses) {
return addStatuses(Arrays.asList(statuses));
}
/**
* Queries by these document statuses.
*
* @param statuses the statuses to set
* @return this
*/
public BoxQuery addStatuses(Collection statuses) {
this.statuses.addAll(statuses);
return this;
}
/**
* Adds all statuses to the query.
*
* @return this
*/
public BoxQuery addAllStatuses() {
this.statuses.addAll(ALL_STATUSES);
return this;
}
/**
* Clears all the facets.
*
* @return this
*/
public BoxQuery clearFacets() {
facets = new LinkedHashSet<>();
return this;
}
/**
* Clears all the fields.
*
* @return this
*/
public BoxQuery clearFields() {
fields = new LinkedHashSet<>();
return this;
}
/**
* Clears all the ids.
*
* @return this
*/
public BoxQuery clearIds() {
ids.clear();
return this;
}
/**
* Clears all the statuses.
*
* @return this
*/
public BoxQuery clearStatuses() {
statuses = new LinkedHashSet<>();
return this;
}
/**
* Returns the cursor. If null, the cursor was not explicitly set.
*
* @return the cursor
*/
public Optional getCursor() {
return cursor;
}
/**
* Returns the cursor or the default cursor if cursor not set.
*
* @return the limit
*/
public long getCursorOrDefault() {
return cursor.orElse(isAscendingOrder() ? DEFAULT_CURSOR : DEFAULT_CURSOR_DESC);
}
/**
* Returns the offset.
*
* @return the offset
*/
public Optional getOffset() {
return offset;
}
/**
* Returns the sort order.
*
* @return the order
*/
public Optional getOrder() {
return order;
}
/**
* Returns the sort order.
*
* @return the order
*/
public Order getOrderOrDefault() {
return order.orElse(BoxQuery.DEFAULT_ORDER);
}
/**
* Returns the specified facets.
*
* @return the facets
*/
public Set getFacets() {
return facets;
}
/**
* Returns the specified fields.
*
* @return the fields
*/
public Set getFields() {
return fields;
}
/**
* Returns the specified ids.
*
* @return the ids
*/
public List getIds() {
return ids;
}
/**
* Returns the limit. If null, no limit was specified. Null does not mean NO_LIMIT. It means a
* default limit should be used.
*
* @return the limit
*/
public Optional getLimit() {
return limit;
}
/**
* Returns the limit or the default limit if limit not set.
*
* @return the limit
*/
public long getLimitOrDefault() {
return limit.orElse(BoxQuery.DEFAULT_LIMIT);
}
/**
* Returns the specified statuses.
*
* @return the statuses
*/
public Set getStatuses() {
return statuses;
}
/**
* Returns the statuses or the default statuses if none set.
*
* @return the statuses
*/
public Set getStatusesOrDefault() {
return statuses.isEmpty() ? DEFAULT_STATUSES : statuses;
}
/**
* Returns the specified status string values.
*
* @return the status string values
*/
public Set getStatusValues() {
return statuses.stream().map(BoxDocument.Status::toString).collect(Collectors.toSet());
}
/**
* Returns the status string values or the default status string values if none set.
*
* @return the status string values
*/
public Set getStatusValuesOrDefault() {
return getStatusesOrDefault().stream()
.map(BoxDocument.Status::toString)
.collect(Collectors.toSet());
}
/**
* Returns whether or not the order is ascending.
*
* @return whether or not the order is ascending
*/
public boolean isAscendingOrder() {
return getOrderOrDefault() == Order.ASC;
}
/**
* Returns whether or not the order is descending.
*
* @return whether or not the order is descending
*/
public boolean isDescendingOrder() {
return getOrderOrDefault() == Order.DESC;
}
/**
* Whether or not this is a harvest query rather than an ID query.
*
* @return whether or not is a harvest query
*/
public boolean isHarvestQuery() {
return ids.isEmpty();
}
/**
* Whether or not this is an ID query rather than harvest query.
*
* @return whether or not is an ID query
*/
public boolean isIdQuery() {
return !isHarvestQuery();
}
/**
* Whether or not to ask Box to (re)process the document now and return the result. Not valid for
* harvest type queries
*
* @return the process
*/
public Optional isProcess() {
return process;
}
/**
* Whether or not to wait for documents to be processed.
*
* @return the wait
*/
public Optional isWait() {
return wait;
}
/**
* Sets the order to be ascending (default).
*
* @return this
*/
public BoxQuery setAscendingOrder() {
return setOrder(Order.ASC);
}
/**
* Sets the order to be descending.
*
* @return this
*/
public BoxQuery setDescendingOrder() {
return setOrder(Order.DESC);
}
/**
* Sets the cursor. Documents are ordered by cursor ascending so this is used for paging. Only
* documents greater than or equal to this cursor will be returned. Applicable only for harvest
* queries.
*
* @param cursor the cursor to set
* @return this
*/
public BoxQuery setCursor(long cursor) {
return setCursor((Long) cursor);
}
/**
* Sets the cursor. Documents are ordered by cursor ascending so this is used for paging. Only
* documents greater than or equal to this cursor will be returned. Applicable only for harvest
* queries.
*
* @param cursor the cursor to set
* @return this
*/
public BoxQuery setCursor(Long cursor) {
this.cursor = Optional.ofNullable(cursor);
return this;
}
/**
* Clears any set fields and adds the document field.
*
* @return this
*/
public BoxQuery setDocumentOnly() {
clearFields();
addFields(DOCUMENT_FIELD);
return this;
}
/**
* Adds filter facets. Facets across facet groups are ANDed. Facets within a facet group are ORed.
* Applicable only for harvest queries.
*
* @param facets the facets to add
* @return this
*/
public BoxQuery setFacets(Collection extends Facet> facets) {
clearFacets();
addFacets(facets);
return this;
}
/**
* Limit the document to only these fields. Dot notation.
*
* @param fields the fields to add
* @return this
*/
public BoxQuery setFields(Collection fields) {
clearFields();
addFields(fields);
return this;
}
/**
* Limits the number of documents returned to no more than this number. This is effectively the
* page size. A limit of {@link #UNLIMITED} means return all documents. Applicable only for
* harvest queries.
*
* @param limit the limit to set
* @return this
*/
public BoxQuery setLimit(long limit) {
return setLimit((Long) limit);
}
/**
* Limits the number of documents returned to no more than this number. This is effectively the
* page size. A limit of {@link #UNLIMITED} means return all documents. Applicable only for
* harvest queries.
*
* @param limit the limit to set
* @return this
*/
public BoxQuery setLimit(Long limit) {
this.limit = Optional.ofNullable(limit);
return this;
}
/**
* The number of documents to skip in the results set.
*
* @param offset the offset to set
* @return this
*/
public BoxQuery setOffset(long offset) {
return setOffset((Long) offset);
}
/**
* The number of documents to skip in the results set.
*
* @param offset the offset to set
* @return this
*/
public BoxQuery setOffset(Long offset) {
this.offset = Optional.ofNullable(offset);
return this;
}
/**
* Sets the sort order.
*
* @param order the order to set
* @return this
*/
public BoxQuery setOrder(Order order) {
this.order = Optional.ofNullable(order);
return this;
}
/**
* Clears any set fields and adds the box metadata field.
*
* @return this
*/
public BoxQuery setMetadataOnly() {
clearFields();
addFields(METADATA_FIELD);
return this;
}
/**
* Whether or not to ask Box to (re)process the document now and return the result. Not valid for
* harvest type queries.
*
* @param process the process to set
* @return this
*/
public BoxQuery setProcess(Boolean process) {
this.process = Optional.ofNullable(process);
return this;
}
/**
* Sets statuses to be queried.
*
* @param statuses the statuses to set
* @return this
*/
public BoxQuery setStatuses(Collection statuses) {
clearStatuses();
addStatuses(statuses);
return this;
}
/**
* Sets the limit to UNLIMITED. Same as limit(BoxQuery.UNLIMITED).
*
* @return this
*/
public BoxQuery setUnlimited() {
return setLimit(UNLIMITED);
}
/**
* Whether or not to wait for Box to process the document before returning. The document is
* immediately returned if it is already processed. Not valid for harvest type queries. Default
* false.
*
* @param wait the wait to set
* @return this
*/
public BoxQuery setWait(Boolean wait) {
this.wait = Optional.ofNullable(wait);
return this;
}
/**
* Order ascending or descending.
*
* @author Charles Draper
*/
public static enum Order {
/** Ascending. */
ASC,
/** Descending. */
DESC
}
}