sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 02/05: Review the fix about accepting bounding boxes as filter initialization time. Move implementation to the location where decisions are done (which types to convert, wrap-around method to apply). A goal is also to keep in the same class the code that will need to be changed if we use more extensively the <G> parameter type in filter implementations.
Date Sat, 31 Jul 2021 13:39:41 GMT
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 cba0f622a2de61d812df5e296d6411b56caa9f9b
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Sat Jul 31 13:04:35 2021 +0200

    Review the fix about accepting bounding boxes as filter initialization time.
    Move implementation to the location where decisions are done (which types to convert,
wrap-around method to apply).
    A goal is also to keep in the same class the code that will need to be changed if we use
more extensively the <G> parameter type in filter implementations.
---
 .../apache/sis/filter/BinaryGeometryFilter.java    | 12 +++---
 .../apache/sis/internal/feature/Geometries.java    | 46 ++++++----------------
 .../sis/internal/filter/GeometryConverter.java     | 42 +++++++++++++++++---
 3 files changed, 55 insertions(+), 45 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 47e22d5..c14bb98 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
@@ -29,11 +29,11 @@ import org.apache.sis.internal.filter.Node;
 import org.apache.sis.util.ArgumentChecks;
 
 // Branch-dependent imports
-import org.opengis.filter.BinarySpatialOperator;
 import org.opengis.filter.Filter;
 import org.opengis.filter.Literal;
 import org.opengis.filter.Expression;
 import org.opengis.filter.SpatialOperator;
+import org.opengis.filter.BinarySpatialOperator;
 import org.opengis.filter.InvalidFilterValueException;
 
 
@@ -44,6 +44,7 @@ import org.opengis.filter.InvalidFilterValueException;
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
+ * @author  Alexis Manin (Geomatys)
  * @version 1.1
  *
  * @param  <R>  the type of resources (e.g. {@link org.opengis.feature.Feature}) used
as inputs.
@@ -104,18 +105,17 @@ abstract class BinaryGeometryFilter<R,G> extends Node implements
SpatialOperator
         final GeometryWrapper<G> value;
         if (geometry2 instanceof Literal<?,?>) {
             literal = (Literal<? super R, ?>) geometry2;
-            value = expression2.apply(null);
+            value   = expression2.apply(null);
             index   = 1;
         } else if (geometry1 instanceof Literal<?,?>) {
             literal = (Literal<? super R, ?>) geometry1;
-            value = expression1.apply(null);
-            index = 0;
+            value   = expression1.apply(null);
+            index   = 0;
         } else {
             literal = null;
-            value = null;
+            value   = null;
             index   = -1;
         }
-
         try {
             context = new SpatialOperationContext(null, value, systemUnit, index);
             if (value != null) {
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
index 91506e4..78f6796 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
@@ -23,12 +23,10 @@ import java.util.Optional;
 import java.util.Iterator;
 import org.opengis.geometry.DirectPosition;
 import org.opengis.geometry.Envelope;
-import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.apache.sis.geometry.AbstractEnvelope;
 import org.apache.sis.geometry.GeneralEnvelope;
-import org.apache.sis.geometry.ImmutableEnvelope;
 import org.apache.sis.geometry.WraparoundMethod;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.cs.AxesConvention;
@@ -37,7 +35,6 @@ import org.apache.sis.math.Vector;
 import org.apache.sis.setup.GeometryLibrary;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.Classes;
-import org.apache.sis.util.UnconvertibleObjectException;
 
 
 /**
@@ -222,14 +219,23 @@ public abstract class Geometries<G> implements Serializable {
 
     /**
      * Returns a wrapper for the given {@code <G>} or {@code GeometryWrapper<G>}
instance.
-     * The given object shall be an instance of {@link #rootClass} or {@link #pointClass}.
+     * The given object can be one of the following choices:
+     *
+     * <ul>
+     *   <li>{@code null}, in which case this method returns {@code null}.</li>
+     *   <li>An instance of {@code GeometryWrapper<G>}, in which case the given
object is returned unchanged.
+     *       Note that instances of {@code GeometryWrapper<?>} for implementations
other than {@code <G>}
+     *       will cause a {@link ClassCastException} to be thrown.</li>
+     *   <li>An instance of {@link #rootClass} or {@link #pointClass}.</li>
+     * </ul>
+     *
      * This method can be used as an alternative to {@link #wrap(Object)} when the specified
      * geometry shall be an implementation of the specific {@linkplain #library}.
      *
      * @param  geometry  the geometry instance to wrap (can be {@code null}).
-     * @return a wrapper for the given geometry implementation, or {@code null}.
-     * @throws ClassCastException if the the given object is not an implementation
-     *         of the library identified by {@link #library}.
+     * @return a wrapper for the given geometry implementation, or {@code null} if the given
object was null.
+     * @throws ClassCastException if the the given object is not a wrapper or a geometry
object
+     *         of the implementation of the library identified by {@link #library}.
      *
      * @see #wrap(Object)
      */
@@ -471,32 +477,6 @@ public abstract class Geometries<G> implements Serializable {
     }
 
     /**
-     * Convert a given object to a geometry. For now, only bounding boxes are supported.
No Wrap-around resolution
-     * is applied. This method is a workaround to attempt conversion of an arbitrary value
to a geometry. When more
-     * context is available, prefer using directly typed methods. For example, if you have
an {@link Envelope}, you
-     * should use {@link Geometries#toGeometry2D(Envelope, WraparoundMethod)} directly.
-     *
-     * @param value An object to map to Geometry API if needed. Currently supported convertible
types are
-     * {@link GeographicBoundingBox} and {@link Envelope}. If param is null or already converted,
it is returned as is.
-     * @param adjustmentStrategy The wrap-around method to use if we've got to convert an
envelope. If null, default to
-     *                           {@link WraparoundMethod#NONE}.
-     * @return The conversion result, possibly null.
-     * @throws UnconvertibleObjectException If no conversion strategy exists for given object.
-     * @see #toGeometry2D(Envelope, WraparoundMethod) envelope conversion method.
-     */
-    public GeometryWrapper<G> toGeometry(Object value, WraparoundMethod adjustmentStrategy)
throws UnconvertibleObjectException {
-        if (value == null) return null;
-        else try {
-            if (value instanceof GeographicBoundingBox) value = new ImmutableEnvelope((GeographicBoundingBox)
value);
-            // TODO: what wrap-around method to use ? Should we assume user must manage it
before-hand ?
-            if (value instanceof Envelope) value = toGeometry2D((Envelope) value, adjustmentStrategy
== null ? WraparoundMethod.NONE : adjustmentStrategy);
-            return castOrWrap(value);
-        } catch (RuntimeException e) {
-            throw new UnconvertibleObjectException("Geometry conversion: unsupported value
type: "+value.getClass().getCanonicalName(), e);
-        }
-    }
-
-    /**
      * Merges a sequence of points or polylines into a single polyline instances.
      * Each previous polyline will be a separated path in the new polyline instances.
      * The implementation returned by this method is an instance of {@link #rootClass}.
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 abf559c..ba048a7 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
@@ -19,22 +19,29 @@ package org.apache.sis.internal.filter;
 import java.util.List;
 import java.util.Collection;
 import java.util.Collections;
-import org.apache.sis.geometry.WraparoundMethod;
 import org.opengis.util.ScopedName;
+import org.opengis.geometry.Envelope;
+import org.opengis.metadata.extent.GeographicBoundingBox;
+import org.apache.sis.util.Classes;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.feature.Geometries;
 import org.apache.sis.internal.feature.GeometryWrapper;
+import org.apache.sis.geometry.ImmutableEnvelope;
+import org.apache.sis.geometry.WraparoundMethod;
 import org.apache.sis.filter.Optimization;
 
 // Branch-dependent imports
 import org.opengis.filter.Expression;
+import org.opengis.filter.InvalidFilterValueException;
 
 
 /**
- * Expression whose results is a geometry wrapper.
+ * Expression whose results is a geometry wrapper. This converter evaluates another expression,
+ * which is given at construction time, potentially converts the result then wraps it.
  *
  * @author  Martin Desruisseaux (Geomatys)
+ * @author  Alexis Manin (Geomatys)
  * @version 1.1
  *
  * @param  <R>  the type of resources (e.g. {@link org.opengis.feature.Feature}) used
as inputs.
@@ -116,16 +123,39 @@ final class GeometryConverter<R,G> extends Node implements Optimization.OnExpres
     }
 
     /**
-     * Evaluates the expression for producing a result of the given type.
+     * Evaluates the expression and converts the value to a geometry wrapper.
+     * For now, only "native" geometry objects, envelope and bounding boxes are supported.
+     * No Wrap-around resolution is applied.
+     *
+     * <p>This method is a workaround for attempting conversion of an arbitrary value
to a geometry.
+     * When more context is available, the chain of {@code if (x instanceof y)} statements
should
+     * be replaced by subclasses invoking directly the appropriate method. For example if
we know
+     * that values are {@link Envelope}, we should use {@link Geometries#toGeometry2D(Envelope,
+     * WraparoundMethod)} directly.</p>
+     *
+     * @todo Try to change the class parameterized type for restricting to geometries {@code
<G>}.
+     *       If we can do that, remove all {@code if} statements for doing only geometry
wrapping.
+     *       If we can not do that, check how to propagate the wrap-around policy from some
context.
      *
      * @param  input  the geometry to evaluate with this expression.
      * @return the geometry boundary.
+     * @throws InvalidFilterValueException if the expression result is not an instance of
a supported type.
      */
     @Override
     public GeometryWrapper<G> apply(final R input) {
-        // TODO: review if this component should only cast geometries. If conversion is kept,
check how to propagate
-        // wrap-around method from build context.
-        return library.toGeometry(expression.apply(input), WraparoundMethod.NONE);
+        final Object value = expression.apply(input);
+        final Envelope envelope;
+        if (value instanceof GeographicBoundingBox) {
+            envelope = new ImmutableEnvelope((GeographicBoundingBox) value);
+        } else if (value instanceof Envelope) {
+            envelope = (Envelope) value;
+        } else try {
+            return library.castOrWrap(value);
+        } catch (ClassCastException e) {
+            throw new InvalidFilterValueException(Errors.format(
+                    Errors.Keys.IllegalClass_2, library.rootClass, Classes.getClass(value)),
e);
+        }
+        return library.toGeometry2D(envelope, WraparoundMethod.NONE);
     }
 
     /**

Mime
View raw message