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

com.marklogic.client.query.StructuredQueryBuilder Maven / Gradle / Ivy

/*
 * Copyright 2012-2015 MarkLogic Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.marklogic.client.query;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import javax.xml.XMLConstants;
import javax.xml.bind.DatatypeConverter;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import com.marklogic.client.MarkLogicIOException;
import com.marklogic.client.impl.AbstractQueryDefinition;
import com.marklogic.client.impl.RawQueryDefinitionImpl;
import com.marklogic.client.io.BaseHandle;
import com.marklogic.client.io.Format;
import com.marklogic.client.io.OutputStreamSender;
import com.marklogic.client.io.marker.BufferableHandle;
import com.marklogic.client.io.marker.OperationNotSupported;
import com.marklogic.client.io.marker.StructureWriteHandle;
import com.marklogic.client.io.marker.XMLWriteHandle;
import com.marklogic.client.util.EditableNamespaceContext;
import com.marklogic.client.util.IterableNamespaceContext;

/**
 * StructuredQueryBuilder builds a query for documents in the database.
 * Several concrete the query definition classes are now deprecated because you can
 * instead use the more general {@link StructuredQueryDefinition StructuredQueryDefinition} interface
 * as the type for query definitions.  For instance, here is a
 * forward-compatible approach for capturing an AND query definition
 * in a variable:
 * 
StructuredQueryDefinition andQry = structuredQueryBuilder.and(... query definitions ...);
*/ public class StructuredQueryBuilder { final static private String SEARCH_API_NS="http://marklogic.com/appservices/search"; /* * This map is used to prevent reuse of reserved prefixes in path expressions. */ final static private Map reserved = new HashMap(); static { reserved.put("search", SEARCH_API_NS); reserved.put("xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI); reserved.put("xs", XMLConstants.W3C_XML_SCHEMA_NS_URI); }; private static Templates extractor; private String builderOptionsURI = null; /** * Used only for serializing StructuredQueryDefinitions. */ private IterableNamespaceContext namespaces; /** * Control over ordering for use in near queries. */ public enum Ordering { ORDERED, UNORDERED; } /** * A comparison operator for use in range queries. */ public enum Operator { LT, LE, GT, GE, EQ, NE; } /** * Whether a query should search the document or its associated properties. * The value "DOCUMENT" is here for backward-compatibility but deprecated * in favor of DOCUMENTS. */ public enum FragmentScope { @Deprecated DOCUMENT, DOCUMENTS, PROPERTIES; } /** * A TextIndex can be used for word and value queries. */ public interface TextIndex { } /** * A RangeIndex can be used for range queries. The range index * must be defined in the database configuration. */ public interface RangeIndex { } /** * A GeospatialIndex can be used for geospatial queries. The * geospatial index must be defined in the database configuration. */ public interface GeospatialIndex { } /** * A ContainerIndex can be used for container queries. */ public interface ContainerIndex { } /** * An Element represents an element in database documents. */ public interface Element extends ContainerIndex, RangeIndex, TextIndex { } /** * An Attribute represents an attribute in database documents. */ public interface Attribute { } /** * An ElementAttribute represents an attribute on an element * in database documents. */ public interface ElementAttribute extends RangeIndex, TextIndex { } /** * A Field represents a field defined in the database configuration. */ public interface Field extends RangeIndex, TextIndex { } /** * A JSONProperty represents a key in JSON database documents. */ public interface JSONProperty extends Element, ContainerIndex, RangeIndex, TextIndex { } /** * A PathIndex represents an index defined with an XPath * in the database configuration. */ public interface PathIndex extends RangeIndex { } /** * Zero-argument constructor. */ public StructuredQueryBuilder() { this((IterableNamespaceContext) null); } /** * Constructs a query builder for queries against the options * persisted with the specified name. The query can include * constraint queries for any constraints defined by the options. * @param optionsName the name of the persisted query options */ public StructuredQueryBuilder(String optionsName) { this((IterableNamespaceContext) null); builderOptionsURI = optionsName; } /** * Constructs a query builder for queries using the specified * namespace bindings. * @param namespaces the bindings of prefixes and namespaces */ public StructuredQueryBuilder(IterableNamespaceContext namespaces) { super(); setNamespaces(namespaces); } /** * Constructs a query builder for queries against the options * persisted with the specified name using the specified * namespace bindings. The query can include constraint queries * for any constraints defined by the options. * @param optionsName the name of the persisted query options * @param namespaces the bindings of prefixes and namespaces */ public StructuredQueryBuilder(String optionsName, IterableNamespaceContext namespaces) { this(namespaces); builderOptionsURI = optionsName; } /** * Builds a structured query in XML from the list of query definitions. * The structured query can be passed to the search() method of QueryManager. * @param queries the query definitions * @return the structured query */ public RawStructuredQueryDefinition build(StructuredQueryDefinition... queries) { checkQueries(queries); return new RawQueryDefinitionImpl.Structured( new StructuredQueryXMLWriter(queries), builderOptionsURI ); } /** * Defines an AND query over the list of query definitions. * @param queries the query definitions * @return the StructuredQueryDefinition for the AND query */ public AndQuery and(StructuredQueryDefinition... queries) { checkQueries(queries); return new AndQuery(queries); } /** * Defines an OR query over the list of query definitions. * @param queries the query definitions * @return the StructuredQueryDefinition for the OR query */ public OrQuery or(StructuredQueryDefinition... queries) { checkQueries(queries); return new OrQuery(queries); } /** * Defines a NOT query for a query definition. To negate * a list of query definitions, define an AND or * OR query over the list and define the NOT query over * the AND or OR query. * @param query the query definition * @return the StructuredQueryDefinition for the NOT query */ public NotQuery not(StructuredQueryDefinition query) { checkQuery(query); return new NotQuery(query); } /** * Defines an AND NOT query combining a positive and negative * query. You can use an AND or OR query over a list of query * definitions as the positive or negative query. * @param positive the positive query definition * @param negative the negative query definition * @return the StructuredQueryDefinition for the AND NOT query */ public AndNotQuery andNot(StructuredQueryDefinition positive, StructuredQueryDefinition negative) { checkQuery(positive); checkQuery(negative); return new AndNotQuery(positive, negative); } /** * Defines a NEAR query over the list of query definitions * with default parameters. * @param queries the query definitions * @return the StructuredQueryDefinition for the NEAR query */ public NearQuery near(StructuredQueryDefinition... queries) { checkQueries(queries); return new NearQuery(queries); } /** * Defines a NEAR query over the list of query definitions * with specified parameters. * @param distance the proximity for the query terms * @param weight the weight for the query * @param order the ordering for the query terms * @param queries the query definitions * @return the StructuredQueryDefinition for the NEAR query */ public NearQuery near(int distance, double weight, Ordering order, StructuredQueryDefinition... queries) { checkQueries(queries); return new NearQuery(distance, weight, order, queries); } /** * Associates a query with the content of documents (as opposed to * the properties of documents). * @param query the query definition * @return the StructuredQueryDefinition for the document fragment query */ public DocumentFragmentQuery documentFragment(StructuredQueryDefinition query) { checkQuery(query); return new DocumentFragmentQuery(query); } /** * Associates a query with the properties of documents (as opposed to * the content of documents). * @param query the query definition * @return the StructuredQueryDefinition for the properties query */ public PropertiesQuery properties(StructuredQueryDefinition query) { checkQuery(query); return new PropertiesQuery(query); } /** * Associates a query with durable locks on documents (as opposed to * the content or properties of documents). Such lock fragments are * created with xdmp:lock-acquire(). * @param query the query definition * @return the StructuredQueryDefinition for the locks query */ public LocksQuery locks(StructuredQueryDefinition query) { checkQuery(query); return new LocksQuery(query); } /** * Matches a query within the substructure contained by an element or JSON property. * @param index the element or JSON property * @param query the query over the contained substructure * @return the StructuredQueryDefinition for the container query */ public StructuredQueryDefinition containerQuery(ContainerIndex index, StructuredQueryDefinition query) { checkQuery(query); return new ContainerQuery(index, query); } /** * Matches documents belonging to at least one * of the criteria collections. * @param uris the identifiers for the criteria collections * @return the StructuredQueryDefinition for the collection query */ public CollectionQuery collection(String... uris) { return new CollectionQuery(uris); } /** * Matches documents at the specified depth within at least one * of the criteria directories. * @param isInfinite true to match a document at any level of depth * @param uris the identifiers for the criteria directories * @return the StructuredQueryDefinition for the directory query */ public DirectoryQuery directory(boolean isInfinite, String... uris) { return new DirectoryQuery(isInfinite, uris); } /** * Matches documents at the specified depth within at least one * of the criteria directories. * @param depth specifies how many subdirectories deep to traverse * A value of 1 means to exclude subdirectories. * @param uris the identifiers for the criteria directories * @return the StructuredQueryDefinition for the directory query */ public DirectoryQuery directory(int depth, String... uris) { return new DirectoryQuery(depth, uris); } /** * Matches the specified documents. * @param uris the identifiers for the documents * @return the StructuredQueryDefinition for the document query */ public DocumentQuery document(String... uris) { return new DocumentQuery(uris); } /** * Matches documents containing the specified terms. * @param terms the possible terms to match * @return the StructuredQueryDefinition for the term query */ public TermQuery term(String... terms) { return new TermQuery(null, terms); } /** * Matches documents containing the specified terms, modifying * the contribution of the match to the score with the weight. * @param weight the multiplier for the match in the document ranking * @param terms the possible terms to match * @return the StructuredQueryDefinition for the term query */ public TermQuery term(double weight, String... terms) { return new TermQuery(weight, terms); } /** * Matches an element, attribute, JSON property, or field * that has a value with the same string value as at least one * of the criteria values. * @param index the value container * @param values the possible values to match * @return the StructuredQueryDefinition for the value query */ public StructuredQueryDefinition value(TextIndex index, String... values) { return new ValueQuery(index, null, null, null, values); } /** * Matches a JSON property that has a value with the same boolean value * as at least one of the criteria values. Note this method will not match * any XML node. * @param index the value container * @param value either true or false * @return the StructuredQueryDefinition for the value query */ public StructuredQueryDefinition value(TextIndex index, Boolean value) { return new ValueQuery(index, null, null, null, new Object[] {value}); } /** * Matches an JSON property that has a value with the same numeric * value as at least one of the criteria values. Note this method will not * match any XML node. * @param index the value container * @param values the possible values to match * @return the StructuredQueryDefinition for the value query */ public StructuredQueryDefinition value(TextIndex index, Number... values) { return new ValueQuery(index, null, null, null, values); } /** * Matches an element, attribute, JSON property, or field * that has a value with the same string value as at least one * of the criteria values. * @param index the value container * @param scope whether the query matches the document content or properties * @param options options for fine tuning the query * @param weight the multiplier for the match in the document ranking * @param values the possible values to match * @return the StructuredQueryDefinition for the value query */ public StructuredQueryDefinition value(TextIndex index, FragmentScope scope, String[] options, double weight, String... values) { return new ValueQuery(index, scope, options, weight, values); } /** * Matches a JSON property that has a value with the same boolean * value as at least one of the criteria values. Note this method will not * match any XML node. * @param index the value container * @param scope whether the query matches the document content or properties * @param options options for fine tuning the query * @param weight the multiplier for the match in the document ranking * @param value either true or false * @return the StructuredQueryDefinition for the value query */ public StructuredQueryDefinition value(TextIndex index, FragmentScope scope, String[] options, double weight, Boolean value) { return new ValueQuery(index, scope, options, weight, new Object[] {value}); } /** * Matches a JSON property that has a value with the same numeric * value as at least one of the criteria values. Note this method will not * match any XML node. * @param index the value container * @param scope whether the query matches the document content or properties * @param options options for fine tuning the query * @param weight the multiplier for the match in the document ranking * @param values the possible values to match * @return the StructuredQueryDefinition for the value query */ public StructuredQueryDefinition value(TextIndex index, FragmentScope scope, String[] options, double weight, Number... values) { return new ValueQuery(index, scope, options, weight, values); } /** * Matches an element, attribute, JSON property, or field * that has at least one of the criteria words. * @param index the word container * @param words the possible words to match * @return the StructuredQueryDefinition for the word query */ public StructuredQueryDefinition word(TextIndex index, String... words) { return new WordQuery(index, null, null, null, words); } /** * Matches an element, attribute, JSON property, or field * that has at least one of the criteria words. * @param index the word container * @param scope whether the query matches the document content or properties * @param options options for fine tuning the query * @param weight the multiplier for the match in the document ranking * @param words the possible words to match * @return the StructuredQueryDefinition for the word query */ public StructuredQueryDefinition word(TextIndex index, FragmentScope scope, String[] options, double weight, String... words) { return new WordQuery(index, scope, options, weight, words); } /** * Matches an element, attribute, JSON property, field, or path * whose value that has the correct datatyped comparison with * one of the criteria values. * @param index the range container * @param type the datatype of the container and specified values * @param operator the comparison with the criteria values * @param values the possible datatyped values for the comparison * @return the StructuredQueryDefinition for the range query */ public StructuredQueryDefinition range(RangeIndex index, String type, Operator operator, Object... values) { return new RangeQuery(index, type, null, null, null, operator, values); } /** * Matches an element, attribute, JSON property, field, or path * whose value that has the correct datatyped comparison with * one of the criteria values. * @param index the range container * @param type * @param collation the identifier for the strategy for comparing types * @param operator the comparison with the criteria values * @param values the possible datatyped values for the comparison * @return the StructuredQueryDefinition for the range query */ public StructuredQueryDefinition range(RangeIndex index, String type, String collation, Operator operator, Object... values) { return new RangeQuery(index, type, collation, null, null, operator, values); } /** * Matches an element, attribute, JSON property, field, or path * whose value that has the correct datatyped comparison with * one of the criteria values. * @param index the range container * @param type * @param collation the identifier for the strategy for comparing types * @param scope whether the query matches the document content or properties * @param operator the comparison with the criteria values * @param values the possible datatyped values for the comparison * @return the StructuredQueryDefinition for the range query */ public StructuredQueryDefinition range(RangeIndex index, String type, String collation, FragmentScope scope, Operator operator, Object... values) { return new RangeQuery(index, type, collation, scope, null, operator, values); } /** * Matches an element, attribute, JSON property, field, or path * whose value that has the correct datatyped comparison with * one of the criteria values. * @param index the range container * @param type the datatype of the container and specified values * @param options options for fine tuning the query * @param operator the comparison with the criteria values * @param values the possible datatyped values for the comparison * @return the StructuredQueryDefinition for the range query */ public StructuredQueryDefinition range(RangeIndex index, String type, String[] options, Operator operator, Object... values) { return new RangeQuery(index, type, null, null, options, operator, values); } /** * Matches an element, attribute, JSON property, field, or path * whose value that has the correct datatyped comparison with * one of the criteria values. * @param index the range container * @param type * @param collation the identifier for the strategy for comparing types * @param options options for fine tuning the query * @param operator the comparison with the criteria values * @param values the possible datatyped values for the comparison * @return the StructuredQueryDefinition for the range query */ public StructuredQueryDefinition range(RangeIndex index, String type, String collation, String[] options, Operator operator, Object... values) { return new RangeQuery(index, type, collation, null, options, operator, values); } /** * Matches an element, attribute, JSON property, field, or path * whose value that has the correct datatyped comparison with * one of the criteria values. * @param index the range container * @param type * @param collation the identifier for the strategy for comparing types * @param scope whether the query matches the document content or properties * @param options options for fine tuning the query * @param operator the comparison with the criteria values * @param values the possible datatyped values for the comparison * @return the StructuredQueryDefinition for the range query */ public StructuredQueryDefinition range(RangeIndex index, String type, String collation, FragmentScope scope, String[] options, Operator operator, Object... values) { return new RangeQuery(index, type, collation, scope, options, operator, values); } /** * Matches an element, element pair, element attribute, pair, or path * specifying a geospatial point that appears within one of the criteria regions. * @param index the container for the coordinates of the geospatial point * @param regions the possible regions containing the point * @return the StructuredQueryDefinition for the geospatial query */ public StructuredQueryDefinition geospatial(GeospatialIndex index, Region... regions) { checkRegions(regions); return new GeospatialQuery(index, null, regions, null); } /** * Matches an element, element pair, element attribute, pair, or path * specifying a geospatial point that appears within one of the criteria regions. * @param index the container for the coordinates of the geospatial point * @param scope whether the query matches the document content or properties * @param options options for fine tuning the query * @param regions the possible regions containing the point * @return the StructuredQueryDefinition for the geospatial query */ public StructuredQueryDefinition geospatial(GeospatialIndex index, FragmentScope scope, String[] options, Region... regions) { checkRegions(regions); return new GeospatialQuery(index, scope, regions, options); } /** * Identifies a namespaced element to match with a query. * @param qname the name of the element * @return the element identifier */ public Element element(QName qname) { return new ElementImpl(qname); } /** * Identifies a simple element to match with a query. * @param name the name of the element * @return the element identifier */ public Element element(String name) { return new ElementImpl(name); } /** * Identifies a namespaced attribute to match with a query. * @param qname the name of the attribute * @return the attribute identifier */ public Attribute attribute(QName qname) { return new AttributeImpl(qname); } /** * Identifies a simple attribute to match with a query. * @param name the name of the attribute * @return the attribute identifier */ public Attribute attribute(String name) { return new AttributeImpl(name); } /** * Identifies an element having an attribute to match with a query. * @param element the element identifier * @param attribute the attribute identifier * @return the identifier for the element-attribute pair */ public ElementAttribute elementAttribute(Element element, Attribute attribute) { return new ElementAttributeImpl(element, attribute); } /** * Identifies a field to match with a query. Fields are defined * in the configuration for the database. * @param name the name of the field * @return the identifier for the field */ public Field field(String name) { return new FieldImpl(name); } /** * Identifies a JSON property to match with a query. * @param name the name of the JSON property * @return the identifier for the JSON property */ public JSONProperty jsonProperty(String name) { return new JSONPropertyImpl(name); } /** * Identifies a path index to match with a query. * @param path the indexed path * @return the identifier for the path index */ public PathIndex pathIndex(String path) { return new PathIndexImpl(path); } /** * Identifies a json property whose text has the point format latitude and longitude * coordinates to match with a geospatial query. * @param jsonProperty the json property containing the geospatial coordinates * @return the specification for the index on the geospatial coordinates */ public GeospatialIndex geoJSONProperty(JSONProperty jsonProperty) { if ( jsonProperty == null ) throw new IllegalArgumentException("jsonProperty cannot be null"); return new GeoJSONPropertyImpl(jsonProperty); } /** * Identifies a parent json property with a child json property whose text has * the latitude and longitude coordinates to match with a geospatial query. * @param parent the parent of the json property with the coordinates * @param jsonProperty the json property containing the geospatial coordinates * @return the specification for the index on the geospatial coordinates */ public GeospatialIndex geoJSONProperty(JSONProperty parent, JSONProperty jsonProperty) { if ( parent == null ) throw new IllegalArgumentException("parent cannot be null"); if ( jsonProperty == null ) throw new IllegalArgumentException("jsonProperty cannot be null"); return new GeoJSONPropertyImpl(parent, jsonProperty); } /** * Identifies a parent json property with child latitude and longitude json properties * to match with a geospatial query. * @param parent the parent json property of lat and lon * @param lat the json property with the latitude coordinate * @param lon the json property with the longitude coordinate * @return the specification for the index on the geospatial coordinates */ public GeospatialIndex geoJSONPropertyPair(JSONProperty parent, JSONProperty lat, JSONProperty lon) { if ( parent == null ) throw new IllegalArgumentException("parent cannot be null"); if ( lat == null ) throw new IllegalArgumentException("lat cannot be null"); if ( lon == null ) throw new IllegalArgumentException("lon cannot be null"); return new GeoJSONPropertyPairImpl(parent, lat, lon); } /** * Identifies an element whose text has the latitude and longitude * coordinates to match with a geospatial query. * @param element the element containing the geospatial coordinates * @return the specification for the index on the geospatial coordinates */ public GeospatialIndex geoElement(Element element) { return new GeoElementImpl(element); } /** * Identifies a parent element with a child element whose text has * the latitude and longitude coordinates to match with a geospatial query. * @param parent the parent of the element with the coordinates * @param element the element containing the geospatial coordinates * @return the specification for the index on the geospatial coordinates */ public GeospatialIndex geoElement(Element parent, Element element) { return new GeoElementImpl(parent, element); } /** * Identifies a parent element with child latitude and longitude elements * to match with a geospatial query. * @param parent the parent of the element with the coordinates * @param lat the element with the latitude coordinate * @param lon the element with the longitude coordinate * @return the specification for the index on the geospatial coordinates */ public GeospatialIndex geoElementPair(Element parent, Element lat, Element lon) { return new GeoElementPairImpl(parent, lat, lon); } /** * Identifies a parent element with child latitude and longitude attributes * to match with a geospatial query. * @param parent the parent of the element with the coordinates * @param lat the attribute with the latitude coordinate * @param lon the attribute with the longitude coordinate * @return the specification for the index on the geospatial coordinates */ public GeospatialIndex geoAttributePair(Element parent, Attribute lat, Attribute lon) { return new GeoAttributePairImpl(parent, lat, lon); } /** * Identifies a path with the latitude and longitude to match * with a geospatial query. * @param pathIndex the indexed path * @return the specification for the index on the geospatial coordinates */ public GeospatialIndex geoPath(PathIndex pathIndex) { return new GeoPathImpl(pathIndex); } /** * Specifies a geospatial point. * @param latitude the latitude coordinate * @param longitude the longitude coordinate * @return the definition of the point */ public Point point(double latitude, double longitude) { return new Point(latitude, longitude); } /** * Specifies a geospatial region as a circle, * supplying coordinates for the center. * @param latitude the latitude coordinate of the center * @param longitude the longitude coordinate of the center * @param radius the radius of the circle * @return the definition of the circle */ public Circle circle(double latitude, double longitude, double radius) { return new Circle(latitude, longitude, radius); } /** * Specifies a geospatial region as a circle, * supplying a point for the center. * @param center the point defining the center * @param radius the radius of the circle * @return the definition of the circle */ public Circle circle(Point center, double radius) { return new Circle(center.getLatitude(), center.getLongitude(), radius); } /** * Specifies a geospatial region as a box, supplying * the coordinates for the perimeter. * @param south the latitude of the south coordinate * @param west the longitude of the west coordinate * @param north the latitude of the north coordinate * @param east the longitude of the east coordinate * @return the definition of the box */ public Box box(double south, double west, double north, double east) { return new Box(south, west, north, east); } /** * Specifies a geospatial region as an arbitrary polygon. * @param points the list of points defining the perimeter of the region * @return the definition of the polygon */ public Polygon polygon(Point... points) { return new Polygon(points); } /** * Matches a query within the substructure of the container specified * by the constraint. * @param constraintName the constraint definition * @param query the query definition * @return the StructuredQueryDefinition for the element constraint query */ public StructuredQueryDefinition containerConstraint(String constraintName, StructuredQueryDefinition query) { checkQuery(query); return new ContainerConstraintQuery(constraintName, query); } /** * @deprecated Matches a query within the substructure of the container specified * by the constraint. * This method is deprecated in favor of the more general * {@link #containerConstraint(String, StructuredQueryDefinition) containerConstraint()} method. * @param constraintName the constraint definition * @param query the query definition * @return the StructuredQueryDefinition for the element constraint query */ @Deprecated public ElementConstraintQuery elementConstraint(String constraintName, StructuredQueryDefinition query) { checkQuery(query); return new ElementConstraintQuery(constraintName, query); } /** * Associates a query with the properties of documents (as opposed to * the content of documents) with the specified constraint. * @param constraintName the constraint definition * @param query the query definition * @return the StructuredQueryDefinition for the properties constraint query */ public PropertiesConstraintQuery propertiesConstraint(String constraintName, StructuredQueryDefinition query) { checkQuery(query); return new PropertiesConstraintQuery(constraintName, query); } /** * Matches documents belonging to at least one * of the criteria collections with the specified constraint. * @param constraintName the constraint definition * @param uris the identifiers for the criteria collections * @return the StructuredQueryDefinition for the collection constraint query */ public CollectionConstraintQuery collectionConstraint(String constraintName, String... uris) { return new CollectionConstraintQuery(constraintName, uris); } /** * Matches the container specified by the constraint when it * has a value with the same string value as at least one * of the criteria values. * @param constraintName the constraint definition * @param values the possible values to match * @return the StructuredQueryDefinition for the value constraint query */ public ValueConstraintQuery valueConstraint(String constraintName, String... values) { return new ValueConstraintQuery(constraintName, values); } /** * Matches the container specified by the constraint when it * has a value with the same string value as at least one * of the criteria values. * @param constraintName the constraint definition * @param weight the multiplier for the match in the document ranking * @param values the possible values to match * @return the StructuredQueryDefinition for the value constraint query */ public ValueConstraintQuery valueConstraint(String constraintName, double weight, String... values) { return new ValueConstraintQuery(constraintName, weight, values); } /** * Matches the container specified by the constraint when it * has at least one of the criteria words. * @param constraintName the constraint definition * @param words the possible words to match * @return the StructuredQueryDefinition for the word constraint query */ public WordConstraintQuery wordConstraint(String constraintName, String... words) { return new WordConstraintQuery(constraintName, words); } /** * Matches the container specified by the constraint when it * has at least one of the criteria words. * @param constraintName the constraint definition * @param weight the multiplier for the match in the document ranking * @param words the possible words to match * @return the StructuredQueryDefinition for the word constraint query */ public WordConstraintQuery wordConstraint(String constraintName, double weight, String... words) { return new WordConstraintQuery(constraintName, weight, words); } /** * Matches the container specified by the constraint * whose value that has the correct datatyped comparison with * one of the criteria values. * @param constraintName the constraint definition * @param operator the comparison with the criteria values * @param values the possible datatyped values for the comparison * @return the StructuredQueryDefinition for the range constraint query */ public RangeConstraintQuery rangeConstraint(String constraintName, Operator operator, String... values) { return new RangeConstraintQuery(constraintName, operator, values); } /** * Matches the container specified by the constraint * whose geospatial point appears within one of the criteria regions. * @param constraintName the constraint definition * @param regions the possible regions containing the point * @return the StructuredQueryDefinition for the geospatial constraint query */ public GeospatialConstraintQuery geospatialConstraint(String constraintName, Region... regions) { checkRegions(regions); return new GeospatialConstraintQuery(constraintName, regions); } /** * Matches documents as specified by a constraint that implements * a custom query parameterized with the supplied text. * @param constraintName the constraint definition * @param text the input to the custom query * @return the StructuredQueryDefinition for the custom constraint query */ public CustomConstraintQuery customConstraint(String constraintName, String... text) { return new CustomConstraintQuery(constraintName, text); } /* ************************************************************************************* */ // TODO IN A FUTURE RELEASE: remove the deprecated innerSerialize() method protected abstract class AbstractStructuredQuery extends AbstractQueryDefinition implements StructuredQueryDefinition { public AbstractStructuredQuery() { optionsUri = builderOptionsURI; } public String serialize() { return serializeQueries(this); } /** * Returns the query as a partial string. This method will be removed in a future * release. * @return the query content */ @Deprecated public String innerSerialize() { return extractQueryContent(serializeQueries(this)); } public abstract void innerSerialize(XMLStreamWriter serializer) throws Exception; } // TODO IN A FUTURE RELEASE: change the visibility of the deprecated // classes from public to package and change the return type of the // builder methods to StructuredQueryDefinition /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of AndQuery. */ @Deprecated public class AndQuery extends AbstractStructuredQuery { private StructuredQueryDefinition[] queries; /** * @deprecated Use the and() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public AndQuery(StructuredQueryDefinition... queries) { super(); this.queries = queries; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { writeQueryList(serializer, "and-query", convertQueries(queries)); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface as the type for instances of OrQuery. */ @Deprecated public class OrQuery extends AbstractStructuredQuery { private StructuredQueryDefinition[] queries; /** * @deprecated Use the or() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public OrQuery(StructuredQueryDefinition... queries) { super(); this.queries = queries; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { writeQueryList(serializer, "or-query", convertQueries(queries)); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface as the type for instances of NotQuery. */ @Deprecated public class NotQuery extends AbstractStructuredQuery { private StructuredQueryDefinition query; /** * @deprecated Use the not() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public NotQuery(StructuredQueryDefinition query) { super(); this.query = query; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { writeQuery(serializer, "not-query", (AbstractStructuredQuery) query); } } private class NotInQuery extends AbstractStructuredQuery { private StructuredQueryDefinition positive; private StructuredQueryDefinition negative; /** * @deprecated Use the notIn() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public NotInQuery(StructuredQueryDefinition positive, StructuredQueryDefinition negative) { super(); this.positive = positive; this.negative = negative; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("not-in-query"); writeQuery(serializer, "positive-query", (AbstractStructuredQuery) positive); writeQuery(serializer, "negative-query", (AbstractStructuredQuery) negative); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of AndNotQuery. */ @Deprecated public class AndNotQuery extends AbstractStructuredQuery { private StructuredQueryDefinition positive; private StructuredQueryDefinition negative; /** * @deprecated Use the andNot() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public AndNotQuery(StructuredQueryDefinition positive, StructuredQueryDefinition negative) { super(); this.positive = positive; this.negative = negative; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("and-not-query"); writeQuery(serializer, "positive-query", (AbstractStructuredQuery) positive); writeQuery(serializer, "negative-query", (AbstractStructuredQuery) negative); serializer.writeEndElement(); } } private class BoostQuery extends AbstractStructuredQuery { private StructuredQueryDefinition matchingQuery; private StructuredQueryDefinition boostingQuery; /** * @deprecated Use the boost() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public BoostQuery(StructuredQueryDefinition matchingQuery, StructuredQueryDefinition boostingQuery) { super(); this.matchingQuery = matchingQuery; this.boostingQuery = boostingQuery; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("boost-query"); writeQuery(serializer, "matching-query", (AbstractStructuredQuery) matchingQuery); writeQuery(serializer, "boosting-query", (AbstractStructuredQuery) boostingQuery); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of DocumentQuery. */ @Deprecated public class DocumentQuery extends AbstractStructuredQuery { private String[] uris = null; /** * @deprecated Use the document() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public DocumentQuery(String... uris) { super(); this.uris = uris; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("document-query"); writeTextList(serializer, "uri", uris); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of TermQuery. */ @Deprecated public class TermQuery extends AbstractStructuredQuery { private String[] terms = null; private Double weight = 0.0; /** * @deprecated Use the term() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public TermQuery(Double weight, String... terms) { super(); this.weight = weight; this.terms = terms; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("term-query"); writeTextList(serializer, "text", terms); writeText(serializer, "weight", weight); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of NearQuery. */ @Deprecated public class NearQuery extends AbstractStructuredQuery { private Integer distance; private Double weight; private Ordering order; private StructuredQueryDefinition[] queries; /** * @deprecated Use the near() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public NearQuery(StructuredQueryDefinition... queries) { super(); this.queries = queries; } public NearQuery(Integer distance, Double weight, Ordering order, StructuredQueryDefinition... queries) { this.distance = distance; this.weight = weight; this.order = order; this.queries = queries; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("near-query"); writeQueryList(serializer, queries); if (order != null) { serializer.writeStartElement("ordered"); serializer.writeCharacters( Boolean.toString(order == Ordering.ORDERED)); serializer.writeEndElement(); } writeText(serializer, "distance", distance); writeText(serializer, "distance-weight", weight); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of CollectionQuery. */ @Deprecated public class CollectionQuery extends AbstractStructuredQuery { private String uris[] = null; /** * @deprecated Use the collection() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public CollectionQuery(String... uris) { super(); this.uris = uris; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("collection-query"); writeTextList(serializer, "uri", uris); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of DirectoryQuery. */ @Deprecated public class DirectoryQuery extends AbstractStructuredQuery { private String uris[]; private Boolean isInfinite; private Integer depth; /** * @deprecated Use the directory() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public DirectoryQuery(Boolean isInfinite, String... uris) { super(); this.isInfinite = isInfinite; this.uris = uris; this.depth = null; } DirectoryQuery(Integer depth, String... uris) { super(); this.isInfinite = false; this.uris = uris; this.depth = depth; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("directory-query"); if (depth != null) { serializer.writeAttribute("depth", Integer.toString(depth)); } writeTextList(serializer, "uri", uris); writeText(serializer, "infinite", isInfinite); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of DocumentFragmentQuery. */ @Deprecated public class DocumentFragmentQuery extends AbstractStructuredQuery { private StructuredQueryDefinition query; /** * @deprecated Use the documentFragment() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public DocumentFragmentQuery(StructuredQueryDefinition query) { super(); this.query = query; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { writeQuery(serializer, "document-fragment-query", (AbstractStructuredQuery) query); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of PropertiesQuery. */ @Deprecated public class PropertiesQuery extends AbstractStructuredQuery { private StructuredQueryDefinition query; /** * @deprecated Use the properties() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public PropertiesQuery(StructuredQueryDefinition query) { super(); this.query = query; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { writeQuery(serializer, "properties-fragment-query", (AbstractStructuredQuery) query); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of LocksQuery. */ @Deprecated public class LocksQuery extends AbstractStructuredQuery { private StructuredQueryDefinition query; /** * @deprecated Use the locks() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public LocksQuery(StructuredQueryDefinition query) { super(); this.query = query; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { writeQuery(serializer, "locks-fragment-query", (AbstractStructuredQuery) query); } } /** * Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of ContainerConstraintQuery. */ private class ContainerConstraintQuery extends AbstractStructuredQuery { private String name; private StructuredQueryDefinition query; /** * Use the containerConstraint() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ public ContainerConstraintQuery(String constraintName, StructuredQueryDefinition query) { super(); name = constraintName; this.query = query; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("container-constraint-query"); writeText(serializer, "constraint-name", name); writeQuery(serializer, query); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of ElementConstraintQuery. */ @Deprecated public class ElementConstraintQuery extends AbstractStructuredQuery { private String name; private StructuredQueryDefinition query; /** * @deprecated Use the elementConstraint() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public ElementConstraintQuery(String constraintName, StructuredQueryDefinition query) { super(); name = constraintName; this.query = query; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("element-constraint-query"); writeText(serializer, "constraint-name", name); writeQuery(serializer, query); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of PropertiesConstraintQuery. */ @Deprecated public class PropertiesConstraintQuery extends AbstractStructuredQuery { private String name; private StructuredQueryDefinition query; /** * @deprecated Use the propertiesConstraint() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public PropertiesConstraintQuery(String constraintName, StructuredQueryDefinition query) { super(); name = constraintName; this.query = query; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("properties-constraint-query"); writeText(serializer, "constraint-name", name); writeQuery(serializer, query); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of CollectionConstraintQuery. */ @Deprecated public class CollectionConstraintQuery extends AbstractStructuredQuery { String name = null; String[] uris = null; /** * @deprecated Use the collectionConstraint() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public CollectionConstraintQuery(String constraintName, String... uris) { super(); name = constraintName; this.uris = uris; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("collection-constraint-query"); writeText(serializer, "constraint-name", name); writeTextList(serializer, "uri", uris); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of ValueConstraintQuery. */ @Deprecated public class ValueConstraintQuery extends AbstractStructuredQuery { String name; String[] values; Double weight; /** * @deprecated Use the valueConstraint() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public ValueConstraintQuery(String constraintName, String... values) { super(); name = constraintName; this.values = values; } public ValueConstraintQuery(String constraintName, Double weight, String... values) { name = constraintName; this.values = values; this.weight = weight; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("value-constraint-query"); writeText(serializer, "constraint-name", name); writeTextList(serializer, "text", values); writeText(serializer, "weight", weight); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of WordConstraintQuery. */ @Deprecated public class WordConstraintQuery extends AbstractStructuredQuery { String name; String[] words; Double weight; /** * @deprecated Use the wordConstraint() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public WordConstraintQuery(String constraintName, String... words) { super(); name = constraintName; this.words = words; } public WordConstraintQuery(String constraintName, Double weight, String... words) { name = constraintName; this.words = words; this.weight = weight; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("word-constraint-query"); writeText(serializer, "constraint-name", name); writeTextList(serializer, "text", words); writeText(serializer, "weight", weight); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of RangeConstraintQuery. */ @Deprecated public class RangeConstraintQuery extends AbstractStructuredQuery { String name = null; String[] values = null; Operator operator = null; /** * @deprecated Use the rangeConstraint() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public RangeConstraintQuery(String constraintName, Operator operator, String... values) { super(); name = constraintName; this.values = values; this.operator = operator; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("range-constraint-query"); writeText(serializer, "constraint-name", name); writeTextList(serializer, "value", values); writeText(serializer, "range-operator", operator); serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of GeospatialConstraintQuery. */ @Deprecated public class GeospatialConstraintQuery extends AbstractStructuredQuery { String name = null; Region[] regions = null; /** * @deprecated Use the geospatialConstraint() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public GeospatialConstraintQuery(String constraintName, Region... regions) { super(); name = constraintName; this.regions = regions; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("geospatial-constraint-query"); writeText(serializer, "constraint-name", name); for (Region region : regions) { ((RegionImpl) region).innerSerialize(serializer); } serializer.writeEndElement(); } } /** * @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface * as the type for instances of CustomConstraintQuery. */ @Deprecated public class CustomConstraintQuery extends AbstractStructuredQuery { private String terms[] = null; private String name = null; /** * @deprecated Use the customConstraint() builder method of StructuredQueryBuilder * and type the object as an instance of the StructuredQueryDefinition interface. */ @Deprecated public CustomConstraintQuery(String constraintName, String... terms) { super(); name = constraintName; this.terms = terms; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("custom-constraint-query"); writeText(serializer, "constraint-name", name); writeTextList(serializer, "text", terms); serializer.writeEndElement(); } } class ContainerQuery extends AbstractStructuredQuery { private ContainerIndex index; private StructuredQueryDefinition query; ContainerQuery(ContainerIndex index, StructuredQueryDefinition query) { this.index = index; this.query = query; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("container-query"); ((IndexImpl) index).innerSerialize(serializer); writeQuery(serializer, query); serializer.writeEndElement(); } } abstract class TextQuery extends AbstractStructuredQuery { TextIndex index; FragmentScope scope; String[] values; String[] options; Double weight; TextQuery(TextIndex index, FragmentScope scope, String[] options, Double weight, String[] values) { this.index = index; this.scope = scope; this.options = options; this.weight = weight; this.values = values; } public void innerSerialize(XMLStreamWriter serializer) throws Exception { ((IndexImpl) index).innerSerialize(serializer); if (scope != null) { if (scope == FragmentScope.DOCUMENT) { writeText(serializer, "fragment-scope", "documents"); } else { writeText(serializer, "fragment-scope", scope.toString().toLowerCase()); } } writeTextList(serializer, "text", values); writeTextList(serializer, "term-option", options); writeText(serializer, "weight", weight); } } class ValueQuery extends AbstractStructuredQuery { TextIndex index; FragmentScope scope; String[] options; Double weight; Object[] values; ValueQuery(TextIndex index, FragmentScope scope, String[] options, Double weight, Object[] values) { this.index = index; this.scope = scope; this.options = options; this.weight = weight; this.values = values; } public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("value-query"); if ( values != null && values.length > 0 ) { if ( values[0] == null ) { serializer.writeAttribute("type", "null"); } else if ( values[0] instanceof String ) { serializer.writeAttribute("type", "string"); } else if ( values[0] instanceof Number ) { serializer.writeAttribute("type", "number"); } else if ( values[0] instanceof Boolean ) { serializer.writeAttribute("type", "boolean"); } } ((IndexImpl) index).innerSerialize(serializer); if (scope != null) { if (scope == FragmentScope.DOCUMENT) { writeText(serializer, "fragment-scope", "documents"); } else { writeText(serializer, "fragment-scope", scope.toString().toLowerCase()); } } if ( values != null ) { for ( Object value: values ) { if ( value == null ) { } else { writeText(serializer, "text", value); } } } writeTextList(serializer, "term-option", options); writeText(serializer, "weight", weight); serializer.writeEndElement(); } } // QUESTION: why collation on word but not values? class WordQuery extends TextQuery { WordQuery(TextIndex index, FragmentScope scope, String[] options, Double weight, String[] values) { super(index, scope, options, weight, values); } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("word-query"); super.innerSerialize(serializer); serializer.writeEndElement(); } } class RangeQuery extends AbstractStructuredQuery { RangeIndex index; FragmentScope scope; String type; String collation; String[] options; Operator operator; String[] values; RangeQuery(RangeIndex index, String type, String collation, FragmentScope scope, String[] rangeOptions, Operator operator, Object[] values) { this.index = index; this.type = type; this.collation = collation; this.scope = scope; this.options = rangeOptions; this.operator = operator; this.values = new String[values.length]; for (int i=0; i < values.length; i++) { Object value = values[i]; this.values[i] = (value instanceof String) ? (String) value : value.toString(); } } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("range-query"); if (type != null) { serializer.writeAttribute("type", type); if (collation!= null) { serializer.writeAttribute("collation", collation); } } ((IndexImpl) index).innerSerialize(serializer); if (scope != null) { writeText(serializer, "fragment-scope", scope.toString().toLowerCase()); } writeTextList(serializer, "value", values); if (operator != null) { writeText(serializer, "range-operator", operator.toString().toUpperCase()); } writeTextList(serializer, "range-option", options); serializer.writeEndElement(); } } class GeospatialQuery extends AbstractStructuredQuery { GeospatialIndex index; FragmentScope scope; Region[] regions; String[] options; GeospatialQuery(GeospatialIndex index, FragmentScope scope, Region[] regions, String[] options) { this.index = index; this.scope = scope; this.regions = regions; this.options = options; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { String elemName = null; if (index instanceof GeoJSONPropertyImpl) elemName = "geo-json-property-query"; else if (index instanceof GeoJSONPropertyPairImpl) elemName = "geo-json-property-pair-query"; else if (index instanceof GeoElementImpl) elemName = "geo-elem-query"; else if (index instanceof GeoElementPairImpl) elemName = "geo-elem-pair-query"; else if (index instanceof GeoAttributePairImpl) elemName = "geo-attr-pair-query"; else if (index instanceof GeoPathImpl) elemName = "geo-path-query"; else throw new IllegalStateException( "unknown index class: "+index.getClass().getName()); serializer.writeStartElement(elemName); ((IndexImpl) index).innerSerialize(serializer); if (scope != null) { writeText(serializer, "fragment-scope", scope.toString().toLowerCase()); } writeTextList(serializer, "geo-option", options); for (Region region : regions) { ((RegionImpl) region).innerSerialize(serializer); } serializer.writeEndElement(); } } class TemporalAxis implements Axis { private String name; TemporalAxis(String name) { this.name = name; } public String toString() { return name; } } class TemporalPeriod extends AbstractStructuredQuery implements Period { private String formattedStart; private String formattedEnd; private String[] options; TemporalPeriod(String start, String end) { this.formattedStart = start; this.formattedEnd = end; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("period"); writeText(serializer, "period-start", formattedStart); writeText(serializer, "period-end", formattedEnd); serializer.writeEndElement(); } } class TemporalPeriodRangeQuery extends AbstractStructuredQuery { private Axis[] axes; private TemporalOperator operator; private Period[] periods; private String[] options; TemporalPeriodRangeQuery(Axis[] axes, TemporalOperator operator, Period[] periods, String... options) { this.axes = axes; this.operator = operator; this.periods = periods; this.options = options; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("period-range-query"); writeTextList(serializer, "axis", axes); writeText(serializer, "temporal-operator", operator.toString().toLowerCase()); for ( Period period : periods ) { ((TemporalPeriod) period).innerSerialize(serializer); } writeTextList(serializer, "query-option", options); serializer.writeEndElement(); } } class TemporalPeriodCompareQuery extends AbstractStructuredQuery { private Axis axis1; private TemporalOperator operator; private Axis axis2; private String[] options; TemporalPeriodCompareQuery(Axis axis1, TemporalOperator operator, Axis axis2, String[] options) { this.axis1 = axis1; this.operator = operator; this.axis2 = axis2; this.options = options; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("period-compare-query"); writeText(serializer, "axis1", axis1); writeText(serializer, "temporal-operator", operator.toString().toLowerCase()); writeText(serializer, "axis2", axis2); writeTextList(serializer, "query-option", options); serializer.writeEndElement(); } } class TemporalLsqtQuery extends AbstractStructuredQuery { private String temporalCollection; private String formattedTimestamp = null; private double weight; private String[] options; TemporalLsqtQuery(String temporalCollection, String timestamp, double weight, String[] options) { this.temporalCollection = temporalCollection; if ( timestamp != null ) { this.formattedTimestamp = timestamp; } this.weight = weight; this.options = options; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("lsqt-query"); writeText(serializer, "temporal-collection", temporalCollection); if ( formattedTimestamp != null && formattedTimestamp.length() > 0 ) { writeText(serializer, "timestamp", formattedTimestamp); } writeText(serializer, "weight", weight); writeTextList(serializer, "query-option", options); serializer.writeEndElement(); } } /* ************************************************************************************* */ protected abstract class IndexImpl { protected abstract void innerSerialize(XMLStreamWriter serializer) throws Exception; } class ElementImpl extends IndexImpl implements Element { String name; QName qname; ElementImpl(QName qname) { this.qname = qname; } ElementImpl(String name) { this.name = name; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializeNamedIndex(serializer, "element", qname, name); } } class AttributeImpl extends IndexImpl implements Attribute { String name; QName qname; AttributeImpl(QName qname) { this.qname = qname; } AttributeImpl(String name) { this.name = name; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializeNamedIndex(serializer, "attribute", qname, name); } } class ElementAttributeImpl extends IndexImpl implements ElementAttribute { Element element; Attribute attribute; ElementAttributeImpl(Element element, Attribute attribute) { this.element = element; this.attribute = attribute; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { ((IndexImpl) element).innerSerialize(serializer); ((IndexImpl) attribute).innerSerialize(serializer); } } class FieldImpl extends IndexImpl implements Field { String name; FieldImpl(String name) { this.name = name; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("field"); serializer.writeAttribute("name", name); serializer.writeEndElement(); } } class JSONPropertyImpl extends IndexImpl implements JSONProperty { String name; JSONPropertyImpl(String name) { this.name = name; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { writeText(serializer, "json-property", name); } } class PathIndexImpl extends IndexImpl implements PathIndex { String path; PathIndexImpl(String path) { this.path = path; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { writeText(serializer, "path-index", path); } } class GeoJSONPropertyImpl extends IndexImpl implements GeospatialIndex { JSONProperty parent; JSONProperty jsonProperty; GeoJSONPropertyImpl(JSONProperty jsonProperty) { super(); this.jsonProperty = jsonProperty; } GeoJSONPropertyImpl(JSONProperty parent, JSONProperty jsonProperty) { this(jsonProperty); this.parent = parent; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { if (parent != null && parent instanceof JSONPropertyImpl) { JSONPropertyImpl parentImpl = (JSONPropertyImpl) parent; writeText(serializer, "parent-property", parentImpl.name); } JSONPropertyImpl jsonPropertyImpl = (JSONPropertyImpl) jsonProperty; writeText(serializer, "json-property", jsonPropertyImpl.name); } } class GeoJSONPropertyPairImpl extends IndexImpl implements GeospatialIndex { JSONProperty parent; JSONProperty lat; JSONProperty lon; GeoJSONPropertyPairImpl(JSONProperty parent, JSONProperty lat, JSONProperty lon) { this.parent = parent; this.lat = lat; this.lon = lon; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { JSONPropertyImpl parentImpl = (JSONPropertyImpl) parent; JSONPropertyImpl latImpl = (JSONPropertyImpl) lat; JSONPropertyImpl lonImpl = (JSONPropertyImpl) lon; writeText(serializer, "parent-property", parentImpl.name); writeText(serializer, "lat-property", latImpl.name); writeText(serializer, "lon-property", lonImpl.name); } } class GeoElementImpl extends IndexImpl implements GeospatialIndex { Element parent; Element element; GeoElementImpl(Element element) { super(); this.element = element; } GeoElementImpl(Element parent, Element element) { this(element); this.parent = parent; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { if (parent != null && parent instanceof ElementImpl) { ElementImpl parentImpl = (ElementImpl) parent; serializeNamedIndex(serializer, "parent", parentImpl.qname, parentImpl.name); } else if (parent != null && parent instanceof IndexImpl) { IndexImpl parentImpl = (IndexImpl) parent; parentImpl.innerSerialize(serializer); } if ( element instanceof ElementImpl ) { ElementImpl elementImpl = (ElementImpl) element; serializeNamedIndex(serializer, "element", elementImpl.qname, elementImpl.name); } else if ( element instanceof IndexImpl ) { IndexImpl indexImpl = (IndexImpl) element; indexImpl.innerSerialize(serializer); } } } class GeoElementPairImpl extends IndexImpl implements GeospatialIndex { Element parent; Element lat; Element lon; GeoElementPairImpl(Element parent, Element lat, Element lon) { this.parent = parent; this.lat = lat; this.lon = lon; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { ElementImpl parentImpl = (ElementImpl) parent; ElementImpl latImpl = (ElementImpl) lat; ElementImpl lonImpl = (ElementImpl) lon; serializeNamedIndex(serializer, "parent", parentImpl.qname, parentImpl.name); serializeNamedIndex(serializer, "lat", latImpl.qname, latImpl.name); serializeNamedIndex(serializer, "lon", lonImpl.qname, lonImpl.name); } } class GeoAttributePairImpl extends IndexImpl implements GeospatialIndex { Element parent; Attribute lat; Attribute lon; GeoAttributePairImpl(Element parent, Attribute lat, Attribute lon) { this.parent = parent; this.lat = lat; this.lon = lon; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { ElementImpl parentImpl = (ElementImpl) parent; AttributeImpl latImpl = (AttributeImpl) lat; AttributeImpl lonImpl = (AttributeImpl) lon; serializeNamedIndex(serializer, "parent", parentImpl.qname, parentImpl.name); serializeNamedIndex(serializer, "lat", latImpl.qname, latImpl.name); serializeNamedIndex(serializer, "lon", lonImpl.qname, lonImpl.name); } } private class GeoPathImpl extends IndexImpl implements GeospatialIndex { PathIndex pathIndex; GeoPathImpl(PathIndex pathIndex) { this.pathIndex = pathIndex; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { PathIndexImpl pathIndexImpl = (PathIndexImpl) pathIndex; pathIndexImpl.innerSerialize(serializer); ; } } /** * A region matched by a geospatial query. */ public interface Region { // TODO IN A FUTURE RELEASE: remove the deprecated serialize() method /** * @deprecated Returns the region as a partial string. This method will be removed in a future * release. * @return the query content identifying a region */ @Deprecated public abstract String serialize(); } // TODO IN A FUTURE RELEASE: separate a public Point interface // from a package PointImpl class protected abstract class RegionImpl { /** * @deprecated Returns the region as a partial string. This method will be removed in a future * release. * @return the query content identifying a region */ @Deprecated public String serialize() { return extractQueryContent(serializeRegions(this)); } protected abstract void innerSerialize(XMLStreamWriter serializer) throws Exception; } /** * @deprecated Treat the Point class as an interface that extends Region. */ @Deprecated public class Point extends RegionImpl implements Region { private double lat = 0.0; private double lon = 0.0; /** * @deprecated Use the point() builder method of StructuredQueryBuilder. */ @Deprecated public Point(double latitude, double longitude) { lat = latitude; lon = longitude; } @Deprecated public double getLatitude() { return lat; } @Deprecated public double getLongitude() { return lon; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("point"); writeText(serializer, "latitude", String.valueOf(lat)); writeText(serializer, "longitude", String.valueOf(lon)); serializer.writeEndElement(); } } // TODO IN A FUTURE RELEASE: change the visibility of the deprecated // classes from public to package and change the return type of the builder // methods to Region /** * @deprecated Use the Region interface as the type for instances of Circle. */ @Deprecated public class Circle extends RegionImpl implements Region { private Point center = null; private double radius = 0.0; /** * @deprecated Use the circle() builder method of StructuredQueryBuilder * and type the object as an instance of the Region interface. */ @Deprecated public Circle(double latitude, double longitude, double radius) { center = new Point(latitude, longitude); this.radius = radius; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("circle"); writeText(serializer, "radius", String.valueOf(radius)); center.innerSerialize(serializer); serializer.writeEndElement(); } } /** * @deprecated Use the Region interface as the type for instances of Box. */ @Deprecated public class Box extends RegionImpl implements Region { private double south, west, north, east; /** * @deprecated Use the box() builder method of StructuredQueryBuilder * and type the object as an instance of the Region interface. */ @Deprecated public Box(double south, double west, double north, double east) { this.south = south; this.west = west; this.north = north; this.east = east; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("box"); writeText(serializer, "south", String.valueOf(south)); writeText(serializer, "west", String.valueOf(west)); writeText(serializer, "north", String.valueOf(north)); writeText(serializer, "east", String.valueOf(east)); serializer.writeEndElement(); } } /** * @deprecated Use the Region interface as the type for instances of Polygon. */ @Deprecated public class Polygon extends RegionImpl implements Region { private Point[] points; /** * @deprecated Use the polygon() builder method of StructuredQueryBuilder * and type the object as an instance of the Region interface. */ @Deprecated public Polygon(Point... points) { this.points = points; } @Override public void innerSerialize(XMLStreamWriter serializer) throws Exception { serializer.writeStartElement("polygon"); for (Point point: points) { point.innerSerialize(serializer); } serializer.writeEndElement(); } } private void checkQueries(StructuredQueryDefinition... queries) { if (queries != null) { for (StructuredQueryDefinition query: queries) { checkQuery(query); } } } private void checkQuery(StructuredQueryDefinition query) { if (query != null && !AbstractStructuredQuery.class.isAssignableFrom( query.getClass())) { throw new IllegalArgumentException( "Only built queries are supported: "+ query.getClass().getName()); } } private void checkRegions(Region... regions) { if (regions != null) { for (Region region: regions) { checkRegion(region); } } } private void checkRegion(Region region) { if (region != null && !RegionImpl.class.isAssignableFrom( region.getClass())) { throw new IllegalArgumentException( "Only built regions are supported: "+ region.getClass().getName()); } } static private XMLStreamWriter makeSerializer(OutputStream out) { XMLOutputFactory factory = XMLOutputFactory.newInstance(); factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true); try { XMLStreamWriter serializer = factory.createXMLStreamWriter(out, "UTF-8"); serializer.setDefaultNamespace("http://marklogic.com/appservices/search"); serializer.setPrefix("xs", XMLConstants.W3C_XML_SCHEMA_NS_URI); return serializer; } catch (Exception e) { throw new MarkLogicIOException(e); } } private String serializeRegions(RegionImpl... regions) { return serializeQueriesImpl((Object[]) regions); } private String serializeQueries(AbstractStructuredQuery... queries) { return serializeQueriesImpl((Object[]) queries); } private String serializeQueriesImpl(Object... objects) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); writeStructuredQueryImpl(baos, objects); return baos.toString("UTF-8"); } catch (Exception e) { throw new MarkLogicIOException(e); } } private void writeStructuredQuery(OutputStream out, AbstractStructuredQuery... queries) { writeStructuredQueryImpl(out, (Object[]) queries); } private void writeStructuredQueryImpl(OutputStream out, Object... objects) { try { XMLStreamWriter serializer = makeSerializer(out); // omit the XML prolog // serializer.writeStartDocument(); serializer.writeStartElement("query"); if (objects != null) { if (objects instanceof AbstractStructuredQuery[]) { if (namespaces != null) { for (String prefix : namespaces.getAllPrefixes()) { serializer.writeNamespace(prefix, namespaces.getNamespaceURI(prefix)); } } for (AbstractStructuredQuery query: (AbstractStructuredQuery[]) objects) { query.innerSerialize(serializer); } } else if (objects instanceof RegionImpl[]) { for (RegionImpl region: (RegionImpl[]) objects) { region.innerSerialize(serializer); } } } serializer.writeEndElement(); // serializer.writeEndDocument(); serializer.flush(); serializer.close(); } catch (Exception e) { throw new MarkLogicIOException(e); } } // TODO IN A FUTURE RELEASE: remove the transformation once the deprecated serialization // methods are removed static private Transformer makeExtractorTransformer() { try { if (extractor == null) { extractor = TransformerFactory.newInstance().newTemplates(new StreamSource(new StringReader( ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ ""+ "" ))); } return extractor.newTransformer(); } catch (TransformerConfigurationException e) { throw new MarkLogicIOException(e); } } static private String extractQueryContent(String query) { if (query == null) { return null; } try { StringWriter writer = new StringWriter(); makeExtractorTransformer().transform( new StreamSource(new StringReader(query)), new StreamResult(writer) ); return writer.toString(); } catch (TransformerException e) { throw new MarkLogicIOException(e); } } static private void serializeNamedIndex(XMLStreamWriter serializer, String elemName, QName qname, String name) throws Exception { serializer.writeStartElement(elemName); if (qname != null) { String ns = qname.getNamespaceURI(); serializer.writeAttribute("ns", (ns != null) ? ns : ""); serializer.writeAttribute("name", qname.getLocalPart()); } else { serializer.writeAttribute("ns", ""); serializer.writeAttribute("name", name); } serializer.writeEndElement(); } static private void writeText(XMLStreamWriter serializer, String container, Object object) throws Exception { if (object == null) { return; } serializer.writeStartElement(container); serializer.writeCharacters( (object instanceof String) ? (String) object : object.toString() ); serializer.writeEndElement(); } static private void writeTextList(XMLStreamWriter serializer, String container, Object[] objects) throws Exception { if (objects == null) { return; } for (Object object: objects) { if ( object == null ) continue; serializer.writeStartElement(container); serializer.writeCharacters( (object instanceof String) ? (String) object : object.toString() ); serializer.writeEndElement(); } } static private void writeQuery(XMLStreamWriter serializer, StructuredQueryDefinition query) throws Exception { ((AbstractStructuredQuery) query).innerSerialize(serializer); } static private void writeQueryList(XMLStreamWriter serializer, StructuredQueryDefinition... queries) throws Exception { if (queries == null) { return; } for (AbstractStructuredQuery query: convertQueries(queries)) { query.innerSerialize(serializer); } } static private void writeQuery(XMLStreamWriter serializer, String container, AbstractStructuredQuery query) throws Exception { serializer.writeStartElement(container); if (query != null) { query.innerSerialize(serializer); } serializer.writeEndElement(); } static private void writeQueryList(XMLStreamWriter serializer, String container, AbstractStructuredQuery... queries) throws Exception { serializer.writeStartElement(container); if (queries != null) { for (AbstractStructuredQuery query: queries) { query.innerSerialize(serializer); } } serializer.writeEndElement(); } static private AbstractStructuredQuery[] convertQueries(StructuredQueryDefinition... queries) { if (queries == null) { return null; } AbstractStructuredQuery[] innerQueries = new AbstractStructuredQuery[queries.length]; for (int i=0; i < queries.length; i++) { innerQueries[i] = (AbstractStructuredQuery) queries[i]; } return innerQueries; } class StructuredQueryXMLWriter extends BaseHandle implements StructureWriteHandle, XMLWriteHandle, BufferableHandle, OutputStreamSender { StructuredQueryDefinition[] queries; StructuredQueryXMLWriter(StructuredQueryDefinition[] queries) { super(); super.setResendable(true); super.setFormat(Format.XML); this.queries = queries; } @Override protected OutputStreamSender sendContent() { return this; } @Override public void setFormat(Format format) { if (format != Format.XML) throw new IllegalArgumentException("StructuredQueryWriter supports the XML format only"); } @Override public void fromBuffer(byte[] buffer) { throw new UnsupportedOperationException("Cannot set StructuredQueryWriter from buffer"); } @Override public byte[] toBuffer() { try { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); write(buffer); return buffer.toByteArray(); } catch (IOException e) { throw new MarkLogicIOException(e); } } @Override public String toString() { try { return new String(toBuffer(), "UTF-8"); } catch (IOException e) { throw new MarkLogicIOException(e); } } @Override public void write(OutputStream out) throws IOException { writeStructuredQuery(out, convertQueries(queries)); } } /** * Converts the list of options used for a range query to an array * as a convenience. * @param options the list of range query options * @return the range query options as an array */ public String[] rangeOptions(String... options) { return options; } /** * Defines a boost query for the matching and boosting query definitions. The matching * or boosting query definitions can each be an AND or OR query definition for complex * combinations of criteria. * @param matchingQuery the query definition that filters documents * @param boostingQuery the query definition that increases the rank for some filtered documents * @return the StructuredQueryDefinition for the boost query */ public StructuredQueryDefinition boost(StructuredQueryDefinition matchingQuery, StructuredQueryDefinition boostingQuery) { return new BoostQuery(matchingQuery, boostingQuery); } /** * Defines a not-in query for the positive and negative query definitions. These query definitions * can each be an AND or OR query definition for complex combinations of criteria. * @param positive the query definition that includes documents * @param negative the query definition that excludes documents * @return the StructuredQueryDefinition for the not-in query */ public StructuredQueryDefinition notIn(StructuredQueryDefinition positive, StructuredQueryDefinition negative) { return new NotInQuery(positive, negative); } /** * Gets the namespace bindings used for the query. * @return the namespace bindings */ public IterableNamespaceContext getNamespaces() { return namespaces; } /** * Specifies the namespace bindings used for the query. You can use * the {@link com.marklogic.client.util.EditableNamespaceContext EditableNamespaceContext} * class to instantiate a set of bindings between namespace prefixes and Uris. * @param namespaces the namespace bindings */ public void setNamespaces(IterableNamespaceContext namespaces) { EditableNamespaceContext newNamespaces = makeNamespaces(); if (namespaces != null) { for (String prefix: namespaces.getAllPrefixes()) { String nsUri = namespaces.getNamespaceURI(prefix); if (!newNamespaces.containsKey(prefix)) { newNamespaces.put(prefix, nsUri); } else if (!nsUri.equals(newNamespaces.getNamespaceURI(prefix))) { throw new IllegalArgumentException( "Cannot change namespace URI for prefix: "+prefix); } } } this.namespaces = newNamespaces; } private EditableNamespaceContext makeNamespaces() { EditableNamespaceContext newNamespaces = new EditableNamespaceContext(); for (Map.Entry entry: reserved.entrySet()) { newNamespaces.put(entry.getKey(), entry.getValue()); } return newNamespaces; } /** * The Allen and ISO SQL 2011 temporal operators available for use in * {@link #temporalPeriodRange temporalPeriodRange} * or {@link #temporalPeriodCompare temporalPeriodCompare} queries. * @see * Temporal Developer's Guide -> Period Comparison Operators */ public enum TemporalOperator { ALN_EQUALS, ALN_CONTAINS, ALN_CONTAINED_BY, ALN_MEETS, ALN_MET_BY, ALN_BEFORE, ALN_AFTER, ALN_STARTS, ALN_STARTED_BY, ALN_FINISHES, ALN_FINISHED_BY, ALN_OVERLAPS, ALN_OVERLAPPED_BY, ISO_CONTAINS, ISO_OVERLAPS, ISO_SUCCEEDS, ISO_PRECEDES, ISO_IMM_SUCCEEDS, ISO_IMM_PRECEDES, ISO_EQUALS; }; /** * An axis for use in {@link #temporalPeriodRange temporalPeriodRange} * or {@link #temporalPeriodCompare temporalPeriodCompare} queries. */ public interface Axis {}; /** * A temporal period for use in {@link #temporalPeriodRange temporalPeriodRange} * queries. */ public interface Period {}; /** * Identify an axis for use in {@link #temporalPeriodRange temporalPeriodRange} * or {@link #temporalPeriodCompare temporalPeriodCompare} queries. * @param name the name of the axis as configured in the server */ public StructuredQueryBuilder.Axis axis(String name) { return new TemporalAxis(name); } /** * Construct a temporal period for use in {@link #temporalPeriodRange temporalPeriodRange} * queries. * @param start the start date/time for this period * @param end the end date/time for this period */ public StructuredQueryBuilder.Period period(Calendar start, Calendar end) { return new TemporalPeriod(DatatypeConverter.printDateTime(start), DatatypeConverter.printDateTime(end)); } /** * Construct a temporal period for use in {@link #temporalPeriodRange temporalPeriodRange} * queries. * @param start the start date/time for this period, in ISO 8601 format * @param end the end date/time for this period, in ISO 8601 format */ public StructuredQueryBuilder.Period period(String start, String end) { return new TemporalPeriod(start, end); } /** * Matches documents that have a value in the specified axis that matches the specified * period using the specified operator. * @param axis the axis of document temporal values used to determine which documents have * values that match this query * @param operator the operator used to determine if values in the axis match the specified period * @param period the period considered using the operator * @param options string options from the list for * cts:period-range-query calls * @see cts:period-range-query * @see * Structured Queries: period-range-query */ public StructuredQueryDefinition temporalPeriodRange(Axis axis, TemporalOperator operator, Period period, String... options) { if ( axis == null ) throw new IllegalArgumentException("axis cannot be null"); if ( period == null ) throw new IllegalArgumentException("period cannot be null"); return temporalPeriodRange(new Axis[] {axis}, operator, new Period[] {period}, options); } /** * @param axes the set of axes of document temporal values used to determine which documents have * values that match this query * @param operator the operator used to determine if values in the axis match the specified period * @param periods the periods considered using the operator. When multiple periods are specified, * the query matches if a value matches any period. * @param options string options from the list for * cts:period-range-query calls * @see cts:period-range-query * @see * Structured Queries: period-range-query */ public StructuredQueryDefinition temporalPeriodRange(Axis[] axes, TemporalOperator operator, Period[] periods, String... options) { if ( axes == null ) throw new IllegalArgumentException("axes cannot be null"); if ( operator == null ) throw new IllegalArgumentException("operator cannot be null"); if ( periods == null ) throw new IllegalArgumentException("periods cannot be null"); return new TemporalPeriodRangeQuery(axes, operator, periods, options); } /** * Matches documents that have a relevant pair of period values. Values from axis1 must match * values from axis2 using the specified operator. * @param axis1 the first axis of document temporal values * values that match this query * @param operator the operator used to determine if values in the axis match the specified period * @param axis2 the second axis of document temporal values * @param options string options from the list for * cts:period-compare-query calls * @see cts:period-compare-query * @see * Structured Queries: period-compare-query */ public StructuredQueryDefinition temporalPeriodCompare(Axis axis1, TemporalOperator operator, Axis axis2, String... options) { if ( axis1 == null ) throw new IllegalArgumentException("axis1 cannot be null"); if ( operator == null ) throw new IllegalArgumentException("operator cannot be null"); if ( axis2 == null ) throw new IllegalArgumentException("axis2 cannot be null"); return new TemporalPeriodCompareQuery(axis1, operator, axis2, options); } /** * Matches documents with LSQT prior to timestamp * @param temporalCollection the temporal collection to query * @param time documents with lsqt equal to or prior to this timestamp will match * @param weight the weight for for this query * @param options string options from the list for * cts:lsqt-query calls * @see cts:lsqt-query * @see * Structured Queries: lsqt-query */ public StructuredQueryDefinition temporalLsqtQuery(String temporalCollection, Calendar time, double weight, String... options) { if ( temporalCollection == null ) throw new IllegalArgumentException("temporalCollection cannot be null"); return new TemporalLsqtQuery(temporalCollection, DatatypeConverter.printDateTime(time), weight, options); } /** * Matches documents with LSQT prior to timestamp * @param temporalCollection the temporal collection to query * @param timestamp timestamp in ISO 8601 format - documents with lsqt equal to or * prior to this timestamp will match * @param weight the weight for for this query * @param options string options from the list for * cts:lsqt-query calls * @see cts:lsqt-query * @see * Structured Queries: lsqt-query */ public StructuredQueryDefinition temporalLsqtQuery(String temporalCollection, String timestamp, double weight, String... options) { if ( temporalCollection == null ) throw new IllegalArgumentException("temporalCollection cannot be null"); return new TemporalLsqtQuery(temporalCollection, timestamp, weight, options); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy