Author: desruisseaux
Date: Mon May 7 10:43:29 2018
New Revision: 1831086
URL: http://svn.apache.org/viewvc?rev=1831086&view=rev
Log:
Complete revision of filter package, except DefaultFilterFactory which will
need a severe revision of its API (but this task need to be done in GeoAPI
first).
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractComparisonOperator.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyIsEqualTo.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyName.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractComparisonOperator.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractComparisonOperator.java?rev=1831086&r1=1831085&r2=1831086&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractComparisonOperator.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractComparisonOperator.java
[UTF-8] Mon May 7 10:43:29 2018
@@ -67,9 +67,10 @@ abstract class AbstractComparisonOperato
/**
* Creates a new binary comparison operator.
+ * It is caller responsibility to ensure that no argument is null.
*/
AbstractComparisonOperator(final Expression expression1, final Expression
expression2,
- final boolean matchCase, final
MatchAction matchAction)
+ final boolean matchCase, final MatchAction
matchAction)
{
this.expression1 = expression1;
this.expression2 = expression2;
@@ -78,6 +79,12 @@ abstract class AbstractComparisonOperato
}
/**
+ * Returns the mathematical symbol for this comparison operator.
+ * The symbol should be one of the following: {@literal < > ≤ ≥ = ≠}.
+ */
+ protected abstract char symbol();
+
+ /**
* Returns the first of the two expressions to be compared by this
operator.
*/
@Override
@@ -115,4 +122,41 @@ abstract class AbstractComparisonOperato
public final MatchAction getMatchAction() {
return matchAction;
}
+
+ /**
+ * Returns a hash code value for this comparison operator.
+ */
+ @Override
+ public final int hashCode() {
+ int hash = (31 * expression1.hashCode() + expression2.hashCode()) * 37
+ matchAction.hashCode();
+ if (matchCase) hash = ~hash;
+ return hash ^ symbol(); // Use the symbol as a way to
differentiate the subclasses.
+ }
+
+ /**
+ * Compares this operator with the given object for equality.
+ */
+ @Override
+ public final boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj != null && obj.getClass() == getClass()) {
+ final AbstractComparisonOperator other =
(AbstractComparisonOperator) obj;
+ return matchCase == other.matchCase &&
+ expression1.equals(other.expression1) &&
+ expression2.equals(other.expression2) &&
+ matchAction.equals(other.matchAction);
+ }
+ return false;
+ }
+
+ /**
+ * Returns a string representation of this comparison operator.
+ */
+ @Override
+ public final String toString() {
+ return new StringBuilder(30).append(expression1).append('
').append(symbol()).append(' ')
+ .append(expression2).toString();
+ }
}
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java?rev=1831086&r1=1831085&r2=1831086&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
[UTF-8] Mon May 7 10:43:29 2018
@@ -18,76 +18,14 @@ package org.apache.sis.filter;
import java.util.List;
import java.util.Set;
-import org.opengis.filter.And;
-import org.opengis.filter.Filter;
-import org.opengis.filter.FilterFactory2;
-import org.opengis.filter.Id;
-import org.opengis.filter.MatchAction;
-import org.opengis.filter.Not;
-import org.opengis.filter.Or;
-import org.opengis.filter.PropertyIsBetween;
-import org.opengis.filter.PropertyIsEqualTo;
-import org.opengis.filter.PropertyIsGreaterThan;
-import org.opengis.filter.PropertyIsGreaterThanOrEqualTo;
-import org.opengis.filter.PropertyIsLessThan;
-import org.opengis.filter.PropertyIsLessThanOrEqualTo;
-import org.opengis.filter.PropertyIsLike;
-import org.opengis.filter.PropertyIsNil;
-import org.opengis.filter.PropertyIsNotEqualTo;
-import org.opengis.filter.PropertyIsNull;
-import org.opengis.filter.capability.ArithmeticOperators;
-import org.opengis.filter.capability.ComparisonOperators;
-import org.opengis.filter.capability.FilterCapabilities;
-import org.opengis.filter.capability.FunctionName;
-import org.opengis.filter.capability.Functions;
-import org.opengis.filter.capability.GeometryOperand;
-import org.opengis.filter.capability.IdCapabilities;
-import org.opengis.filter.capability.Operator;
-import org.opengis.filter.capability.ScalarCapabilities;
-import org.opengis.filter.capability.SpatialCapabilities;
-import org.opengis.filter.capability.SpatialOperator;
-import org.opengis.filter.capability.SpatialOperators;
-import org.opengis.filter.capability.TemporalCapabilities;
-import org.opengis.filter.capability.TemporalOperand;
-import org.opengis.filter.capability.TemporalOperators;
-import org.opengis.filter.expression.Add;
-import org.opengis.filter.expression.Divide;
-import org.opengis.filter.expression.Expression;
-import org.opengis.filter.expression.Function;
-import org.opengis.filter.expression.Literal;
-import org.opengis.filter.expression.Multiply;
-import org.opengis.filter.expression.PropertyName;
-import org.opengis.filter.expression.Subtract;
-import org.opengis.filter.identity.FeatureId;
-import org.opengis.filter.identity.GmlObjectId;
-import org.opengis.filter.identity.Identifier;
-import org.opengis.filter.sort.SortBy;
-import org.opengis.filter.sort.SortOrder;
-import org.opengis.filter.spatial.BBOX;
-import org.opengis.filter.spatial.Beyond;
-import org.opengis.filter.spatial.Contains;
-import org.opengis.filter.spatial.Crosses;
-import org.opengis.filter.spatial.DWithin;
-import org.opengis.filter.spatial.Disjoint;
-import org.opengis.filter.spatial.Equals;
-import org.opengis.filter.spatial.Intersects;
-import org.opengis.filter.spatial.Overlaps;
-import org.opengis.filter.spatial.Touches;
-import org.opengis.filter.spatial.Within;
-import org.opengis.filter.temporal.After;
-import org.opengis.filter.temporal.AnyInteracts;
-import org.opengis.filter.temporal.Before;
-import org.opengis.filter.temporal.Begins;
-import org.opengis.filter.temporal.BegunBy;
-import org.opengis.filter.temporal.During;
-import org.opengis.filter.temporal.EndedBy;
-import org.opengis.filter.temporal.Ends;
-import org.opengis.filter.temporal.Meets;
-import org.opengis.filter.temporal.MetBy;
-import org.opengis.filter.temporal.OverlappedBy;
-import org.opengis.filter.temporal.TContains;
-import org.opengis.filter.temporal.TEquals;
-import org.opengis.filter.temporal.TOverlaps;
+import org.opengis.filter.*;
+import org.opengis.filter.capability.*;
+import org.opengis.filter.expression.*;
+import org.opengis.filter.identity.*;
+import org.opengis.filter.sort.*;
+import org.opengis.filter.spatial.*;
+import org.opengis.filter.temporal.*;
+import org.opengis.filter.capability.SpatialOperator; // Resolve
ambiguity with org.opengis.filter.spatial.
import org.opengis.geometry.Envelope;
import org.opengis.geometry.Geometry;
import org.opengis.util.GenericName;
@@ -95,7 +33,12 @@ import org.apache.sis.util.ArgumentCheck
/**
- * Default implementation of GeoAPI filter factory.
+ * Default implementation of GeoAPI filter factory for creation of {@link
Filter} and {@link Expression} instances.
+ *
+ * <div class="warning"><b>Warning:</b> most methods in this class are still
unimplemented.
+ * This is a very early draft subject to changes.
+ * <b>TODO: the API of this class needs severe revision! DO NOT RELEASE.</b>
+ * See <a href="https://github.com/opengeospatial/geoapi/issues/32">GeoAPI
issue #32</a>.</div>
*
* @author Johann Sorel (Geomatys)
* @version 1.0
@@ -103,13 +46,28 @@ import org.apache.sis.util.ArgumentCheck
* @module
*/
public class DefaultFilterFactory implements FilterFactory2 {
+ /**
+ * Creates a new factory.
+ */
public DefaultFilterFactory() {
}
// SPATIAL FILTERS
/////////////////////////////////////////////////////////
/**
- * {@inheritDoc }
+ * Creates an operator that evaluates to {@code true} when the bounding
box of the feature's geometry overlaps
+ * the given bounding box.
+ *
+ * @param propertyName name of geometry property (for a {@link
PropertyName} to access a feature's Geometry)
+ * @param minx minimum "x" value (for a literal envelope).
+ * @param miny minimum "y" value (for a literal envelope).
+ * @param maxx maximum "x" value (for a literal envelope).
+ * @param maxy maximum "y" value (for a literal envelope).
+ * @param srs identifier of the Coordinate Reference System to
use for a literal envelope.
+ * @return operator that evaluates to {@code true} when the bounding box
of the feature's geometry overlaps
+ * the bounding box provided in arguments to this method.
+ *
+ * @see #bbox(Expression, Envelope)
*/
@Override
public BBOX bbox(final String propertyName, final double minx,
@@ -138,7 +96,15 @@ public class DefaultFilterFactory implem
}
/**
- * {@inheritDoc }
+ * Creates an operator that checks if all of a feature's geometry is more
distant than the given distance
+ * from the given geometry.
+ *
+ * @param propertyName name of geometry property (for a {@link
PropertyName} to access a feature's Geometry).
+ * @param geometry the geometry from which to evaluate the distance.
+ * @param distance minimal distance for evaluating the expression as
{@code true}.
+ * @param units units of the given {@code distance}.
+ * @return operator that evaluates to {@code true} when all of a feature's
geometry is more distant than
+ * the given distance from the given geometry.
*/
@Override
public Beyond beyond(final String propertyName, final Geometry geometry,
@@ -404,6 +370,7 @@ public class DefaultFilterFactory implem
*/
@Override
public PropertyName property(final String name) {
+ ArgumentChecks.ensureNonNull("name", name);
return new DefaultPropertyName(name);
}
@@ -428,9 +395,13 @@ public class DefaultFilterFactory implem
* {@inheritDoc }
*/
@Override
- public PropertyIsEqualTo equal(final Expression expr1,
- final Expression expr2, final boolean matchCase, MatchAction
matchAction) {
- return new DefaultPropertyIsEqualTo(expr1, expr2, matchCase,
matchAction);
+ public PropertyIsEqualTo equal(final Expression expression1, final
Expression expression2,
+ final boolean matchCase, final MatchAction
matchAction)
+ {
+ ArgumentChecks.ensureNonNull("expression1", expression1);
+ ArgumentChecks.ensureNonNull("expression2", expression2);
+ ArgumentChecks.ensureNonNull("matchAction", matchAction);
+ return new DefaultPropertyIsEqualTo(expression1, expression2,
matchCase, matchAction);
}
/**
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyIsEqualTo.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyIsEqualTo.java?rev=1831086&r1=1831085&r2=1831086&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyIsEqualTo.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyIsEqualTo.java
[UTF-8] Mon May 7 10:43:29 2018
@@ -17,38 +17,76 @@
package org.apache.sis.filter;
import java.util.Objects;
+import org.apache.sis.util.Numbers;
import org.opengis.filter.FilterVisitor;
import org.opengis.filter.MatchAction;
import org.opengis.filter.PropertyIsEqualTo;
import org.opengis.filter.expression.Expression;
+
/**
- * Immutable PropertyIsEqualTo filter.
+ * Filter operator that compares that its two sub-expressions are equal to
each other.
*
- * @author Johann Sorel (Geomatys)
+ * @author Johann Sorel (Geomatys)
* @version 1.0
* @since 1.0
* @module
*/
final class DefaultPropertyIsEqualTo extends AbstractComparisonOperator
implements PropertyIsEqualTo {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = -5549267988142039640L;
+
+ /**
+ * Creates a new comparison operator.
+ * It is caller responsibility to ensure that no argument is null.
+ */
+ DefaultPropertyIsEqualTo(Expression expression1, Expression expression2,
boolean matchCase, MatchAction matchAction) {
+ super(expression1, expression2, matchCase, matchAction);
+ }
- DefaultPropertyIsEqualTo(Expression exp1, Expression exp2, boolean
matchCase, MatchAction matchAction) {
- super(exp1, exp2, matchCase, matchAction);
+ /**
+ * Returns the mathematical symbol for this comparison operator.
+ */
+ @Override
+ protected char symbol() {
+ return '=';
}
/**
- * {@inheritDoc }
+ * Determines if the test represented by this filter passed.
+ *
+ * @todo Use locale-sensitive {@link java.text.Collator} for string
comparisons.
*/
@Override
public boolean evaluate(Object object) {
final Object r1 = expression1.evaluate(object);
final Object r2 = expression2.evaluate(object);
- //TODO be more relax on equality testing, for example
Date,TimeStamp,Instant or numerics
- return Objects.equals(r1, r2);
+ if (Objects.equals(r1, r2)) {
+ return true;
+ } else if (r1 instanceof Number && r2 instanceof Number) {
+ @SuppressWarnings("unchecked") final Class<? extends Number> c1 =
(Class<? extends Number>) r1.getClass();
+ @SuppressWarnings("unchecked") final Class<? extends Number> c2 =
(Class<? extends Number>) r2.getClass();
+ if (c1 != c2) {
+ final Class<? extends Number> c = Numbers.widestClass(c1, c2);
+ return Numbers.cast((Number) r1, c).equals(
+ Numbers.cast((Number) r2, c));
+ }
+ } else if (r1 instanceof CharSequence && r2 instanceof CharSequence) {
+ final String s1 = r1.toString();
+ final String s2 = r2.toString();
+ if (!matchCase) {
+ return s1.equalsIgnoreCase(s2);
+ } else if (r1 != s1 || r2 != s2) {
+ return s1.equals(s2);
+ }
+ }
+ return false;
}
/**
- * {@inheritDoc }
+ * Accepts a visitor.
*/
@Override
public Object accept(FilterVisitor visitor, Object extraData) {
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyName.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyName.java?rev=1831086&r1=1831085&r2=1831086&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyName.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultPropertyName.java
[UTF-8] Mon May 7 10:43:29 2018
@@ -17,11 +17,12 @@
package org.apache.sis.filter;
import java.util.Map;
-import java.util.Objects;
import java.io.Serializable;
-import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.collection.BackingStoreException;
-import org.apache.sis.feature.builder.FeatureTypeBuilder;
+import org.apache.sis.util.Classes;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.feature.DefaultAssociationRole;
+
+import static java.util.Collections.singletonMap;
// Branch-dependent imports
import org.opengis.feature.Feature;
@@ -35,9 +36,9 @@ import org.opengis.filter.expression.Pro
/**
- * Immutable property name expression.
- * A property name does not store any value, it acts as an indirection to a
- * property value of the evaluated feature.
+ * Expression whose value is computed by retrieving the value indicated by the
provided name.
+ * A property name does not store any value; it acts as an indirection to a
property value of
+ * the evaluated feature.
*
* @author Johann Sorel (Geomatys)
* @version 1.0
@@ -50,56 +51,72 @@ final class DefaultPropertyName extends
*/
private static final long serialVersionUID = -8474562134021521300L;
- private final String property;
+ /**
+ * Name of the property from which to retrieve the value.
+ */
+ private final String name;
/**
+ * Creates a new expression retrieving values from a property of the given
name.
+ * It is caller responsibility to ensure that the given name is non-null.
*
- * @param property attribute name
+ * @param name name of the property (usually a feature attribute).
*/
- DefaultPropertyName(final String property) {
- ArgumentChecks.ensureNonNull("property", property);
- this.property = property;
+ DefaultPropertyName(final String name) {
+ this.name = name;
}
/**
- * {@inheritDoc }
+ * Returns the name of the property whose value will be returned by the
{@link #evaluate evaluate} method.
*/
@Override
public String getPropertyName() {
- return property;
+ return name;
}
/**
- * {@inheritDoc }
+ * Returns the value of the property of the given name.
+ * The {@code candidate} object can be any of the following type:
+ *
+ * <ul>
+ * <li>A {@link Feature}, in which case {@link
Feature#getPropertyValue(String)} will be invoked.</li>
+ * <li>A {@link Map}, in which case {@link Map#get(Object)} will be
invoked.</li>
+ * </ul>
+ *
+ * If no value is found for the given property, then this method returns
{@code null}.
*/
@Override
public Object evaluate(final Object candidate) {
if (candidate instanceof Feature) {
try {
- return ((Feature) candidate).getPropertyValue(property);
+ return ((Feature) candidate).getPropertyValue(name);
} catch (PropertyNotFoundException ex) {
- return null;
+ // Null will be returned below.
+ // TODO: report a warning somewhere?
}
} else if (candidate instanceof Map<?,?>) {
- return ((Map<?,?>) candidate).get(property);
+ return ((Map<?,?>) candidate).get(name);
}
return null;
}
/**
- * {@inheritDoc }
+ * Returns the expected type of values produced by this expression when a
feature of the given type is evaluated.
+ *
+ * @throws IllegalArgumentException if this method can not determine the
property type for the given feature type.
*/
@Override
- public PropertyType expectedType(FeatureType type) {
- PropertyType propertyType = type.getProperty(property);
+ public PropertyType expectedType(final FeatureType type) {
+ PropertyType propertyType = type.getProperty(name); // May
throw IllegalArgumentException.
while (propertyType instanceof Operation) {
- IdentifiedType it = ((Operation) propertyType).getResult();
- if (it instanceof FeatureType) {
- propertyType = new
FeatureTypeBuilder().addAssociation(type).setName(property).build();
- } else if (it instanceof PropertyType) {
+ final IdentifiedType it = ((Operation) propertyType).getResult();
+ if (it instanceof PropertyType) {
propertyType = (PropertyType) it;
+ } else if (it instanceof FeatureType) {
+ propertyType = new
DefaultAssociationRole(singletonMap(DefaultAssociationRole.NAME_KEY, name),
type, 1, 1);
} else {
- throw new BackingStoreException("Unexpected operation result
type "+it);
+ throw new
IllegalArgumentException(Errors.format(Errors.Keys.IllegalPropertyValueClass_3,
+ name, PropertyType.class,
Classes.getStandardType(Classes.getClass(it))));
}
}
return propertyType;
@@ -114,26 +131,26 @@ final class DefaultPropertyName extends
}
/**
- * Returns a hash-code value for this property.
+ * Returns a hash-code value for this expression.
*/
@Override
public boolean equals(final Object obj) {
- return (obj instanceof DefaultPropertyName) &&
property.equals(((DefaultPropertyName) obj).property);
+ return (obj instanceof DefaultPropertyName) &&
name.equals(((DefaultPropertyName) obj).name);
}
/**
- * Returns a hash-code value for this property.
+ * Returns a hash-code value for this expression.
*/
@Override
public int hashCode() {
- return Objects.hashCode(property) ^ (int) serialVersionUID;
+ return name.hashCode() ^ (int) serialVersionUID;
}
/**
- * Returns a string representation of this property.
+ * Returns a string representation of this expression.
*/
@Override
public String toString() {
- return '{' + property + '}';
+ return '{' + name + '}';
}
}
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java?rev=1831086&r1=1831085&r2=1831086&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/filter/package-info.java
[UTF-8] Mon May 7 10:43:29 2018
@@ -22,7 +22,10 @@
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
* @version 1.0
- * @since 1.0
+ *
+ * @see <a
href="http://docs.opengeospatial.org/is/09-026r2/09-026r2.html">OGC® Filter
Encoding 2.0 Encoding Standard</a>
+ *
+ * @since 1.0
* @module
*/
package org.apache.sis.filter;
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java?rev=1831086&r1=1831085&r2=1831086&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FeatureExpression.java
[UTF-8] Mon May 7 10:43:29 2018
@@ -40,6 +40,7 @@ public interface FeatureExpression {
*
* @param type the type of features on which to apply this expression.
* @return expected expression result type.
+ * @throws IllegalArgumentException if this method can not determine the
property type for the given feature type.
*/
PropertyType expectedType(FeatureType type);
}