This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit fa65ecf05431a6d88d0f7a017822ad99019694ce Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Thu Sep 9 15:05:29 2021 +0200 Move Query sub-types to public package. --- .../sis/internal/filter}/SortByComparator.java | 2 +- .../org/apache/sis/internal/map/SEPortrayer.java | 2 +- .../apache/sis/internal/map/SEPortrayerTest.java | 2 +- .../sis/internal/sql/feature/FeatureStream.java | 2 +- .../org/apache/sis/storage/sql/SQLStoreTest.java | 2 +- .../sis/internal/storage/JoinFeatureSet.java | 2 +- .../sis/internal/storage/query/package-info.java | 32 ----- .../storage/query => storage}/CoverageQuery.java | 28 ++-- .../storage/query => storage}/CoverageSubset.java | 6 +- .../storage/query => storage}/FeatureQuery.java | 141 ++++++++++++++------- .../java/org/apache/sis/storage/FeatureSet.java | 1 - .../storage/query => storage}/FeatureSubset.java | 21 ++- .../apache/sis/storage/GridCoverageResource.java | 1 - .../main/java/org/apache/sis/storage/Query.java | 5 +- .../query => storage}/CoverageQueryTest.java | 4 +- .../FeatureQueryTest.java} | 8 +- .../query => storage}/GridResourceMock.java | 2 +- .../apache/sis/test/suite/StorageTestSuite.java | 4 +- 18 files changed, 140 insertions(+), 125 deletions(-) diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SortByComparator.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/SortByComparator.java similarity index 99% rename from storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SortByComparator.java rename to core/sis-feature/src/main/java/org/apache/sis/internal/filter/SortByComparator.java index 37aeaee..3727386 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SortByComparator.java +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/SortByComparator.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sis.internal.storage.query; +package org.apache.sis.internal.filter; import java.util.Arrays; import java.util.List; diff --git a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/SEPortrayer.java b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/SEPortrayer.java index 19765d1..9b267af 100644 --- a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/SEPortrayer.java +++ b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/SEPortrayer.java @@ -43,7 +43,7 @@ import org.apache.sis.filter.DefaultFilterFactory; import org.apache.sis.geometry.Envelopes; import org.apache.sis.geometry.GeneralEnvelope; import org.apache.sis.internal.feature.AttributeConvention; -import org.apache.sis.internal.storage.query.FeatureQuery; +import org.apache.sis.storage.FeatureQuery; import org.apache.sis.portrayal.MapItem; import org.apache.sis.portrayal.MapLayer; import org.apache.sis.portrayal.MapLayers; diff --git a/core/sis-portrayal/src/test/java/org/apache/sis/internal/map/SEPortrayerTest.java b/core/sis-portrayal/src/test/java/org/apache/sis/internal/map/SEPortrayerTest.java index 8f8b16b..d35ca20 100644 --- a/core/sis-portrayal/src/test/java/org/apache/sis/internal/map/SEPortrayerTest.java +++ b/core/sis-portrayal/src/test/java/org/apache/sis/internal/map/SEPortrayerTest.java @@ -35,7 +35,7 @@ import org.apache.sis.filter.DefaultFilterFactory; import org.apache.sis.geometry.GeneralEnvelope; import org.apache.sis.internal.feature.AttributeConvention; import org.apache.sis.internal.storage.MemoryFeatureSet; -import org.apache.sis.internal.storage.query.FeatureQuery; +import org.apache.sis.storage.FeatureQuery; import org.apache.sis.portrayal.MapItem; import org.apache.sis.portrayal.MapLayer; import org.apache.sis.portrayal.MapLayers; diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/FeatureStream.java b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/FeatureStream.java index af89400..e6f8790 100644 --- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/FeatureStream.java +++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/FeatureStream.java @@ -31,7 +31,7 @@ import org.apache.sis.filter.Optimization; import org.apache.sis.internal.metadata.sql.SQLBuilder; import org.apache.sis.internal.stream.DeferredStream; import org.apache.sis.internal.stream.PaginedStream; -import org.apache.sis.internal.storage.query.SortByComparator; +import org.apache.sis.internal.filter.SortByComparator; import org.apache.sis.storage.DataStoreException; import org.apache.sis.util.collection.BackingStoreException; import org.apache.sis.util.ArgumentChecks; diff --git a/storage/sis-sqlstore/src/test/java/org/apache/sis/storage/sql/SQLStoreTest.java b/storage/sis-sqlstore/src/test/java/org/apache/sis/storage/sql/SQLStoreTest.java index d7a810d..2f4c2a9 100644 --- a/storage/sis-sqlstore/src/test/java/org/apache/sis/storage/sql/SQLStoreTest.java +++ b/storage/sis-sqlstore/src/test/java/org/apache/sis/storage/sql/SQLStoreTest.java @@ -26,7 +26,7 @@ import org.apache.sis.storage.FeatureSet; import org.apache.sis.storage.StorageConnector; import org.apache.sis.storage.DataStoreException; import org.apache.sis.filter.DefaultFilterFactory; -import org.apache.sis.internal.storage.query.FeatureQuery; +import org.apache.sis.storage.FeatureQuery; import org.apache.sis.test.sql.TestDatabase; import org.apache.sis.test.TestUtilities; import org.apache.sis.test.TestCase; diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/JoinFeatureSet.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/JoinFeatureSet.java index 0977396..c74e056 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/JoinFeatureSet.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/JoinFeatureSet.java @@ -29,7 +29,7 @@ import org.apache.sis.feature.FeatureOperations; import org.apache.sis.feature.DefaultFeatureType; import org.apache.sis.feature.DefaultAssociationRole; import org.apache.sis.internal.feature.AttributeConvention; -import org.apache.sis.internal.storage.query.FeatureQuery; +import org.apache.sis.storage.FeatureQuery; import org.apache.sis.storage.FeatureSet; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.event.StoreListeners; diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/package-info.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/package-info.java deleted file mode 100644 index a75a1c9..0000000 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/package-info.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -/** - * Default implementation of query operations. - * - * <STRONG>Do not use!</STRONG> - * - * This package is for internal use by SIS only. Classes in this package - * may change in incompatible ways in any future version without notice. - * - * @author Johann Sorel (Geomatys) - * @author Martin Desruisseaux (Geomatys) - * @version 1.1 - * @since 1.0 - * @module - */ -package org.apache.sis.internal.storage.query; diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/CoverageQuery.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageQuery.java similarity index 90% rename from storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/CoverageQuery.java rename to storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageQuery.java index 9e9dd1c..c668af6 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/CoverageQuery.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageQuery.java @@ -14,10 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sis.internal.storage.query; +package org.apache.sis.storage; import java.util.Arrays; import java.util.Objects; +import java.io.Serializable; import java.math.RoundingMode; import org.opengis.metadata.extent.GeographicBoundingBox; import org.apache.sis.measure.Angle; @@ -25,15 +26,16 @@ import org.apache.sis.measure.Latitude; import org.apache.sis.measure.Longitude; import org.apache.sis.measure.AngleFormat; import org.apache.sis.coverage.grid.GridGeometry; -import org.apache.sis.storage.GridCoverageResource; -import org.apache.sis.storage.Query; -import org.apache.sis.storage.UnsupportedQueryException; import org.apache.sis.util.ArgumentChecks; /** - * A simple query configuration for coverage resources for requesting a subset of the domain and the range. - * Experimental for now, may move to public API in a future version. + * Definition of filtering to apply for fetching a subset of {@link GridCoverageResource}. + * This query allows requesting a subset of the coverage domain and the range. + * + * <h2>Optional values</h2> + * All aspects of this query are optional and initialized to "none". + * Unless otherwise specified, all methods accept a null argument or can return a null value, which means "none". * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) @@ -41,7 +43,12 @@ import org.apache.sis.util.ArgumentChecks; * @since 1.1 * @module */ -public final class CoverageQuery extends Query implements Cloneable { +public class CoverageQuery extends Query implements Cloneable, Serializable { + /** + * For cross-version compatibility. + */ + private static final long serialVersionUID = -4296814883807414158L; + /** * Desired grid extent and resolution, or {@code null} for reading the whole domain. */ @@ -115,7 +122,7 @@ public final class CoverageQuery extends Query implements Cloneable { } /** - * Set a number of additional cells to read on each border of the source grid coverage. + * Sets a number of additional cells to read on each border of the source grid coverage. * If non-zero, this property expands the {@linkplain #getDomain() domain} to be read * by the specified margin. * @@ -158,7 +165,7 @@ public final class CoverageQuery extends Query implements Cloneable { * @return a view over the given coverage resource containing only the given domain and range. * @throws UnsupportedQueryException if this query contains filtering options not yet supported. */ - public GridCoverageResource execute(final GridCoverageResource source) throws UnsupportedQueryException { + final GridCoverageResource execute(final GridCoverageResource source) throws UnsupportedQueryException { ArgumentChecks.ensureNonNull("source", source); return new CoverageSubset(source, clone()); } @@ -214,7 +221,8 @@ public final class CoverageQuery extends Query implements Cloneable { } /** - * Returns a textual representation looking like an SQL Select query. + * Returns a textual representation of this query for debugging purposes. + * The default implementation returns a string that looks like an SQL Select query. * * @return textual representation of this query. */ diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/CoverageSubset.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageSubset.java similarity index 97% rename from storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/CoverageSubset.java rename to storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageSubset.java index eb0a1a4..4ff419f 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/CoverageSubset.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageSubset.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sis.internal.storage.query; +package org.apache.sis.storage; import java.util.Arrays; import java.util.List; @@ -25,11 +25,7 @@ import org.apache.sis.coverage.grid.GridDerivation; import org.apache.sis.coverage.grid.GridRoundingMode; import org.apache.sis.coverage.grid.GridClippingMode; import org.apache.sis.coverage.grid.DisjointExtentException; -import org.apache.sis.storage.GridCoverageResource; import org.apache.sis.storage.event.StoreListeners; -import org.apache.sis.storage.DataStoreException; -import org.apache.sis.storage.DataStoreReferencingException; -import org.apache.sis.storage.NoSuchDataException; import org.apache.sis.internal.storage.Resources; import org.apache.sis.internal.storage.AbstractGridResource; import org.apache.sis.internal.util.UnmodifiableArrayList; diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureQuery.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureQuery.java similarity index 80% rename from storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureQuery.java rename to storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureQuery.java index 67baf3b..d34fa2e 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureQuery.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureQuery.java @@ -14,23 +14,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sis.internal.storage.query; +package org.apache.sis.storage; import java.util.Arrays; import java.util.Map; -import java.util.List; import java.util.LinkedHashMap; import java.util.Objects; +import java.util.OptionalLong; +import java.io.Serializable; import javax.measure.Quantity; import javax.measure.quantity.Length; import org.opengis.util.GenericName; import org.apache.sis.feature.builder.FeatureTypeBuilder; import org.apache.sis.feature.builder.PropertyTypeBuilder; import org.apache.sis.internal.feature.FeatureExpression; -import org.apache.sis.internal.util.UnmodifiableArrayList; +import org.apache.sis.internal.filter.SortByComparator; import org.apache.sis.internal.storage.Resources; -import org.apache.sis.storage.FeatureSet; -import org.apache.sis.storage.Query; import org.apache.sis.util.ArgumentChecks; import org.apache.sis.util.Classes; import org.apache.sis.util.collection.Containers; @@ -49,21 +48,40 @@ import org.opengis.filter.InvalidFilterValueException; /** - * Mimics {@code SQL SELECT} statements using OGC Filter and Expressions. + * Definition of filtering to apply for fetching a subset of {@link FeatureSet}. + * This query mimics {@code SQL SELECT} statements using OGC Filter and Expressions. * Information stored in this query can be used directly with {@link java.util.stream.Stream} API. * + * <h2>Terminology</h2> + * This class uses relational database terminology: + * <ul> + * <li>A <cite>selection</cite> is a filter choosing the features instances to include in the subset. + * In relational databases, a feature instances are mapped to table rows.</li> + * <li>A <cite>projection</cite> (not to be confused with map projection) is the set of feature property to keep. + * In relational databases, feature properties are mapped to table columns.</li> + * </ul> + * + * <h2>Optional values</h2> + * All aspects of this query are optional and initialized to "none". + * Unless otherwise specified, all methods accept a null argument or can return a null value, which means "none". + * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) * @version 1.1 - * @since 1.0 + * @since 1.1 * @module */ -public class FeatureQuery extends Query implements Cloneable { +public class FeatureQuery extends Query implements Cloneable, Serializable { + /** + * For cross-version compatibility. + */ + private static final long serialVersionUID = -5841189659773611160L; + /** * Sentinel limit value for queries of unlimited length. - * This value can be given to {@link #setLimit(long)} or retrieved from {@link #getLimit()}. + * This value applies to the {@link #limit} field. */ - public static final long UNLIMITED = -1; + private static final long UNLIMITED = -1; /** * The properties to retrieve, or {@code null} if all properties shall be included in the query. @@ -87,6 +105,7 @@ public class FeatureQuery extends Query implements Cloneable { /** * The number of feature instances to skip from the beginning. + * This is zero if there is no instance to skip. * * @see #getOffset() * @see #setOffset(long) @@ -96,6 +115,7 @@ public class FeatureQuery extends Query implements Cloneable { /** * The maximum number of feature instances contained in the {@code FeatureSet}. + * This is {@link #UNLIMITED} if there is no limit. * * @see #getLimit() * @see #setLimit(long) @@ -113,7 +133,7 @@ public class FeatureQuery extends Query implements Cloneable { /** * Hint used by resources to optimize returned features. - * Different stores makes use of vector tiles of different scales. + * Different stores make use of vector tiles of different scales. * A {@code null} value means to query data at their full resolution. * * @see #getLinearResolution() @@ -122,33 +142,54 @@ public class FeatureQuery extends Query implements Cloneable { private Quantity<Length> linearResolution; /** - * Creates a new query retrieving no property and applying no filter. + * Creates a new query applying no filter. */ public FeatureQuery() { - selection = Filter.include(); limit = UNLIMITED; } /** * Sets the properties to retrieve, or {@code null} if all properties shall be included in the query. + * This convenience method wraps the given expression in {@link NamedExpression}s without alias and + * delegates to {@link #setProjection(NamedExpression...)}. + * + * @param properties properties to retrieve, or {@code null} to retrieve all properties. + * @throws IllegalArgumentException if a property is duplicated. + */ + @SafeVarargs + public final void setProjection(final Expression<? super Feature, ?>... properties) { + NamedExpression[] wrappers = null; + if (properties != null) { + wrappers = new NamedExpression[properties.length]; + for (int i=0; i<wrappers.length; i++) { + final Expression<? super Feature, ?> e = properties[i]; + ArgumentChecks.ensureNonNullElement("properties", i, e); + wrappers[i] = new NamedExpression(e); + } + } + setProjection(wrappers); + } + + /** + * Sets the properties to retrieve, or {@code null} if all properties shall be included in the query. * A query column may use a simple or complex expression and an alias to create a new type of property * in the returned features. * * <p>This is equivalent to the column names in the {@code SELECT} clause of a SQL statement. * Subset of columns is called <cite>projection</cite> in relational database terminology.</p> * - * @param projection properties to retrieve, or {@code null} to retrieve all properties. + * @param properties properties to retrieve, or {@code null} to retrieve all properties. * @throws IllegalArgumentException if a property or an alias is duplicated. */ @SuppressWarnings("AssignmentToCollectionOrArrayFieldFromParameter") - public void setProjection(NamedExpression... projection) { - if (projection != null) { - ArgumentChecks.ensureNonEmpty("projection", projection); - projection = projection.clone(); - final Map<Object,Integer> uniques = new LinkedHashMap<>(Containers.hashMapCapacity(projection.length)); - for (int i=0; i<projection.length; i++) { - final NamedExpression c = projection[i]; - ArgumentChecks.ensureNonNullElement("projection", i, c); + public void setProjection(NamedExpression... properties) { + if (properties != null) { + ArgumentChecks.ensureNonEmpty("properties", properties); + properties = properties.clone(); + final Map<Object,Integer> uniques = new LinkedHashMap<>(Containers.hashMapCapacity(properties.length)); + for (int i=0; i<properties.length; i++) { + final NamedExpression c = properties[i]; + ArgumentChecks.ensureNonNullElement("properties", i, c); final Object key = c.alias != null ? c.alias : c.expression; final Integer p = uniques.putIfAbsent(key, i); if (p != null) { @@ -156,17 +197,18 @@ public class FeatureQuery extends Query implements Cloneable { } } } - this.projection = projection; + this.projection = properties; } /** * Returns the properties to retrieve, or {@code null} if all properties shall be included in the query. - * This is the list of expressions specified in the last call to {@link #setProjection(NamedExpression[])}. + * This is the expressions specified in the last call to {@link #setProjection(NamedExpression[])}. + * The default value is null. * * @return properties to retrieve, or {@code null} to retrieve all feature properties. */ - public List<NamedExpression> getProjection() { - return UnmodifiableArrayList.wrap(projection); + public NamedExpression[] getProjection() { + return (projection != null) ? projection.clone() : null; } /** @@ -174,18 +216,18 @@ public class FeatureQuery extends Query implements Cloneable { * Features that do not pass the filter are discarded. * Discarded features are not counted for the {@linkplain #setLimit(long) query limit}. * - * @param selection the filter, or {@link Filter#include()} if none. + * @param selection the filter, or {@code null} if none. */ public void setSelection(final Filter<? super Feature> selection) { - ArgumentChecks.ensureNonNull("selection", selection); this.selection = selection; } /** * Returns the filter for trimming feature instances. * This is the value specified in the last call to {@link #setSelection(Filter)}. + * The default value is {@code null}, which means that no filtering is applied. * - * @return the filter, or {@link Filter#include()} if none. + * @return the filter, or {@code null} if none. */ public Filter<? super Feature> getSelection() { return selection; @@ -209,6 +251,7 @@ public class FeatureQuery extends Query implements Cloneable { /** * Returns the number of feature instances to skip from the beginning. * This is the value specified in the last call to {@link #setOffset(long)}. + * The default value is zero, which means that no features are skipped. * * @return the number of feature instances to skip from the beginning. */ @@ -217,18 +260,23 @@ public class FeatureQuery extends Query implements Cloneable { } /** + * Removes any limit defined by {@link #setLimit(long)}. + */ + public void setUnlimited() { + limit = UNLIMITED; + } + + /** * Set the maximum number of feature instances contained in the {@code FeatureSet}. * Offset and limit are often combined to obtain paging. * * <p>Note that setting this property can be costly on parallelized streams. * See {@link java.util.stream.Stream#limit(long)} for more information.</p> * - * @param limit maximum number of feature instances contained in the {@code FeatureSet}, or {@link #UNLIMITED}. + * @param limit maximum number of feature instances contained in the {@code FeatureSet}. */ public void setLimit(final long limit) { - if (limit != UNLIMITED) { - ArgumentChecks.ensurePositive("limit", limit); - } + ArgumentChecks.ensurePositive("limit", limit); this.limit = limit; } @@ -236,16 +284,15 @@ public class FeatureQuery extends Query implements Cloneable { * Returns the maximum number of feature instances contained in the {@code FeatureSet}. * This is the value specified in the last call to {@link #setLimit(long)}. * - * @return maximum number of feature instances contained in the {@code FeatureSet}, or {@link #UNLIMITED}. + * @return maximum number of feature instances contained in the {@code FeatureSet}, or empty if none. */ - public long getLimit() { - return limit; + public OptionalLong getLimit() { + return (limit >= 0) ? OptionalLong.of(limit) : OptionalLong.empty(); } /** * Sets the expressions to use for sorting the feature instances. - * {@code SortBy} objects are used to order the {@link org.opengis.feature.Feature} instances - * returned by the {@link org.apache.sis.storage.FeatureSet}. + * {@code SortBy} objects are used to order the {@link Feature} instances returned by the {@link FeatureSet}. * {@code SortBy} clauses are applied in declaration order, like SQL. * * @param properties expressions to use for sorting the feature instances, @@ -262,8 +309,7 @@ public class FeatureQuery extends Query implements Cloneable { /** * Sets the expressions to use for sorting the feature instances. - * {@code SortBy} objects are used to order the {@link org.opengis.feature.Feature} instances - * returned by the {@link org.apache.sis.storage.FeatureSet}. + * {@code SortBy} objects are used to order the {@link Feature} instances returned by the {@link FeatureSet}. * * @param sortBy expressions to use for sorting the feature instances, or {@code null} if none. */ @@ -273,7 +319,7 @@ public class FeatureQuery extends Query implements Cloneable { /** * Returns the expressions to use for sorting the feature instances. - * They are the values specified in the last call to {@link #setSortBy(SortBy)}. + * This is the value specified in the last call to {@link #setSortBy(SortBy)}. * * @return expressions to use for sorting the feature instances, or {@code null} if none. */ @@ -306,9 +352,15 @@ public class FeatureQuery extends Query implements Cloneable { * In relational database terminology, subset of columns is called <cite>projection</cite>. * Columns can be given to the {@link FeatureQuery#setProjection(NamedExpression[])} method. */ - public static class NamedExpression { + public static class NamedExpression implements Serializable { + /** + * For cross-version compatibility. + */ + private static final long serialVersionUID = -6919525113513842514L; + /** * The literal, value reference or more complex expression to be retrieved by a {@code Query}. + * Never {@code null}. */ public final Expression<? super Feature, ?> expression; @@ -447,7 +499,7 @@ public class FeatureQuery extends Query implements Cloneable { * @param source the set of features to filter, sort or process. * @return a view over the given feature set containing only the filtered feature instances. */ - public FeatureSet execute(final FeatureSet source) { + final FeatureSet execute(final FeatureSet source) { ArgumentChecks.ensureNonNull("source", source); return new FeatureSubset(source, clone()); } @@ -527,7 +579,8 @@ public class FeatureQuery extends Query implements Cloneable { } /** - * Returns a textual representation looking like an SQL Select query. + * Returns a textual representation of this query for debugging purposes. + * The default implementation returns a string that looks like an SQL Select query. * * @return textual representation of this query. */ diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSet.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSet.java index d7534b7..fc97a9c 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSet.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSet.java @@ -18,7 +18,6 @@ package org.apache.sis.storage; import java.util.stream.Stream; import org.apache.sis.util.ArgumentChecks; -import org.apache.sis.internal.storage.query.FeatureQuery; // Branch-dependent imports import org.opengis.feature.Feature; diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureSubset.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSubset.java similarity index 89% rename from storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureSubset.java rename to storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSubset.java index 2452752..47c98e0 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureSubset.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSubset.java @@ -14,16 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sis.internal.storage.query; +package org.apache.sis.storage; -import java.util.List; +import java.util.OptionalLong; import java.util.stream.Stream; import org.apache.sis.internal.feature.FeatureUtilities; import org.apache.sis.internal.storage.AbstractFeatureSet; import org.apache.sis.internal.storage.Resources; -import org.apache.sis.storage.DataStoreContentException; -import org.apache.sis.storage.DataStoreException; -import org.apache.sis.storage.FeatureSet; import org.apache.sis.storage.event.StoreListeners; // Branch-dependent imports @@ -99,7 +96,7 @@ final class FeatureSubset extends AbstractFeatureSet { * Apply filter. */ final Filter<? super Feature> selection = query.getSelection(); - if (!Filter.include().equals(selection)) { + if (selection != null && !selection.equals(Filter.include())) { stream = stream.filter(selection); } /* @@ -119,20 +116,20 @@ final class FeatureSubset extends AbstractFeatureSet { /* * Apply limit. */ - final long limit = query.getLimit(); - if (limit >= 0) { - stream = stream.limit(limit); + final OptionalLong limit = query.getLimit(); + if (limit.isPresent()) { + stream = stream.limit(limit.getAsLong()); } /* * Transform feature instances. * Note: "projection" here is in relational database sense, not map projection. */ - final List<FeatureQuery.NamedExpression> projection = query.getProjection(); + final FeatureQuery.NamedExpression[] projection = query.getProjection(); if (projection != null) { @SuppressWarnings({"unchecked", "rawtypes"}) - final Expression<? super Feature, ?>[] expressions = new Expression[projection.size()]; + final Expression<? super Feature, ?>[] expressions = new Expression[projection.length]; for (int i=0; i<expressions.length; i++) { - expressions[i] = projection.get(i).expression; + expressions[i] = projection[i].expression; } final FeatureType type = getType(); final String[] names = FeatureUtilities.getNames(type.getProperties(false)); diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/GridCoverageResource.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/GridCoverageResource.java index a0dfe3b..e30cf6b 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/storage/GridCoverageResource.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/GridCoverageResource.java @@ -20,7 +20,6 @@ import java.util.List; import org.apache.sis.coverage.SampleDimension; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.coverage.grid.GridCoverage; -import org.apache.sis.internal.storage.query.CoverageQuery; import org.apache.sis.util.ArgumentChecks; diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/Query.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/Query.java index 548f6bb..2aa4b8f 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/storage/Query.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/Query.java @@ -17,6 +17,7 @@ package org.apache.sis.storage; import org.opengis.feature.Feature; +import org.opengis.filter.QueryExpression; /** @@ -54,10 +55,8 @@ import org.opengis.feature.Feature; * * @since 0.8 * @module - * - * @todo Retrofit {@link org.opengis.filter.QueryExpression}. */ -public abstract class Query { +public abstract class Query implements QueryExpression { /* * Current version does not yet contain any field. But some fields may be added in the future. * For example some methods from org.apache.sis.internal.storage.query.FeatureQuery may move here. diff --git a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/CoverageQueryTest.java b/storage/sis-storage/src/test/java/org/apache/sis/storage/CoverageQueryTest.java similarity index 97% rename from storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/CoverageQueryTest.java rename to storage/sis-storage/src/test/java/org/apache/sis/storage/CoverageQueryTest.java index b515937..eef4d96 100644 --- a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/CoverageQueryTest.java +++ b/storage/sis-storage/src/test/java/org/apache/sis/storage/CoverageQueryTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sis.internal.storage.query; +package org.apache.sis.storage; import org.opengis.metadata.spatial.DimensionNameType; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -24,8 +24,6 @@ import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.internal.referencing.j2d.AffineTransform2D; import org.apache.sis.referencing.crs.HardCodedCRS; -import org.apache.sis.storage.DataStoreException; -import org.apache.sis.storage.GridCoverageResource; import org.apache.sis.test.TestCase; import org.junit.Test; diff --git a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/SimpleQueryTest.java b/storage/sis-storage/src/test/java/org/apache/sis/storage/FeatureQueryTest.java similarity index 97% rename from storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/SimpleQueryTest.java rename to storage/sis-storage/src/test/java/org/apache/sis/storage/FeatureQueryTest.java index a66c759..cbe7414 100644 --- a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/SimpleQueryTest.java +++ b/storage/sis-storage/src/test/java/org/apache/sis/storage/FeatureQueryTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sis.internal.storage.query; +package org.apache.sis.storage; import java.util.List; import java.util.Arrays; @@ -22,8 +22,6 @@ import java.util.stream.Collectors; import org.apache.sis.feature.builder.FeatureTypeBuilder; import org.apache.sis.internal.storage.MemoryFeatureSet; import org.apache.sis.filter.DefaultFilterFactory; -import org.apache.sis.storage.DataStoreException; -import org.apache.sis.storage.FeatureSet; import org.apache.sis.test.TestUtilities; import org.apache.sis.test.TestCase; import org.junit.Test; @@ -49,7 +47,7 @@ import org.opengis.filter.SortOrder; * @since 1.0 * @module */ -public final strictfp class SimpleQueryTest extends TestCase { +public final strictfp class FeatureQueryTest extends TestCase { /** * An arbitrary amount of features, all of the same type. */ @@ -68,7 +66,7 @@ public final strictfp class SimpleQueryTest extends TestCase { /** * Creates a new test. */ - public SimpleQueryTest() { + public FeatureQueryTest() { final FeatureTypeBuilder ftb = new FeatureTypeBuilder(); ftb.setName("Test"); ftb.addAttribute(Integer.class).setName("value1"); diff --git a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/GridResourceMock.java b/storage/sis-storage/src/test/java/org/apache/sis/storage/GridResourceMock.java similarity index 98% rename from storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/GridResourceMock.java rename to storage/sis-storage/src/test/java/org/apache/sis/storage/GridResourceMock.java index b984874..0971c06 100644 --- a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/GridResourceMock.java +++ b/storage/sis-storage/src/test/java/org/apache/sis/storage/GridResourceMock.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sis.internal.storage.query; +package org.apache.sis.storage; import java.util.List; import java.util.Collections; diff --git a/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java b/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java index a89fc63..1231745 100644 --- a/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java +++ b/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java @@ -46,8 +46,8 @@ import org.junit.BeforeClass; org.apache.sis.storage.ProbeResultTest.class, org.apache.sis.storage.StorageConnectorTest.class, org.apache.sis.storage.event.StoreListenersTest.class, - org.apache.sis.internal.storage.query.CoverageQueryTest.class, - org.apache.sis.internal.storage.query.SimpleQueryTest.class, + org.apache.sis.storage.CoverageQueryTest.class, + org.apache.sis.storage.FeatureQueryTest.class, org.apache.sis.internal.storage.xml.MimeTypeDetectorTest.class, org.apache.sis.internal.storage.xml.StoreProviderTest.class, org.apache.sis.internal.storage.xml.StoreTest.class,