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

org.geotools.data.Query Maven / Gradle / Ivy

Go to download

The main module contains the GeoTools public interfaces that are used by other GeoTools modules (and GeoTools applications). Where possible we make use industry standard terms as provided by OGC and ISO standards. The formal GeoTools public api consists of gt-metadata, jts and the gt-main module. The main module contains the default implementations that are available provided to other GeoTools modules using our factory system. Factories are obtained from an appropriate FactoryFinder, giving applications a chance configure the factory used using the Factory Hints facilities. FilterFactory ff = CommonFactoryFinder.getFilterFactory(); Expression expr = ff.add( expression1, expression2 ); If you find yourself using implementation specific classes chances are you doing it wrong: Expression expr = new AddImpl( expression1, expressiom2 );

The newest version!
/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 *
 *    (C) 2008-2015, Open Source Geospatial Foundation (OSGeo)
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation;
 *    version 2.1 of the License.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 */
package org.geotools.data;

import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.util.factory.Hints;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.identity.ResourceId;
import org.opengis.filter.identity.Version;
import org.opengis.filter.sort.SortBy;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

/**
 * Encapsulates a request for data, typically as:
 *
 * 

 * Query query = ...
 * myFeatureSource.getFeatures(query);
 * 
* * The query class is based on the Web Feature Server specification and offers a few interesting * capabilities such as the ability to sort results and use a filter (similar to the WHERE clause in * SQL). * *

Additional capabilities: * *

    *
  • {@linkplain #setMaxFeatures(int)} and {@linkplain #setStartIndex(Integer)} can be used * implement 'paging' through the data source's content. This is useful if, for example, the * FeatureSource has an upper limit on the number of features it can return in a single * request or you are working with limited memory. *
  • {@linkplain #setHandle(String)} can be used to give the query a mnemonic name which will * appear in error reporing and logs. *
  • {@linkplain #setCoordinateSystem(CoordinateReferenceSystem)} is used to to specify the * coordinate system that retrieved features will be "forced" into. This is often used to * correct a feature source when the application and the data format have different ideas * about the coordinate system (for example, the "axis order" issue). *
  • {@linkplain #setCoordinateSystemReproject(CoordinateReferenceSystem)} is used to ask for * the retrieved features to be reproejcted. *
* * Vendor specific: * *
    *
  • {@linkplain setHints(Hints)} is used to specify venfor specific capabilities provided by a * feature source implementation. *
* * Joins: * *

The Query class supports the concepts of joins in that a query can result in a join of the * feature type to other feature types in the same datastore. For example, the following would be a * spatial join that selected the country that contain a particular city. * *


 * Query query = new Query("countries");
 * Join join = new Join("cities", CQL.toFilter("CONTAINS(geometry, b.geometry)"));
 * join.setAlias("b");
 * join.setFilter(CQL.toFilter("CITY_NAME = 'Canmore'"))
 * query.getJoins().add(join);
 * 
* * Example: * *

 * Filter filter = CQL.toFilter("NAME like '%land'");
 * Query query = new Query( "countries", filter );
 *
 * FeatureCollection features = featureSource.getFeatures( query );
 * 
* * @author Chris Holmes * @version $Id$ */ public class Query { /** * When specifying properties to select, setting this hint flag true tells the datastore to * include mandatory properties (i.e. properties with minOccurs >= 1) in the end result, * irrespective of whether they are not included in the list of properties. * *

Datastores may implement adding all mandatory properties to the end result when this flag * is set to true. For example: * *

Object includeProps = query.getHints().get(Query.INCLUDE_MANDATORY_PROPS); if * (includeProps instanceof Boolean && ((Boolean)includeProps).booleanValue()) { * query.setProperties (DataUtilities.addMandatoryProperties(type, query.getProperties())); } */ public static Hints.Key INCLUDE_MANDATORY_PROPS = new Hints.Key(Boolean.class); /** * Constant (actually null) used to represent no namespace restrictions on the returned result, * should be considered ANY_URI */ public static final URI NO_NAMESPACE = null; /** So getMaxFeatures does not return null we use a very large number. */ public static final int DEFAULT_MAX = Integer.MAX_VALUE; /** * Implements a query that will fetch all features from a datasource. This query should retrieve * all properties, with no maxFeatures, no filtering, and the default featureType. */ public static final Query ALL = new ALLQuery(); /** * Implements a query that will fetch all the FeatureIDs from a datasource. This query should * retrieve no properties, with no maxFeatures, no filtering, and the a featureType with no * attribtues. */ public static final Query FIDS = new FIDSQuery(); /** * A constant (empty String array) that can be used with {@linkplain * #setPropertyNames(String[])} to indicate that no properties are to be retrieved. * *

Note the query will still return a result - limited to FeatureIDs. */ public static final String[] NO_NAMES = new String[0]; /** * A constant (value {@code null}) that can be used with {@linkplain * #setPropertyNames(String[])} to indicate that all properties are to be retrieved. */ public static final String[] ALL_NAMES = null; /** * A constant (empty String array) that can be used with {@linkplain * #setProperties(Collection)} to indicate that no properties are to be retrieved. * *

Note the query will still return a result - limited to FeatureIDs. */ public static final List NO_PROPERTIES = Collections.emptyList(); /** * A constant (value {@code null}) that can be used with {@linkplain * #setProperties(Collection)} to indicate that all properties are to be * retrieved. */ public static final List ALL_PROPERTIES = null; /** The properties to fetch */ protected List properties; /** The maximum numbers of features to fetch */ protected int maxFeatures = Query.DEFAULT_MAX; /** The index of the first feature to process */ protected Integer startIndex = null; /** The filter to constrain the request. */ protected Filter filter = Filter.INCLUDE; /** The typeName to get */ protected String typeName; /** The optional alias for type name */ protected String alias; /** The namespace to get */ protected URI namespace = Query.NO_NAMESPACE; /** The handle associated with this query. */ protected String handle; /** Coordinate System associated with this query */ protected CoordinateReferenceSystem coordinateSystem; /** Reprojection associated associated with this query */ protected CoordinateReferenceSystem coordinateSystemReproject; /** Sorting for the query */ protected SortBy[] sortBy; /** The version according to WFS 1.0 and 1.1 specs */ protected String version; /** The hints to be used during query execution */ protected Hints hints; /** join clauses for this query */ protected List joins = new ArrayList(); /** * Default constructor. Use setter methods to configure the Query before use (the default Query * will retrieve all features). */ public Query() { // no arg } /** * Constructor. * * @param typeName the name of the featureType to retrieve */ public Query(String typeName) { this(typeName, Filter.INCLUDE); } /** * Constructor. * * @param typeName the name of the featureType to retrieve. * @param filter the OGC filter to constrain the request. */ public Query(String typeName, Filter filter) { this(typeName, filter, Query.ALL_NAMES); } /** * Constructor. * * @param typeName the name of the featureType to retrieve. * @param filter the OGC filter to constrain the request. * @param properties an array of the properties to fetch. */ public Query(String typeName, Filter filter, String[] properties) { this(typeName, null, filter, Query.DEFAULT_MAX, properties, null); } /** * Constructor. * * @param typeName the name of the featureType to retrieve. * @param filter the OGC filter to constrain the request. * @param properties a list of the properties to fetch. */ public Query(String typeName, Filter filter, List properties) { this(typeName, null, filter, Query.DEFAULT_MAX, properties, null); } /** * Constructor. * * @param typeName the name of the featureType to retrieve. * @param filter the OGC filter to constrain the request. * @param maxFeatures the maximum number of features to be returned. * @param propNames an array of the properties to fetch. * @param handle the name to associate with this query. */ public Query( String typeName, Filter filter, int maxFeatures, String[] propNames, String handle) { this(typeName, null, filter, maxFeatures, propNames, handle); } /** * Constructor. * * @param typeName the name of the featureType to retrieve. * @param filter the OGC filter to constrain the request. * @param maxFeatures the maximum number of features to be returned. * @param properties a list of the properties to fetch. * @param handle the name to associate with this query. */ public Query( String typeName, Filter filter, int maxFeatures, List properties, String handle) { this(typeName, null, filter, maxFeatures, properties, handle); } /** * Constructor. * * @param typeName the name of the featureType to retrieve. * @param namespace Namespace for provided typeName, or null if unspecified * @param filter the OGC filter to constrain the request. * @param maxFeatures the maximum number of features to be returned. * @param propNames an array of the properties to fetch. * @param handle the name to associate with the query. */ public Query( String typeName, URI namespace, Filter filter, int maxFeatures, String[] propNames, String handle) { this.typeName = typeName; this.filter = filter; this.namespace = namespace; this.maxFeatures = maxFeatures; this.handle = handle; setPropertyNames(propNames); } /** * Constructor. * * @param typeName the name of the featureType to retrieve. * @param namespace Namespace for provided typeName, or null if unspecified * @param filter the OGC filter to constrain the request. * @param maxFeatures the maximum number of features to be returned. * @param properties a list of the property names to fetch. * @param handle the name to associate with the query. */ public Query( String typeName, URI namespace, Filter filter, int maxFeatures, List properties, String handle) { this.typeName = typeName; this.filter = filter; this.namespace = namespace; this.maxFeatures = maxFeatures; this.handle = handle; this.properties = properties == null ? null : new ArrayList(properties); } /** * Copy contructor. * * @param query the query to copy */ public Query(Query query) { this( query.getTypeName(), query.getNamespace(), query.getFilter(), query.getMaxFeatures(), query.getProperties(), query.getHandle()); this.sortBy = query.getSortBy(); this.coordinateSystem = query.getCoordinateSystem(); this.coordinateSystemReproject = query.getCoordinateSystemReproject(); this.version = query.getVersion(); this.hints = query.getHints(); this.startIndex = query.getStartIndex(); this.alias = query.getAlias(); this.joins = new ArrayList(); for (Join j : query.getJoins()) { this.joins.add(new Join(j)); } } /** * Get the names of the properties that this Query will retrieve as part of the returned * {@linkplain org.geotools.feature.FeatureCollection}. * * @return the attributes to be used in the returned FeatureCollection. * @see #retrieveAllProperties() * @task REVISIT: make a FidProperties object, instead of an array size 0. I think Query.FIDS * fills this role to some degree. Query.FIDS.equals( filter ) would meet this need? */ public String[] getPropertyNames() { if (properties == null) { return null; } String[] propertyNames = new String[properties.size()]; for (int i = 0; i < properties.size(); i++) { PropertyName propertyName = properties.get(i); if (propertyName != null) { String xpath = propertyName.getPropertyName(); propertyNames[i] = xpath; } } return propertyNames; } /** * Set the names of the properties that this Query should retrieve as part of the returned * {@linkplain org.geotools.feature.FeatureCollection}. As well as an array of names, the * following constants can be used: * *

    *
  • {@linkplain #ALL_NAMES} to retrieve all properties. *
  • {@linkplain #NO_NAMES} to indicate no properties are required, just feature IDs. *
* * The available properties can be determined with {@linkplain FeatureSource#getSchema()}. If * properties that are not part of the source's schema are requested an exception will be * thrown. * * @param propNames the names of the properties to retrieve or one of {@linkplain #ALL_NAMES} or * {@linkplain #NO_NAMES}. */ public void setPropertyNames(String[] propNames) { if (propNames == null) { properties = ALL_PROPERTIES; return; } final FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); properties = new ArrayList(propNames.length); for (int i = 0; i < propNames.length; i++) { String xpath = propNames[i]; if (xpath != null) { properties.add(ff.property(xpath)); } } } /** * Get the names of the properties that this Query will retrieve values for as part of the * returned {@linkplain org.geotools.feature.FeatureCollection}. * * @return the xpath expressions to be used in the returned FeatureCollection. * @see #retrieveAllProperties() */ public List getProperties() { if (properties == ALL_PROPERTIES) { return ALL_PROPERTIES; } return Collections.unmodifiableList(properties); } /** * Set the names of the properties that this Query should retrieve as part of the returned * {@linkplain org.geotools.feature.FeatureCollection}. As well as an array of names, the * following constants can be used: * *
    *
  • {@linkplain #ALL_PROPERTIES} to retrieve all properties. *
  • {@linkplain #NO_PROPERTIES} to indicate no properties are required, just feature IDs. *
* * The available properties can be determined with {@linkplain FeatureSource#getSchema()}. If * properties that are not part of the source's schema are requested an exception will be * thrown. * * @param propNames the names of the properties to retrieve or one of {@linkplain * #ALL_PROPERTIES} or {@linkplain #NO_PROPERTIES}. */ public void setProperties(List propNames) { this.properties = propNames == ALL_PROPERTIES ? ALL_PROPERTIES : new ArrayList(propNames); } /** * Set the names of the properties that this Query should retrieve as part of the returned * {@linkplain org.geotools.feature.FeatureCollection}. * *

The available properties can be determined with {@linkplain FeatureSource#getSchema()}. If * properties that are not part of the source's schema are requested an exception will be * thrown. * * @param propNames the names of the properties to retrieve or {@linkplain #ALL_NAMES}; an empty * List can be passed in to indicate that only feature IDs should be retrieved * @task REVISIT: This syntax is really obscure. Consider having an fid or featureID * propertyName that datasource implementors look for instead of looking to see if the list * size is 0. */ public void setPropertyNames(List propNames) { if (propNames == null) { this.properties = ALL_PROPERTIES; return; } final FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); properties = new ArrayList(propNames.size()); for (int i = 0; i < propNames.size(); i++) { String xpath = propNames.get(i); if (xpath != null) { properties.add(ff.property(xpath)); } } } /** * Convenience method to determine if the query should retrieve all properties defined in the * schema of the feature data source. This is equivalent to testing if {@linkplain * #getPropertyNames()} returns {@linkplain #ALL_NAMES}. * * @return true if all properties will be retrieved by this Query; false otherwise */ public boolean retrieveAllProperties() { return properties == null; } /** * Get the maximum number of features that will be retrieved by this Query. * *

Note: This is the only method that is not directly out of the Query element in the WFS * specification. It is instead a part of a GetFeature request, which can hold one or more * queries. But each of those in turn will need a maxFeatures, so it is needed here. * *

If the value returned here is max integer then the number of features should not be * limited. * * @return the maximum number of features that will be retrieved by this query */ public int getMaxFeatures() { return this.maxFeatures; } /** * Check if this query allows an unlimited number of features to be returned. * *

* * @return true maxFeatures is less then zero, or equal to Integer.MAX_VALUE. */ public boolean isMaxFeaturesUnlimited() { return maxFeatures < 0 || maxFeatures == Integer.MAX_VALUE; } /** * Sets the maximum number of features that should be retrieved by this query. The default is to * retrieve all features. * * @param maxFeatures the maximum number of features to retrieve */ public void setMaxFeatures(int maxFeatures) { this.maxFeatures = maxFeatures; } /** * Get the index of the first feature to retrieve. * * @return the index of the first feature to retrieve or {@code null} if no start index is * defined. */ public Integer getStartIndex() { return this.startIndex; } /** * Set the index of the first feature to retrieve. This can be used in conjuction with * {@linkplain #setMaxFeatures(int) } to 'page' through a feature data source. * * @param startIndex index of the first feature to retrieve or {@code null} to indicate no start * index * @throws IllegalArgumentException if startIndex is less than 0 */ public void setStartIndex(Integer startIndex) { if (startIndex != null && startIndex.intValue() < 0) { throw new IllegalArgumentException( "startIndex shall be a positive integer: " + startIndex); } this.startIndex = startIndex; } /** * Gets the filter used to define constraints on the features that will be retrieved by this * Query. * * @return The filter that defines constraints on the query. */ public Filter getFilter() { return this.filter; } /** * Sets the filter to constrain the features that will be retrieved by this Query. If no filter * is set all features will be retrieved (taking into account any bounds set via {@linkplain * #setMaxFeatures(int) } and {@linkplain #setStartIndex(java.lang.Integer) }). * *

The default is {@linkplain Filter#INCLUDE}. * * @param filter the OGC filter which features must pass through to be retrieved by this Query. */ public void setFilter(Filter filter) { this.filter = filter; } /** * Get the name of the feature type to be queried. * * @return the name of the feature type to be returned with this query. */ public String getTypeName() { return this.typeName; } /** * Sets the name of the feature type to be queried. If no typename is specified, then the data * source's default type will be used. When working with sources such as shapefiles that only * support one feature type this method can be ignored. * * @param typeName the name of the featureType to retrieve. */ public void setTypeName(String typeName) { this.typeName = typeName; } /** * An alias substitutable for {@link #getTypeName()}. * *

This value is typically used in a join query in which the join filter requires * disambiguation due to property name overlaps between joined types. * * @since 8.0 */ public String getAlias() { return alias; } /** * Sets the type name alias. * * @since 8.0 * @see #getAlias() */ public void setAlias(String alias) { this.alias = alias; } /** * Get the namespace of the feature type to be queried. * * @return the gml namespace of the feature type to be returned with this query */ public URI getNamespace() { return namespace; } /** Set the namespace of the feature type to be queried. */ public void setNamespace(URI namespace) { this.namespace = namespace; } /** * Get the handle (mnemonic name) that will be associated with this Query. The handle is used in * logging and error reporting. * * @return the name to refer to this query. */ public String getHandle() { return this.handle; } /** * Set the handle (mnemonic name) that will be associated with this Query. The handle is used in * logging and error reporting. * * @param handle the name to refer to this query. */ public void setHandle(String handle) { this.handle = handle; } /** * Defines version or version range requested. *

* * From WFS Spec: The version attribute is included in order to * accommodate systems that support feature versioning. A value of {@linkplain #ALL} * indicates that all versions of a feature should be fetched. Otherwise * an integer, n, can be specified to return the n th version of a * feature. The version numbers start at '1' which is the oldest version. * If a version value larger than the largest version is specified then * the latest version is return. The default action shall be for the query * to return the latest version. Systems that do not support versioning * can ignore the parameter and return the only version that they have. *

* GeoTools employs the following options: *

    *
  • {@link #setVersion(Date)}: "date: dow mon dd hh:mm:ss zzz yyyy"
  • *
  • {@link #setVersion(int)}: "index"
  • *
  • {@link #setVersion(org.opengis.filter.identity.Version.Action)): "PREVIOUS", "LAST", "NEXT", "FIRST", "ALL"
  • *
  • {@link #setVersion(Date, Date): "start: dow mon dd hh:mm:ss zzz yyyy end: dow mon dd hh:mm:ss zzz yyyy" *
* @return the version of the feature to return, or null for LAST. */ public String getVersion() { return version; } public void setVersion(int index) { this.version = String.valueOf(index); } public void setVersion(Date date) { this.version = date == null ? null : "date:" + date; } public void setVersion(Version.Action action) { this.version = action == null ? null : action.name(); } public void setVersion(Date startTime, Date endTime) { if (startTime == null || endTime == null) { this.version = null; } else { this.version = "start:" + startTime + " end:" + endTime; } } public void setVersion(ResourceId history) { if (history.getStartTime() != null && history.getEndTime() != null) { setVersion(history.getStartTime(), history.getEndTime()); } else if (history.getVersion() != null) { Version ver = history.getVersion(); if (ver.isVersionAction()) { setVersion(ver.getVersionAction()); } else if (ver.isDateTime()) { setVersion(ver.getDateTime()); } else if (ver.isIndex()) { setVersion(ver.getIndex()); } } } /** * Set the version of features to retrieve where this is supported by the data source being * queried. * * @see #getVersion() getVersion() for explanation * @since 2.4 */ public void setVersion(String version) { this.version = version; } /** * Get the coordinate system to use as an override for features retrieved by this Query. * * @return The coordinate system to be returned for Features from this Query (override the set * coordinate system). */ public CoordinateReferenceSystem getCoordinateSystem() { return coordinateSystem; } /** * Provide an override coordinate system to apply to features retrieved by this Query. * *

This denotes a request to temporarily override the coordinate system contained in * the feature data source being queried. The same coordinate values will be used, but the * features retrieved will appear in this Coordinate System. * *

This change is not persistent and only applies to the features returned by this Query. If * used in conjunction with {@link #getCoordinateSystemReproject()} the reprojection will occur * from {@link #getCoordinateSystem()} to {@link #getCoordinateSystemReproject()}. * * @param system the coordinate system to apply to features retrieved by this Query */ public void setCoordinateSystem(CoordinateReferenceSystem system) { coordinateSystem = system; } /** * If reprojection has been requested, this returns the coordinate system that features * retrieved by this Query will be reprojected into. * * @return the coordinate system that features will be reprojected into (if set) * @see #setCoordinateSystemReproject( CoordinateReferenceSystem ) */ public CoordinateReferenceSystem getCoordinateSystemReproject() { return coordinateSystemReproject; } /** * Request that features retrieved by this Query be reprojected into the given coordinate * system. * *

If used in conjunction with {@link #setCoordinateSystem(CoordinateReferenceSystem)} the * reprojection will occur from the overridden coordinate system to the system specified here. */ public void setCoordinateSystemReproject(CoordinateReferenceSystem system) { coordinateSystemReproject = system; } /** * SortBy results according to indicated property and order. * *

SortBy is part of the Filter 1.1 specification, it is referenced by WFS1.1 and Catalog * 2.0.x specifications and is used to organize results. The SortBy's are ment to be applied in * order: * *

    *
  • SortBy( year, ascending ) *
  • SortBy( month, decsending ) *
* * Would produce something like: * *

     * [year=2002 month=4],[year=2002 month=3],[year=2002 month=2],
     * [year=2002 month=1],[year=2003 month=12],[year=2002 month=4],
     * 
* *

SortBy should be considered at the same level of abstraction as Filter, and like Filter * you may sort using properties not listed in getPropertyNames. * *

At a technical level the interface SortBy2 is used to indicate the additional requirements * of a GeoTools implementation. The pure WFS 1.1 specification itself is limited to SortBy. * * @return SortBy array or order of application */ public SortBy[] getSortBy() { return sortBy; } /** Sets the sort by information. */ public void setSortBy(SortBy[] sortBy) { this.sortBy = sortBy; } /** * Get hints that have been set to control the query execution. * * @return hints that are set (may be empty) * @see #setHints(Hints) setHints(Hints) for more explanation */ public Hints getHints() { if (hints == null) { hints = new Hints(); } return hints; } /** * Set hints to control the query execution. * *

Hints can control such things as: * *

    *
  • the GeometryFactory to be used *
  • a generalization distance to be applied *
  • the fetch size to be used in JDBC queries *
* * The set of hints supported can be found by calling {@linkplain * org.geotools.data.FeatureSource#getSupportedHints() }. * *

Note: Data sources may ignore hints (depending on their values) and no mechanism currently * exists to discover which hints where actually used during the query's execution. * * @see Hints#FEATURE_DETACHED * @see Hints#JTS_GEOMETRY_FACTORY * @see Hints#JTS_COORDINATE_SEQUENCE_FACTORY * @see Hints#JTS_PRECISION_MODEL * @see Hints#JTS_SRID * @see Hints#GEOMETRY_DISTANCE * @see Hints#FEATURE_2D * @param hints the hints to apply */ public void setHints(Hints hints) { this.hints = hints; } /** * Hashcode based on all parameters other than the handle. * * @return hascode for this Query */ @Override public int hashCode() { String[] n = getPropertyNames(); return ((n == null) ? (-1) : ((n.length == 0) ? 0 : (n.length | n[0].hashCode()))) | getMaxFeatures() | ((getFilter() == null) ? 0 : getFilter().hashCode()) | ((getTypeName() == null) ? 0 : getTypeName().hashCode()) | ((getVersion() == null) ? 0 : getVersion().hashCode()) | ((getCoordinateSystem() == null) ? 0 : getCoordinateSystem().hashCode()) | ((getCoordinateSystemReproject() == null) ? 0 : getCoordinateSystemReproject().hashCode()) | getStartIndex(); } /** * Equality based on all query parameters other than the handle. * * @param obj Other object to compare against * @return true if this Query matches the other object; false otherwise */ @Override public boolean equals(Object obj) { if ((obj == null) || !(obj instanceof Query)) { return false; } if (this == obj) return true; Query other = (Query) obj; return Arrays.equals(getPropertyNames(), other.getPropertyNames()) && (retrieveAllProperties() == other.retrieveAllProperties()) && (getMaxFeatures() == other.getMaxFeatures()) && ((getFilter() == null) ? (other.getFilter() == null) : getFilter().equals(other.getFilter())) && ((getTypeName() == null) ? (other.getTypeName() == null) : getTypeName().equals(other.getTypeName())) && ((getVersion() == null) ? (other.getVersion() == null) : getVersion().equals(other.getVersion())) && ((getCoordinateSystem() == null) ? (other.getCoordinateSystem() == null) : getCoordinateSystem().equals(other.getCoordinateSystem())) && ((getCoordinateSystemReproject() == null) ? (other.getCoordinateSystemReproject() == null) : getCoordinateSystemReproject() .equals(other.getCoordinateSystemReproject())) && isSortEquals(other) && Objects.equals(getStartIndex(), other.getStartIndex()) && (getHints() == null ? (other.getHints() == null) : getHints().equals(other.getHints())); } /** Compares the sortby by their effect (null and empty arrays are considered the same) */ private boolean isSortEquals(Query other) { if (this.sortBy == null || this.sortBy.length == 0) { return other.getSortBy() == null || other.getSortBy().length == 0; } return Arrays.equals(getSortBy(), other.getSortBy()); } /** * Return a string representation of this Query. * * @return a string representation of this Query */ @Override public String toString() { StringBuffer returnString = new StringBuffer("Query:"); if (handle != null) { returnString.append(" [" + handle + "]"); } returnString.append("\n feature type: " + typeName); if (filter != null) { returnString.append("\n filter: " + filter.toString()); } returnString.append("\n [properties: "); if ((properties == null) || (properties.size() == 0)) { returnString.append(" ALL ]"); } else { for (int i = 0; i < properties.size(); i++) { returnString.append(properties.get(i)); if (i < (properties.size() - 1)) { returnString.append(", "); } } returnString.append("]"); } if (sortBy != null && sortBy.length > 0) { returnString.append("\n [sort by: "); for (int i = 0; i < sortBy.length; i++) { SortBy sb = sortBy[i]; if (sb == SortBy.NATURAL_ORDER) { returnString.append("NATURAL"); } else if (sb == SortBy.REVERSE_ORDER) { returnString.append("REVERSE"); } else { returnString.append(sb.getPropertyName().getPropertyName()); returnString.append(" "); returnString.append(sb.getSortOrder().name()); } if (i < (sortBy.length - 1)) { returnString.append(", "); } } returnString.append("]"); } return returnString.toString(); } /** * The list of joins for this query. * *

Each {@link Join} object specifies a feature type to join to. The join may only reference * a feature type from within the same datastore. * * @see Join */ public List getJoins() { return joins; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy