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 2023/05/01 15:27:05 UTC
[sis] 01/02: Implement the `getResourceClass()` method added in `Filter` and `Expression` interfaces. That method make possible to determine whether some optimizations are allowed or not.
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
commit 26a0f263d22459f766629a67e3c382a37dfe5868
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Mon May 1 13:38:39 2023 +0200
Implement the `getResourceClass()` method added in `Filter` and `Expression` interfaces.
That method make possible to determine whether some optimizations are allowed or not.
---
.../org/apache/sis/feature/FeatureOperations.java | 2 +-
.../org/apache/sis/filter/AssociationValue.java | 10 +++++++++-
.../java/org/apache/sis/filter/BinaryFunction.java | 11 +++++++++++
.../apache/sis/filter/BinaryGeometryFilter.java | 11 +++++++++++
.../org/apache/sis/filter/ComparisonFilter.java | 6 ++++++
.../apache/sis/filter/DefaultFilterFactory.java | 4 ++--
.../java/org/apache/sis/filter/FilterNode.java | 13 +++++++++++--
.../org/apache/sis/filter/IdentifierFilter.java | 19 ++++++++++++-------
.../java/org/apache/sis/filter/LikeFilter.java | 8 ++++++++
.../java/org/apache/sis/filter/LogicalFilter.java | 17 +++++++++++++++++
.../java/org/apache/sis/filter/Optimization.java | 8 ++++----
.../java/org/apache/sis/filter/PropertyValue.java | 12 ++++++++++--
.../java/org/apache/sis/filter/UnaryFunction.java | 10 ++++++++++
.../sis/internal/coverage/j2d/ObservableImage.java | 2 +-
.../sis/internal/filter/GeometryConverter.java | 8 ++++++++
.../java/org/apache/sis/internal/filter/Node.java | 22 +++++++++++++++++++++-
.../internal/filter/sqlmm/FunctionWithSRID.java | 9 +++++++++
.../internal/filter/sqlmm/GeometryConstructor.java | 8 ++++++++
.../sis/internal/filter/sqlmm/OneGeometry.java | 18 +++++++++++++++++-
.../apache/sis/internal/filter/sqlmm/ST_Point.java | 12 ++++++++++++
.../sis/internal/filter/sqlmm/ST_Transform.java | 8 ++++++++
.../sis/internal/filter/sqlmm/TwoGeometries.java | 16 ++++++++++++++++
.../apache/sis/filter/IdentifierFilterTest.java | 4 +++-
.../org/apache/sis/filter/LeafExpressionTest.java | 3 ++-
.../apache/sis/internal/filter/FunctionMock.java | 8 ++++++++
.../sis/internal/filter/FunctionNamesTest.java | 2 ++
.../sis/internal/filter/ValueReferenceMock.java | 8 ++++++++
27 files changed, 235 insertions(+), 24 deletions(-)
diff --git a/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureOperations.java b/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureOperations.java
index b9ab137a05..b4ab1692d0 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureOperations.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureOperations.java
@@ -290,7 +290,7 @@ public final class FeatureOperations extends Static {
/**
* Creates an operation which delegates the computation to a given expression producing values of unknown type.
* This method can be used as an alternative to {@link #expression expression(…)} when the constraint on the
- * parameterized type {@code <V>} between {@code expression} and {@code result} can not be enforced at compile time.
+ * parameterized type {@code <V>} between {@code expression} and {@code result} cannot be enforced at compile time.
* This method casts or converts the expression to the expected type by a call to
* {@link Expression#toValueType(Class)}.
*
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/AssociationValue.java b/core/sis-feature/src/main/java/org/apache/sis/filter/AssociationValue.java
index 16d967535c..c8d714b8d5 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/AssociationValue.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/AssociationValue.java
@@ -42,7 +42,7 @@ import org.opengis.filter.ValueReference;
* (the tip) is evaluated by a {@link PropertyValue}.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.4
*
* @param <V> the type of value computed by the expression.
*
@@ -94,6 +94,14 @@ final class AssociationValue<V> extends LeafExpression<Feature, V>
this.accessor = accessor;
}
+ /**
+ * Returns the class of resources expected by this expression.
+ */
+ @Override
+ public final Class<Feature> getResourceClass() {
+ return Feature.class;
+ }
+
/**
* For {@link #toString()} implementation.
*/
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 b7c33e33a2..a149e05cf9 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
@@ -84,6 +84,17 @@ abstract class BinaryFunction<R,V1,V2> extends Node {
this.expression2 = expression2;
}
+ /**
+ * Returns the class of resources expected by this filter.
+ * Defined for {@link Filter#getResourceClass()} and {@link Expression#getResourceClass()} implementations.
+ *
+ * @return type of resources accepted by this filter, or {@code null} if inconsistent.
+ */
+ public final Class<? super R> getResourceClass() {
+ return specializedClass(expression1.getResourceClass(),
+ expression2.getResourceClass());
+ }
+
/**
* Returns the expressions used as parameters by this function.
* Defined for {@link Expression#getParameters()} implementations.
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/BinaryGeometryFilter.java b/core/sis-feature/src/main/java/org/apache/sis/filter/BinaryGeometryFilter.java
index f668f78886..8b62b37a7f 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/BinaryGeometryFilter.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/BinaryGeometryFilter.java
@@ -164,6 +164,17 @@ abstract class BinaryGeometryFilter<R,G> extends FilterNode<R> implements Spatia
return unwrapped;
}
+ /**
+ * Returns the class of resources expected by this filter.
+ *
+ * @return type of resources accepted by this filter, or {@code null} if inconsistent.
+ */
+ @Override
+ public final Class<? super R> getResourceClass() {
+ return specializedClass(expression1.getResourceClass(),
+ expression2.getResourceClass());
+ }
+
/**
* Returns the two expressions used as parameters by this filter.
*/
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/ComparisonFilter.java b/core/sis-feature/src/main/java/org/apache/sis/filter/ComparisonFilter.java
index 1853662fe7..791e545b61 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/ComparisonFilter.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/ComparisonFilter.java
@@ -812,6 +812,12 @@ abstract class ComparisonFilter<R> extends BinaryFunction<R,Object,Object>
this.upper = new LessThanOrEqualTo<>(expression, upper, true, MatchAction.ANY);
}
+ /** Returns the class of resources expected by this filter. */
+ @Override public final Class<? super R> getResourceClass() {
+ return specializedClass(lower.getResourceClass(),
+ upper.getResourceClass());
+ }
+
/**
* Returns the 3 children of this node. Since {@code lower.expression2}
* is the same as {@code upper.expression1}, that repetition is omitted.
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 5f381105b0..7d56e36cc1 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
@@ -186,7 +186,7 @@ public abstract class DefaultFilterFactory<R,G,T> extends AbstractFactory implem
*/
@Override
public ResourceId<Feature> resourceId(final String identifier) {
- return new IdentifierFilter<>(identifier);
+ return new IdentifierFilter(identifier);
}
/**
@@ -207,7 +207,7 @@ public abstract class DefaultFilterFactory<R,G,T> extends AbstractFactory implem
public ResourceId<Feature> resourceId(final String identifier, final Version version,
final Instant startTime, final Instant endTime)
{
- return new IdentifierFilter<>(identifier);
+ return new IdentifierFilter(identifier);
}
/**
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/FilterNode.java b/core/sis-feature/src/main/java/org/apache/sis/filter/FilterNode.java
index d5a8c25b85..d35ad68a46 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/FilterNode.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/FilterNode.java
@@ -58,10 +58,19 @@ abstract class FilterNode<R> extends Node implements Filter<R> {
* @param <R> desired parameterized type.
* @param template the filter from which to get the runtime value of {@code <R>}.
* @param other the predicate to cast to a filter compatible with the target.
- * @return the casted predicate, or {@code null} if it can not be casted.
+ * @return the casted predicate, or {@code null} if it cannot be casted.
*/
+ @SuppressWarnings("unchecked")
static <R> Filter<R> castOrNull(final Filter<R> template, final Predicate<? super R> other) {
- // TODO
+ if (other instanceof Filter<?>) {
+ final Class<?> type = template.getResourceClass();
+ if (type != null) {
+ final Class<?> to = ((Filter<?>) other).getResourceClass();
+ if (to != null && type.isAssignableFrom(to)) {
+ return (Filter<R>) other;
+ }
+ }
+ }
return null;
}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/IdentifierFilter.java b/core/sis-feature/src/main/java/org/apache/sis/filter/IdentifierFilter.java
index fbfe274224..3e2ec855a0 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/IdentifierFilter.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/IdentifierFilter.java
@@ -34,12 +34,9 @@ import org.opengis.filter.ResourceId;
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
* @version 1.4
- *
- * @param <R> the type of resources used as inputs.
- *
- * @since 1.1
+ * @since 1.1
*/
-final class IdentifierFilter<R extends Feature> extends FilterNode<R> implements ResourceId<R> {
+final class IdentifierFilter extends FilterNode<Feature> implements ResourceId<Feature> {
/**
* For cross-version compatibility.
*/
@@ -58,6 +55,14 @@ final class IdentifierFilter<R extends Feature> extends FilterNode<R> implements
this.identifier = identifier;
}
+ /**
+ * Returns the class of resources expected by this expression.
+ */
+ @Override
+ public Class<Feature> getResourceClass() {
+ return Feature.class;
+ }
+
/**
* Returns the identifiers of feature instances to accept.
*/
@@ -70,7 +75,7 @@ final class IdentifierFilter<R extends Feature> extends FilterNode<R> implements
* Returns the parameters of this filter.
*/
@Override
- public List<Expression<R,?>> getExpressions() {
+ public List<Expression<Feature,?>> getExpressions() {
return List.of(new LeafExpression.Literal<>(identifier));
}
@@ -88,7 +93,7 @@ final class IdentifierFilter<R extends Feature> extends FilterNode<R> implements
* is one of the identifier specified at {@code IdentifierFilter} construction time.
*/
@Override
- public boolean test(R object) {
+ public boolean test(final Feature object) {
if (object == null) {
return false;
}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/LikeFilter.java b/core/sis-feature/src/main/java/org/apache/sis/filter/LikeFilter.java
index f4cb6bbc7d..d2651378be 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/LikeFilter.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/LikeFilter.java
@@ -161,6 +161,14 @@ final class LikeFilter<R> extends FilterNode<R> implements LikeOperator<R>, Opti
return new LikeFilter<>(this, effective[0]);
}
+ /**
+ * Returns the class of resources expected by this filter.
+ */
+ @Override
+ public Class<? super R> getResourceClass() {
+ return expression.getResourceClass();
+ }
+
/**
* Returns the children of this node for displaying purposes.
* This is used by {@link #toString()}, {@link #hashCode()} and {@link #equals(Object)} implementations.
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/LogicalFilter.java b/core/sis-feature/src/main/java/org/apache/sis/filter/LogicalFilter.java
index 4dee42760d..0bdde0b4e6 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/LogicalFilter.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/LogicalFilter.java
@@ -86,6 +86,18 @@ abstract class LogicalFilter<R> extends FilterNode<R> implements LogicalOperator
*/
protected abstract LogicalFilter<R> createSameType(Collection<? extends Filter<R>> op);
+ /**
+ * Returns the class of resources expected by this filter.
+ */
+ @Override
+ public Class<? super R> getResourceClass() {
+ Class<? super R> type = Object.class;
+ for (final Filter<R> operand : operands) {
+ type = specializedClass(type, operand.getResourceClass());
+ }
+ return type;
+ }
+
/**
* Returns a list containing all of the child filters of this object.
*/
@@ -230,6 +242,11 @@ abstract class LogicalFilter<R> extends FilterNode<R> implements LogicalOperator
return LogicalOperatorName.NOT;
}
+ /** Returns the class of resources expected by this filter. */
+ @Override public Class<? super R> getResourceClass() {
+ return operand.getResourceClass();
+ }
+
/** Symbol of the operation. */
@Override protected char symbol() {
return '¬';
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/Optimization.java b/core/sis-feature/src/main/java/org/apache/sis/filter/Optimization.java
index d13ef64099..2f1ca09039 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/Optimization.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/Optimization.java
@@ -233,8 +233,8 @@ public class Optimization {
/**
* Returns the {@code AND} logical operation between this filter and the given predicate.
- * If the given predicate is an instance of {@link Filter}, then the returned predicate
- * is an instance of {@code Optimization.OnFilter}.
+ * If the given predicate is an instance of {@code Filter<R>}, then the returned predicate
+ * is an instance of {@code Optimization.OnFilter<R>}.
*
* @param other the other predicate.
* @return the {@code AND} logical operation between this filter and the given predicate.
@@ -253,8 +253,8 @@ public class Optimization {
/**
* Returns the {@code OR} logical operation between this filter and the given predicate.
- * If the given predicate is an instance of {@link Filter}, then the returned predicate
- * is an instance of {@code Optimization.OnFilter}.
+ * If the given predicate is an instance of {@code Filter<R>}, then the returned predicate
+ * is an instance of {@code Optimization.OnFilter<R>}.
*
* @param other the other predicate.
* @return the {@code OR} logical operation between this filter and the given predicate.
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/PropertyValue.java b/core/sis-feature/src/main/java/org/apache/sis/filter/PropertyValue.java
index 20d281e95e..cae63556d3 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/PropertyValue.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/PropertyValue.java
@@ -46,7 +46,7 @@ import org.opengis.filter.ValueReference;
*
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.4
*
* @param <V> the type of value computed by the expression.
*
@@ -76,7 +76,7 @@ abstract class PropertyValue<V> extends LeafExpression<Feature,V>
protected final boolean isVirtual;
/**
- * The prefix in a x-path for considering a property as virual.
+ * The prefix in a x-path for considering a property as virtual.
*/
static final String VIRTUAL_PREFIX = "/*/";
@@ -133,6 +133,14 @@ split: if (path != null) {
return (path == null || path.isEmpty()) ? tip : new AssociationValue<>(path, tip);
}
+ /**
+ * Returns the class of resources expected by this expression.
+ */
+ @Override
+ public final Class<Feature> getResourceClass() {
+ return Feature.class;
+ }
+
/**
* For {@link #toString()}, {@link #hashCode()} and {@link #equals(Object)} implementations.
*/
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/UnaryFunction.java b/core/sis-feature/src/main/java/org/apache/sis/filter/UnaryFunction.java
index 4cc5327b6c..cff832db14 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/UnaryFunction.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/UnaryFunction.java
@@ -65,6 +65,16 @@ class UnaryFunction<R,V> extends Node {
this.expression = expression;
}
+ /**
+ * Returns the class of resources expected by this filter.
+ * Defined for {@link Filter#getResourceClass()} implementations.
+ *
+ * @return type of resources accepted by this filter, or {@code null} if inconsistent.
+ */
+ public final Class<? super R> getResourceClass() {
+ return expression.getResourceClass();
+ }
+
/**
* Returns the expression used as parameter by this function.
* Defined for {@link Expression#getParameters()} implementations.
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ObservableImage.java b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ObservableImage.java
index 04942d510a..07279f0ef8 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ObservableImage.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ObservableImage.java
@@ -36,7 +36,7 @@ import org.apache.sis.util.ArraysExt;
* <p>This class should be used in preference to {@link BufferedImage} when the image may be the
* source of {@link org.apache.sis.image.ImageProcessor} operations. It is the case In particular
* when this image is given to {@link org.apache.sis.coverage.grid.GridCoverage2D} constructor.
- * We can not prevent {@link BufferedImage} to implement {@link WritableRenderedImage}, but we
+ * We cannot prevent {@link BufferedImage} to implement {@link WritableRenderedImage}, but we
* can give a change to Apache SIS to be notified about modifications to pixel data.</p>
*
* @author Martin Desruisseaux (Geomatys)
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/GeometryConverter.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/GeometryConverter.java
index edb9f26946..a9bcf55dc4 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/GeometryConverter.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/GeometryConverter.java
@@ -106,6 +106,14 @@ final class GeometryConverter<R,G> extends Node implements Optimization.OnExpres
return NAME;
}
+ /**
+ * Returns the class of resources expected by this expression.
+ */
+ @Override
+ public Class<? super R> getResourceClass() {
+ return expression.getResourceClass();
+ }
+
/**
* Returns the expression used as parameters for this function.
* This is the value specified at construction time.
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/Node.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/Node.java
index f48299a752..581588efb3 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/Node.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/Node.java
@@ -19,10 +19,10 @@ package org.apache.sis.internal.filter;
import java.util.Map;
import java.util.IdentityHashMap;
import java.util.Collection;
-import java.io.Serializable;
import java.util.Collections;
import java.util.function.Predicate;
import java.util.logging.Logger;
+import java.io.Serializable;
import org.opengis.util.CodeList;
import org.opengis.util.LocalName;
import org.opengis.util.ScopedName;
@@ -96,6 +96,26 @@ public abstract class Node implements Serializable {
type, 1, 1, null, (AttributeType<?>[]) null);
}
+ /**
+ * Returns the most specialized class of the given pair of class. A specialized class is guaranteed to exist
+ * if parametrized type safety has not been bypassed with unchecked casts, because {@code <R>} is always valid.
+ * However this method is not guaranteed to be able to find that specialized type, because it could be none of
+ * the given arguments if {@code t1}, {@code t2} and {@code <R>} are interfaces with {@code <R>} extending both
+ * {@code t1} and {@code t2}.
+ *
+ * @param <R> the compile-time type of resources expected by filters or expressions.
+ * @param t1 the runtime type of resources expected by the first filter or expression. May be null.
+ * @param t2 the runtime type of resources expected by the second filter or expression. May be null.
+ * @return the most specialized type of resources, or {@code null} if it cannot be determined.
+ */
+ protected static <R> Class<? super R> specializedClass(final Class<? super R> t1, final Class<? super R> t2) {
+ if (t1 != null && t2 != null) {
+ if (t1.isAssignableFrom(t2)) return t2;
+ if (t2.isAssignableFrom(t1)) return t1;
+ }
+ return null;
+ }
+
/**
* Returns the mathematical symbol for this binary function.
* For comparison operators, the symbol should be one of {@literal < > ≤ ≥ = ≠}.
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/FunctionWithSRID.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/FunctionWithSRID.java
index daa6f702d8..b2640be641 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/FunctionWithSRID.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/FunctionWithSRID.java
@@ -206,6 +206,15 @@ search: if (crs instanceof CoordinateReferenceSystem) {
}
}
+ /**
+ * Returns the class of resources expected by this expression.
+ * Subclasses should override this method.
+ */
+ @Override
+ public Class<? super R> getResourceClass() {
+ return (srid != null) ? srid.getResourceClass() : Object.class;
+ }
+
/**
* Provides the type of values produced by this expression when a feature of the given type is evaluated.
*
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/GeometryConstructor.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/GeometryConstructor.java
index a687d91527..bebef3918e 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/GeometryConstructor.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/GeometryConstructor.java
@@ -77,6 +77,14 @@ class GeometryConstructor<R,G> extends FunctionWithSRID<R> {
return new GeometryConstructor<>(operation, effective, getGeometryLibrary());
}
+ /**
+ * Returns the class of resources expected by this expression.
+ */
+ @Override
+ public Class<? super R> getResourceClass() {
+ return specializedClass(geometry.getResourceClass(), super.getResourceClass());
+ }
+
/**
* Returns the sub-expressions that will be evaluated to provide the parameters to the function.
*/
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/OneGeometry.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/OneGeometry.java
index b1c7432548..2ce129b57d 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/OneGeometry.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/OneGeometry.java
@@ -26,7 +26,7 @@ import org.opengis.filter.Expression;
/**
* SQLMM spatial functions taking a single geometry operand.
- * This base class assume that the geometry is the only parameter.
+ * This base class assumes that the geometry is the only parameter.
* Subclasses may add other kind of parameters.
*
* @author Johann Sorel (Geomatys)
@@ -75,6 +75,14 @@ class OneGeometry<R,G> extends SpatialFunction<R> {
return getGeometryLibrary(geometry);
}
+ /**
+ * Returns the class of resources expected by this expression.
+ */
+ @Override
+ public Class<? super R> getResourceClass() {
+ return geometry.getResourceClass();
+ }
+
/**
* Returns the sub-expressions that will be evaluated to provide the parameters to the function.
*/
@@ -127,6 +135,14 @@ class OneGeometry<R,G> extends SpatialFunction<R> {
return new WithArgument<>(operation, effective, getGeometryLibrary());
}
+ /**
+ * Returns the class of resources expected by this expression.
+ */
+ @Override
+ public Class<? super R> getResourceClass() {
+ return specializedClass(super.getResourceClass(), argument.getResourceClass());
+ }
+
/**
* Returns the sub-expressions that will be evaluated to provide the parameters to the function.
*/
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Point.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Point.java
index 19d0e6ca91..eeb2809a65 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Point.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Point.java
@@ -98,6 +98,18 @@ final class ST_Point<R,G> extends FunctionWithSRID<R> {
return library;
}
+ /**
+ * Returns the class of resources expected by this expression.
+ */
+ @Override
+ public Class<? super R> getResourceClass() {
+ Class<? super R> type = super.getResourceClass();
+ for (final Expression<R,?> p : parameters) {
+ type = specializedClass(type, p.getResourceClass());
+ }
+ return type;
+ }
+
/**
* Returns the sub-expressions that will be evaluated to provide the parameters to the function.
*/
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Transform.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Transform.java
index 463b1e2660..887ae43dc4 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Transform.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Transform.java
@@ -93,6 +93,14 @@ final class ST_Transform<R,G> extends FunctionWithSRID<R> {
return new ST_Transform<>(effective, getGeometryLibrary());
}
+ /**
+ * Returns the class of resources expected by this expression.
+ */
+ @Override
+ public Class<? super R> getResourceClass() {
+ return specializedClass(geometry.getResourceClass(), super.getResourceClass());
+ }
+
/**
* Returns a handler for the library of geometric objects used by this expression.
*/
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/TwoGeometries.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/TwoGeometries.java
index e394a62f31..ad06f76fa8 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/TwoGeometries.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/TwoGeometries.java
@@ -115,6 +115,14 @@ class TwoGeometries<R,G> extends SpatialFunction<R> {
return getGeometryLibrary(geometry1);
}
+ /**
+ * Returns the class of resources expected by this expression.
+ */
+ @Override
+ public Class<? super R> getResourceClass() {
+ return specializedClass(geometry1.getResourceClass(), geometry2.getResourceClass());
+ }
+
/**
* Returns the sub-expressions that will be evaluated to provide the parameters to the function.
*/
@@ -172,6 +180,14 @@ class TwoGeometries<R,G> extends SpatialFunction<R> {
return new WithArgument<>(operation, effective, getGeometryLibrary());
}
+ /**
+ * Returns the class of resources expected by this expression.
+ */
+ @Override
+ public Class<? super R> getResourceClass() {
+ return specializedClass(super.getResourceClass(), argument.getResourceClass());
+ }
+
/**
* Returns the sub-expressions that will be evaluated to provide the parameters to the function.
*/
diff --git a/core/sis-feature/src/test/java/org/apache/sis/filter/IdentifierFilterTest.java b/core/sis-feature/src/test/java/org/apache/sis/filter/IdentifierFilterTest.java
index 10d75b2326..d005888119 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/filter/IdentifierFilterTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/filter/IdentifierFilterTest.java
@@ -35,7 +35,7 @@ import org.opengis.filter.FilterFactory;
*
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.4
* @since 1.1
*/
public final class IdentifierFilterTest extends TestCase {
@@ -81,6 +81,7 @@ public final class IdentifierFilterTest extends TestCase {
final Feature f3 = ftb.clear().setName("Test 3").build().newInstance();
final Filter<Feature> id = factory.resourceId("123");
+ assertEquals(Feature.class, id.getResourceClass());
assertTrue (id.test(f1));
assertTrue (id.test(f2));
assertFalse(id.test(f3));
@@ -103,6 +104,7 @@ public final class IdentifierFilterTest extends TestCase {
factory.resourceId("abc"),
factory.resourceId("123"));
+ assertEquals(Feature.class, id.getResourceClass());
assertTrue (id.test(f1));
assertTrue (id.test(f2));
assertFalse(id.test(f3));
diff --git a/core/sis-feature/src/test/java/org/apache/sis/filter/LeafExpressionTest.java b/core/sis-feature/src/test/java/org/apache/sis/filter/LeafExpressionTest.java
index 1444efaf01..c1b80108a7 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/filter/LeafExpressionTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/filter/LeafExpressionTest.java
@@ -33,7 +33,7 @@ import org.opengis.filter.ValueReference;
* Tests {@link LeafExpression}.
*
* @author Johann Sorel (Geomatys)
- * @version 1.1
+ * @version 1.4
* @since 1.1
*/
public final class LeafExpressionTest extends TestCase {
@@ -93,6 +93,7 @@ public final class LeafExpressionTest extends TestCase {
final Feature f = ftb.setName("Test").build().newInstance();
ValueReference<Feature,?> ref = factory.property("some_property");
+ assertEquals(Feature.class, ref.getResourceClass());
assertNull(ref.apply(f));
assertNull(ref.apply(null));
diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/FunctionMock.java b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/FunctionMock.java
index dc25a40a7c..5faece4129 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/FunctionMock.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/FunctionMock.java
@@ -64,6 +64,14 @@ final class FunctionMock implements Expression<Map<String,?>, Object> {
return Names.createScopedName(null, null, name);
}
+ /**
+ * Returns the type of resources accepted by this mock.
+ */
+ @Override
+ public Class<Map> getResourceClass() {
+ return Map.class;
+ }
+
/**
* Returns the function parameters.
*/
diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/FunctionNamesTest.java b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/FunctionNamesTest.java
index f3ee5e5c43..3ec880cfcd 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/FunctionNamesTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/FunctionNamesTest.java
@@ -60,6 +60,7 @@ public final class FunctionNamesTest extends TestCase {
*/
private static abstract class FilterBase implements ComparisonOperator<Object> {
@Override public List<Expression<Object,?>> getExpressions() {return List.of();}
+ @Override public Class<Object> getResourceClass() {return Object.class;}
@Override public boolean test(Object resource) {return false;}
}
@@ -121,6 +122,7 @@ public final class FunctionNamesTest extends TestCase {
final var expression = new ValueReference<Object,Object>() {
@Override public String getXPath() {return null;}
@Override public Object apply(Object o) {return null;}
+ @Override public Class<Object> getResourceClass() {return Object.class;}
@Override public <N> Expression<Object,N> toValueType(Class<N> target) {
throw new UnsupportedOperationException();
}
diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/ValueReferenceMock.java b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/ValueReferenceMock.java
index 90eb9a1f75..0e56410095 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/ValueReferenceMock.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/ValueReferenceMock.java
@@ -56,6 +56,14 @@ final class ValueReferenceMock<V> implements ValueReference<Map<String,?>, V> {
this.type = type;
}
+ /**
+ * Returns the type of resources accepted by this mock.
+ */
+ @Override
+ public Class<Map> getResourceClass() {
+ return Map.class;
+ }
+
/**
* Returns the name of the property for which to get values.
*/