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 968260ebad0013fc75b60e6ef8a65c92c058d8de
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Aug 2 18:11:02 2023 +0200

    Add a `FunctionRegister.describe(String)` method.
---
 .../sis/internal/filter/FunctionRegister.java      |  12 +-
 .../internal/filter/sqlmm/FunctionDescription.java | 176 +++++++++++++++++++++
 .../apache/sis/internal/filter/sqlmm/Registry.java |  13 ++
 .../apache/sis/internal/filter/sqlmm/SQLMM.java    |  31 +++-
 .../internal/filter/sqlmm/RegistryTestCase.java    |  18 +++
 5 files changed, 246 insertions(+), 4 deletions(-)

diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/FunctionRegister.java
 
b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/FunctionRegister.java
index 109a55da51..0a147fcae7 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/FunctionRegister.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/FunctionRegister.java
@@ -18,6 +18,7 @@ package org.apache.sis.internal.filter;
 
 import java.util.Collection;
 import org.opengis.filter.Expression;
+import org.opengis.filter.capability.AvailableFunction;
 
 
 /**
@@ -57,7 +58,16 @@ public interface FunctionRegister {
     Collection<String> getNames();
 
     /**
-     * Create a new function of the given name with given parameters.
+     * Describes the parameters of a function.
+     *
+     * @param  name        name of the function to describe (not null).
+     * @return description of the function parameters.
+     * @throws IllegalArgumentException if function name is unknown..
+     */
+    AvailableFunction describe(String name) throws IllegalArgumentException;
+
+    /**
+     * Creates a new function of the given name with given parameters.
      *
      * @param  <R>         the type of resources (e.g. {@link 
org.opengis.feature.Feature}) used as inputs.
      * @param  name        name of the function to create (not null).
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/FunctionDescription.java
 
b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/FunctionDescription.java
new file mode 100644
index 0000000000..d3b8407ef9
--- /dev/null
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/FunctionDescription.java
@@ -0,0 +1,176 @@
+/*
+ * 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.internal.filter.sqlmm;
+
+import java.util.List;
+import org.opengis.util.LocalName;
+import org.opengis.util.TypeName;
+import org.apache.sis.util.iso.Names;
+import org.apache.sis.internal.feature.Geometries;
+import org.apache.sis.internal.feature.GeometryType;
+
+// Branch-dependent imports
+import org.opengis.filter.capability.Argument;
+import org.opengis.filter.capability.AvailableFunction;
+
+
+/**
+ * Description of a SQLMM function with its parameters.
+ *
+ * @todo Argument descriptions are incomplete. They have no good names,
+ *       and the types are missing (null) except for geometry types.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.4
+ *
+ * @see SQLMM#description(Geometries)
+ *
+ * @since 1.4
+ */
+final class FunctionDescription implements AvailableFunction {
+    /**
+     * The function name in SQLMM namespace.
+     *
+     * @see #getName()
+     */
+    private final LocalName name;
+
+    /**
+     * The name and type of each argument expected by this function.
+     * This list is unmodifiable.
+     *
+     * @see #getArguments()
+     */
+    private final List<Argument> arguments;
+
+    /**
+     * The type of return value.
+     *
+     * @see #getReturnType()
+     */
+    private final TypeName result;
+
+    /**
+     * Creates a new description for the given SQLMM function.
+     *
+     * @param  function  the SQLMM function for which to create a description.
+     * @param  library   the geometry library implementation in use.
+     */
+    FunctionDescription(final SQLMM function, final Geometries<?> library) {
+        name = createLocalName(function.name());
+        final Arg[] args = new Arg[function.maxParamCount];
+        for (int i=0; i<args.length; i++) {
+            final GeometryType type;
+            switch (i) {
+                case 0:  type = function.geometryType1; break;
+                case 1:  type = function.geometryType2; break;
+                default: type = null; break;
+            }
+            args[i] = new Arg(i, (type != null) ? type.getTypeName(library) : 
null);
+        }
+        arguments = List.of(args);
+        result = function.getGeometryType().map((t) -> t.getTypeName(library))
+                         .orElseGet(() -> 
Names.createTypeName(function.getReturnType(library)));
+    }
+
+    /**
+     * Creates a name which is local in SQLMM namespace.
+     *
+     * @param  name  text of the name to create.
+     * @return name which is local in SQLMM namespace.
+     */
+    private static LocalName createLocalName(final String name) {
+        return Names.createLocalName("SQLMM", null, name);
+    }
+
+    /**
+     * Returns the function name in SQLMM namespace. This is the {@linkplain 
SQLMM#name() name}
+     * of the enumeration value, but wrapped in a {@link LocalName} with the 
"SQLMM" namespace.
+     *
+     * @return the function name.
+     */
+    @Override
+    public LocalName getName() {
+        return name;
+    }
+
+    /**
+     * Returns the name and type of each argument expected by this function.
+     *
+     * @return arguments that the function accepts.
+     */
+    @Override
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
+    public List<Argument> getArguments() {
+        return arguments;
+    }
+
+    /**
+     * Returns the type of return value.
+     *
+     * @return the type of return value.
+     */
+    @Override
+    public TypeName getReturnType() {
+        return result;
+    }
+
+    /**
+     * Description of an argument of a SQLMM function.
+     *
+     * @todo Argument names are not informative.
+     * @todo Argument types are unknown if not geometric.
+     */
+    private static final class Arg implements Argument {
+        /**
+         * The argument name.
+         */
+        private final LocalName name;
+
+        /**
+         * The value type, or {@code null} if unknown.
+         */
+        private final TypeName type;
+
+        /**
+         * Creates a new argument description.
+         *
+         * @param  i     index of the argument being created.
+         * @param  type  the argument type, or {@code null} if unknown.
+         */
+        Arg(final int i, final TypeName type) {
+            this.name = createLocalName("arg" + (i+1));
+            this.type = type;
+        }
+
+        /**
+         * {@return the name of the argument}.
+         */
+        @Override
+        public LocalName getName() {
+            return name;
+        }
+
+        /**
+         * {@return the name of the type of the argument}.
+         */
+        @Override
+        public TypeName getValueType() {
+            return type;
+        }
+    }
+}
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/Registry.java
 
b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/Registry.java
index 37371d0870..b71a9e5148 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/Registry.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/Registry.java
@@ -24,6 +24,7 @@ import org.apache.sis.internal.jdk17.JDK17;
 
 // Branch-dependent imports
 import org.opengis.filter.Expression;
+import org.opengis.filter.capability.AvailableFunction;
 
 
 /**
@@ -66,6 +67,18 @@ public final class Registry implements FunctionRegister {
         return JDK17.toList(Arrays.stream(SQLMM.values()).map(SQLMM::name));
     }
 
+    /**
+     * Describes the parameters of a function.
+     *
+     * @param  name  name of the function to describe.
+     * @return description of the function parameters.
+     * @throws IllegalArgumentException if function name is unknown..
+     */
+    @Override
+    public AvailableFunction describe(final String name) {
+        return SQLMM.valueOf(name).description(library);
+    }
+
     /**
      * Create a new function of the given name with given parameters.
      * It is caller's responsibility to ensure that the given array is 
non-null,
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/SQLMM.java
 
b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/SQLMM.java
index c8c3615032..f43e86f6e8 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/SQLMM.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/SQLMM.java
@@ -16,9 +16,11 @@
  */
 package org.apache.sis.internal.filter.sqlmm;
 
+import java.util.EnumMap;
 import java.util.Optional;
 import javax.measure.Quantity;
 import org.opengis.geometry.Envelope;
+import org.apache.sis.setup.GeometryLibrary;
 import org.apache.sis.internal.feature.Geometries;
 import org.apache.sis.internal.feature.GeometryType;
 
@@ -26,6 +28,7 @@ import static org.apache.sis.internal.feature.GeometryType.*;
 
 // Branch-dependent imports
 import org.opengis.filter.SpatialOperatorName;
+import org.opengis.filter.capability.AvailableFunction;
 
 
 /**
@@ -34,7 +37,7 @@ import org.opengis.filter.SpatialOperatorName;
  * Enumeration values order is the approximated declaration order in SQLMM 
standard.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.4
  *
  * @see <a href="https://www.iso.org/standard/60343.html";>ISO 13249-3 - 
SQLMM</a>
  *
@@ -783,10 +786,18 @@ public enum SQLMM {
     /**
      * Type of value returned by the method as a {@link Class} or a {@link 
GeometryType}.
      *
-     * @see #getReturnType()
+     * @see #getReturnType(Geometries)
      */
     private final Object returnType;
 
+    /**
+     * Description of this SQLMM function, created when first needed.
+     * The associated Java type depends on the geometry library.
+     *
+     * @see #description(Geometries)
+     */
+    private transient EnumMap<GeometryLibrary,AvailableFunction> descriptions;
+
     /**
      * Creates a new enumeration value for an operation expecting exactly one 
geometry object
      * and no other argument.
@@ -827,13 +838,27 @@ public enum SQLMM {
         this.returnType    = returnType;
     }
 
+    /**
+     * Returns a description of this SQLMM function.
+     * The Java types associated to arguments and return value depend on which 
geometry library is used.
+     *
+     * @param  library  the geometry ilibrary implementation to use.
+     * @return description of this SQLMM function.
+     */
+    public final synchronized AvailableFunction description(final 
Geometries<?> library) {
+        if (descriptions == null) {
+            descriptions = new EnumMap<>(GeometryLibrary.class);
+        }
+        return descriptions.computeIfAbsent(library.library, (key) -> new 
FunctionDescription(this, library));
+    }
+
     /**
      * Returns the number of parameters that are geometry objects. Those 
parameters shall be first.
      * This value shall be between {@link #minParamCount} and {@link 
#maxParamCount}.
      *
      * @return number of parameters that are geometry objects.
      */
-    public int geometryCount() {
+    public final int geometryCount() {
         return (geometryType1 == null) ? 0 :
                (geometryType2 == null) ? 1 : 2;
     }
diff --git 
a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryTestCase.java
 
b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryTestCase.java
index 11fa836c57..4aac037849 100644
--- 
a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryTestCase.java
+++ 
b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryTestCase.java
@@ -50,6 +50,7 @@ import org.opengis.filter.Literal;
 import org.opengis.filter.Expression;
 import org.opengis.filter.FilterFactory;
 import org.opengis.filter.ValueReference;
+import org.opengis.filter.capability.AvailableFunction;
 
 
 /**
@@ -127,6 +128,23 @@ public abstract class RegistryTestCase<G> extends TestCase 
{
         this.supportCRS = supportCRS;
     }
 
+    /**
+     * Tests {@link Registry#describe(String)}.
+     */
+    @Test
+    public void testDescribe() {
+        final Registry r = new Registry(library);
+        AvailableFunction desc = r.describe("ST_Transform");
+        assertEquals("SQLMM:ST_Transform", 
desc.getName().toFullyQualifiedName().toString());
+        assertEquals("OGC:Geometry", 
desc.getReturnType().toFullyQualifiedName().toString());
+        assertEquals(library.rootClass, 
desc.getReturnType().toJavaType().get());
+
+        desc = r.describe("ST_PointFromText");
+        assertEquals("ST_PointFromText", desc.getName().toString());
+        assertEquals("OGC:Point", 
desc.getReturnType().toFullyQualifiedName().toString());
+        assertEquals(library.pointClass, 
desc.getReturnType().toJavaType().get());
+    }
+
     /**
      * Verifies that attempts to create a function of the given name fail if 
no argument is provided.
      */

Reply via email to