Author: desruisseaux
Date: Mon May 7 17:32:22 2018
New Revision: 1831113
URL: http://svn.apache.org/viewvc?rev=1831113&view=rev
Log:
Review of org.apache.sis.internal.storage.query package.
Added:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureSetView.java
- copied, changed from r1831112,
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQueryFeatureSet.java
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/package-info.java
(with props)
Removed:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQueryFeatureSet.java
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureUtilities.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/package-info.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/Containers.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/package-info.java
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQuery.java
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SortByComparator.java
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/Query.java
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/SimpleQueryTest.java
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureUtilities.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureUtilities.java?rev=1831113&r1=1831112&r2=1831113&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureUtilities.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureUtilities.java
[UTF-8] Mon May 7 17:32:22 2018
@@ -18,6 +18,10 @@ package org.apache.sis.internal.feature;
import java.util.Map;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import org.opengis.util.GenericName;
import org.opengis.metadata.Identifier;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
@@ -36,7 +40,7 @@ import org.opengis.feature.PropertyType;
*
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
* @since 0.8
* @module
*/
@@ -90,4 +94,33 @@ public final class FeatureUtilities exte
}
return null;
}
+
+ /**
+ * Gets the name of all given properties. If any property is null or has a
null name,
+ * then the corresponding entry in the returned array will be null.
+ *
+ * @param properties the properties for which to get the names, or
{@code null}.
+ * @return the name of all given properties, or {@code null} if the given
list was null.
+ */
+ public static String[] getNames(final Collection<? extends PropertyType>
properties) {
+ if (properties == null) {
+ return null;
+ }
+ final String[] names = new String[properties.size()];
+ final Iterator<? extends PropertyType> it = properties.iterator();
+ for (int i=0; i < names.length; i++) {
+ final PropertyType property = it.next();
+ if (property != null) {
+ final GenericName name = property.getName();
+ if (name != null) {
+ names[i] = name.toString();
+ }
+ }
+ }
+ // Should not have any element left, unless collection size changed
during iteration.
+ if (it.hasNext()) {
+ throw new ConcurrentModificationException();
+ }
+ return names;
+ }
}
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/package-info.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/package-info.java?rev=1831113&r1=1831112&r2=1831113&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/package-info.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/package-info.java
[UTF-8] Mon May 7 17:32:22 2018
@@ -26,6 +26,7 @@
* may change in incompatible ways in any future version without notice.
*
* @author Johann Sorel (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
* @version 1.0
* @since 0.7
* @module
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/Containers.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/Containers.java?rev=1831113&r1=1831112&r2=1831113&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/Containers.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/Containers.java
[UTF-8] Mon May 7 17:32:22 2018
@@ -19,6 +19,7 @@ package org.apache.sis.util.collection;
import java.util.Map;
import java.util.Set;
import java.util.List;
+import java.util.Iterator;
import java.util.Collection;
import org.apache.sis.util.Static;
import org.apache.sis.util.ArgumentChecks;
@@ -33,7 +34,7 @@ import org.apache.sis.internal.util.Unmo
* in this class implement the {@code CheckedContainer} interface.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 0.4
+ * @version 1.0
* @since 0.3
* @module
*/
@@ -268,4 +269,37 @@ public final class Containers extends St
}
return count + r;
}
+
+ /**
+ * Compares element-by-element the values provided by two iterators, in
iteration order. Let {@code o1} be an
+ * element from the first iterator and {@code o2} the element at the same
position from the second iterator.
+ * This method returns the result of the first {@code o1.compareTo(o2)}
call which returned a value different
+ * than zero. If all {@code o1.compareTo(o2)} calls returned zero, then
this method returns -1 if {@code it1}
+ * iteration finished before {@code it2}, +1 if {@code it2} iteration
finished before {@code it1}, or 0 if both
+ * iterators finished in same time.
+ *
+ * <p>Iterators may return null elements. Null elements are considered
"after" any non-null element.</p>
+ *
+ * @param <E> the type of elements returned by the iterators.
+ * @param it1 the first iterator (can not be null).
+ * @param it2 the second iterator (can not be null).
+ * @return -1 if the content given by the first iterator is considered
"before" the content given by the second
+ * iterator, +1 if considered "after", or 0 if considered equal.
+ *
+ * @since 1.0
+ */
+ public static <E extends Comparable<E>> int compare(final Iterator<E> it1,
final Iterator<? extends E> it2) {
+ while (it1.hasNext()) {
+ if (!it2.hasNext()) return +1; // it1 longer than it2.
+ final E o1 = it1.next();
+ final E o2 = it2.next();
+ if (o1 != o2) {
+ if (o1 == null) return +1;
+ if (o2 == null) return -1;
+ final int c = o1.compareTo(o2);
+ if (c != 0) return c;
+ }
+ }
+ return it2.hasNext() ? -1 : 0;
+ }
}
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/package-info.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/package-info.java?rev=1831113&r1=1831112&r2=1831113&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/package-info.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/package-info.java
[UTF-8] Mon May 7 17:32:22 2018
@@ -51,7 +51,7 @@
* </ul>
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 0.3
+ * @version 1.0
* @since 0.3
* @module
*/
Modified:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java?rev=1831113&r1=1831112&r2=1831113&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java
[UTF-8] Mon May 7 17:32:22 2018
@@ -45,6 +45,16 @@ public abstract class AbstractFeatureSet
}
/**
+ * Creates a new feature set with the same warning listeners than the
given resource,
+ * or {@code null} if the listeners are unknown.
+ *
+ * @param resource the resources from which to get the listeners, or
{@code null} if none.
+ */
+ protected AbstractFeatureSet(final FeatureSet resource) {
+ super(resource);
+ }
+
+ /**
* Requests a subset of features and/or feature properties from this
resource.
* The default implementation try to execute the queries by filtering the
* {@linkplain #features(boolean) stream of features}, which may be
inefficient.
@@ -58,7 +68,7 @@ public abstract class AbstractFeatureSet
@Override
public FeatureSet subset(final Query query) throws DataStoreException {
if (query instanceof SimpleQuery) {
- return SimpleQuery.executeOnCPU(this, (SimpleQuery) query);
+ return ((SimpleQuery) query).execute(this);
} else {
return FeatureSet.super.subset(query);
}
Modified:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java?rev=1831113&r1=1831112&r2=1831113&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java
[UTF-8] Mon May 7 17:32:22 2018
@@ -57,6 +57,16 @@ public abstract class AbstractResource i
}
/**
+ * Creates a new resource with the same warning listeners than the given
resource,
+ * or {@code null} if the listeners are unknown.
+ *
+ * @param resource the resources from which to get the listeners, or
{@code null} if none.
+ */
+ protected AbstractResource(final Resource resource) {
+ listeners = (resource instanceof AbstractResource) ?
((AbstractResource) resource).listeners : null;
+ }
+
+ /**
* Returns the locale for error messages or warnings.
* Returns {@code null} if no locale is explicitly defined.
*
Copied:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureSetView.java
(from r1831112,
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQueryFeatureSet.java)
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureSetView.java?p2=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureSetView.java&p1=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQueryFeatureSet.java&r1=1831112&r2=1831113&rev=1831113&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQueryFeatureSet.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureSetView.java
[UTF-8] Mon May 7 17:32:22 2018
@@ -16,67 +16,90 @@
*/
package org.apache.sis.internal.storage.query;
-import java.util.Collections;
import java.util.List;
-import java.util.function.Function;
-import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.opengis.geometry.Envelope;
+import org.opengis.metadata.Metadata;
+import org.apache.sis.internal.feature.FeatureUtilities;
+import org.apache.sis.internal.storage.AbstractFeatureSet;
import org.apache.sis.metadata.iso.DefaultMetadata;
import org.apache.sis.metadata.iso.citation.DefaultCitation;
import org.apache.sis.metadata.iso.identification.DefaultDataIdentification;
-import org.apache.sis.referencing.NamedIdentifier;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.FeatureSet;
-import org.apache.sis.storage.Query;
-import org.apache.sis.storage.UnsupportedQueryException;
-import org.apache.sis.storage.event.ChangeEvent;
-import org.apache.sis.storage.event.ChangeListener;
+
+// Branch-dependent imports
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureType;
-import org.opengis.feature.PropertyType;
import org.opengis.filter.Filter;
import org.opengis.filter.sort.SortBy;
-import org.opengis.geometry.Envelope;
-import org.opengis.metadata.Metadata;
-import org.opengis.util.GenericName;
+import org.opengis.filter.expression.Expression;
+
/**
+ * The result of {@link SimpleQuery#execute(FeatureSet)} executed using Java
{@link Stream} methods.
+ * Queries executed by this class do not benefit from accelerations provided
for example by databases.
+ * This class should be used only as a fallback when the query can not be
executed natively by
+ * {@link FeatureSet#subset(Query)}.
*
- * @author Johann Sorel (Geomatys)
+ * @author Johann Sorel (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
* @version 1.0
* @since 1.0
* @module
*/
-final class SimpleQueryFeatureSet implements FeatureSet {
-
+final class FeatureSetView extends AbstractFeatureSet {
+ /**
+ * The set of feature instances to filter, sort or process.
+ */
private final FeatureSet source;
+
+ /**
+ * The query for filtering the source set of features.
+ */
private final SimpleQuery query;
+
+ /**
+ * The type of features in this set. May or may not be the same as {@link
#source}.
+ * This is computed when first needed.
+ */
private FeatureType resultType;
+
+ /**
+ * A description of this set of features, computed when first needed.
+ */
private DefaultMetadata metadata;
- public SimpleQueryFeatureSet(FeatureSet source, SimpleQuery query) {
+ /**
+ * Creates a new set of features by filtering the given set using the
given query.
+ */
+ FeatureSetView(final FeatureSet source, final SimpleQuery query) {
+ super(source);
this.source = source;
this.query = query;
}
+ /**
+ * Returns {@code null} since computing the envelope would be costly.
+ */
@Override
- public Envelope getEnvelope() throws DataStoreException {
+ public Envelope getEnvelope() {
return null;
}
+ /**
+ * Computes information about this resource.
+ * Current implementation sets only the resource name.
+ */
@Override
public synchronized Metadata getMetadata() throws DataStoreException {
if (metadata == null) {
- final FeatureType type = getType();
-
+ final DefaultCitation citation = new
DefaultCitation(getType().getName().toInternationalString());
final DefaultDataIdentification identification = new
DefaultDataIdentification();
- final NamedIdentifier identifier = new
NamedIdentifier(type.getName());
- final DefaultCitation citation = new
DefaultCitation(type.getName().toString());
- citation.setIdentifiers(Collections.singleton(identifier));
identification.setCitation(citation);
final DefaultMetadata metadata = new DefaultMetadata();
-
metadata.setIdentificationInfo(Collections.singleton(identification));
+ metadata.getIdentificationInfo().add(identification);
metadata.freeze();
this.metadata = metadata;
@@ -84,84 +107,70 @@ final class SimpleQueryFeatureSet implem
return metadata;
}
+ /**
+ * Returns a description of properties that are common to all features in
this dataset.
+ */
@Override
public synchronized FeatureType getType() throws DataStoreException {
if (resultType == null) {
- resultType = SimpleQuery.expectedType(source.getType(), query);
+ resultType = query.expectedType(source.getType());
}
return resultType;
}
+ /**
+ * Returns a stream of all features contained in this dataset.
+ */
@Override
- public FeatureSet subset(Query query) throws UnsupportedQueryException,
DataStoreException {
- if (query instanceof SimpleQuery) {
- return SimpleQuery.executeOnCPU(this, (SimpleQuery) query);
- }
- return FeatureSet.super.subset(query);
- }
-
- @Override
- public Stream<Feature> features(boolean parallel) throws
DataStoreException {
-
+ public Stream<Feature> features(final boolean parallel) throws
DataStoreException {
Stream<Feature> stream = source.features(parallel);
-
- //apply filter
+ /*
+ * Apply filter.
+ */
final Filter filter = query.getFilter();
if (!Filter.INCLUDE.equals(filter)) {
stream = stream.filter(filter::evaluate);
}
-
- //apply sort by
+ /*
+ * Apply sorting.
+ */
final SortBy[] sortBy = query.getSortBy();
if (sortBy.length > 0) {
stream = stream.sorted(new SortByComparator(sortBy));
}
-
- //apply offset
+ /*
+ * Apply offset.
+ */
final long offset = query.getOffset();
if (offset > 0) {
stream = stream.skip(offset);
}
-
- //apply limit
+ /*
+ * Apply limit.
+ */
final long limit = query.getLimit();
if (limit >= 0) {
stream = stream.limit(limit);
}
-
- //transform feature
+ /*
+ * Transform feature instances.
+ */
final List<SimpleQuery.Column> columns = query.getColumns();
if (columns != null) {
- final SimpleQuery.Column[] cols = columns.toArray(new
SimpleQuery.Column[0]);
+ final Expression[] expressions = new Expression[columns.size()];
+ for (int i=0; i<expressions.length; i++) {
+ expressions[i] = columns.get(i).expression;
+ }
final FeatureType type = getType();
- final String[] names = type.getProperties(false).stream()
- .map(PropertyType::getName)
- .map(GenericName::tip)
- .map(Object::toString)
- .collect(Collectors.toList())
- .toArray(new String[0]);
-
- stream = stream.map(new Function<Feature, Feature>() {
- @Override
- public Feature apply(Feature t) {
- final Feature f = type.newInstance();
- for (int i=0;i<cols.length;i++) {
- f.setPropertyValue(names[i],
cols[i].expression.evaluate(t));
- }
- return f;
+ final String[] names =
FeatureUtilities.getNames(type.getProperties(false));
+ stream = stream.map(t -> {
+ final Feature f = type.newInstance();
+ for (int i=0; i < expressions.length; i++) {
+ f.setPropertyValue(names[i], expressions[i].evaluate(t));
}
+ return f;
});
}
-
return stream;
}
-
- @Override
- public <T extends ChangeEvent> void addListener(ChangeListener<? super T>
listener, Class<T> eventType) {
- }
-
- @Override
- public <T extends ChangeEvent> void removeListener(ChangeListener<? super
T> listener, Class<T> eventType) {
- }
-
}
Modified:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQuery.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQuery.java?rev=1831113&r1=1831112&r2=1831113&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQuery.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQuery.java
[UTF-8] Mon May 7 17:32:22 2018
@@ -17,324 +17,409 @@
package org.apache.sis.internal.storage.query;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
-import org.opengis.feature.AttributeType;
-import org.opengis.feature.FeatureAssociationRole;
-import org.opengis.feature.FeatureType;
-import org.opengis.feature.PropertyType;
-import org.opengis.filter.Filter;
-import org.opengis.filter.expression.Expression;
-import org.opengis.filter.sort.SortBy;
import org.opengis.util.GenericName;
import org.apache.sis.feature.builder.FeatureTypeBuilder;
import org.apache.sis.internal.feature.FeatureExpression;
+import org.apache.sis.internal.util.UnmodifiableArrayList;
import org.apache.sis.storage.FeatureSet;
import org.apache.sis.storage.Query;
import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.collection.BackingStoreException;
+import org.apache.sis.util.Classes;
+import org.apache.sis.util.Debug;
import org.apache.sis.util.iso.Names;
+import org.apache.sis.util.resources.Errors;
+
+// Branch-dependent imports
+import org.opengis.filter.Filter;
+import org.opengis.filter.sort.SortBy;
+import org.opengis.filter.expression.Expression;
+import org.opengis.feature.FeatureType;
+import org.opengis.feature.PropertyType;
+import org.opengis.feature.AttributeType;
+import org.opengis.feature.FeatureAssociationRole;
+
/**
- * A simple query mimics SQL SELECT using OGC Filter and Expressions.
+ * 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.
*
- * @author Johann Sorel (Geomatys)
+ * @author Johann Sorel (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
* @version 1.0
* @since 1.0
* @module
*/
public class SimpleQuery implements Query {
+ /**
+ * Sentinel limit value for queries of unlimited length.
+ * This value can be given to {@link #setLimit(long)} or retrieved from
{@link #getLimit()}.
+ */
+ private static final long UNLIMITED = -1;
- private static final SortBy[] EMPTY_SORTBY = new SortBy[0];
+ /**
+ * The columns to retrieve, or {@code null} if all columns shall be
included in the query.
+ *
+ * @see #getColumns()
+ * @see #setColumns(Column...)
+ */
+ private Column[] columns;
- private List<Column> columns;
- private Filter filter = Filter.INCLUDE;
- private long offset;
- private long limit = -1;
- private SortBy[] sortBy = EMPTY_SORTBY;
- private final Map<String,Object> hints = new HashMap<>();
+ /**
+ * The filter for trimming feature instances.
+ *
+ * @see #getFilter()
+ * @see #setFilter(Filter)
+ */
+ private Filter filter;
- public SimpleQuery() {
- }
+ /**
+ * The number of records to skip from the beginning.
+ *
+ * @see #getOffset()
+ * @see #setOffset(long)
+ * @see java.util.stream.Stream#skip(long)
+ */
+ private long skip;
/**
- * Set query columns.
- * A query column may use a simple or complex expression and a alias
- * to create a new type of returned feature.<br>
+ * The maximum number of records contained in the {@code FeatureSet}.
*
- * @return query columns or null to get all feature properties.
+ * @see #getLimit()
+ * @see #setLimit(long)
+ * @see java.util.stream.Stream#limit(long)
*/
- public List<Column> getColumns() {
- return columns;
+ private long limit;
+
+ /**
+ * The expressions to use for sorting the feature instances.
+ *
+ * @see #getSortBy()
+ * @see #setSortBy(SortBy...)
+ */
+ private SortBy[] sortBy;
+
+ /**
+ * Creates a new query retrieving no column and applying no filter.
+ */
+ public SimpleQuery() {
+ filter = Filter.INCLUDE;
+ sortBy = SortBy.UNSORTED;
+ limit = UNLIMITED;
}
/**
- * Returns the query columns.
- * @param columns query expressions or null to get all properties.
+ * Sets the columns to retrieve, or {@code null} if all columns 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.
+ * This is equivalent to the column names in the {@code SELECT} clause of
a SQL statement.
+ *
+ * @param columns columns to retrieve, or null to retrieve all properties.
*/
- public void setColumns(List<Column> columns) {
+ @SuppressWarnings("AssignmentToCollectionOrArrayFieldFromParameter")
+ public void setColumns(Column... columns) {
+ columns = columns.clone();
+ for (int i=0; i<columns.length; i++) {
+ ArgumentChecks.ensureNonNullElement("columns", i, columns[i]);
+ }
this.columns = columns;
}
/**
- * Get query filter.
- * The filter is used to trim features, features who do not pass the filter
- * are discarded.<br>
- * Discarded features are not counted is there is a query limit defined.
+ * Returns the columns to retrieve, or {@code null} if all columns shall
be included in the query.
+ * This is the columns specified in the last call to {@link
#setColumns(Column...)}.
*
- * @return query filter, never null
+ * @return columns to retrieve, or null to retrieve all feature properties.
*/
- public Filter getFilter() {
- return filter;
+ public List<Column> getColumns() {
+ return UnmodifiableArrayList.wrap(columns);
}
/**
- * Set query filter.
+ * Sets a filter for trimming feature instances.
+ * Features that do not pass the filter are discarded.
+ * Discarded features are not counted for the {@linkplain #setLimit(long)
query limit}.
*
- * @param filter not null, use Filter.INCLUDE for all results
+ * @param filter the filter, or {@link Filter#INCLUDE} if none.
*/
- public void setFilter(Filter filter) {
+ public void setFilter(final Filter filter) {
+ ArgumentChecks.ensureNonNull("filter", filter);
this.filter = filter;
}
/**
- * Returns the query offset.
- * The offset is the number of records to skip from the beginning.<br>
- * Offset and limit are often combined to obtain paging.
+ * Returns the filter for trimming feature instances.
+ * This is the value specified in the last call to {@link
#setFilter(Filter)}.
*
- * @return offset
+ * @return the filter, or {@link Filter#INCLUDE} if none.
*/
- public long getOffset() {
- return offset;
+ public Filter getFilter() {
+ return filter;
}
/**
- * Set query start offset.
+ * Sets the number of records to skip from the beginning.
+ * Offset and limit are often combined to obtain paging.
+ * The offset can not be negative.
*
- * @param offset zero or positive
+ * <p>Note that setting this property can be costly on parallelized
streams.
+ * See {@link java.util.stream.Stream#skip(long)} for more information.</p>
+ *
+ * @param skip the number of records to skip from the beginning.
*/
- public void setOffset(long offset) {
- this.offset = offset;
+ public void setOffset(final long skip) {
+ ArgumentChecks.ensurePositive("skip", skip);
+ this.skip = skip;
}
/**
- * Returns the query limit.
- * The limit is the maximum number of records that will contain the
FeatureSet.<br>
- * Offset and limit are often combined to obtain paging.
+ * Returns the number of records to skip from the beginning.
+ * This is the value specified in the last call to {@link
#setOffset(long)}.
*
- * @return limit or -1 for unlimited
+ * @return the number of records to skip from the beginning.
*/
- public long getLimit() {
- return limit;
+ public long getOffset() {
+ return skip;
}
/**
- * Set query limit.
+ * Set the maximum number of records 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 positive or -1 for unlimited
+ * @param limit maximum number of records contained in the {@code
FeatureSet}, or {@link #UNLIMITED}.
*/
- public void setLimit(long limit) {
+ public void setLimit(final long limit) {
+ if (limit != UNLIMITED) {
+ ArgumentChecks.ensurePositive("limit", limit);
+ }
this.limit = limit;
}
/**
- * Returns the query sort by parameters.
- * SortBy objects are used to order Features returned by the
FeatureSet.<br>
- * The first SortBy is applied first then the others as in SQL.
+ * Returns the maximum number of records contained in the {@code
FeatureSet}.
+ * This is the value specified in the last call to {@link #setLimit(long)}.
*
- * @return sort by array, never null, can be empty
+ * @return maximum number of records contained in the {@code FeatureSet},
or {@link #UNLIMITED}.
*/
- public SortBy[] getSortBy() {
- return sortBy == EMPTY_SORTBY ? EMPTY_SORTBY : sortBy.clone();
+ public long getLimit() {
+ return limit;
}
/**
- * Set query sort by elements.
+ * 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} clauses are applied
+ * in declaration order, like SQL.
*
- * @param sortBy
+ * @param sortBy expressions to use for sorting the feature instances.
*/
+ @SuppressWarnings("AssignmentToCollectionOrArrayFieldFromParameter")
public void setSortBy(SortBy... sortBy) {
- this.sortBy = sortBy == null ? EMPTY_SORTBY : sortBy;
+ if (sortBy == null || sortBy.length == 0) {
+ sortBy = SortBy.UNSORTED;
+ } else {
+ sortBy = sortBy.clone();
+ for (int i=0; i < sortBy.length; i++) {
+ ArgumentChecks.ensureNonNullElement("sortBy", i, sortBy[i]);
+ }
+ }
+ this.sortBy = sortBy;
}
/**
- * Different FeatureSet may have more capabilities then what is provided
- * with the SimpleQuery class.<br>
- * Hints allow the user to pass more query parameters.<br>
- * Unsupported hints will be ignored by the FeatureSet.<br>
- * The returned map is modifiable.
+ * Returns the expressions to use for sorting the feature instances.
+ * They are the values specified in the last call to {@link
#setSortBy(SortBy...)}.
*
- * @return modifiable map of query hints
+ * @return expressions to use for sorting the feature instances, or an
empty array if none.
*/
- public Map<String, Object> getHints() {
- return hints;
- }
-
- @Override
- public int hashCode() {
- int hash = 7;
- hash = 97 * hash + Objects.hashCode(this.columns);
- hash = 97 * hash + Objects.hashCode(this.filter);
- hash = 97 * hash + (int) (this.offset ^ (this.offset >>> 32));
- hash = 97 * hash + (int) (this.limit ^ (this.limit >>> 32));
- hash = 97 * hash + Arrays.deepHashCode(this.sortBy);
- return hash;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final SimpleQuery other = (SimpleQuery) obj;
- if (this.offset != other.offset) {
- return false;
- }
- if (this.limit != other.limit) {
- return false;
- }
- if (!Objects.equals(this.columns, other.columns)) {
- return false;
- }
- if (!Objects.equals(this.filter, other.filter)) {
- return false;
- }
- if (!Arrays.deepEquals(this.sortBy, other.sortBy)) {
- return false;
- }
- if (!Objects.equals(this.hints, other.hints)) {
- return false;
- }
- return true;
+ public SortBy[] getSortBy() {
+ return (sortBy.length == 0) ? SortBy.UNSORTED : sortBy.clone();
}
-
/**
- * A query column.
- * Just an expression and an optional alias.
+ * A property or expression to be retrieved by a {@code Query}, together
with the name to assign to it.
+ * Columns can be given to the {@link SimpleQuery#setColumns(Column...)}
method.
*/
public static class Column {
+ /**
+ * The literal, property name or more complex expression to be
retrieved by a {@code Query}.
+ */
public final Expression expression;
+
+ /**
+ * The name to assign to the expression result, or {@code null} if
unspecified.
+ */
public final GenericName alias;
- public Column(Expression expression) {
+ /**
+ * Creates a new column with the given expression and no name.
+ *
+ * @param expression the literal, property name or expression to be
retrieved by a {@code Query}.
+ */
+ public Column(final Expression expression) {
ArgumentChecks.ensureNonNull("expression", expression);
this.expression = expression;
this.alias = null;
}
- public Column(Expression expression, GenericName alias) {
+ /**
+ * Creates a new column with the given expression and the given name.
+ *
+ * @param expression the literal, property name or expression to be
retrieved by a {@code Query}.
+ * @param alias the name to assign to the expression result, or
{@code null} if unspecified.
+ */
+ public Column(final Expression expression, final GenericName alias) {
ArgumentChecks.ensureNonNull("expression", expression);
this.expression = expression;
this.alias = alias;
}
- public Column(Expression expression, String alias) {
+ /**
+ * Creates a new column with the given expression and the given name.
+ * This constructor creates a {@link org.opengis.util.LocalName} from
the given string.
+ *
+ * @param expression the literal, property name or expression to be
retrieved by a {@code Query}.
+ * @param alias the name to assign to the expression result, or
{@code null} if unspecified.
+ */
+ public Column(final Expression expression, final String alias) {
ArgumentChecks.ensureNonNull("expression", expression);
- this.alias = alias == null ? null : Names.createLocalName(null,
null, alias);
this.expression = expression;
+ this.alias = (alias != null) ? Names.createLocalName(null, null,
alias) : null;
}
/**
- * Returns the column expected property type.
- * @param type
- * @return
+ * Returns the expected property type for this column.
+ *
+ * @see SimpleQuery#expectedType(FeatureType)
*/
- public PropertyType expectedType(FeatureType type) {
+ final PropertyType expectedType(final FeatureType type) {
PropertyType resultType;
if (expression instanceof FeatureExpression) {
resultType = ((FeatureExpression)
expression).expectedType(type);
} else {
+ // TODO: remove this hack if we can get more type-safe
Expression.
resultType = expression.evaluate(type, PropertyType.class);
}
- if (alias != null) {
- //rename result type
- if (resultType instanceof AttributeType) {
- resultType = new
FeatureTypeBuilder().addAttribute((AttributeType<?>)
resultType).setName(alias).build();
- } else if (resultType instanceof FeatureAssociationRole) {
- resultType = new
FeatureTypeBuilder().addAssociation((FeatureAssociationRole)
resultType).setName(alias).build();
- } else {
- throw new BackingStoreException("Expression "+expression+"
returned an unexpected property type result "+resultType);
+ if (alias != null && !alias.equals(resultType.getName())) {
+ // Rename the result type.
+ resultType = new
FeatureTypeBuilder().addProperty(resultType).setName(alias).build();
+ if (!(resultType instanceof AttributeType<?>) && !(resultType
instanceof FeatureAssociationRole)) {
+ throw new
IllegalArgumentException(Errors.format(Errors.Keys.IllegalPropertyValueClass_3,
+ alias, AttributeType.class,
Classes.getStandardType(Classes.getClass(resultType))));
}
}
return resultType;
}
+ /**
+ * Returns a hash code value for this column.
+ *
+ * @return a hash code value.
+ */
@Override
public int hashCode() {
- int hash = 3;
- hash = 29 * hash + Objects.hashCode(this.expression);
- hash = 29 * hash + Objects.hashCode(this.alias);
- return hash;
+ return 37 * expression.hashCode() + Objects.hashCode(alias);
}
+ /**
+ * Compares this column with the given object for equality.
+ *
+ * @param obj the object to compare with this column.
+ * @return whether the two objects are equal.
+ */
@Override
- public boolean equals(Object obj) {
- if (this == obj) {
+ public boolean equals(final Object obj) {
+ if (obj == this) {
return true;
}
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
+ if (obj != null && getClass() == obj.getClass()) {
+ final Column other = (Column) obj;
+ return expression.equals(other.expression) &&
Objects.equals(alias, other.alias);
}
- final Column other = (Column) obj;
- if (!Objects.equals(this.expression, other.expression)) {
- return false;
- }
- if (!Objects.equals(this.alias, other.alias)) {
- return false;
+ return false;
+ }
+
+ /**
+ * Returns a string representation of this column for debugging
purpose.
+ *
+ * @return a string representation of this column.
+ */
+ @Debug
+ @Override
+ public String toString() {
+ final StringBuilder b = new
StringBuilder(getClass().getSimpleName()).append('[');
+ if (alias != null) {
+ b.append('"').append(alias).append('"');
}
- return true;
+ return b.append(']').toString();
}
}
/**
- * Execute the query on the CPU.
- * <p>
- * All operations are processed in java on the CPU, this may use
considerable
- * resources. Consider giving the query to the FeatureSet to allow it to
- * optimize the query.
- * <p>
- * <p>
- * The returned FeatureSet do not cache the resulting Features, the query
is
- * processed on each call to features() method.
- * </p>
+ * Applies this query on the given feature set. The default implementation
executes the query using the default
+ * {@link java.util.stream.Stream} methods. Queries executed by this
method may not benefit from accelerations
+ * provided for example by databases. This method should be used only as a
fallback when the query can not be
+ * executed natively by {@link FeatureSet#subset(Query)}.
+ *
+ * <p>The returned {@code FeatureSet} does not cache the resulting {@code
Feature} instances;
+ * the query is processed on every call to the {@link
FeatureSet#features(boolean)} method.</p>
*
- * @param source base FeatureSet to process.
- * @param query Query to apply on source
- * @return resulting query FeatureSet
+ * @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 static FeatureSet executeOnCPU(FeatureSet source, SimpleQuery
query) {
- return new SimpleQueryFeatureSet(source, query);
+ public FeatureSet execute(final FeatureSet source) {
+ ArgumentChecks.ensureNonNull("source", source);
+ return new FeatureSetView(source, this);
}
/**
- * Evaluate the expected returned type of a simple query.
- *
- * @param source
- * @param query
- * @return
+ * Returns the expected property type for this query executed on features
of the given type.
*/
- public static FeatureType expectedType(FeatureType source, SimpleQuery
query) {
-
- final List<Column> columns = query.getColumns();
- if (columns == null) return source;
-
- final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
- ftb.setName(source.getName());
- for (Column col : columns) {
+ final FeatureType expectedType(final FeatureType source) {
+ if (columns == null) {
+ return source; // All columns included: result is of the
same type.
+ }
+ final FeatureTypeBuilder ftb = new
FeatureTypeBuilder().setName(source.getName());
+ for (final Column col : columns) {
ftb.addProperty(col.expectedType(source));
}
return ftb.build();
}
+
+ /**
+ * Returns a hash code value for this query.
+ *
+ * @return a hash value for this query.
+ */
+ @Override
+ public int hashCode() {
+ return 97 * Arrays.hashCode(columns) + 31 * filter.hashCode()
+ + 7 * Arrays.hashCode(sortBy) + Long.hashCode(limit ^ skip);
+ }
+
+ /**
+ * Compares this query with the given object for equality.
+ *
+ * @param obj the object to compare with this query.
+ * @return whether the two objects are equal.
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj != null && getClass() == obj.getClass()) {
+ final SimpleQuery other = (SimpleQuery) obj;
+ return skip == other.skip &&
+ limit == other.limit &&
+ filter.equals(other.filter) &&
+ Arrays.equals(columns, other.columns) &&
+ Arrays.equals(sortBy, other.sortBy);
+ }
+ return true;
+ }
}
Modified:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SortByComparator.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SortByComparator.java?rev=1831113&r1=1831112&r2=1831113&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SortByComparator.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SortByComparator.java
[UTF-8] Mon May 7 17:32:22 2018
@@ -16,87 +16,101 @@
*/
package org.apache.sis.internal.storage.query;
-import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
+import java.util.Iterator;
+import org.apache.sis.util.collection.Containers;
+
+// Branch-dependent imports
import org.opengis.feature.Feature;
-import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.sort.SortBy;
import org.opengis.filter.sort.SortOrder;
+import org.opengis.filter.expression.Expression;
+
/**
- * Comparator to sort Features with a given array of query SortBy[].
+ * Comparator sorting features by an array of {@code SortBy} expressions,
applied in order.
*
- * @author Johann Sorel (Geomatys)
+ * @author Johann Sorel (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
* @version 1.0
* @since 1.0
* @module
+ *
+ * @todo Current implementation has unchecked casts. Fixing that may require a
revision of filter interfaces.
+ * See <a
href="https://github.com/opengeospatial/geoapi/issues/32">GeoAPI issue #32</a>.
*/
-public final class SortByComparator implements Comparator<Feature> {
+final class SortByComparator implements Comparator<Feature> {
+ /**
+ * The expression to evaluate for getting the values to sort.
+ */
+ private final Expression[] properties;
- private final SortBy[] orders;
+ /**
+ * {@code false} for ascending order, {@code true} for descending order.
+ * If unspecified or unknown, we assume ascending order.
+ */
+ private final boolean[] descending;
- public SortByComparator(final SortBy... orders) {
- if (orders == null || orders.length == 0) {
- throw new IllegalArgumentException("SortBy array can not be null
or empty.");
+ /**
+ * Creates a new comparator for the given sort expressions.
+ * It is caller responsibility to ensure that the given array is non-empty.
+ */
+ SortByComparator(final SortBy[] orders) {
+ properties = new Expression[orders.length];
+ descending = new boolean [orders.length];
+ for (int i=0; i<orders.length; i++) {
+ final SortBy order = orders[i];
+ properties[i] = order.getPropertyName();
+ descending[i] = SortOrder.DESCENDING.equals(order.getSortOrder());
}
-
- this.orders = orders;
}
/**
- * {@inheritDoc }
+ * Compares two features for order. Returns -1 if {@code f1} should be
sorted before {@code f2},
+ * +1 if {@code f2} should be after {@code f1}, or 0 if both are equal.
Null features are sorted
+ * after all non-null features, regardless sorting order.
*/
@Override
public int compare(final Feature f1, final Feature f2) {
-
- for (final SortBy order : orders) {
- final PropertyName property = order.getPropertyName();
- Object val1 = property.evaluate(f1);
- Object val2 = property.evaluate(f2);
- if (val1 instanceof Collection) {
- //TODO find a correct way to compare collection values
- //pick the first value
- if (((Collection) val1).isEmpty()) {
- val1 = null;
- } else {
- val1 = ((Collection) val1).iterator().next();
- }
- }
- if (val2 instanceof Collection) {
- //TODO find a correct way to compare collection values
- //pick the first value
- if (((Collection) val2).isEmpty()) {
- val2 = null;
- } else {
- val2 = ((Collection) val2).iterator().next();
+ if (f1 != f2) {
+ if (f1 == null) return +1;
+ if (f2 == null) return -1;
+ for (int i=0; i<properties.length; i++) {
+ final Expression property = properties[i];
+ Comparable<?> o1 = (Comparable<?>) property.evaluate(f1);
+ Comparable<?> o2 = (Comparable<?>) property.evaluate(f2);
+ if (o1 != o2) {
+ if (o1 == null) return +1;
+ if (o2 == null) return -1;
+ final int result;
+ /*
+ * No @SuppressWarnings("unchecked") below: those casts
are really unsafe;
+ * we can not make them safe with current Filter API. See
GeoAPI issue #32.
+ */
+ if (o1 instanceof Iterable<?>) {
+ result = Containers.compare(((Iterable)
o1).iterator(), iterator(o2));
+ } else if (o2 instanceof Iterable<?>) {
+ result = Containers.compare(iterator(o1), ((Iterable)
o2).iterator());
+ } else {
+ result = ((Comparable) o1).compareTo(o2);
+ }
+ if (result != 0) {
+ return descending[i] ? -result : result;
+ }
}
}
-
- final Comparable o1 = Comparable.class.cast(val1);
- final Comparable o2 = Comparable.class.cast(val2);
-
- if (o1 == null) {
- if (o2 == null) {
- continue;
- }
- return -1;
- } else if (o2 == null) {
- return 1;
- }
-
- final int result;
- if (order.getSortOrder() == SortOrder.ASCENDING) {
- result = o1.compareTo(o2);
- } else {
- result = o2.compareTo(o1);
- }
-
- if (result != 0) {
- return result;
- }
}
-
return 0;
}
+ /**
+ * Returns an iterator for the given object.
+ *
+ * @todo Intentionally raw return type, but no {@literal @SuppressWarning}
annotation because this
+ * is a real problem with current Filter API which needs to be
fixed. See GeoAPI issue #32.
+ */
+ private static Iterator iterator(final Object o) {
+ return (o instanceof Iterable<?>) ? ((Iterable<?>) o).iterator() :
Collections.singleton(o).iterator();
+ }
}
Added:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/package-info.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/package-info.java?rev=1831113&view=auto
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/package-info.java
(added)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/package-info.java
[UTF-8] Mon May 7 17:32:22 2018
@@ -0,0 +1,32 @@
+/*
+ * 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.0
+ * @since 1.0
+ * @module
+ */
+package org.apache.sis.internal.storage.query;
Propchange:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/package-info.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/package-info.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Modified:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/Query.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/Query.java?rev=1831113&r1=1831112&r2=1831113&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/Query.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/Query.java
[UTF-8] Mon May 7 17:32:22 2018
@@ -33,15 +33,17 @@ import org.opengis.feature.Feature;
* <code>{@linkplain java.util.function.Predicate}<{@linkplain
Feature}></code>
* while the second domain is equivalent to using
* <code>{@linkplain java.util.function.UnaryOperator}<{@linkplain
Feature}></code>.
- * It is technically possible to use {@code Query} for performing more generic
feature transformations,
+ *
+ * <div class="note"><b>Note:</b>
+ * it is technically possible to use {@code Query} for performing more generic
feature transformations,
* for example inserting new properties computed from other properties, but
such {@code Query} usages
* should be rare since transformations (or more generic processing) are the
topic of another package.
* Queries are rather descriptive objects used by {@link FeatureSet} to
optimize search operations
- * as much as possible on the resource, using for example caches and indexes.
+ * as much as possible on the resource, using for example caches and
indexes.</div>
*
- * <p>Compared to the SQL language, {@code Query} contains the information in
the {@code SELECT} and
+ * Compared to the SQL language, {@code Query} contains the information in the
{@code SELECT} and
* {@code WHERE} clauses of a SQL statement. A {@code Query} typically
contains filtering capabilities
- * and (sometime) simple attribute transformations. Well known query languages
include SQL and CQL.</p>
+ * and (sometime) simple attribute transformations. Well known query languages
include SQL and CQL.
*
* @author Johann Sorel (Geomatys)
* @version 0.8
Modified:
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/SimpleQueryTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/SimpleQueryTest.java?rev=1831113&r1=1831112&r2=1831113&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/SimpleQueryTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/SimpleQueryTest.java
[UTF-8] Mon May 7 17:32:22 2018
@@ -24,24 +24,28 @@ import org.apache.sis.internal.storage.M
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.FeatureSet;
import org.apache.sis.test.TestCase;
-import static org.junit.Assert.*;
import org.junit.Test;
-import org.opengis.feature.AttributeType;
+
+import static org.junit.Assert.*;
+
+// Branch-dependent imports
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureType;
import org.opengis.feature.PropertyType;
+import org.opengis.feature.AttributeType;
import org.opengis.filter.MatchAction;
import org.opengis.filter.sort.SortOrder;
+
/**
* Tests {@link SimpleQuery}.
*
- * @author Johann Sorel (Geomatys)
+ * @author Johann Sorel (Geomatys)
* @version 1.0
* @since 1.0
* @module
*/
-public class SimpleQueryTest extends TestCase {
+public final strictfp class SimpleQueryTest extends TestCase {
private static final FeatureType TYPE;
private static final Feature[] FEATURES;
@@ -76,7 +80,7 @@ public class SimpleQueryTest extends Tes
/**
* Verify query limit.
*
- * @throws DataStoreException
+ * @throws DataStoreException if an error occurred while executing the
query.
*/
@Test
public void testLimit() throws DataStoreException {
@@ -84,7 +88,7 @@ public class SimpleQueryTest extends Tes
final SimpleQuery query = new SimpleQuery();
query.setLimit(2);
- final FeatureSet fs = SimpleQuery.executeOnCPU(FEATURESET, query);
+ final FeatureSet fs = query.execute(FEATURESET);
final Feature[] result =
fs.features(false).collect(Collectors.toList()).toArray(new Feature[0]);
assertEquals(FEATURES[0], result[0]);
@@ -94,7 +98,7 @@ public class SimpleQueryTest extends Tes
/**
* Verify query offset.
*
- * @throws DataStoreException
+ * @throws DataStoreException if an error occurred while executing the
query.
*/
@Test
public void testOffset() throws DataStoreException {
@@ -102,7 +106,7 @@ public class SimpleQueryTest extends Tes
final SimpleQuery query = new SimpleQuery();
query.setOffset(2);
- final FeatureSet fs = SimpleQuery.executeOnCPU(FEATURESET, query);
+ final FeatureSet fs = query.execute(FEATURESET);
final Feature[] result =
fs.features(false).collect(Collectors.toList()).toArray(new Feature[0]);
assertEquals(FEATURES[2], result[0]);
@@ -113,7 +117,7 @@ public class SimpleQueryTest extends Tes
/**
* Verify query sortby.
*
- * @throws DataStoreException
+ * @throws DataStoreException if an error occurred while executing the
query.
*/
@Test
public void testSortBy() throws DataStoreException {
@@ -125,7 +129,7 @@ public class SimpleQueryTest extends Tes
factory.sort("value2", SortOrder.DESCENDING)
);
- final FeatureSet fs = SimpleQuery.executeOnCPU(FEATURESET, query);
+ final FeatureSet fs = query.execute(FEATURESET);
final Feature[] result =
fs.features(false).collect(Collectors.toList()).toArray(new Feature[0]);
assertEquals(FEATURES[3], result[0]);
@@ -138,7 +142,7 @@ public class SimpleQueryTest extends Tes
/**
* Verify query filter.
*
- * @throws DataStoreException
+ * @throws DataStoreException if an error occurred while executing the
query.
*/
@Test
public void testFilter() throws DataStoreException {
@@ -147,7 +151,7 @@ public class SimpleQueryTest extends Tes
final SimpleQuery query = new SimpleQuery();
query.setFilter(factory.equal(factory.property("value1"),
factory.literal(2), true, MatchAction.ALL));
- final FeatureSet fs = SimpleQuery.executeOnCPU(FEATURESET, query);
+ final FeatureSet fs = query.execute(FEATURESET);
final Feature[] result =
fs.features(false).collect(Collectors.toList()).toArray(new Feature[0]);
assertEquals(FEATURES[1], result[0]);
@@ -157,21 +161,19 @@ public class SimpleQueryTest extends Tes
/**
* Verify query columns.
*
- * @throws DataStoreException
+ * @throws DataStoreException if an error occurred while executing the
query.
*/
@Test
public void testColumns() throws DataStoreException {
final DefaultFilterFactory factory = new DefaultFilterFactory();
final SimpleQuery query = new SimpleQuery();
- query.setColumns(Arrays.asList(
- new SimpleQuery.Column(factory.property("value1"),
(String)null),
- new SimpleQuery.Column(factory.property("value1"), "renamed1"),
- new SimpleQuery.Column(factory.literal("a literal"),
"computed")
- ));
+ query.setColumns(new SimpleQuery.Column(factory.property("value1"),
(String)null),
+ new SimpleQuery.Column(factory.property("value1"),
"renamed1"),
+ new SimpleQuery.Column(factory.literal("a literal"),
"computed"));
query.setLimit(1);
- final FeatureSet fs = SimpleQuery.executeOnCPU(FEATURESET, query);
+ final FeatureSet fs = query.execute(FEATURESET);
final Feature[] results =
fs.features(false).collect(Collectors.toList()).toArray(new Feature[0]);
assertEquals(1, results.length);