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:06 UTC
[sis] 02/02: Remove the `FilterNode` class, replaced by default implementation of `Optimization.OnFilter` methods.
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 cb0796b4951fae9b9847cff17c8df15632aa86cf
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Mon May 1 15:10:04 2023 +0200
Remove the `FilterNode` class, replaced by default implementation of `Optimization.OnFilter` methods.
---
.../apache/sis/filter/BinaryGeometryFilter.java | 3 +-
.../org/apache/sis/filter/ComparisonFilter.java | 13 ++-
.../java/org/apache/sis/filter/FilterNode.java | 114 ---------------------
.../org/apache/sis/filter/IdentifierFilter.java | 13 ++-
.../java/org/apache/sis/filter/LikeFilter.java | 3 +-
.../java/org/apache/sis/filter/LogicalFilter.java | 5 +-
.../java/org/apache/sis/filter/Optimization.java | 29 +++++-
.../org/apache/sis/filter/LogicalFilterTest.java | 21 +++-
8 files changed, 75 insertions(+), 126 deletions(-)
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 8b62b37a7f..5bb4d09ba6 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
@@ -26,6 +26,7 @@ import org.apache.sis.internal.feature.Geometries;
import org.apache.sis.internal.feature.GeometryWrapper;
import org.apache.sis.internal.feature.SpatialOperationContext;
import org.apache.sis.internal.feature.AttributeConvention;
+import org.apache.sis.internal.filter.Node;
import org.apache.sis.util.ArgumentChecks;
// Branch-dependent imports
@@ -55,7 +56,7 @@ import org.opengis.feature.PropertyNotFoundException;
*
* @since 1.1
*/
-abstract class BinaryGeometryFilter<R,G> extends FilterNode<R> implements SpatialOperator<R>, Optimization.OnFilter<R> {
+abstract class BinaryGeometryFilter<R,G> extends Node implements SpatialOperator<R>, Optimization.OnFilter<R> {
/**
* For cross-version compatibility.
*/
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 791e545b61..b593f590c3 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
@@ -36,6 +36,7 @@ import java.time.temporal.ChronoField;
import java.time.temporal.Temporal;
import org.apache.sis.math.Fraction;
import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.internal.filter.Node;
// Branch-dependent imports
import org.opengis.filter.Filter;
@@ -796,7 +797,7 @@ abstract class ComparisonFilter<R> extends BinaryFunction<R,Object,Object>
*
* @see org.apache.sis.filter.LogicalFilter.And
*/
- static final class Between<R> extends FilterNode<R> implements BetweenComparisonOperator<R> {
+ static final class Between<R> extends Node implements BetweenComparisonOperator<R>, Optimization.OnFilter<R> {
/** For cross-version compatibility during (de)serialization. */
private static final long serialVersionUID = -2434954008425799595L;
@@ -812,6 +813,14 @@ abstract class ComparisonFilter<R> extends BinaryFunction<R,Object,Object>
this.upper = new LessThanOrEqualTo<>(expression, upper, true, MatchAction.ANY);
}
+ /**
+ * Creates a new filter of the same type but different parameters.
+ */
+ @Override
+ public Filter<R> recreate(final Expression<R,?>[] effective) {
+ return new Between<>(effective[0], effective[1], effective[2]);
+ }
+
/** Returns the class of resources expected by this filter. */
@Override public final Class<? super R> getResourceClass() {
return specializedClass(lower.getResourceClass(),
@@ -828,7 +837,7 @@ abstract class ComparisonFilter<R> extends BinaryFunction<R,Object,Object>
/** Returns the expression to be compared by this operator, together with boundaries. */
@Override public List<Expression<R,?>> getExpressions() {
- return List.of(lower.expression1, lower.expression2, upper.expression2);
+ return List.of(getExpression(), getLowerBoundary(), getUpperBoundary());
}
/** Returns the expression to be compared. */
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
deleted file mode 100644
index d35ad68a46..0000000000
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/FilterNode.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.function.Predicate;
-import org.apache.sis.internal.filter.Node;
-
-// Branch-dependent imports
-import org.opengis.filter.Filter;
-
-
-/**
- * Base class of some (not all) nodes that are filters. This base class overrides {@link Predicate}
- * methods for building other {@link Filter} objects instead of default Java implementations that
- * Apache SIS cannot recognize.
- *
- * <p><b>Note:</b> this class duplicates the method definition in {@link Optimization.OnFilter}.
- * This duplication exists because not all filter implementations extends this class, and not all
- * implementations implement the {@link Optimization.OnFilter} interface.</p>
- *
- * @author Martin Desruisseaux (Geomatys)
- * @version 1.4
- *
- * @param <R> the type of resources (e.g. {@link org.opengis.feature.Feature}) used as inputs.
- *
- * @since 1.1
- */
-abstract class FilterNode<R> extends Node implements Filter<R> {
- /**
- * For cross-version compatibility.
- */
- private static final long serialVersionUID = -1272149643938168189L;
-
- /**
- * Creates a new node.
- */
- FilterNode() {
- }
-
- /**
- * If the given predicate can be casted to a filter of the same parameterized type as the template,
- * returns {@code other} casted to that type. Otherwise returns {@code null}.
- *
- * @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 cannot be casted.
- */
- @SuppressWarnings("unchecked")
- static <R> Filter<R> castOrNull(final Filter<R> template, final Predicate<? super R> other) {
- 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;
- }
-
- /**
- * Returns the {@code AND} logical operation between this filter and the given predicate.
- * This method duplicates the {@link Optimization.OnFilter#and(Predicate)} method, but is
- * defined because not all subclasses implement the {@code Optimization} inner interface.
- */
- @Override
- public final Predicate<R> and(final Predicate<? super R> other) {
- final Filter<R> filter = castOrNull(this, other);
- if (filter != null) {
- return new LogicalFilter.And<>(this, filter);
- } else {
- return Filter.super.and(other);
- }
- }
-
- /**
- * Returns the {@code OR} logical operation between this filter and the given predicate.
- * This method duplicates the {@link Optimization.OnFilter#or(Predicate)} method, but is
- * defined because not all subclasses implement the {@code Optimization} inner interface.
- */
- @Override
- public final Predicate<R> or(final Predicate<? super R> other) {
- final Filter<R> filter = castOrNull(this, other);
- if (filter != null) {
- return new LogicalFilter.Or<>(this, filter);
- } else {
- return Filter.super.and(other);
- }
- }
-
- /**
- * Returns the logical negation of this filter.
- */
- @Override
- public final Predicate<R> negate() {
- return new LogicalFilter.Not<>(this);
- }
-}
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 3e2ec855a0..102fc4363e 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
@@ -19,12 +19,14 @@ package org.apache.sis.filter;
import java.util.List;
import java.util.Collection;
import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.internal.filter.Node;
import org.apache.sis.internal.feature.AttributeConvention;
// Branch-dependent imports
import org.opengis.feature.Feature;
import org.opengis.filter.Expression;
import org.opengis.filter.ResourceId;
+import org.opengis.filter.Filter;
/**
@@ -36,7 +38,7 @@ import org.opengis.filter.ResourceId;
* @version 1.4
* @since 1.1
*/
-final class IdentifierFilter extends FilterNode<Feature> implements ResourceId<Feature> {
+final class IdentifierFilter extends Node implements ResourceId<Feature>, Optimization.OnFilter<Feature> {
/**
* For cross-version compatibility.
*/
@@ -55,6 +57,15 @@ final class IdentifierFilter extends FilterNode<Feature> implements ResourceId<F
this.identifier = identifier;
}
+ /**
+ * Nothing to optimize here. The {@code Optimization.OnFilter} interface
+ * is implemented for inheriting the AND, OR and NOT methods overriding.
+ */
+ @Override
+ public Filter<Feature> optimize(Optimization optimization) {
+ return this;
+ }
+
/**
* Returns the class of resources expected by this expression.
*/
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 d2651378be..bc3a4ab79e 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
@@ -20,6 +20,7 @@ import java.util.List;
import java.util.Collection;
import java.util.regex.Pattern;
import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.internal.filter.Node;
// Branch-dependent imports
import org.opengis.filter.Filter;
@@ -38,7 +39,7 @@ import org.opengis.filter.LikeOperator;
*
* @since 1.1
*/
-final class LikeFilter<R> extends FilterNode<R> implements LikeOperator<R>, Optimization.OnFilter<R> {
+final class LikeFilter<R> extends Node implements LikeOperator<R>, Optimization.OnFilter<R> {
/**
* For cross-version compatibility.
*/
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 0bdde0b4e6..8dc2b23b28 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
@@ -20,6 +20,7 @@ import java.util.List;
import java.util.Collection;
import java.util.LinkedHashSet;
import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.internal.filter.Node;
import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.internal.util.UnmodifiableArrayList;
@@ -41,7 +42,7 @@ import org.opengis.filter.LogicalOperatorName;
*
* @since 1.1
*/
-abstract class LogicalFilter<R> extends FilterNode<R> implements LogicalOperator<R>, Optimization.OnFilter<R> {
+abstract class LogicalFilter<R> extends Node implements LogicalOperator<R>, Optimization.OnFilter<R> {
/**
* For cross-version compatibility.
*/
@@ -223,7 +224,7 @@ abstract class LogicalFilter<R> extends FilterNode<R> implements LogicalOperator
*
* @param <R> the type of resources used as inputs.
*/
- static final class Not<R> extends FilterNode<R> implements LogicalOperator<R>, Optimization.OnFilter<R> {
+ static final class Not<R> extends Node implements LogicalOperator<R>, Optimization.OnFilter<R> {
/** For cross-version compatibility. */
private static final long serialVersionUID = -1296823195138427781L;
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 2f1ca09039..0e6d2f985c 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
@@ -231,10 +231,31 @@ public class Optimization {
return this;
}
+ /**
+ * If the given predicate can be casted to a filter of the same parameterized type as this,
+ * returns {@code other} casted to that type. Otherwise returns {@code null}.
+ *
+ * @param other the predicate to cast to a filter compatible with this.
+ * @return the casted predicate, or {@code null} if it cannot be casted.
+ */
+ @SuppressWarnings("unchecked")
+ private Filter<R> castOrNull(final Predicate<? super R> other) {
+ if (other instanceof Filter<?>) {
+ final Class<?> type = getResourceClass();
+ if (type != null) {
+ final Class<?> to = ((Filter<?>) other).getResourceClass();
+ if (to != null && type.isAssignableFrom(to)) {
+ return (Filter<R>) other;
+ }
+ }
+ }
+ return null;
+ }
+
/**
* Returns the {@code AND} logical operation between this filter and the given predicate.
* If the given predicate is an instance of {@code Filter<R>}, then the returned predicate
- * is an instance of {@code Optimization.OnFilter<R>}.
+ * is also an instance of {@code Filter<R>}.
*
* @param other the other predicate.
* @return the {@code AND} logical operation between this filter and the given predicate.
@@ -243,7 +264,7 @@ public class Optimization {
*/
@Override
default Predicate<R> and(final Predicate<? super R> other) {
- final Filter<R> filter = FilterNode.castOrNull(this, other);
+ final Filter<R> filter = castOrNull(other);
if (filter != null) {
return new LogicalFilter.And<>(this, filter);
} else {
@@ -254,7 +275,7 @@ public class Optimization {
/**
* Returns the {@code OR} logical operation between this filter and the given predicate.
* If the given predicate is an instance of {@code Filter<R>}, then the returned predicate
- * is an instance of {@code Optimization.OnFilter<R>}.
+ * is also an instance of {@code Filter<R>}.
*
* @param other the other predicate.
* @return the {@code OR} logical operation between this filter and the given predicate.
@@ -263,7 +284,7 @@ public class Optimization {
*/
@Override
default Predicate<R> or(final Predicate<? super R> other) {
- final Filter<R> filter = FilterNode.castOrNull(this, other);
+ final Filter<R> filter = castOrNull(other);
if (filter != null) {
return new LogicalFilter.Or<>(this, filter);
} else {
diff --git a/core/sis-feature/src/test/java/org/apache/sis/filter/LogicalFilterTest.java b/core/sis-feature/src/test/java/org/apache/sis/filter/LogicalFilterTest.java
index c48f45871c..5111178236 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/filter/LogicalFilterTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/filter/LogicalFilterTest.java
@@ -21,6 +21,7 @@ import java.util.List;
import java.util.Collection;
import java.util.function.Function;
import java.util.function.BiFunction;
+import java.util.function.Predicate;
import org.apache.sis.feature.builder.FeatureTypeBuilder;
import org.apache.sis.test.TestCase;
import org.junit.Test;
@@ -141,11 +142,19 @@ public final class LogicalFilterTest extends TestCase {
assertArrayEquals(new Filter<?>[] {f1, f2}, filter.getOperands().toArray());
assertEquals(expected, filter.test(null));
assertSerializedEquals(filter);
-
+ /*
+ * Same test, using the constructor accepting any number of operands.
+ */
filter = anyArity.apply(List.of(f1, f2, f1));
assertArrayEquals(new Filter<?>[] {f1, f2, f1}, filter.getOperands().toArray());
assertEquals(expected, filter.test(null));
assertSerializedEquals(filter);
+ /*
+ * Test the `Predicate` methods, which should be overridden by `Optimization.OnFilter`.
+ */
+ assertInstanceOf("Predicate.and(…)", Optimization.OnFilter.class, f1.and(f2));
+ assertInstanceOf("Predicate.or(…)", Optimization.OnFilter.class, f1.or(f2));
+ assertInstanceOf("Predicate.negate()", Optimization.OnFilter.class, f1.negate());
}
/**
@@ -174,6 +183,16 @@ public final class LogicalFilterTest extends TestCase {
assertFalse(factory.not(filterTrue ).test(feature));
assertTrue (factory.not(filterFalse).test(feature));
+ /*
+ * Test the `Predicate` methods, which should be overridden by `Optimization.OnFilter`.
+ */
+ Predicate<Feature> predicate = filterTrue.and(filterFalse);
+ assertInstanceOf("Predicate.and(…)", Optimization.OnFilter.class, predicate);
+ assertFalse(predicate.test(feature));
+
+ predicate = filterTrue.or(filterFalse);
+ assertInstanceOf("Predicate.or(…)", Optimization.OnFilter.class, predicate);
+ assertTrue(predicate.test(feature));
}
/**