Author: jsorel
Date: Wed Apr 25 15:22:58 2018
New Revision: 1830086
URL: http://svn.apache.org/viewvc?rev=1830086&view=rev
Log:
DataStore : add in memory feature set and simple query implementations
Added:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultSortBy.java
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ArrayFeatureSet.java
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/
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/SimpleQueryFeatureSet.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/test/java/org/apache/sis/internal/storage/query/
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/SimpleQueryTest.java
Modified:
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
Added:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultSortBy.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultSortBy.java?rev=1830086&view=auto
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultSortBy.java
(added)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultSortBy.java
Wed Apr 25 15:22:58 2018
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package org.apache.sis.filter;
+
+import org.opengis.filter.expression.PropertyName;
+import org.opengis.filter.sort.SortBy;
+import org.opengis.filter.sort.SortOrder;
+
+/**
+ * Immutable SortBy.
+ *
+ * @author Johann Sorel (Geomatys)
+ * @version 1.0
+ * @since 1.0
+ * @module
+ */
+public class DefaultSortBy implements SortBy {
+
+ private final PropertyName property;
+ private final SortOrder order;
+
+ /**
+ *
+ * @param property sort by property applied on.
+ * @param order sorting order
+ */
+ public DefaultSortBy(PropertyName property, SortOrder order) {
+ this.property = property;
+ this.order = order;
+ }
+
+ /**
+ * {@inheritDoc }
+ */
+ @Override
+ public PropertyName getPropertyName() {
+ return property;
+ }
+
+ /**
+ * {@inheritDoc }
+ */
+ @Override
+ public SortOrder getSortOrder() {
+ return order;
+ }
+
+}
Added:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ArrayFeatureSet.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ArrayFeatureSet.java?rev=1830086&view=auto
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ArrayFeatureSet.java
(added)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ArrayFeatureSet.java
Wed Apr 25 15:22:58 2018
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+package org.apache.sis.internal.storage;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.stream.Stream;
+import org.apache.sis.internal.storage.query.SimpleQuery;
+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.DataStore;
+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.util.ArgumentChecks;
+import org.apache.sis.util.logging.WarningListeners;
+import org.opengis.feature.Feature;
+import org.opengis.feature.FeatureType;
+import org.opengis.metadata.Metadata;
+
+/**
+ * FeatureSet implementation stored in memory.
+ *
+ * <p>
+ * Note-1 : This implementation is read-only for now but will become writable.
+ * </p>
+ * <p>
+ * Note-2 : this class is experimental.
+ * </p>
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+public final class ArrayFeatureSet extends AbstractFeatureSet implements
FeatureSet {
+
+ private final Metadata metadata;
+ private final FeatureType type;
+ private final Collection<Feature> features;
+
+ /**
+ * Creates a new feature set in memory.
+ *
+ * @param listeners the set of registered warning listeners for the data
store.
+ * @param type stored features type.
+ * @param features collection of stored features, this collection will not
be copied.
+ * @param metadata can be null
+ */
+ public ArrayFeatureSet(final WarningListeners<DataStore> listeners,
FeatureType type, Collection<Feature> features, Metadata metadata) {
+ super(listeners);
+ ArgumentChecks.ensureNonNull("type", type);
+ ArgumentChecks.ensureNonNull("features", type);
+ this.type = type;
+ this.features = features;
+
+ if (metadata == null) {
+ 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 md = new DefaultMetadata();
+ md.setIdentificationInfo(Collections.singleton(identification));
+ md.freeze();
+ metadata = md;
+ }
+
+ this.metadata = metadata;
+ }
+
+ @Override
+ public FeatureType getType() throws DataStoreException {
+ return type;
+ }
+
+ @Override
+ public Metadata getMetadata() throws DataStoreException {
+ return metadata;
+ }
+
+ @Override
+ public Stream<Feature> features(boolean bln) throws DataStoreException {
+ return bln ? features.parallelStream() : features.stream();
+ }
+
+ @Override
+ public FeatureSet subset(Query query) throws UnsupportedQueryException,
DataStoreException {
+ if (query instanceof SimpleQuery) {
+ return SimpleQuery.executeOnCPU(this, (SimpleQuery) query);
+ }
+ return FeatureSet.super.subset(query);
+ }
+
+}
Added:
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=1830086&view=auto
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQuery.java
(added)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQuery.java
Wed Apr 25 15:22:58 2018
@@ -0,0 +1,309 @@
+/*
+ * 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.
+ */
+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.apache.sis.feature.builder.FeatureTypeBuilder;
+import org.apache.sis.storage.FeatureSet;
+import org.apache.sis.storage.Query;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.iso.Names;
+import org.opengis.feature.FeatureType;
+import org.opengis.filter.Filter;
+import org.opengis.filter.expression.Expression;
+import org.opengis.filter.sort.SortBy;
+import org.opengis.util.GenericName;
+
+/**
+ * A simple query mimics SQL SELECT using OGC Filter and Expressions.
+ *
+ * @author Johann Sorel (Geomatys)
+ * @version 1.0
+ * @since 1.0
+ * @module
+ */
+public class SimpleQuery implements Query {
+
+ private static final SortBy[] EMPTY_SORTBY = new SortBy[0];
+
+ 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<>();
+
+ public SimpleQuery() {
+ }
+
+ /**
+ * 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>
+ *
+ * @return query columns or null to get all feature properties.
+ */
+ public List<Column> getColumns() {
+ return columns;
+ }
+
+ /**
+ * Returns the query columns.
+ * @param columns query expressions or null to get all properties.
+ */
+ public void setColumns(List<Column> columns) {
+ 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.
+ *
+ * @return query filter, never null
+ */
+ public Filter getFilter() {
+ return filter;
+ }
+
+ /**
+ * Set query filter.
+ *
+ * @param filter not null, use Filter.INCLUDE for all results
+ */
+ public void setFilter(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.
+ *
+ * @return offset
+ */
+ public long getOffset() {
+ return offset;
+ }
+
+ /**
+ * Set query start offset.
+ *
+ * @param offset zero or positive
+ */
+ public void setOffset(long offset) {
+ this.offset = offset;
+ }
+
+ /**
+ * 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.
+ *
+ * @return limit or -1 for unlimited
+ */
+ public long getLimit() {
+ return limit;
+ }
+
+ /**
+ * Set query limit.
+ *
+ * @param limit positive or -1 for unlimited
+ */
+ public void setLimit(long 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.
+ *
+ * @return sort by array, never null, can be empty
+ */
+ public SortBy[] getSortBy() {
+ return sortBy == EMPTY_SORTBY ? EMPTY_SORTBY : sortBy.clone();
+ }
+
+ /**
+ * Set query sort by elements.
+ *
+ * @param sortBy
+ */
+ public void setSortBy(SortBy... sortBy) {
+ this.sortBy = sortBy == null ? EMPTY_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.
+ *
+ * @return modifiable map of query hints
+ */
+ 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;
+ }
+
+
+ /**
+ * A query column.
+ * Just an expression and an optional alias.
+ */
+ public static class Column {
+ public final Expression expression;
+ public final GenericName alias;
+
+ public Column(Expression expression) {
+ ArgumentChecks.ensureNonNull("expression", expression);
+ this.expression = expression;
+ this.alias = null;
+ }
+
+ public Column(Expression expression, GenericName alias) {
+ ArgumentChecks.ensureNonNull("expression", expression);
+ this.expression = expression;
+ this.alias = alias;
+ }
+
+ public Column(Expression expression, String alias) {
+ ArgumentChecks.ensureNonNull("expression", expression);
+ this.alias = Names.createLocalName(null, null, alias);
+ this.expression = expression;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 29 * hash + Objects.hashCode(this.expression);
+ hash = 29 * hash + Objects.hashCode(this.alias);
+ 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 Column other = (Column) obj;
+ if (!Objects.equals(this.expression, other.expression)) {
+ return false;
+ }
+ if (!Objects.equals(this.alias, other.alias)) {
+ return false;
+ }
+ return true;
+ }
+
+ }
+
+ /**
+ * 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>
+ *
+ * @param source base FeatureSet to process.
+ * @param query Query to apply on source
+ * @return resulting query FeatureSet
+ */
+ public static FeatureSet executeOnCPU(FeatureSet source, SimpleQuery
query) {
+ return new SimpleQueryFeatureSet(source, query);
+ }
+
+ /**
+ * Evaluate the expected returned type of a simple query.
+ *
+ * @param source
+ * @param query
+ * @return
+ */
+ public static FeatureType expectedType(FeatureType source, SimpleQuery
query) {
+
+ final List<Column> columns = query.getColumns();
+ if (columns == null) return source;
+
+ final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
+
+
+ return ftb.build();
+ }
+}
Added:
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/SimpleQueryFeatureSet.java?rev=1830086&view=auto
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQueryFeatureSet.java
(added)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SimpleQueryFeatureSet.java
Wed Apr 25 15:22:58 2018
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+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.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;
+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;
+
+/**
+ *
+ * @author Johann Sorel (Geomatys)
+ * @version 1.0
+ * @since 1.0
+ * @module
+ */
+final class SimpleQueryFeatureSet implements FeatureSet {
+
+ private final FeatureSet source;
+ private final SimpleQuery query;
+ private FeatureType resultType;
+ private DefaultMetadata metadata;
+
+ public SimpleQueryFeatureSet(FeatureSet source, SimpleQuery query) {
+ this.source = source;
+ this.query = query;
+ }
+
+ @Override
+ public Envelope getEnvelope() throws DataStoreException {
+ return null;
+ }
+
+ @Override
+ public synchronized Metadata getMetadata() throws DataStoreException {
+ if (metadata == null) {
+ final FeatureType type = getType();
+
+ 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.freeze();
+
+ this.metadata = metadata;
+ }
+ return metadata;
+ }
+
+ @Override
+ public synchronized FeatureType getType() throws DataStoreException {
+ if (resultType == null) {
+ resultType = SimpleQuery.expectedType(source.getType(), query);
+ }
+ return resultType;
+ }
+
+ @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 {
+
+ Stream<Feature> stream = source.features(parallel);
+
+ //apply filter
+ final Filter filter = query.getFilter();
+ if (!Filter.INCLUDE.equals(filter)) {
+ stream.filter(filter::evaluate);
+ }
+
+ //apply sort by
+ final SortBy[] sortBy = query.getSortBy();
+ if (sortBy.length > 0) {
+ stream = stream.sorted(new SortByComparator(sortBy));
+ }
+
+ //apply offset
+ final long offset = query.getOffset();
+ if (offset > 0) {
+ stream = stream.skip(offset);
+ }
+
+ //apply limit
+ final long limit = query.getLimit();
+ if (limit >= 0) {
+ stream = stream.limit(limit);
+ }
+
+ //transform feature
+ final List<SimpleQuery.Column> columns = query.getColumns();
+ if (columns != null) {
+ final SimpleQuery.Column[] cols = columns.toArray(new
SimpleQuery.Column[0]);
+ 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.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;
+ }
+ });
+ }
+
+ 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) {
+ }
+
+}
Added:
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=1830086&view=auto
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SortByComparator.java
(added)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/SortByComparator.java
Wed Apr 25 15:22:58 2018
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+package org.apache.sis.internal.storage.query;
+
+import java.util.Collection;
+import java.util.Comparator;
+import org.opengis.feature.Feature;
+import org.opengis.filter.expression.PropertyName;
+import org.opengis.filter.sort.SortBy;
+import org.opengis.filter.sort.SortOrder;
+
+/**
+ * Comparator to sort Features with a given array of query SortBy[].
+ *
+ * @author Johann Sorel (Geomatys)
+ * @version 1.0
+ * @since 1.0
+ * @module
+ */
+public final class SortByComparator implements Comparator<Feature> {
+
+ private final SortBy[] orders;
+
+ public SortByComparator(final SortBy... orders) {
+ if (orders == null || orders.length == 0) {
+ throw new IllegalArgumentException("SortBy array can not be null
or empty.");
+ }
+
+ this.orders = orders;
+ }
+
+ /**
+ * {@inheritDoc }
+ */
+ @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();
+ }
+ }
+
+ 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;
+ }
+
+}
Added:
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=1830086&view=auto
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/SimpleQueryTest.java
(added)
+++
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/query/SimpleQueryTest.java
Wed Apr 25 15:22:58 2018
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+package org.apache.sis.internal.storage.query;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
+import org.apache.sis.feature.builder.FeatureTypeBuilder;
+import org.apache.sis.filter.DefaultPropertyName;
+import org.apache.sis.filter.DefaultSortBy;
+import org.apache.sis.internal.storage.ArrayFeatureSet;
+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.Feature;
+import org.opengis.feature.FeatureType;
+import org.opengis.filter.sort.SortOrder;
+
+/**
+ * Tests {@link SimpleQuery}.
+ *
+ * @author Johann Sorel (Geomatys)
+ * @version 1.0
+ * @since 1.0
+ * @module
+ */
+public class SimpleQueryTest extends TestCase {
+
+ private static final FeatureType TYPE;
+ private static final Feature[] FEATURES;
+ private static final FeatureSet FEATURESET;
+ static {
+ final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
+ ftb.setName("Test");
+ ftb.addAttribute(Integer.class).setName("value1");
+ ftb.addAttribute(Integer.class).setName("value2");
+ TYPE = ftb.build();
+
+ final Feature f1 = TYPE.newInstance();
+ f1.setPropertyValue("value1", 3);
+ f1.setPropertyValue("value2", 1);
+ final Feature f2 = TYPE.newInstance();
+ f2.setPropertyValue("value1", 2);
+ f2.setPropertyValue("value2", 2);
+ final Feature f3 = TYPE.newInstance();
+ f3.setPropertyValue("value1", 2);
+ f3.setPropertyValue("value2", 1);
+ final Feature f4 = TYPE.newInstance();
+ f4.setPropertyValue("value1", 1);
+ f4.setPropertyValue("value2", 1);
+ final Feature f5 = TYPE.newInstance();
+ f5.setPropertyValue("value1", 4);
+ f5.setPropertyValue("value2", 1);
+
+ FEATURES = new Feature[]{f1,f2,f3,f4,f5};
+ FEATURESET = new ArrayFeatureSet(null, TYPE, Arrays.asList(FEATURES),
null);
+ }
+
+ /**
+ * Verify query limit.
+ *
+ * @throws DataStoreException
+ */
+ @Test
+ public void testLimit() throws DataStoreException {
+
+ final SimpleQuery query = new SimpleQuery();
+ query.setLimit(2);
+
+ final FeatureSet fs = SimpleQuery.executeOnCPU(FEATURESET, query);
+ final Feature[] result =
fs.features(false).collect(Collectors.toList()).toArray(new Feature[0]);
+
+ assertEquals(FEATURES[0], result[0]);
+ assertEquals(FEATURES[1], result[1]);
+ }
+
+ /**
+ * Verify query offset.
+ *
+ * @throws DataStoreException
+ */
+ @Test
+ public void testOffset() throws DataStoreException {
+
+ final SimpleQuery query = new SimpleQuery();
+ query.setOffset(2);
+
+ final FeatureSet fs = SimpleQuery.executeOnCPU(FEATURESET, query);
+ final Feature[] result =
fs.features(false).collect(Collectors.toList()).toArray(new Feature[0]);
+
+ assertEquals(FEATURES[2], result[0]);
+ assertEquals(FEATURES[3], result[1]);
+ assertEquals(FEATURES[4], result[2]);
+ }
+
+ /**
+ * Verify query sortby.
+ *
+ * @throws DataStoreException
+ */
+ @Test
+ public void testSortBy() throws DataStoreException {
+
+ final SimpleQuery query = new SimpleQuery();
+ query.setSortBy(
+ new DefaultSortBy(new DefaultPropertyName("value1"),
SortOrder.ASCENDING),
+ new DefaultSortBy(new DefaultPropertyName("value2"),
SortOrder.DESCENDING)
+ );
+
+ final FeatureSet fs = SimpleQuery.executeOnCPU(FEATURESET, query);
+ final Feature[] result =
fs.features(false).collect(Collectors.toList()).toArray(new Feature[0]);
+
+ assertEquals(FEATURES[3], result[0]);
+ assertEquals(FEATURES[1], result[1]);
+ assertEquals(FEATURES[2], result[2]);
+ assertEquals(FEATURES[0], result[3]);
+ assertEquals(FEATURES[4], result[4]);
+ }
+
+}
Modified:
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java?rev=1830086&r1=1830085&r2=1830086&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
[UTF-8] Wed Apr 25 15:22:58 2018
@@ -50,6 +50,7 @@ import org.junit.BeforeClass;
org.apache.sis.internal.storage.csv.StoreProviderTest.class,
org.apache.sis.internal.storage.csv.StoreTest.class,
org.apache.sis.internal.storage.folder.StoreTest.class,
+ org.apache.sis.internal.storage.query.SimpleQueryTest.class,
org.apache.sis.storage.DataStoresTest.class
})
public final strictfp class StorageTestSuite extends TestSuite {