You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2019/08/24 15:11:40 UTC
[sis] branch geoapi-4.0 updated: Initial implementation of
TemporalFunction.
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 86e4d51 Initial implementation of TemporalFunction.
86e4d51 is described below
commit 86e4d51108d70451178397e57db31ce2b2704d81
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Sat Aug 24 17:11:12 2019 +0200
Initial implementation of TemporalFunction.
---
.../org/apache/sis/filter/ArithmeticFunction.java | 16 +-
.../java/org/apache/sis/filter/BinaryFunction.java | 14 +
.../org/apache/sis/filter/ComparisonFunction.java | 50 +-
.../apache/sis/filter/DefaultFilterFactory.java | 6 +-
.../org/apache/sis/filter/TemporalFunction.java | 621 ++++++++++++++++-----
.../java/org/apache/sis/filter/PeriodLiteral.java | 116 ++++
.../apache/sis/filter/TemporalFunctionTest.java | 159 ++++--
7 files changed, 766 insertions(+), 216 deletions(-)
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/ArithmeticFunction.java b/core/sis-feature/src/main/java/org/apache/sis/filter/ArithmeticFunction.java
index 3a5705b..f998ddf 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/ArithmeticFunction.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/ArithmeticFunction.java
@@ -133,7 +133,7 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
* The "Add" (+) expression.
*/
static final class Add extends ArithmeticFunction implements org.opengis.filter.expression.Add {
- /** For cross-version compatibility. */
+ /** For cross-version compatibility during (de)serialization. */
private static final long serialVersionUID = 5445433312445869201L;
/** Description of results of the {@value #NAME} expression. */
@@ -156,7 +156,7 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
@Override protected Number applyAsInteger (BigInteger left, BigInteger right) {return left.add(right);}
@Override protected Number applyAsLong (long left, long right) {return Math.addExact(left, right);}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(ExpressionVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
@@ -167,7 +167,7 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
* The "Sub" (−) expression.
*/
static final class Subtract extends ArithmeticFunction implements org.opengis.filter.expression.Subtract {
- /** For cross-version compatibility. */
+ /** For cross-version compatibility during (de)serialization. */
private static final long serialVersionUID = 3048878022726271508L;
/** Description of results of the {@value #NAME} expression. */
@@ -190,7 +190,7 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
@Override protected Number applyAsInteger (BigInteger left, BigInteger right) {return left.subtract(right);}
@Override protected Number applyAsLong (long left, long right) {return Math.subtractExact(left, right);}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(ExpressionVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
@@ -201,7 +201,7 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
* The "Mul" (×) expression.
*/
static final class Multiply extends ArithmeticFunction implements org.opengis.filter.expression.Multiply {
- /** For cross-version compatibility. */
+ /** For cross-version compatibility during (de)serialization. */
private static final long serialVersionUID = -1300022614832645625L;
/** Description of results of the {@value #NAME} expression. */
@@ -224,7 +224,7 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
@Override protected Number applyAsInteger (BigInteger left, BigInteger right) {return left.multiply(right);}
@Override protected Number applyAsLong (long left, long right) {return Math.multiplyExact(left, right);}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(ExpressionVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
@@ -235,7 +235,7 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
* The "Div" (÷) expression.
*/
static final class Divide extends ArithmeticFunction implements org.opengis.filter.expression.Divide {
- /** For cross-version compatibility. */
+ /** For cross-version compatibility during (de)serialization. */
private static final long serialVersionUID = -7709291845568648891L;
/** Description of results of the {@value #NAME} expression. */
@@ -273,7 +273,7 @@ abstract class ArithmeticFunction extends BinaryFunction implements BinaryExpres
}
}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(ExpressionVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/BinaryFunction.java b/core/sis-feature/src/main/java/org/apache/sis/filter/BinaryFunction.java
index d0e0b12..943f5c5 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/BinaryFunction.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/BinaryFunction.java
@@ -77,6 +77,9 @@ abstract class BinaryFunction extends Node {
/**
* Returns the first of the two expressions to be used by this function.
* This is the value specified at construction time.
+ *
+ * @see org.opengis.filter.BinaryComparisonOperator#getExpression1()
+ * @see org.opengis.filter.temporal.BinaryTemporalOperator#getExpression1()
*/
public final Expression getExpression1() {
return expression1;
@@ -85,6 +88,9 @@ abstract class BinaryFunction extends Node {
/**
* Returns the second of the two expressions to be used by this function.
* This is the value specified at construction time.
+ *
+ * @see org.opengis.filter.BinaryComparisonOperator#getExpression1()
+ * @see org.opengis.filter.temporal.BinaryTemporalOperator#getExpression2()
*/
public final Expression getExpression2() {
return expression2;
@@ -102,10 +108,13 @@ abstract class BinaryFunction extends Node {
/**
* Evaluates the expression for producing a result of numeric type.
* This method delegates to one of the {@code applyAs(…)} methods.
+ * If no {@code applyAs(…)} implementations can return null values,
+ * this this method never return {@code null}.
*
* @param left the left operand. Can not be null.
* @param right the right operand. Can not be null.
* @return result of this function applied on the two given operands.
+ * May be {@code null} only if an {@code applyAs(…)} implementation returned a null value.
* @throws ArithmeticException if the operation overflows the capacity of the type used.
*/
protected final Number apply(final Number left, final Number right) {
@@ -139,6 +148,7 @@ abstract class BinaryFunction extends Node {
* Calculates this function using given operands of {@code long} primitive type. If this function is a
* filter, then this method should returns an {@link Integer} value 0 or 1 for false or true respectively.
* Otherwise the result is usually a {@link Long}, except for division which may produce a floating point number.
+ * This method may return {@code null} if the operation can not apply on numbers.
*
* @throws ArithmeticException if the operation overflows the 64 bits integer capacity.
*/
@@ -148,6 +158,7 @@ abstract class BinaryFunction extends Node {
* Calculates this function using given operands of {@code double} primitive type. If this function is a
* filter, then this method should returns an {@link Integer} value 0 or 1 for false or true respectively.
* Otherwise the result is usually a {@link Double}.
+ * This method may return {@code null} if the operation can not apply on numbers.
*/
protected abstract Number applyAsDouble(double left, double right);
@@ -155,6 +166,7 @@ abstract class BinaryFunction extends Node {
* Calculates this function using given operands of {@code Fraction} type. If this function is a filter,
* then this method should returns an {@link Integer} value 0 or 1 for false or true respectively.
* Otherwise the result is usually a {@link Fraction}.
+ * This method may return {@code null} if the operation can not apply on numbers.
*/
protected abstract Number applyAsFraction(Fraction left, Fraction right);
@@ -162,6 +174,7 @@ abstract class BinaryFunction extends Node {
* Calculates this function using given operands of {@code BigInteger} type. If this function is a filter,
* then this method should returns an {@link Integer} value 0 or 1 for false or true respectively.
* Otherwise the result is usually a {@link BigInteger}.
+ * This method may return {@code null} if the operation can not apply on numbers.
*/
protected abstract Number applyAsInteger(BigInteger left, BigInteger right);
@@ -169,6 +182,7 @@ abstract class BinaryFunction extends Node {
* Calculates this function using given operands of {@code BigDecimal} type. If this function is a filter,
* then this method should returns an {@link Integer} value 0 or 1 for false or true respectively.
* Otherwise the result is usually a {@link BigDecimal}.
+ * This method may return {@code null} if the operation can not apply on numbers.
*/
protected abstract Number applyAsDecimal(BigDecimal left, BigDecimal right);
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/ComparisonFunction.java b/core/sis-feature/src/main/java/org/apache/sis/filter/ComparisonFunction.java
index 9e2f78e..dcfccfd 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/ComparisonFunction.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/ComparisonFunction.java
@@ -333,7 +333,7 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
* This method handles a few types from the {@link java.time} package and legacy types like
* {@link Date} (with a special case for SQL dates) and {@link Calendar}.
*/
- private static Instant toInstant(final Object value) {
+ static Instant toInstant(final Object value) {
if (value instanceof Instant) {
return (Instant) value;
} else if (value instanceof OffsetDateTime) {
@@ -503,13 +503,13 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
/**
- * The "LessThan" {@literal (<)} expression.
+ * The {@value #NAME} {@literal (<)} filter.
*/
static final class LessThan extends ComparisonFunction implements org.opengis.filter.PropertyIsLessThan {
- /** For cross-version compatibility. */
+ /** For cross-version compatibility during (de)serialization. */
private static final long serialVersionUID = 6126039112844823196L;
- /** Creates a new expression for the {@value #NAME} operation. */
+ /** Creates a new filter for the {@value #NAME} operation. */
LessThan(Expression expression1, Expression expression2, boolean isMatchingCase, MatchAction matchAction) {
super(expression1, expression2, isMatchingCase, matchAction);
}
@@ -530,7 +530,7 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
@Override protected boolean compare (ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right) {return left.isBefore(right);}
@Override protected boolean compare (ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right) {return left.isBefore(right);}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
@@ -538,13 +538,13 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
/**
- * The "LessThanOrEqualTo" (≤) expression.
+ * The {@value #NAME} (≤) filter.
*/
static final class LessThanOrEqualTo extends ComparisonFunction implements org.opengis.filter.PropertyIsLessThanOrEqualTo {
- /** For cross-version compatibility. */
+ /** For cross-version compatibility during (de)serialization. */
private static final long serialVersionUID = 6357459227911760871L;
- /** Creates a new expression for the {@value #NAME} operation. */
+ /** Creates a new filter for the {@value #NAME} operation. */
LessThanOrEqualTo(Expression expression1, Expression expression2, boolean isMatchingCase, MatchAction matchAction) {
super(expression1, expression2, isMatchingCase, matchAction);
}
@@ -565,7 +565,7 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
@Override protected boolean compare (ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right) {return !left.isAfter(right);}
@Override protected boolean compare (ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right) {return !left.isAfter(right);}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
@@ -573,13 +573,13 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
/**
- * The "GreaterThan" {@literal (>)} expression.
+ * The {@value #NAME} {@literal (>)} filter.
*/
static final class GreaterThan extends ComparisonFunction implements org.opengis.filter.PropertyIsGreaterThan {
- /** For cross-version compatibility. */
+ /** For cross-version compatibility during (de)serialization. */
private static final long serialVersionUID = 8605517892232632586L;
- /** Creates a new expression for the {@value #NAME} operation. */
+ /** Creates a new filter for the {@value #NAME} operation. */
GreaterThan(Expression expression1, Expression expression2, boolean isMatchingCase, MatchAction matchAction) {
super(expression1, expression2, isMatchingCase, matchAction);
}
@@ -600,7 +600,7 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
@Override protected boolean compare (ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right) {return left.isAfter(right);}
@Override protected boolean compare (ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right) {return left.isAfter(right);}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
@@ -608,13 +608,13 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
/**
- * The "GreaterThanOrEqualTo" (≥) expression.
+ * The {@value #NAME} (≥) filter.
*/
static final class GreaterThanOrEqualTo extends ComparisonFunction implements org.opengis.filter.PropertyIsGreaterThanOrEqualTo {
- /** For cross-version compatibility. */
+ /** For cross-version compatibility during (de)serialization. */
private static final long serialVersionUID = 1514185657159141882L;
- /** Creates a new expression for the {@value #NAME} operation. */
+ /** Creates a new filter for the {@value #NAME} operation. */
GreaterThanOrEqualTo(Expression expression1, Expression expression2, boolean isMatchingCase, MatchAction matchAction) {
super(expression1, expression2, isMatchingCase, matchAction);
}
@@ -635,7 +635,7 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
@Override protected boolean compare (ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right) {return !left.isBefore(right);}
@Override protected boolean compare (ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right) {return !left.isBefore(right);}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
@@ -643,13 +643,13 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
/**
- * The "EqualTo" (=) expression.
+ * The {@value #NAME} (=) filter.
*/
static final class EqualTo extends ComparisonFunction implements org.opengis.filter.PropertyIsEqualTo {
- /** For cross-version compatibility. */
+ /** For cross-version compatibility during (de)serialization. */
private static final long serialVersionUID = 8502612221498749667L;
- /** Creates a new expression for the {@value #NAME} operation. */
+ /** Creates a new filter for the {@value #NAME} operation. */
EqualTo(Expression expression1, Expression expression2, boolean isMatchingCase, MatchAction matchAction) {
super(expression1, expression2, isMatchingCase, matchAction);
}
@@ -670,7 +670,7 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
@Override protected boolean compare (ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right) {return left.isEqual(right);}
@Override protected boolean compare (ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right) {return left.isEqual(right);}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
@@ -678,13 +678,13 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
/**
- * The "NotEqualTo" (≠) expression.
+ * The {@value #NAME} (≠) filter.
*/
static final class NotEqualTo extends ComparisonFunction implements org.opengis.filter.PropertyIsNotEqualTo {
- /** For cross-version compatibility. */
+ /** For cross-version compatibility during (de)serialization. */
private static final long serialVersionUID = -3295957142249035362L;
- /** Creates a new expression for the {@value #NAME} operation. */
+ /** Creates a new filter for the {@value #NAME} operation. */
NotEqualTo(Expression expression1, Expression expression2, boolean isMatchingCase, MatchAction matchAction) {
super(expression1, expression2, isMatchingCase, matchAction);
}
@@ -705,7 +705,7 @@ abstract class ComparisonFunction extends BinaryFunction implements BinaryCompar
@Override protected boolean compare (ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right) {return !left.isEqual(right);}
@Override protected boolean compare (ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right) {return !left.isEqual(right);}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java b/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
index ea6422d..94a1cb4 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/DefaultFilterFactory.java
@@ -652,7 +652,7 @@ public class DefaultFilterFactory implements FilterFactory2 {
*/
@Override
public TContains tcontains(Expression expression1, Expression expression2) {
- return new TemporalFunction.TContains(expression1, expression2);
+ return new TemporalFunction.Contains(expression1, expression2);
}
/**
@@ -660,7 +660,7 @@ public class DefaultFilterFactory implements FilterFactory2 {
*/
@Override
public TEquals tequals(Expression expression1, Expression expression2) {
- return new TemporalFunction.TEquals(expression1, expression2);
+ return new TemporalFunction.Equals(expression1, expression2);
}
/**
@@ -668,7 +668,7 @@ public class DefaultFilterFactory implements FilterFactory2 {
*/
@Override
public TOverlaps toverlaps(Expression expression1, Expression expression2) {
- return new TemporalFunction.TOverlaps(expression1, expression2);
+ return new TemporalFunction.Overlaps(expression1, expression2);
}
// EXPRESSIONS /////////////////////////////////////////////////////////////
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/TemporalFunction.java b/core/sis-feature/src/main/java/org/apache/sis/filter/TemporalFunction.java
index 394f1c8..4aef3b1 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/TemporalFunction.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/TemporalFunction.java
@@ -16,15 +16,28 @@
*/
package org.apache.sis.filter;
-import org.apache.sis.util.ArgumentChecks;
-import org.opengis.filter.Filter;
+import java.util.Date;
+import java.time.Instant;
+import java.math.BigDecimal;
+import java.math.BigInteger;
import org.opengis.filter.FilterVisitor;
import org.opengis.filter.expression.Expression;
+import org.opengis.filter.temporal.BinaryTemporalOperator;
+import org.opengis.temporal.Period;
+import org.apache.sis.math.Fraction;
+
/**
- * Temporal operations between two time values.
+ * Temporal operations between a period and an instant.
* The nature of the operation depends on the subclass.
+ * Subclasses shall override at least one of following methods:
+ *
+ * <ul>
+ * <li>{@link #evaluate(Instant, Instant)}</li>
+ * <li>{@link #evaluate(Period, Instant)}</li>
+ * <li>{@link #evaluate(Period, Period)}</li>
+ * </ul>
*
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
@@ -32,340 +45,676 @@ import org.opengis.filter.expression.Expression;
* @since 1.0
* @module
*/
-abstract class TemporalFunction implements Filter {
+abstract class TemporalFunction extends BinaryFunction implements BinaryTemporalOperator {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = 5392780837658687513L;
/**
- * The first of the two expressions to be used by this function.
+ * Creates a new temporal function.
*
- * @see #getExpression1()
+ * @param expression1 the first of the two expressions to be used by this function.
+ * @param expression2 the second of the two expressions to be used by this function.
*/
- protected final Expression expression1;
+ TemporalFunction(final Expression expression1, final Expression expression2) {
+ super(expression1, expression2);
+ }
/**
- * The second of the two expressions to be used by this function.
+ * Converts a GeoAPI instant to a Java instant. This is a temporary method
+ * to be removed after we revisited {@link org.opengis.temporal} package.
*
- * @see #getExpression2()
+ * @param instant the GeoAPI instant, or {@code null}.
+ * @return the Java instant, or {@code null}.
*/
- protected final Expression expression2;
+ private static Instant toInstant(final org.opengis.temporal.Instant instant) {
+ if (instant != null) {
+ final Date t = instant.getDate();
+ if (t != null) {
+ return t.toInstant();
+ }
+ }
+ return null;
+ }
/**
- * Creates a new temporal function.
- *
- * @param expression1 the first of the two expressions to be used by this function.
- * @param expression2 the second of the two expressions to be used by this function.
+ * Returns {@code true} if {@code self} is non null and before {@code other}.
+ * This is an helper function for {@code evaluate(…)} methods implementations.
*/
- TemporalFunction(final Expression expression1, final Expression expression2) {
- ArgumentChecks.ensureNonNull("expression1", expression1);
- ArgumentChecks.ensureNonNull("expression2", expression2);
- this.expression1 = expression1;
- this.expression2 = expression2;
+ private static boolean isBefore(final org.opengis.temporal.Instant self, final Instant other) {
+ final Instant t = toInstant(self);
+ return (t != null) && t.isBefore(other);
}
/**
- * Returns the first of the two expressions to be used by this function.
- * This is the value specified at construction time.
+ * Returns {@code true} if {@code self} is non null and after {@code other}.
+ * This is an helper function for {@code evaluate(…)} methods implementations.
*/
- public final Expression getExpression1() {
- return expression1;
+ private static boolean isAfter(final org.opengis.temporal.Instant self, final Instant other) {
+ final Instant t = toInstant(self);
+ return (t != null) && t.isAfter(other);
}
/**
- * Returns the second of the two expressions to be used by this function.
- * This is the value specified at construction time.
+ * Returns {@code true} if {@code self} is non null and equal to {@code other}.
+ * This is an helper function for {@code evaluate(…)} methods implementations.
*/
- public final Expression getExpression2() {
- return expression2;
+ private static boolean isEqual(final org.opengis.temporal.Instant self, final Instant other) {
+ final Instant t = toInstant(self);
+ return (t != null) && t.equals(other);
}
/**
- * The "After" filter.
+ * Returns {@code true} if {@code self} is non null and before {@code other}.
+ * This is an helper function for {@code evaluate(…)} methods implementations.
*/
- static final class After extends TemporalFunction implements org.opengis.filter.temporal.After {
+ private static boolean isBefore(final org.opengis.temporal.Instant self,
+ final org.opengis.temporal.Instant other)
+ {
+ final Instant t, o;
+ return ((t = toInstant(self)) != null) && ((o = toInstant(other)) != null) && t.isBefore(o);
+ }
- /** Creates a new expression for the {@value #NAME} operation. */
- After(Expression expression1, Expression expression2) {
+ /**
+ * Returns {@code true} if {@code self} is non null and after {@code other}.
+ * This is an helper function for {@code evaluate(…)} methods implementations.
+ */
+ private static boolean isAfter(final org.opengis.temporal.Instant self,
+ final org.opengis.temporal.Instant other)
+ {
+ final Instant t, o;
+ return ((t = toInstant(self)) != null) && ((o = toInstant(other)) != null) && t.isAfter(o);
+ }
+
+ /**
+ * Returns {@code true} if {@code self} is non null and equal to {@code other}.
+ * This is an helper function for {@code evaluate(…)} methods implementations.
+ */
+ private static boolean isEqual(final org.opengis.temporal.Instant self,
+ final org.opengis.temporal.Instant other)
+ {
+ final Instant t = toInstant(self);
+ return (t != null) && t.equals(toInstant(other));
+ }
+
+ /**
+ * Determines if the test(s) represented by this filter passes with the given operands.
+ * Values of {@link #expression1} and {@link #expression2} shall be two single values.
+ */
+ @Override
+ public final boolean evaluate(final Object candidate) {
+ final Object left = expression1.evaluate(candidate);
+ if (left instanceof Period) {
+ final Object right = expression2.evaluate(candidate);
+ if (right instanceof Period) {
+ return evaluate((Period) left, (Period) right);
+ }
+ final Instant t = ComparisonFunction.toInstant(right);
+ if (t != null) {
+ return evaluate((Period) left, t);
+ }
+ } else {
+ final Instant t = ComparisonFunction.toInstant(left);
+ if (t != null) {
+ final Instant t2 = ComparisonFunction.toInstant(expression2.evaluate(candidate));
+ if (t2 != null) {
+ return evaluate(t, t2);
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Evaluates the filter between two instants.
+ * Both arguments given to this method are non-null.
+ * The {@code self} and {@code other} argument names are chosen to match ISO 19108 tables.
+ */
+ protected boolean evaluate(Instant self, Instant other) {
+ return false;
+ }
+
+ /**
+ * Evaluates the filter between a period and an instant.
+ * Both arguments given to this method are non-null, but period begin or end instant may be null.
+ * The {@code self} and {@code other} argument names are chosen to match ISO 19108 tables.
+ */
+ protected boolean evaluate(Period self, Instant other) {
+ return false;
+ }
+
+ /**
+ * Evaluates the filter between two periods.
+ * Both arguments given to this method are non-null, but period begin or end instant may be null.
+ * The {@code self} and {@code other} argument names are chosen to match ISO 19108 tables.
+ */
+ protected boolean evaluate(Period self, Period other) {
+ return false;
+ }
+
+ /**
+ * No operation on numbers for now. We could revisit this policy in a future version if we
+ * allow the temporal function to have a CRS and to operate on temporal coordinate values.
+ */
+ @Override protected Number applyAsLong (long left, long right) {return null;}
+ @Override protected Number applyAsDouble (double left, double right) {return null;}
+ @Override protected Number applyAsFraction(Fraction left, Fraction right) {return null;}
+ @Override protected Number applyAsInteger (BigInteger left, BigInteger right) {return null;}
+ @Override protected Number applyAsDecimal (BigDecimal left, BigDecimal right) {return null;}
+
+
+ /**
+ * The {@value #NAME} (=) filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self = other}</li>
+ * <li>{@literal self.begin = other.begin AND self.end = other.end}</li>
+ * </ul>
+ */
+ static final class Equals extends TemporalFunction implements org.opengis.filter.temporal.TEquals {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -6060822291802339424L;
+
+ /** Creates a new filter for the {@value #NAME} operation. */
+ Equals(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+ @Override protected char symbol() {return '=';}
+
+ /** Condition defined by ISO 19108:2002 §5.2.3.5. */
+ @Override protected boolean evaluate(final Instant self, final Instant other) {
+ return self.equals(other);
+ }
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(final Period self, final Instant other) {
+ return isEqual(self.getBeginning(), other) &&
+ isEqual(self.getEnding(), other);
}
- /** Implementation of the visitor pattern. */
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return isEqual(self.getBeginning(), other.getBeginning()) &&
+ isEqual(self.getEnding(), other.getEnding());
+ }
+
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
}
+
/**
- * The "AnyInteracts" filter.
+ * The {@value #NAME} {@literal (<)} filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self < other}</li>
+ * <li>{@literal self.end < other}</li>
+ * <li>{@literal self.end < other.begin}</li>
+ * </ul>
*/
- static final class AnyInteracts extends TemporalFunction implements org.opengis.filter.temporal.AnyInteracts {
+ static final class Before extends TemporalFunction implements org.opengis.filter.temporal.Before {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -3422629447456003982L;
- /** Creates a new expression for the {@value #NAME} operation. */
- AnyInteracts(Expression expression1, Expression expression2) {
+ /** Creates a new filter for the {@value #NAME} operation. */
+ Before(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+ @Override protected char symbol() {return '<';}
+
+ /** Condition defined by ISO 19108:2002 §5.2.3.5. */
+ @Override protected boolean evaluate(final Instant self, final Instant other) {
+ return self.isBefore(other);
}
- /** Implementation of the visitor pattern. */
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Instant other) {
+ return isBefore(self.getEnding(), other);
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return isBefore(self.getEnding(), other.getBeginning());
+ }
+
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
}
+
/**
- * The "Before" filter.
+ * The {@value #NAME} {@literal (>)} filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self > other}</li>
+ * <li>{@literal self.begin > other}</li>
+ * <li>{@literal self.begin > other.end}</li>
+ * </ul>
*/
- static final class Before extends TemporalFunction implements org.opengis.filter.temporal.Before {
+ static final class After extends TemporalFunction implements org.opengis.filter.temporal.After {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 5410476260417497682L;
- /** Creates a new expression for the {@value #NAME} operation. */
- Before(Expression expression1, Expression expression2) {
+ /** Creates a new filter for the {@value #NAME} operation. */
+ After(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+ @Override protected char symbol() {return '>';}
+
+ /** Condition defined by ISO 19108:2002 §5.2.3.5. */
+ @Override protected boolean evaluate(final Instant self, final Instant other) {
+ return self.isAfter(other);
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Instant other) {
+ return isAfter(self.getBeginning(), other);
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return isAfter(self.getBeginning(), other.getEnding());
}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
}
+
/**
- * The "Begins" filter.
+ * The {@value #NAME} filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin = other.begin AND self.end < other.end}</li>
+ * </ul>
*/
static final class Begins extends TemporalFunction implements org.opengis.filter.temporal.Begins {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -7880699329127762233L;
- /** Creates a new expression for the {@value #NAME} operation. */
+ /** Creates a new filter for the {@value #NAME} operation. */
Begins(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return isEqual (self.getBeginning(), other.getBeginning()) &&
+ isBefore(self.getEnding(), other.getEnding());
}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
}
+
/**
- * The "BegunBy" filter.
+ * The {@value #NAME} filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin > other.begin AND self.end = other.end}</li>
+ * </ul>
*/
- static final class BegunBy extends TemporalFunction implements org.opengis.filter.temporal.BegunBy {
+ static final class Ends extends TemporalFunction implements org.opengis.filter.temporal.Ends {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -5508229966320563437L;
- /** Creates a new expression for the {@value #NAME} operation. */
- BegunBy(Expression expression1, Expression expression2) {
+ /** Creates a new filter for the {@value #NAME} operation. */
+ Ends(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return isEqual(self.getEnding(), other.getEnding()) &&
+ isAfter(self.getBeginning(), other.getBeginning());
}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
}
+
/**
- * The "During" filter.
+ * The {@value #NAME} filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin = other}</li>
+ * <li>{@literal self.begin = other.begin AND self.end > other.end}</li>
+ * </ul>
*/
- static final class During extends TemporalFunction implements org.opengis.filter.temporal.During {
+ static final class BegunBy extends TemporalFunction implements org.opengis.filter.temporal.BegunBy {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -7212413827394364384L;
- /** Creates a new expression for the {@value #NAME} operation. */
- During(Expression expression1, Expression expression2) {
+ /** Creates a new filter for the {@value #NAME} operation. */
+ BegunBy(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Instant other) {
+ return isEqual(self.getBeginning(), other);
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return isEqual(self.getBeginning(), other.getBeginning()) &&
+ isAfter(self.getEnding(), other.getEnding());
}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
}
+
/**
- * The "EndedBy" filter.
+ * The {@value #NAME} filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.end = other}</li>
+ * <li>{@literal self.begin < other.begin AND self.end = other.end}</li>
+ * </ul>
*/
static final class EndedBy extends TemporalFunction implements org.opengis.filter.temporal.EndedBy {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 8586566103462153666L;
- /** Creates a new expression for the {@value #NAME} operation. */
+ /** Creates a new filter for the {@value #NAME} operation. */
EndedBy(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Instant other) {
+ return isEqual(self.getEnding(), other);
}
- /** Implementation of the visitor pattern. */
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return isEqual (self.getEnding(), other.getEnding()) &&
+ isBefore(self.getBeginning(), other.getBeginning());
+ }
+
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
}
+
/**
- * The "Ends" filter.
+ * The {@value #NAME} filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.end = other.begin}</li>
+ * </ul>
*/
- static final class Ends extends TemporalFunction implements org.opengis.filter.temporal.Ends {
+ static final class Meets extends TemporalFunction implements org.opengis.filter.temporal.Meets {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -3534843269384858443L;
- /** Creates a new expression for the {@value #NAME} operation. */
- Ends(Expression expression1, Expression expression2) {
+ /** Creates a new filter for the {@value #NAME} operation. */
+ Meets(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(final Instant self, final Instant other) {
+ return self.equals(other);
+ }
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(final Period self, final Instant other) {
+ return isEqual(self.getEnding(), other);
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return isEqual(self.getEnding(), other.getBeginning());
}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
}
+
/**
- * The "Meets" filter.
+ * The {@value #NAME} filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin = other.end}</li>
+ * </ul>
*/
- static final class Meets extends TemporalFunction implements org.opengis.filter.temporal.Meets {
+ static final class MetBy extends TemporalFunction implements org.opengis.filter.temporal.MetBy {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 5358059498707330482L;
- /** Creates a new expression for the {@value #NAME} operation. */
- Meets(Expression expression1, Expression expression2) {
+ /** Creates a new filter for the {@value #NAME} operation. */
+ MetBy(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(final Instant self, final Instant other) {
+ return self.equals(other);
+ }
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(final Period self, final Instant other) {
+ return isEqual(self.getBeginning(), other);
}
- /** Implementation of the visitor pattern. */
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return isEqual(self.getBeginning(), other.getEnding());
+ }
+
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
}
+
/**
- * The "MetBy" filter.
+ * The {@value #NAME} filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin > other.begin AND self.end < other.end}</li>
+ * </ul>
*/
- static final class MetBy extends TemporalFunction implements org.opengis.filter.temporal.MetBy {
+ static final class During extends TemporalFunction implements org.opengis.filter.temporal.During {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -4674319635076886196L;
- /** Creates a new expression for the {@value #NAME} operation. */
- MetBy(Expression expression1, Expression expression2) {
+ /** Creates a new filter for the {@value #NAME} operation. */
+ During(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+ @Override protected char symbol() {return '⊊';} // `self` is a proper (or strict) subset of `other`.
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return isAfter (self.getBeginning(), other.getBeginning()) &&
+ isBefore(self.getEnding(), other.getEnding());
}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
}
+
/**
- * The "OverlappedBy" filter.
+ * The {@value #NAME} filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin < other AND self.end > other}</li>
+ * <li>{@literal self.begin < other.begin AND self.end > other.end}</li>
+ * </ul>
*/
- static final class OverlappedBy extends TemporalFunction implements org.opengis.filter.temporal.OverlappedBy {
+ static final class Contains extends TemporalFunction implements org.opengis.filter.temporal.TContains {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 9107531246948034411L;
- /** Creates a new expression for the {@value #NAME} operation. */
- OverlappedBy(Expression expression1, Expression expression2) {
+ /** Creates a new filter for the {@value #NAME} operation. */
+ Contains(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+ @Override protected char symbol() {return '⊋';} // `self` is a proper (or strict) superset of `other`.
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Instant other) {
+ return isBefore(self.getBeginning(), other) &&
+ isAfter (self.getEnding(), other);
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return isBefore(self.getBeginning(), other.getBeginning()) &&
+ isAfter (self.getEnding(), other.getEnding());
}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
}
+
/**
- * The "TContains" filter.
+ * The {@value #NAME} filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin < other.begin AND self.end > other.begin AND self.end < other.end}</li>
+ * </ul>
*/
- static final class TContains extends TemporalFunction implements org.opengis.filter.temporal.TContains {
+ static final class Overlaps extends TemporalFunction implements org.opengis.filter.temporal.TOverlaps {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 1517443045593389773L;
- /** Creates a new expression for the {@value #NAME} operation. */
- TContains(Expression expression1, Expression expression2) {
+ /** Creates a new filter for the {@value #NAME} operation. */
+ Overlaps(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ final Instant selfEnd, otherBegin;
+ return ((selfEnd = toInstant(self .getEnding())) != null) &&
+ ((otherBegin = toInstant(other.getBeginning())) != null) && selfEnd.isAfter(otherBegin) &&
+ isBefore(self.getBeginning(), otherBegin) &&
+ isAfter(other.getEnding(), selfEnd);
}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
}
+
/**
- * The "TEquals" filter.
+ * The {@value #NAME} filter. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin > other.begin AND self.begin < other.end AND self.end > other.end}</li>
+ * </ul>
*/
- static final class TEquals extends TemporalFunction implements org.opengis.filter.temporal.TEquals {
+ static final class OverlappedBy extends TemporalFunction implements org.opengis.filter.temporal.OverlappedBy {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 2228673820507226463L;
- /** Creates a new expression for the {@value #NAME} operation. */
- TEquals(Expression expression1, Expression expression2) {
+ /** Creates a new filter for the {@value #NAME} operation. */
+ OverlappedBy(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
- }
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ final Instant selfBegin, otherEnd;
+ return ((selfBegin = toInstant(self .getBeginning())) != null) &&
+ ((otherEnd = toInstant(other.getEnding())) != null) && selfBegin.isBefore(otherEnd) &&
+ isBefore(other.getBeginning(), selfBegin) &&
+ isAfter (self .getEnding(), otherEnd);
+ }
}
+
/**
- * The "TOverlaps" filter.
+ * The {@value #NAME} filter.
+ * This is a shortcut for NOT (Before OR Meets OR MetBy OR After).
*/
- static final class TOverlaps extends TemporalFunction implements org.opengis.filter.temporal.TOverlaps {
+ static final class AnyInteracts extends TemporalFunction implements org.opengis.filter.temporal.AnyInteracts {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 5972351564286442392L;
- /** Creates a new expression for the {@value #NAME} operation. */
- TOverlaps(Expression expression1, Expression expression2) {
+ /** Creates a new filter for the {@value #NAME} operation. */
+ AnyInteracts(Expression expression1, Expression expression2) {
super(expression1, expression2);
}
- @Override
- public boolean evaluate(Object object) {
- throw new UnsupportedOperationException("Not supported yet.");
+ /** Identification of this operation. */
+ @Override protected String getName() {return NAME;}
+
+ /** Condition defined by OGC filter specification. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ final Instant selfBegin, selfEnd, otherBegin, otherEnd;
+ return ((selfBegin = toInstant(self .getBeginning())) != null) &&
+ ((otherEnd = toInstant(other.getEnding())) != null) && selfBegin.isBefore(otherEnd) &&
+ ((selfEnd = toInstant(self .getEnding())) != null) &&
+ ((otherBegin = toInstant(other.getBeginning())) != null) && selfEnd.isAfter(otherBegin);
}
- /** Implementation of the visitor pattern. */
+ /** Implementation of the visitor pattern (not used by Apache SIS). */
@Override public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
diff --git a/core/sis-feature/src/test/java/org/apache/sis/filter/PeriodLiteral.java b/core/sis-feature/src/test/java/org/apache/sis/filter/PeriodLiteral.java
new file mode 100644
index 0000000..e626ff2
--- /dev/null
+++ b/core/sis-feature/src/test/java/org/apache/sis/filter/PeriodLiteral.java
@@ -0,0 +1,116 @@
+/*
+ * 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 java.util.Date;
+import java.util.Objects;
+import java.io.Serializable;
+import org.opengis.temporal.Period;
+import org.opengis.temporal.Duration;
+import org.opengis.temporal.RelativePosition;
+import org.opengis.temporal.TemporalPosition;
+import org.opengis.temporal.TemporalPrimitive;
+import org.opengis.temporal.TemporalGeometricPrimitive;
+import org.opengis.filter.expression.Literal;
+import org.opengis.filter.expression.ExpressionVisitor;
+import org.opengis.metadata.Identifier;
+import org.apache.sis.test.TestUtilities;
+
+
+/**
+ * A literal expression which returns a period computed from {@link #begin} and {@link #end} fields.
+ * This is used for testing purpose only.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since 1.0
+ * @module
+ */
+@SuppressWarnings("serial")
+final strictfp class PeriodLiteral implements Period, Literal, Serializable {
+ /**
+ * Period beginning and ending.
+ * Pattern is {@code "yyyy-MM-dd HH:mm:ss"} in UTC timezone.
+ */
+ public String begin, end;
+
+ /**
+ * Returns the constant value held by this object.
+ * Returns value should be interpreted as a {@link Period}.
+ */
+ @Override public Object getValue() {return this;}
+ @Override public Object evaluate(Object o) {return this;}
+ @Override public <T> T evaluate(Object o, Class<T> c) {return c.cast(this);}
+
+ /** Implements the visitor pattern (not used by Apache SIS). */
+ @Override public Object accept(ExpressionVisitor visitor, Object extraData) {
+ return visitor.visit(this, extraData);
+ }
+
+ /** Returns a bound of this period. */
+ @Override public org.opengis.temporal.Instant getBeginning() {return instant(begin);}
+ @Override public org.opengis.temporal.Instant getEnding() {return instant(end);}
+
+ /** Wraps the value that defines a period. */
+ private static org.opengis.temporal.Instant instant(final String t) {
+ return new org.opengis.temporal.Instant() {
+ @Override public Date getDate() {return TestUtilities.date(t);}
+ @Override public String toString() {return "Instant[" + t + '[';}
+
+ /** Not needed for the tests. */
+ @Override public Identifier getName() {throw new UnsupportedOperationException();}
+ @Override public TemporalPosition getTemporalPosition() {throw new UnsupportedOperationException();}
+ @Override public RelativePosition relativePosition(TemporalPrimitive o) {throw new UnsupportedOperationException();}
+ @Override public Duration distance(TemporalGeometricPrimitive o) {throw new UnsupportedOperationException();}
+ @Override public Duration length() {throw new UnsupportedOperationException();}
+ };
+ }
+
+ /** Not needed for the tests. */
+ @Override public Identifier getName() {throw new UnsupportedOperationException();}
+ @Override public RelativePosition relativePosition(TemporalPrimitive o) {throw new UnsupportedOperationException();}
+ @Override public Duration distance(TemporalGeometricPrimitive o) {throw new UnsupportedOperationException();}
+ @Override public Duration length() {throw new UnsupportedOperationException();}
+
+ /**
+ * Hash code value. Used by the tests for checking the results of deserialization.
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(begin, end);
+ }
+
+ /**
+ * Compare this period with given object. Used by the tests for checking the results of deserialization.
+ */
+ @Override
+ public boolean equals(final Object other) {
+ if (other instanceof PeriodLiteral) {
+ final PeriodLiteral p = (PeriodLiteral) other;
+ return Objects.equals(begin, p.begin) && Objects.equals(end, p.end);
+ }
+ return false;
+ }
+
+ /**
+ * Returns a string representation for debugging purposes.
+ */
+ @Override
+ public String toString() {
+ return "Period[" + begin + " ... " + end + ']';
+ }
+}
diff --git a/core/sis-feature/src/test/java/org/apache/sis/filter/TemporalFunctionTest.java b/core/sis-feature/src/test/java/org/apache/sis/filter/TemporalFunctionTest.java
index 78b3bdc..057d604 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/filter/TemporalFunctionTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/filter/TemporalFunctionTest.java
@@ -16,18 +16,19 @@
*/
package org.apache.sis.filter;
-import static org.apache.sis.test.Assert.*;
+import org.opengis.filter.FilterFactory;
+import org.opengis.filter.temporal.BinaryTemporalOperator;
import org.apache.sis.test.TestCase;
-import org.junit.Ignore;
import org.junit.Test;
-import org.opengis.filter.Filter;
-import org.opengis.filter.FilterFactory2;
+
+import static org.apache.sis.test.Assert.*;
/**
* Tests {@link TemporalFunction} implementations.
*
* @author Johann Sorel (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
* @version 1.0
* @since 1.0
* @module
@@ -36,122 +37,192 @@ public final strictfp class TemporalFunctionTest extends TestCase {
/**
* The factory to use for creating the objects to test.
*/
- private final FilterFactory2 factory = new DefaultFilterFactory();
+ private final FilterFactory factory;
/**
- * Tests "After" (construction, evaluation, serialization, equality).
+ * The filter to test. This field shall be assigned by each {@code testFoo()} method by invoking
+ * a {@link #factory} method with {@link #expression1} and {@link #expression2} in arguments.
*/
- @Ignore
- @Test
- public void testAfter() {
+ private BinaryTemporalOperator filter;
+
+ /**
+ * The expression to test. They are the arguments to be given to {@link #factory} method.
+ * Each expression will return a period made of {@link PeriodLiteral#begin} and {@link PeriodLiteral#end}.
+ * Date pattern is {@code "yyyy-MM-dd HH:mm:ss"} in UTC timezone.
+ */
+ private final PeriodLiteral expression1, expression2;
+
+ /**
+ * Creates a new test case.
+ */
+ public TemporalFunctionTest() {
+ factory = new DefaultFilterFactory();
+ expression1 = new PeriodLiteral();
+ expression2 = new PeriodLiteral();
+ expression1.begin = expression2.begin = "2010-04-20 10:00:00";
+ expression1.end = expression2.end = "2010-04-25 15:00:00";
+ expression1.begin = expression2.begin = "2010-04-20 10:00:00";
+ expression1.end = expression2.end = "2010-04-25 15:00:00";
}
/**
- * Tests "AnyInteracts" (construction, evaluation, serialization, equality).
+ * Performs some validation on newly created filter.
+ *
+ * @param name expected filter name.
+ */
+ private void validate(final String name) {
+ assertInstanceOf("Expected SIS implementation.", TemporalFunction.class, filter);
+ final TemporalFunction f = ((TemporalFunction) filter);
+ assertEquals("name", name, f.getName());
+ assertSame("expression1", expression1, f.expression1);
+ assertSame("expression2", expression2, f.expression2);
+ assertSerializedEquals(filter);
+ }
+
+ /**
+ * Evaluates the filter.
+ */
+ private boolean evaluate() {
+ return filter.evaluate(null);
+ }
+
+ /**
+ * Tests "TEquals" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
- public void testAnyInteracts() {
+ public void testEquals() {
+ filter = factory.tequals(expression1, expression2);
+ validate("TEquals");
+ assertTrue(evaluate());
}
/**
* Tests "Before" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
public void testBefore() {
+ filter = factory.before(expression1, expression2);
+ validate("Before");
+ assertFalse(evaluate());
}
/**
- * Tests "Begins" (construction, evaluation, serialization, equality).
+ * Tests "After" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
- public void testBegins() {
+ public void testAfter() {
+ filter = factory.after(expression1, expression2);
+ validate("After");
+ assertFalse(evaluate());
}
/**
- * Tests "BegunBy" (construction, evaluation, serialization, equality).
+ * Tests "Begins" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
- public void testBegunBy() {
+ public void testBegins() {
+ filter = factory.begins(expression1, expression2);
+ validate("Begins");
+ assertFalse(evaluate());
}
/**
- * Tests "During" (construction, evaluation, serialization, equality).
+ * Tests "Ends" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
- public void testDuring() {
+ public void testEnds() {
+ filter = factory.ends(expression1, expression2);
+ validate("Ends");
+ assertFalse(evaluate());
}
/**
- * Tests "EndedBy" (construction, evaluation, serialization, equality).
+ * Tests "BegunBy" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
- public void testEndedBy() {
+ public void testBegunBy() {
+ filter = factory.begunBy(expression1, expression2);
+ validate("BegunBy");
+ assertFalse(evaluate());
}
/**
- * Tests "Ends" (construction, evaluation, serialization, equality).
+ * Tests "EndedBy" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
- public void testEnds() {
+ public void testEndedBy() {
+ filter = factory.endedBy(expression1, expression2);
+ validate("EndedBy");
+ assertFalse(evaluate());
}
/**
* Tests "Meets" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
public void testMeets() {
+ filter = factory.meets(expression1, expression2);
+ validate("Meets");
+ assertFalse(evaluate());
}
/**
* Tests "MetBy" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
public void testMetBy() {
+ filter = factory.metBy(expression1, expression2);
+ validate("MetBy");
+ assertFalse(evaluate());
}
/**
- * Tests "OverlappedBy" (construction, evaluation, serialization, equality).
+ * Tests "During" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
- public void testOverlappedBy() {
+ public void testDuring() {
+ filter = factory.during(expression1, expression2);
+ validate("During");
+ assertFalse(evaluate());
}
/**
* Tests "TContains" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
- public void testTContains() {
+ public void testContains() {
+ filter = factory.tcontains(expression1, expression2);
+ validate("TContains");
+ assertFalse(evaluate());
}
/**
- * Tests "TEquals" (construction, evaluation, serialization, equality).
+ * Tests "TOverlaps" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
- public void testTEquals() {
+ public void testOverlaps() {
+ filter = factory.toverlaps(expression1, expression2);
+ validate("TOverlaps");
+ assertFalse(evaluate());
}
/**
- * Tests "TOverlaps" (construction, evaluation, serialization, equality).
+ * Tests "OverlappedBy" (construction, evaluation, serialization, equality).
*/
- @Ignore
@Test
- public void testTOverlaps() {
+ public void testOverlappedBy() {
+ filter = factory.overlappedBy(expression1, expression2);
+ validate("OverlappedBy");
+ assertFalse(evaluate());
}
- private static void assertFilter(boolean expected, Filter op) {
- assertEquals(expected, op.evaluate(null));
- assertSerializedEquals(op);
+ /**
+ * Tests "AnyInteracts" (construction, evaluation, serialization, equality).
+ */
+ @Test
+ public void testAnyInteracts() {
+ filter = factory.anyInteracts(expression1, expression2);
+ validate("AnyInteracts");
+ assertTrue(evaluate());
}
}