sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 03/04: Rename AbstractFunction as NamedFunction with the following modifications: - `name` and `fallback` field replaced by methods to override, since they are often fixed values for a given class. - `equals(Object)` and `hashCode()` implementations inherited from parent class. - Verification that `parameters` argument contains only non-null values.
Date Thu, 15 Aug 2019 15:41:24 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 3cecdda8d4d3cd09e529acad91b1351040f547fa
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Wed Aug 14 16:12:53 2019 +0200

    Rename AbstractFunction as NamedFunction with the following modifications:
    - `name` and `fallback` field replaced by methods to override, since they are often fixed
values for a given class.
    - `equals(Object)` and `hashCode()` implementations inherited from parent class.
    - Verification that `parameters` argument contains only non-null values.
---
 .../java/org/apache/sis/feature/FeatureFormat.java |   1 +
 .../org/apache/sis/filter/AbstractFunction.java    | 136 ------------------
 .../java/org/apache/sis/filter/NamedFunction.java  | 156 +++++++++++++++++++++
 .../src/main/java/org/apache/sis/filter/Node.java  |   6 +-
 .../src/main/java/org/apache/sis/filter/SQLMM.java |  43 ++++--
 .../java/org/apache/sis/filter/ST_Transform.java   |  44 +++---
 .../sis/internal/feature/FunctionRegister.java     |   3 +-
 ...rg.apache.sis.internal.feature.FunctionRegister |   4 +-
 .../test/java/org/apache/sis/filter/SQLMMTest.java |   3 +-
 ide-project/NetBeans/nbproject/genfiles.properties |   2 +-
 ide-project/NetBeans/nbproject/project.xml         |   1 +
 11 files changed, 222 insertions(+), 177 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java b/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
index d1ce168..7bcc201 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
@@ -304,6 +304,7 @@ public class FeatureFormat extends TabularFormat<Object> {
      * @throws IOException if an error occurred while writing to the given appendable.
      */
     @Override
+    @SuppressWarnings("null")       // Many false positives in this method.
     public void format(final Object object, final Appendable toAppendTo) throws IOException
{
         ArgumentChecks.ensureNonNull("object",     object);
         ArgumentChecks.ensureNonNull("toAppendTo", toAppendTo);
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractFunction.java b/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractFunction.java
deleted file mode 100644
index 4620ceb..0000000
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/AbstractFunction.java
+++ /dev/null
@@ -1,136 +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.Collection;
-import java.util.List;
-import org.apache.sis.internal.util.UnmodifiableArrayList;
-import static org.apache.sis.util.ArgumentChecks.*;
-import org.apache.sis.util.ObjectConverters;
-import org.apache.sis.util.UnconvertibleObjectException;
-import org.opengis.filter.expression.Expression;
-import org.opengis.filter.expression.ExpressionVisitor;
-import org.opengis.filter.expression.Function;
-import org.opengis.filter.expression.Literal;
-
-/**
- * Abstract function.
- *
- * @author  Johann Sorel (Geomatys)
- * @version 1.0
- * @since   1.0
- * @module
- */
-abstract class AbstractFunction extends Node implements Function {
-
-    protected final String name;
-    protected final List<Expression> parameters;
-    protected final Literal fallback;
-
-    public AbstractFunction(final String name, final Expression[] parameters, final Literal
fallback) {
-        ensureNonNull("name", name);
-        this.name = name;
-        this.parameters = UnmodifiableArrayList.wrap(parameters);
-        this.fallback = fallback;
-    }
-
-    @Override
-    protected Collection<?> getChildren() {
-        return parameters;
-    }
-
-    /**
-     * {@inheritDoc }
-     */
-    @Override
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * {@inheritDoc }
-     */
-    @Override
-    public List<Expression> getParameters() {
-        return parameters;
-    }
-
-    /**
-     * {@inheritDoc }
-     */
-    @Override
-    public Literal getFallbackValue() {
-        return fallback;
-    }
-
-    /**
-     * {@inheritDoc }
-     * Use the converters utility class to convert the default result object
-     * to the wished class.
-     */
-    @Override
-    public <T> T evaluate(final Object candidate, final Class<T> target) {
-        final Object value = evaluate(candidate);
-        if (target == null) {
-            return (T) value; // TODO - unsafe cast!!!!
-        }
-        try {
-            return ObjectConverters.convert(value, target);
-        } catch (UnconvertibleObjectException ex) {
-            return null;
-        }
-    }
-
-    /**
-     * {@inheritDoc }
-     */
-    @Override
-    public Object accept(final ExpressionVisitor visitor, final Object extraData) {
-        return visitor.visit(this, extraData);
-    }
-
-    @Override
-    public int hashCode() {
-        int hash = 3;
-        hash = 89 * hash + (this.name != null ? this.name.hashCode() : 0);
-        hash = 89 * hash + (this.parameters != null ? this.parameters.hashCode() : 0);
-        hash = 89 * hash + (this.fallback != null ? this.fallback.hashCode() : 0);
-        return hash;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final AbstractFunction other = (AbstractFunction) obj;
-        if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
-            return false;
-        }
-        if (this.parameters != other.parameters && (this.parameters == null || !this.parameters.equals(other.parameters)))
{
-            return false;
-        }
-        if (this.fallback != other.fallback && (this.fallback == null || !this.fallback.equals(other.fallback)))
{
-            return false;
-        }
-        return true;
-    }
-
-}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/NamedFunction.java b/core/sis-feature/src/main/java/org/apache/sis/filter/NamedFunction.java
new file mode 100644
index 0000000..d5a0b46
--- /dev/null
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/NamedFunction.java
@@ -0,0 +1,156 @@
+/*
+ * 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.List;
+import java.util.Collection;
+import org.opengis.filter.expression.Expression;
+import org.opengis.filter.expression.ExpressionVisitor;
+import org.opengis.filter.expression.Function;
+import org.opengis.filter.expression.Literal;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.ObjectConverters;
+import org.apache.sis.util.UnconvertibleObjectException;
+import org.apache.sis.internal.util.UnmodifiableArrayList;
+
+
+/**
+ * Base class of functions having a name and receiving an arbitrary amount of parameters.
+ * This class differs from {@link UnaryFunction} and {@link BinaryFunction} in two ways:
+ *
+ * <ul>
+ *   <li>It has a name used for invoking this function. By contrast, the unary and
binary functions
+ *       are represented by a symbol such as +, and their names are used only for debugging
purposes.</li>
+ *   <li>The number of parameters is not fixed to 1 (unary functions) or 2 (binary
functions).</li>
+ * </ul>
+ *
+ * Subclasses shall override at least the {@link #getName()} method, typically by returning
a hard-coded name
+ * that depends only on the class. If the name may vary for the same class, then the {@link
#equals(Object)}
+ * method should also be overridden.
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+abstract class NamedFunction extends Node implements Function {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 6933519274722660893L;
+
+    /**
+     * The sub-expressions that will be evaluated to provide the parameters to the function.
+     * This list is unmodifiable.
+     *
+     * @see #getParameters()
+     */
+    protected final List<Expression> parameters;
+
+    /**
+     * Creates a new function with the given parameters. This constructor wraps the given
array in a list directly
+     * (without defensive copy). it is caller's responsibility to ensure that the given array
is non-null, has been
+     * cloned and does not contain null elements. Those steps are done by {@link SQLMM#create(String,
Expression...)}.
+     *
+     * @param  parameters  the sub-expressions that will be evaluated to provide the parameters
to the function.
+     */
+    NamedFunction(final Expression[] parameters) {
+        this.parameters = UnmodifiableArrayList.wrap(parameters);
+    }
+
+    /**
+     * Returns the name of the function to be called.
+     * For example, this might be "{@code cos}" or "{@code atan2}".
+     *
+     * <div class="note"><b>Note for implementers:</b>
+     * implementations typically return a hard-coded value. If the returned value may vary
for the same class,
+     * then implementers should override also the {@link #equals(Object)} and {@link #hashCode()}
methods.</div>
+     *
+     * @return the name of this function.
+     */
+    @Override
+    public abstract String getName();
+
+    /**
+     * Returns the sub-expressions that will be evaluated to provide the parameters to the
function.
+     *
+     * @return the sub-expressions providing parameter values.
+     */
+    @Override
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")         // Safe because list is unmodifiable.
+    public final List<Expression> getParameters() {
+        return parameters;
+    }
+
+    /**
+     * Returns the children of this node, which are the {@linkplain #getParameters() parameters
list}.
+     * This is used for information purpose only, for example in order to build a string
representation.
+     *
+     * @return the children of this node.
+     */
+    @Override
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")         // Safe because list is unmodifiable.
+    protected final Collection<?> getChildren() {
+        return parameters;
+    }
+
+    /**
+     * Returns the default value to use if an implementation for this function is not available.
+     * The default implementation returns {@code null}.
+     *
+     * <div class="note"><b>Note for implementers:</b>
+     * implementations typically return a hard-coded value. If the returned value may vary
for the same class,
+     * then implementers should override also the {@link #equals(Object)} and {@link #hashCode()}
methods.</div>
+     *
+     * @return literal to use if an implementation for this function is not available, or
{@code null} if none.
+     */
+    @Override
+    public Literal getFallbackValue() {
+        return null;
+    }
+
+    /**
+     * Evaluates the function for producing a result of the given type.
+     * If this method can not produce a value of the given type, then it returns {@code null}.
+     * The default implementation evaluates the expression {@linkplain #evaluate(Object)
in the default way},
+     * then tries to convert the result to the target type.
+     *
+     * @param  object  to object to evaluate with this expression.
+     * @param  target  the desired type for the expression result.
+     * @return the result, or {@code null} if it can not be of the specified type.
+     */
+    @Override
+    public <T> T evaluate(final Object object, final Class<T> target) {
+        ArgumentChecks.ensureNonNull("target", target);
+        final Object value = evaluate(object);
+        try {
+            return ObjectConverters.convert(value, target);
+        } catch (UnconvertibleObjectException e) {
+            warning(e);
+            return null;                    // As per method contract.
+        }
+    }
+
+    /**
+     * Implementation of the visitor pattern.
+     */
+    @Override
+    public Object accept(final ExpressionVisitor visitor, final Object extraData) {
+        return visitor.visit(this, extraData);
+    }
+}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/Node.java b/core/sis-feature/src/main/java/org/apache/sis/filter/Node.java
index 72f1122..33c185a 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/Node.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/Node.java
@@ -82,7 +82,7 @@ abstract class Node implements Serializable {
     }
 
     /**
-     * Returns a name or symbol for this node. This is used for information purpose only,
+     * Returns a name or symbol for this node. This is used for information purpose,
      * for example in order to build a string representation.
      *
      * @return the name of this node.
@@ -90,8 +90,8 @@ abstract class Node implements Serializable {
     protected abstract String getName();
 
     /**
-     * Returns the children of this node, or an empty collection if none. This is used for
-     * information purpose only, for example in order to build a string representation.
+     * Returns the children of this node, or an empty collection if none. This is used
+     * for information purpose, for example in order to build a string representation.
      *
      * <p>The name of this method is the same as {@link BinaryLogicOperator#getChildren()}
      * in order to have only one method to override.</p>
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/SQLMM.java b/core/sis-feature/src/main/java/org/apache/sis/filter/SQLMM.java
index 6899095..8d4dc3c 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/SQLMM.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/SQLMM.java
@@ -17,24 +17,34 @@
 package org.apache.sis.filter;
 
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.Set;
-import org.apache.sis.internal.feature.FunctionRegister;
 import org.opengis.filter.expression.Expression;
 import org.opengis.filter.expression.Function;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.internal.feature.FunctionRegister;
+
 
 /**
- * SQL/MM function register.
+ * A register of functions defined by the SQL/MM standard.
  *
- * @author Johann Sorel (Geomatys)
+ * @todo Hide from public API.
+ * @todo Implement all SQL/MM specification functions.
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
  */
 public final class SQLMM implements FunctionRegister {
+    /**
+     * Names of all functions known to this register.
+     */
+    private static final Set<String> FUNCTIONS = Collections.singleton(ST_Transform.NAME);
 
-    private static final Set<String> NAMES;
-    static {
-        Set<String> names = new HashSet<>();
-        names.add(ST_Transform.NAME);
-        NAMES = Collections.unmodifiableSet(names);
+    /**
+     * Creates the default register.
+     */
+    public SQLMM() {
     }
 
     @Override
@@ -44,15 +54,20 @@ public final class SQLMM implements FunctionRegister {
 
     @Override
     public Set<String> getNames() {
-        return NAMES;
+        return FUNCTIONS;
     }
 
     @Override
-    public Function create(String name, Expression... parameters) {
+    public Function create(final String name, Expression... parameters) {
+        ArgumentChecks.ensureNonNull("name", name);
+        ArgumentChecks.ensureNonNull("parameters", parameters);
+        parameters = parameters.clone();
+        for (int i=0; i<parameters.length; i++) {
+            ArgumentChecks.ensureNonNullElement("parameters", i, parameters[i]);
+        }
         switch (name) {
-            case ST_Transform.NAME : return new ST_Transform(parameters);
+            case ST_Transform.NAME: return new ST_Transform(parameters);
+            default: throw new IllegalArgumentException("Unknown function " + name);
         }
-        throw new IllegalArgumentException("Unknown function "+name);
     }
-
 }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Transform.java b/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Transform.java
index 790dc45..8b84b41 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Transform.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/ST_Transform.java
@@ -30,23 +30,32 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.util.FactoryException;
 
+
 /**
- * TODO implement all SQL/MM specification functions.
+ * An expression which transforms a geometry from one CRS to another CRS.
  *
  * @author  Johann Sorel (Geomatys)
  * @version 1.0
  * @since   1.0
  * @module
  */
-final class ST_Transform extends AbstractFunction implements FeatureExpression {
-
-    public static final String NAME = "ST_Transform";
+final class ST_Transform extends NamedFunction implements FeatureExpression {
+    /**
+     * Name of this function as defined by SQL/MM standard.
+     */
+    static final String NAME = "ST_Transform";
 
     private final CoordinateReferenceSystem outCrs;
 
-    public ST_Transform(Expression[] parameters) {
-        super(NAME, parameters, null);
-        if (parameters.length != 2) throw new IllegalArgumentException("Reproject function
expect 2 parameters, an expression for the geometry and a literal for the target CRS.");
+    /**
+     * Creates a new function with the given parameters. It is caller's responsibility to
ensure
+     * that the given array is non-null, has been cloned and does not contain null elements.
+     */
+    ST_Transform(final Expression[] parameters) {
+        super(parameters);
+        if (parameters.length != 2) {
+            throw new IllegalArgumentException("Reproject function expect 2 parameters, an
expression for the geometry and a literal for the target CRS.");
+        }
         if (!(parameters[0] instanceof FeatureExpression)) {
             throw new IllegalArgumentException("First expression must be a FeatureExpression");
         }
@@ -74,23 +83,24 @@ final class ST_Transform extends AbstractFunction implements FeatureExpression
{
     }
 
     @Override
-    public Object evaluate(Object object) {
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public Object evaluate(final Object object) {
         final Expression inGeometry = parameters.get(0);
         Geometry geometry = inGeometry.evaluate(object, Geometry.class);
-        if (geometry == null) return null;
-
-        try {
+        if (geometry != null) try {
             return JTS.transform(geometry, outCrs);
-        } catch (TransformException ex) {
-            warning(ex);
-        } catch (FactoryException ex) {
-            warning(ex);
+        } catch (TransformException | FactoryException e) {
+            warning(e);
         }
         return null;
     }
 
     @Override
-    public PropertyType expectedType(FeatureType type) {
+    public PropertyType expectedType(final FeatureType type) {
         final FeatureExpression inGeometry = (FeatureExpression) parameters.get(0);
 
         PropertyType expectedType = inGeometry.expectedType(type);
@@ -103,6 +113,4 @@ final class ST_Transform extends AbstractFunction implements FeatureExpression
{
         }
         return new FeatureTypeBuilder().addAttribute(att).setCRS(outCrs).build();
     }
-
-
 }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FunctionRegister.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FunctionRegister.java
index d96d61a..343e3c3 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FunctionRegister.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/FunctionRegister.java
@@ -20,12 +20,12 @@ import java.util.Set;
 import org.opengis.filter.expression.Expression;
 import org.opengis.filter.expression.Function;
 
+
 /**
  *
  * @author Johann Sorel (Geomatys)
  */
 public interface FunctionRegister {
-
     /**
      *
      * Note : should it be the starting element of all function names to avoid any conflict
?
@@ -50,5 +50,4 @@ public interface FunctionRegister {
      * @throws IllegalArgumentException if function name is unknown or parameters do not
match
      */
     Function create(String name, Expression... parameters) throws IllegalArgumentException;
-
 }
diff --git a/core/sis-feature/src/main/resources/META-INF/services/org.apache.sis.internal.feature.FunctionRegister
b/core/sis-feature/src/main/resources/META-INF/services/org.apache.sis.internal.feature.FunctionRegister
index 669fe2e..d2b068f 100644
--- a/core/sis-feature/src/main/resources/META-INF/services/org.apache.sis.internal.feature.FunctionRegister
+++ b/core/sis-feature/src/main/resources/META-INF/services/org.apache.sis.internal.feature.FunctionRegister
@@ -1 +1,3 @@
-org.apache.sis.filter.SQLMM
\ No newline at end of file
+# Licensed to the Apache Software Foundation (ASF) under one or more contributor license
agreements;
+# and to You under the Apache License, Version 2.0.
+org.apache.sis.filter.SQLMM
diff --git a/core/sis-feature/src/test/java/org/apache/sis/filter/SQLMMTest.java b/core/sis-feature/src/test/java/org/apache/sis/filter/SQLMMTest.java
index d6ec945..c61c9bb 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/filter/SQLMMTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/filter/SQLMMTest.java
@@ -30,6 +30,7 @@ import org.opengis.filter.FilterFactory2;
 import org.opengis.filter.expression.Function;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 
+
 /**
  *
  * @author Johann Sorel (Geomatys)
@@ -91,7 +92,5 @@ public class SQLMMTest extends TestCase {
             Assert.assertEquals(30.0, trs.getX(), 0.0);
             Assert.assertEquals(10.0, trs.getY(), 0.0);
         }
-
     }
-
 }
diff --git a/ide-project/NetBeans/nbproject/genfiles.properties b/ide-project/NetBeans/nbproject/genfiles.properties
index 829da57..ef5c60f 100644
--- a/ide-project/NetBeans/nbproject/genfiles.properties
+++ b/ide-project/NetBeans/nbproject/genfiles.properties
@@ -3,6 +3,6 @@
 build.xml.data.CRC32=58e6b21c
 build.xml.script.CRC32=462eaba0
 build.xml.stylesheet.CRC32=28e38971@1.53.1.46
-nbproject/build-impl.xml.data.CRC32=2c1568a8
+nbproject/build-impl.xml.data.CRC32=17792780
 nbproject/build-impl.xml.script.CRC32=9b707f2e
 nbproject/build-impl.xml.stylesheet.CRC32=3a2fa800@1.91.1.48
diff --git a/ide-project/NetBeans/nbproject/project.xml b/ide-project/NetBeans/nbproject/project.xml
index 0592484..356b276 100644
--- a/ide-project/NetBeans/nbproject/project.xml
+++ b/ide-project/NetBeans/nbproject/project.xml
@@ -131,6 +131,7 @@
             <word>subsamplings</word>
             <word>timezone</word>
             <word>transitioning</word>
+            <word>unary</word>
             <word>Unicode</word>
             <word>uninstall</word>
             <word>unmarshal</word>


Mime
View raw message