sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jso...@apache.org
Subject svn commit: r1830086 - in /sis/branches/JDK8: core/sis-feature/src/main/java/org/apache/sis/filter/ storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/ storage/sis-...
Date Wed, 25 Apr 2018 15:22:58 GMT
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 {



Mime
View raw message