sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jso...@apache.org
Subject [sis] branch feat/sqlmm updated: SQL/MM : cleaning code
Date Wed, 27 Nov 2019 14:46:58 GMT
This is an automated email from the ASF dual-hosted git repository.

jsorel pushed a commit to branch feat/sqlmm
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/feat/sqlmm by this push:
     new 8b5080a  SQL/MM : cleaning code
8b5080a is described below

commit 8b5080abe1f3e50996a043765131bf7bb05dcdc3
Author: jsorel <johann.sorel@geomatys.com>
AuthorDate: Wed Nov 27 15:46:36 2019 +0100

    SQL/MM : cleaning code
---
 .../sis/internal/feature/jts/JTSMapping.java       | 373 +++++++++++++++++++++
 .../filter/sqlmm/AbstractSpatialFunction.java      |   2 +-
 .../apache/sis/internal/filter/sqlmm/SQLMM.java    |   7 -
 .../apache/sis/internal/filter/sqlmm/ST_Area.java  |   6 +-
 .../sis/internal/filter/sqlmm/ST_AsBinary.java     |   6 +-
 .../apache/sis/internal/filter/sqlmm/ST_AsGML.java |   6 +-
 .../sis/internal/filter/sqlmm/ST_AsText.java       |   6 +-
 .../sis/internal/filter/sqlmm/ST_Boundary.java     |   6 +-
 .../sis/internal/filter/sqlmm/ST_Buffer.java       |   2 +-
 .../sis/internal/filter/sqlmm/ST_Centroid.java     |   2 +-
 .../sis/internal/filter/sqlmm/ST_Contains.java     |   6 +-
 .../sis/internal/filter/sqlmm/ST_ConvexHull.java   |   6 +-
 .../sis/internal/filter/sqlmm/ST_CoordDim.java     |   6 +-
 .../sis/internal/filter/sqlmm/ST_Crosses.java      |   6 +-
 .../sis/internal/filter/sqlmm/ST_Difference.java   |   6 +-
 .../sis/internal/filter/sqlmm/ST_Dimension.java    |   6 +-
 .../sis/internal/filter/sqlmm/ST_Disjoint.java     |   6 +-
 .../sis/internal/filter/sqlmm/ST_Distance.java     |   6 +-
 .../sis/internal/filter/sqlmm/ST_EndPoint.java     |   6 +-
 .../sis/internal/filter/sqlmm/ST_Envelope.java     |   6 +-
 .../sis/internal/filter/sqlmm/ST_Equals.java       |   6 +-
 .../internal/filter/sqlmm/ST_ExplicitPoint.java    |   6 +-
 .../sis/internal/filter/sqlmm/ST_ExteriorRing.java |   6 +-
 .../internal/filter/sqlmm/ST_GeomCollection.java   |   6 +-
 .../sis/internal/filter/sqlmm/ST_GeometryN.java    |   6 +-
 .../sis/internal/filter/sqlmm/ST_GeometryType.java |   6 +-
 .../internal/filter/sqlmm/ST_InteriorRingN.java    |   6 +-
 .../sis/internal/filter/sqlmm/ST_Intersection.java |   6 +-
 .../sis/internal/filter/sqlmm/ST_Intersects.java   |   8 +-
 .../apache/sis/internal/filter/sqlmm/ST_Is3D.java  |   6 +-
 .../sis/internal/filter/sqlmm/ST_IsClosed.java     |   6 +-
 .../sis/internal/filter/sqlmm/ST_IsEmpty.java      |   6 +-
 .../sis/internal/filter/sqlmm/ST_IsRing.java       |   6 +-
 .../sis/internal/filter/sqlmm/ST_IsSimple.java     |   6 +-
 .../sis/internal/filter/sqlmm/ST_IsValid.java      |   6 +-
 .../sis/internal/filter/sqlmm/ST_Length.java       |   6 +-
 .../sis/internal/filter/sqlmm/ST_LineString.java   |  72 ++--
 .../internal/filter/sqlmm/ST_MultiLineString.java  |   8 +-
 .../sis/internal/filter/sqlmm/ST_MultiPoint.java   |   6 +-
 .../sis/internal/filter/sqlmm/ST_MultiPolygon.java |   8 +-
 .../internal/filter/sqlmm/ST_NumGeometries.java    |   6 +-
 .../internal/filter/sqlmm/ST_NumInteriorRings.java |   6 +-
 .../sis/internal/filter/sqlmm/ST_NumPoints.java    |   6 +-
 .../sis/internal/filter/sqlmm/ST_Overlaps.java     |   6 +-
 .../sis/internal/filter/sqlmm/ST_Perimeter.java    |   6 +-
 .../apache/sis/internal/filter/sqlmm/ST_Point.java | 113 +++++--
 .../sis/internal/filter/sqlmm/ST_PointN.java       |   6 +-
 .../internal/filter/sqlmm/ST_PointOnSurface.java   |   6 +-
 .../sis/internal/filter/sqlmm/ST_Polygon.java      |   6 +-
 .../sis/internal/filter/sqlmm/ST_Relate.java       |   6 +-
 .../apache/sis/internal/filter/sqlmm/ST_SRID.java  |   6 +-
 .../sis/internal/filter/sqlmm/ST_Simplify.java     |   2 +-
 .../filter/sqlmm/ST_SimplifyPreserveTopology.java  |   2 +-
 .../sis/internal/filter/sqlmm/ST_StartPoint.java   |   6 +-
 .../internal/filter/sqlmm/ST_SymDifference.java    |   6 +-
 .../filter/sqlmm/{todo => }/ST_ToGeomColl.java     |  20 +-
 .../filter/sqlmm/{todo => }/ST_ToLineString.java   |  20 +-
 .../filter/sqlmm/{todo => }/ST_ToMultiLine.java    |  20 +-
 .../filter/sqlmm/{todo => }/ST_ToMultiPoint.java   |  20 +-
 .../filter/sqlmm/{todo => }/ST_ToMultiPolygon.java |  20 +-
 .../filter/sqlmm/{todo => }/ST_ToPoint.java        |  20 +-
 .../filter/sqlmm/{todo => }/ST_ToPolygon.java      |  20 +-
 .../sis/internal/filter/sqlmm/ST_Touches.java      |   6 +-
 .../sis/internal/filter/sqlmm/ST_Transform.java    |   2 +-
 .../apache/sis/internal/filter/sqlmm/ST_Union.java |   6 +-
 .../sis/internal/filter/sqlmm/ST_Within.java       |   6 +-
 .../org/apache/sis/internal/filter/sqlmm/ST_X.java |   6 +-
 .../sis/internal/filter/sqlmm/ST_XFromBinary.java  |  17 +-
 .../sis/internal/filter/sqlmm/ST_XFromGML.java     |  15 +-
 .../sis/internal/filter/sqlmm/ST_XFromText.java    |  17 +-
 .../org/apache/sis/internal/filter/sqlmm/ST_Y.java |   7 +-
 .../org/apache/sis/internal/filter/sqlmm/ST_Z.java |   7 +-
 .../internal/filter/sqlmm/todo/ST_LineString.java  |  49 ---
 .../sis/internal/filter/sqlmm/todo/ST_Point.java   | 131 --------
 .../sis/internal/filter/{ => sqlmm}/SQLMMTest.java |  31 +-
 .../apache/sis/test/suite/FeatureTestSuite.java    |   2 +-
 76 files changed, 919 insertions(+), 380 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/JTSMapping.java b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/JTSMapping.java
new file mode 100644
index 0000000..0937ff6
--- /dev/null
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/JTSMapping.java
@@ -0,0 +1,373 @@
+/*
+ * 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.feature.jts;
+
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.GeometryCollection;
+import org.locationtech.jts.geom.GeometryFactory;
+import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.LinearRing;
+import org.locationtech.jts.geom.MultiLineString;
+import org.locationtech.jts.geom.MultiPoint;
+import org.locationtech.jts.geom.MultiPolygon;
+import org.locationtech.jts.geom.Point;
+import org.locationtech.jts.geom.Polygon;
+
+/**
+ * Set of Utility function and methods for mapping geometry types.
+ *
+ * @author Quentin Boileau (Geomatys)
+ * @author Johann Sorel (Geomatys)
+ * @version 2.0
+ * @since   2.0
+ * @module
+ */
+public final class JTSMapping {
+
+    private static final GeometryFactory GF = new GeometryFactory();
+
+    private JTSMapping() {
+    }
+
+    /**
+     * Force geometry type. If the given geometry is not of given class it will
+     * be adapted.
+     */
+    public static <T extends Geometry> T convertType(final Geometry geom, final Class<T> targetClass) {
+        if (geom == null) {
+            return null;
+        }
+
+        if (targetClass.isInstance(geom)) {
+            return (T) geom;
+        }
+
+        Geometry result;
+        if (targetClass == Point.class) {
+            result = convertToPoint(geom);
+        } else if (targetClass == MultiPoint.class) {
+            result = convertToMultiPoint(geom);
+        } else if (targetClass == LineString.class) {
+            result = convertToLineString(geom);
+        } else if (targetClass == MultiLineString.class) {
+            result = convertToMultiLineString(geom);
+        } else if (targetClass == Polygon.class) {
+            result = convertToPolygon(geom);
+        } else if (targetClass == MultiPolygon.class) {
+            result = convertToMultiPolygon(geom);
+        } else if (targetClass == GeometryCollection.class) {
+            result = convertToGeometryCollection(geom);
+        } else {
+            result = null;
+        }
+
+        if (result != null) {
+            //copy srid and user data
+            result.setSRID(geom.getSRID());
+            result.setUserData(geom.getUserData());
+        }
+
+        return targetClass.cast(result);
+    }
+
+    // Convert to Point --------------------------------------------------------
+    private static Point convertToPoint(final Geometry geom) {
+        if (geom instanceof Point) {
+            return convertToPoint((Point) geom);
+        } else if (geom instanceof MultiPoint) {
+            return convertToPoint((MultiPoint) geom);
+        } else if (geom instanceof LineString) {
+            return convertToPoint((LineString) geom);
+        } else if (geom instanceof MultiLineString) {
+            return convertToPoint((MultiLineString) geom);
+        } else if (geom instanceof Polygon) {
+            return convertToPoint((Polygon) geom);
+        } else if (geom instanceof MultiPolygon) {
+            return convertToPoint((MultiPolygon) geom);
+        }
+        return null;
+    }
+
+    private static Point convertToPoint(final Point pt) {
+        return pt;
+    }
+
+    private static Point convertToPoint(final MultiPoint pt) {
+        return pt.getCentroid();
+    }
+
+    private static Point convertToPoint(final LineString pt) {
+        return pt.getCentroid();
+    }
+
+    private static Point convertToPoint(final MultiLineString pt) {
+        return pt.getCentroid();
+    }
+
+    private static Point convertToPoint(final Polygon pt) {
+        return pt.getCentroid();
+    }
+
+    private static Point convertToPoint(final MultiPolygon pt) {
+        return pt.getCentroid();
+    }
+
+    // Convert to MultiPoint ---------------------------------------------------
+    private static MultiPoint convertToMultiPoint(final Geometry geom) {
+        if (geom instanceof Point) {
+            return convertToMultiPoint((Point) geom);
+        } else if (geom instanceof MultiPoint) {
+            return convertToMultiPoint((MultiPoint) geom);
+        } else if (geom instanceof LineString) {
+            return convertToMultiPoint((LineString) geom);
+        } else if (geom instanceof MultiLineString) {
+            return convertToMultiPoint((MultiLineString) geom);
+        } else if (geom instanceof Polygon) {
+            return convertToMultiPoint((Polygon) geom);
+        } else if (geom instanceof MultiPolygon) {
+            return convertToMultiPoint((MultiPolygon) geom);
+        }
+        return null;
+    }
+
+    private static MultiPoint convertToMultiPoint(final Point pt) {
+        return GF.createMultiPoint(new Point[]{pt});
+    }
+
+    private static MultiPoint convertToMultiPoint(final MultiPoint pt) {
+        return pt;
+    }
+
+    private static MultiPoint convertToMultiPoint(final LineString pt) {
+        return GF.createMultiPoint(pt.getCoordinates());
+    }
+
+    private static MultiPoint convertToMultiPoint(final MultiLineString pt) {
+        return GF.createMultiPoint(pt.getCoordinates());
+    }
+
+    private static MultiPoint convertToMultiPoint(final Polygon pt) {
+        return GF.createMultiPoint(pt.getCoordinates());
+    }
+
+    private static MultiPoint convertToMultiPoint(final MultiPolygon pt) {
+        return GF.createMultiPoint(pt.getCoordinates());
+    }
+
+    // Convert to LineString ---------------------------------------------------
+    private static LineString convertToLineString(final Geometry geom) {
+        if (geom instanceof Point) {
+            return convertToLineString((Point) geom);
+        } else if (geom instanceof MultiPoint) {
+            return convertToLineString((MultiPoint) geom);
+        } else if (geom instanceof LineString) {
+            return convertToLineString((LineString) geom);
+        } else if (geom instanceof MultiLineString) {
+            return convertToLineString((MultiLineString) geom);
+        } else if (geom instanceof Polygon) {
+            return convertToLineString((Polygon) geom);
+        } else if (geom instanceof MultiPolygon) {
+            return convertToLineString((MultiPolygon) geom);
+        }
+        return null;
+    }
+
+    private static LineString convertToLineString(final Point pt) {
+        return GF.createLineString(new Coordinate[]{pt.getCoordinate(), pt.getCoordinate()});
+    }
+
+    private static LineString convertToLineString(final MultiPoint pt) {
+        final Coordinate[] coords = pt.getCoordinates();
+        if (coords.length == 1) {
+            return GF.createLineString(new Coordinate[]{coords[0], coords[0]});
+        } else {
+            return GF.createLineString(coords);
+        }
+    }
+
+    private static LineString convertToLineString(final LineString pt) {
+        return pt;
+    }
+
+    private static LineString convertToLineString(final MultiLineString pt) {
+        return GF.createLineString(pt.getCoordinates());
+    }
+
+    private static LineString convertToLineString(final Polygon pt) {
+        return GF.createLineString(pt.getCoordinates());
+    }
+
+    private static LineString convertToLineString(final MultiPolygon pt) {
+        return GF.createLineString(pt.getCoordinates());
+    }
+
+    // Convert to MultiLineString ----------------------------------------------
+    private static MultiLineString convertToMultiLineString(final Geometry geom) {
+        if (geom instanceof Point) {
+            return convertToMultiLineString((Point) geom);
+        } else if (geom instanceof MultiPoint) {
+            return convertToMultiLineString((MultiPoint) geom);
+        } else if (geom instanceof LineString) {
+            return convertToMultiLineString((LineString) geom);
+        } else if (geom instanceof MultiLineString) {
+            return convertToMultiLineString((MultiLineString) geom);
+        } else if (geom instanceof Polygon) {
+            return convertToMultiLineString((Polygon) geom);
+        } else if (geom instanceof MultiPolygon) {
+            return convertToMultiLineString((MultiPolygon) geom);
+        }
+        return null;
+    }
+
+    private static MultiLineString convertToMultiLineString(final Point pt) {
+        return convertToMultiLineString(convertToLineString(pt));
+    }
+
+    private static MultiLineString convertToMultiLineString(final MultiPoint pt) {
+        return convertToMultiLineString(convertToLineString(pt));
+    }
+
+    private static MultiLineString convertToMultiLineString(final LineString pt) {
+        return GF.createMultiLineString(new LineString[]{pt});
+    }
+
+    private static MultiLineString convertToMultiLineString(final MultiLineString pt) {
+        return pt;
+    }
+
+    private static MultiLineString convertToMultiLineString(final Polygon pt) {
+        return convertToMultiLineString(GF.createLineString(pt.getCoordinates()));
+    }
+
+    private static MultiLineString convertToMultiLineString(final MultiPolygon pt) {
+        final int n = pt.getNumGeometries();
+        final LineString[] geoms = new LineString[n];
+        for (int i = 0; i < n; i++) {
+            geoms[i] = convertToLineString(pt.getGeometryN(i));
+        }
+        return GF.createMultiLineString(geoms);
+    }
+
+    // Convert to Polygon ------------------------------------------------------
+    private static Polygon convertToPolygon(final Geometry geom) {
+        if (geom instanceof Point) {
+            return convertToPolygon((Point) geom);
+        } else if (geom instanceof MultiPoint) {
+            return convertToPolygon((MultiPoint) geom);
+        } else if (geom instanceof LineString) {
+            return convertToPolygon((LineString) geom);
+        } else if (geom instanceof MultiLineString) {
+            return convertToPolygon((MultiLineString) geom);
+        } else if (geom instanceof Polygon) {
+            return convertToPolygon((Polygon) geom);
+        } else if (geom instanceof MultiPolygon) {
+            return convertToPolygon((MultiPolygon) geom);
+        }
+        return null;
+    }
+
+    private static Polygon convertToPolygon(final Point pt) {
+        LinearRing ring = GF.createLinearRing(new Coordinate[]{pt.getCoordinate(), pt.getCoordinate(), pt.getCoordinate(), pt.getCoordinate()});
+        return GF.createPolygon(ring, new LinearRing[0]);
+    }
+
+    private static Polygon convertToPolygon(final MultiPoint pt) {
+        return convertToPolygon(convertToLineString(pt));
+    }
+
+    private static Polygon convertToPolygon(final LineString pt) {
+        return GF.createPolygon(GF.createLinearRing(pt.getCoordinates()), new LinearRing[0]);
+    }
+
+    private static Polygon convertToPolygon(final MultiLineString pt) {
+        return convertToPolygon(convertToLineString(pt));
+    }
+
+    private static Polygon convertToPolygon(final Polygon pt) {
+        return pt;
+    }
+
+    private static Polygon convertToPolygon(final MultiPolygon pt) {
+        final int nbGeom = pt.getNumGeometries();
+        if (nbGeom == 0) {
+            return GF.createPolygon();
+        } else if (nbGeom == 1) {
+            return (Polygon) pt.getGeometryN(0);
+        } else {
+            return convertToPolygon(pt.convexHull());
+        }
+    }
+
+    // Convert to MultiPolygon -------------------------------------------------
+    private static MultiPolygon convertToMultiPolygon(final Geometry geom) {
+        if (geom instanceof Point) {
+            return convertToMultiPolygon((Point) geom);
+        } else if (geom instanceof MultiPoint) {
+            return convertToMultiPolygon((MultiPoint) geom);
+        } else if (geom instanceof LineString) {
+            return convertToMultiPolygon((LineString) geom);
+        } else if (geom instanceof MultiLineString) {
+            return convertToMultiPolygon((MultiLineString) geom);
+        } else if (geom instanceof Polygon) {
+            return convertToMultiPolygon((Polygon) geom);
+        } else if (geom instanceof MultiPolygon) {
+            return convertToMultiPolygon((MultiPolygon) geom);
+        }
+        return null;
+    }
+
+    private static MultiPolygon convertToMultiPolygon(final Point pt) {
+        return convertToMultiPolygon(convertToPolygon(pt));
+    }
+
+    private static MultiPolygon convertToMultiPolygon(final MultiPoint pt) {
+        return convertToMultiPolygon(convertToPolygon(pt));
+    }
+
+    private static MultiPolygon convertToMultiPolygon(final LineString pt) {
+        return convertToMultiPolygon(convertToPolygon(pt));
+    }
+
+    private static MultiPolygon convertToMultiPolygon(final MultiLineString pt) {
+        return convertToMultiPolygon(convertToPolygon(pt));
+    }
+
+    private static MultiPolygon convertToMultiPolygon(final Polygon pt) {
+        return GF.createMultiPolygon(new Polygon[]{pt});
+    }
+
+    private static MultiPolygon convertToMultiPolygon(final MultiPolygon pt) {
+        return pt;
+    }
+
+    private static GeometryCollection convertToGeometryCollection(final Geometry geom) {
+        if (geom instanceof GeometryCollection) {
+            return (GeometryCollection) geom;
+        }
+
+        if (geom instanceof Point) {
+            return convertToMultiPoint(geom);
+        } else if (geom instanceof LineString) {
+            return convertToMultiLineString(geom);
+        } else if (geom instanceof Polygon) {
+            return convertToMultiPolygon(geom);
+        }
+        return null;
+    }
+
+}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/AbstractSpatialFunction.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/AbstractSpatialFunction.java
index e6e98f5..daa3bad 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/AbstractSpatialFunction.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/AbstractSpatialFunction.java
@@ -79,7 +79,7 @@ public abstract class AbstractSpatialFunction extends NamedFunction implements F
 
         return sb.toString();
     }
-    
+
     protected static CoordinateReferenceSystem expectedCrs(FeatureType type, Expression exp) {
 
         final PropertyType expressionType = FeatureExpression.expectedType(exp, type, new FeatureTypeBuilder()).build();
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 e59ed55..ed21ced 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
@@ -23,13 +23,6 @@ import org.opengis.filter.expression.Function;
 import org.opengis.util.FactoryException;
 import org.apache.sis.internal.feature.FunctionRegister;
 import org.apache.sis.internal.feature.Resources;
-import org.apache.sis.internal.filter.sqlmm.todo.ST_ToGeomColl;
-import org.apache.sis.internal.filter.sqlmm.todo.ST_ToLineString;
-import org.apache.sis.internal.filter.sqlmm.todo.ST_ToMultiLine;
-import org.apache.sis.internal.filter.sqlmm.todo.ST_ToMultiPoint;
-import org.apache.sis.internal.filter.sqlmm.todo.ST_ToMultiPolygon;
-import org.apache.sis.internal.filter.sqlmm.todo.ST_ToPoint;
-import org.apache.sis.internal.filter.sqlmm.todo.ST_ToPolygon;
 import org.apache.sis.util.ArgumentChecks;
 
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Area.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Area.java
index 4af564b..8ef34c9 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Area.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Area.java
@@ -35,10 +35,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Area extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 8662819270100042027L;
 
     public static final String NAME = "ST_Area";
 
-    public ST_Area(Expression[] parameters) {
+    public ST_Area(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_AsBinary.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_AsBinary.java
index 2fcfb94..b1aec8d 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_AsBinary.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_AsBinary.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_AsBinary extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 543784193712423026L;
 
     public static final String NAME = "ST_AsBinary";
 
-    public ST_AsBinary(Expression[] parameters) {
+    public ST_AsBinary(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_AsGML.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_AsGML.java
index 94cf609..33ff181 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_AsGML.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_AsGML.java
@@ -33,10 +33,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_AsGML extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -2338915326478992665L;
 
     public static final String NAME = "ST_AsGML";
 
-    public ST_AsGML(Expression[] parameters) {
+    public ST_AsGML(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_AsText.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_AsText.java
index 64de78b..de4279d 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_AsText.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_AsText.java
@@ -35,10 +35,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_AsText extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 8629461252459501038L;
 
     public static final String NAME = "ST_AsText";
 
-    public ST_AsText(Expression[] parameters) {
+    public ST_AsText(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Boundary.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Boundary.java
index f700498..7e0951b 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Boundary.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Boundary.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Boundary extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 6907443570851622576L;
 
     public static final String NAME = "ST_Boundary";
 
-    public ST_Boundary(Expression[] parameters) {
+    public ST_Boundary(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Buffer.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Buffer.java
index b24c25d..ec6a1f5 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Buffer.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Buffer.java
@@ -70,7 +70,7 @@ final class ST_Buffer extends NamedFunction implements FeatureExpression {
      *
      * @throws IllegalArgumentException if the number of arguments is not equal to 2.
      */
-    ST_Buffer(final Expression[] parameters) {
+    ST_Buffer(final Expression... parameters) {
         super(parameters);
         ArgumentChecks.ensureExpectedCount("parameters", 2, parameters.length);
     }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Centroid.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Centroid.java
index f2f2b3b..35d4419 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Centroid.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Centroid.java
@@ -71,7 +71,7 @@ final class ST_Centroid extends NamedFunction implements FeatureExpression {
      *
      * @throws IllegalArgumentException if the number of arguments is not equal to 1.
      */
-    ST_Centroid(final Expression[] parameters) {
+    ST_Centroid(final Expression... parameters) {
         super(parameters);
         ArgumentChecks.ensureExpectedCount("parameters", 1, parameters.length);
     }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Contains.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Contains.java
index 52ebb89..c090ffa 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Contains.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Contains.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Contains extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -7225934838878061249L;
 
     public static final String NAME = "ST_Contains";
 
-    public ST_Contains(Expression[] parameters) {
+    public ST_Contains(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ConvexHull.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ConvexHull.java
index f23d0b9..c151271 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ConvexHull.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ConvexHull.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_ConvexHull extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -2523224117411417556L;
 
     public static final String NAME = "ST_ConvexHull";
 
-    public ST_ConvexHull(Expression[] parameters) {
+    public ST_ConvexHull(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_CoordDim.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_CoordDim.java
index 3b4927b..4f678ce 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_CoordDim.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_CoordDim.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_CoordDim extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 4730101640446055320L;
 
     public static final String NAME = "ST_CoordDim";
 
-    public ST_CoordDim(Expression[] parameters) {
+    public ST_CoordDim(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Crosses.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Crosses.java
index f42f6d9..e289719 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Crosses.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Crosses.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Crosses extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -3578826539931205291L;
 
     public static final String NAME = "ST_Crosses";
 
-    public ST_Crosses(Expression[] parameters) {
+    public ST_Crosses(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Difference.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Difference.java
index 1a1cf6f..f803801 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Difference.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Difference.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Difference extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -6949293332862547418L;
 
     public static final String NAME = "ST_Difference";
 
-    public ST_Difference(Expression[] parameters) {
+    public ST_Difference(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Dimension.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Dimension.java
index 772b9e1..9213307 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Dimension.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Dimension.java
@@ -33,10 +33,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Dimension extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -4084734402948897229L;
 
     public static final String NAME = "ST_Dimension";
 
-    public ST_Dimension(Expression[] parameters) {
+    public ST_Dimension(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Disjoint.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Disjoint.java
index ac69e1a..44c1e47 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Disjoint.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Disjoint.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 public final class ST_Disjoint extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -878251746247560050L;
 
     public static final String NAME = "ST_Disjoint";
 
-    public ST_Disjoint(Expression[] parameters) {
+    public ST_Disjoint(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Distance.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Distance.java
index d69bb48..94de72c 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Distance.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Distance.java
@@ -33,10 +33,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Distance extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 6484941686987546409L;
 
     public static final String NAME = "ST_Distance";
 
-    public ST_Distance(Expression[] parameters) {
+    public ST_Distance(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_EndPoint.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_EndPoint.java
index 43ff1ce..60d3127 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_EndPoint.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_EndPoint.java
@@ -35,10 +35,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_EndPoint extends AbstractAccessorSpatialFunction<LineString> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 3005045080078912918L;
 
     public static final String NAME = "ST_EndPoint";
 
-    public ST_EndPoint(Expression[] parameters) {
+    public ST_EndPoint(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Envelope.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Envelope.java
index d8a34d6..d4d4e08 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Envelope.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Envelope.java
@@ -52,11 +52,15 @@ import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
  * @module
  */
 public class ST_Envelope extends NamedFunction implements FeatureExpression {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 677890922998031096L;
 
     public static final String NAME = "ST_Envelope";
 
     private final Worker worker;
-    public ST_Envelope(Expression[] parameters) {
+    public ST_Envelope(Expression... parameters) {
         super(parameters);
         if (parameters == null || parameters.length != 1) throw new MismatchedDimensionException(
                 String.format(
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Equals.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Equals.java
index ccc35b7..75f9c50 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Equals.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Equals.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Equals extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 7173751615288222316L;
 
     public static final String NAME = "ST_Equals";
 
-    public ST_Equals(Expression[] parameters) {
+    public ST_Equals(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ExplicitPoint.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ExplicitPoint.java
index acb7a57..b18e9c8 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ExplicitPoint.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ExplicitPoint.java
@@ -36,10 +36,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_ExplicitPoint extends AbstractAccessorSpatialFunction<Point> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -519090616041839273L;
 
     public static final String NAME = "ST_ExplicitPoint";
 
-    public ST_ExplicitPoint(Expression[] parameters) {
+    public ST_ExplicitPoint(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ExteriorRing.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ExteriorRing.java
index cd57969..d677f6c 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ExteriorRing.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ExteriorRing.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_ExteriorRing extends AbstractAccessorSpatialFunction<Polygon> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -4351063096217766472L;
 
     public static final String NAME = "ST_ExteriorRing";
 
-    public ST_ExteriorRing(Expression[] parameters) {
+    public ST_ExteriorRing(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_GeomCollection.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_GeomCollection.java
index c41f9c9..0105f44 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_GeomCollection.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_GeomCollection.java
@@ -28,10 +28,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_GeomCollection extends AbstractGeomConstructor {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -6639181263539125735L;
 
     public static final String NAME = "ST_GeomCollection";
 
-    public ST_GeomCollection(Expression[] parameters) {
+    public ST_GeomCollection(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_GeometryN.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_GeometryN.java
index d35a51f..05639dd 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_GeometryN.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_GeometryN.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_GeometryN extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -4368199731276946357L;
 
     public static final String NAME = "ST_GeometryN";
 
-    public ST_GeometryN(Expression[] parameters) {
+    public ST_GeometryN(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_GeometryType.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_GeometryType.java
index 9d3105f..6dfd0f1 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_GeometryType.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_GeometryType.java
@@ -43,6 +43,10 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_GeometryType extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 3950622078110541672L;
 
     public static final String NAME = "ST_GeometryType";
 
@@ -58,7 +62,7 @@ final class ST_GeometryType extends AbstractAccessorSpatialFunction<Geometry> {
         TYPES.put(Geometry.class,           "ST_Geometry");
     }
 
-    public ST_GeometryType(Expression[] parameters) {
+    public ST_GeometryType(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_InteriorRingN.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_InteriorRingN.java
index 162525b..a08ebb3 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_InteriorRingN.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_InteriorRingN.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_InteriorRingN extends AbstractAccessorSpatialFunction<Polygon> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -8020999740090022880L;
 
     public static final String NAME = "ST_InteriorRingN";
 
-    public ST_InteriorRingN(Expression[] parameters) {
+    public ST_InteriorRingN(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Intersection.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Intersection.java
index c8d43a7..d68eb38 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Intersection.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Intersection.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Intersection extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 2438604585868953457L;
 
     public static final String NAME = "ST_Intersection";
 
-    public ST_Intersection(Expression[] parameters) {
+    public ST_Intersection(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Intersects.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Intersects.java
index c814c3d..7ebc615 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Intersects.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Intersects.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Intersects extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -8906412891862094166L;
 
     public static final String NAME = "ST_Intersects";
 
-    public ST_Intersects(Expression[] parameters) {
+    public ST_Intersects(Expression... parameters) {
         super(parameters);
     }
 
@@ -47,7 +51,7 @@ final class ST_Intersects extends AbstractBinarySpatialFunction {
     }
 
     @Override
-    public Object execute(Geometry left, Geometry right, Object... params) throws ParseException {
+    public Boolean execute(Geometry left, Geometry right, Object... params) throws ParseException {
         return left.intersects(right);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Is3D.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Is3D.java
index 8f746d6..658d785 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Is3D.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Is3D.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Is3D extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 1572271391650367796L;
 
     public static final String NAME = "ST_Is3D";
 
-    public ST_Is3D(Expression[] parameters) {
+    public ST_Is3D(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsClosed.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsClosed.java
index 9d687ef..a7e3ce2 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsClosed.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsClosed.java
@@ -35,10 +35,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_IsClosed extends AbstractAccessorSpatialFunction<LineString> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -3036161984738401938L;
 
     public static final String NAME = "ST_IsClosed";
 
-    public ST_IsClosed(Expression[] parameters) {
+    public ST_IsClosed(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsEmpty.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsEmpty.java
index 553e3c7..83d0744 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsEmpty.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsEmpty.java
@@ -33,10 +33,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_IsEmpty extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 2758867462786336526L;
 
     public static final String NAME = "ST_IsEmpty";
 
-    public ST_IsEmpty(Expression[] parameters) {
+    public ST_IsEmpty(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsRing.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsRing.java
index 3410f17..4c76ec6 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsRing.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsRing.java
@@ -35,10 +35,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_IsRing extends AbstractAccessorSpatialFunction<LineString> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 7067326611766377264L;
 
     public static final String NAME = "ST_IsRing";
 
-    public ST_IsRing(Expression[] parameters) {
+    public ST_IsRing(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsSimple.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsSimple.java
index 02f683f..ddd7fee 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsSimple.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsSimple.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_IsSimple extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -4153525354330682049L;
 
     public static final String NAME = "ST_IsSimple";
 
-    public ST_IsSimple(Expression[] parameters) {
+    public ST_IsSimple(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsValid.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsValid.java
index 6fa6c83..52497a0 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsValid.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_IsValid.java
@@ -33,10 +33,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_IsValid extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -7619290650312884723L;
 
     public static final String NAME = "ST_IsValid";
 
-    public ST_IsValid(Expression[] parameters) {
+    public ST_IsValid(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Length.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Length.java
index f4a498b..8ebd793 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Length.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Length.java
@@ -35,10 +35,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Length extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 3778625608653432659L;
 
     public static final String NAME = "ST_Length";
 
-    public ST_Length(Expression[] parameters) {
+    public ST_Length(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_LineString.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_LineString.java
index 571eb60..c7bb0a1 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_LineString.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_LineString.java
@@ -27,10 +27,13 @@ import org.apache.sis.feature.builder.PropertyTypeBuilder;
 import org.apache.sis.internal.filter.NamedFunction;
 import org.apache.sis.internal.feature.FeatureExpression;
 import org.apache.sis.internal.filter.FilterGeometryUtils;
+import static org.apache.sis.internal.filter.FilterGeometryUtils.getWKBReader;
+import static org.apache.sis.internal.filter.FilterGeometryUtils.getWKTReader;
 import org.apache.sis.referencing.CRS;
 import org.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.LineString;
 import org.locationtech.jts.geom.Point;
+import org.locationtech.jts.io.ParseException;
 import org.opengis.feature.FeatureType;
 import org.opengis.filter.expression.Expression;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
@@ -54,6 +57,10 @@ import org.opengis.util.FactoryException;
  * @module
  */
 final class ST_LineString extends NamedFunction implements FeatureExpression {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 3654052127628404584L;
 
     /**
      * Name of this function as defined by SQL/MM standard.
@@ -68,7 +75,7 @@ final class ST_LineString extends NamedFunction implements FeatureExpression {
      *
      * @throws IllegalArgumentException if the number of arguments is less then one.
      */
-    ST_LineString(final Expression[] parameters) {
+    ST_LineString(final Expression... parameters) {
         super(parameters);
         if (parameters.length < 1) {
             throw new IllegalArgumentException("ST_LineString function expect 2 or more parameters");
@@ -95,30 +102,53 @@ final class ST_LineString extends NamedFunction implements FeatureExpression {
         }
 
         Object x = parameters.get(0).evaluate(object);
-        if (x == null) {
-          x = Collections.EMPTY_LIST;
-        } else if (x instanceof Point) {
-            x = Arrays.asList(x);
-        } else if (!(x instanceof Iterable)) {
-            warning(new Exception("ST_LineString called with an object which is not a iterable"));
-            return null;
-        }
+        LineString geometry = null;
+        if (x instanceof byte[]) {
+            //wkb
+            try {
+                //try to convert from WKB
+                geometry = (LineString) getWKBReader().read((byte[]) x);
+            } catch (ParseException | ClassCastException ex) {
+                //we have try
+                warning(ex);
+            }
+        } else if (x instanceof String) {
+            //wkt
+            //todo handle gml
+            try {
+                //try to convert from WKT
+                geometry = (LineString) getWKTReader().read(x.toString());
+            } catch (ParseException | ClassCastException ex) {
+                //we have try
+                warning(ex);
+            }
+        } else {
+            if (x == null) {
+              x = Collections.EMPTY_LIST;
+            } else if (x instanceof Point) {
+                x = Arrays.asList(x);
+            } else if (!(x instanceof Iterable)) {
+                warning(new Exception("ST_LineString called with an object which is not a iterable"));
+                return null;
+            }
 
-        Iterator i = ((Iterable) x).iterator();
-        final List<Coordinate> coords = new ArrayList<>();
-        while (i.hasNext()) {
-            Object cdt = i.next();
-            if (cdt instanceof Point) {
-                coords.add(((Point) cdt).getCoordinate());
-            } else if (cdt instanceof Coordinate) {
-                coords.add(((Coordinate) cdt));
-            } else {
-                //what should we do ?
+            Iterator i = ((Iterable) x).iterator();
+            final List<Coordinate> coords = new ArrayList<>();
+            while (i.hasNext()) {
+                Object cdt = i.next();
+                if (cdt instanceof Point) {
+                    coords.add(((Point) cdt).getCoordinate());
+                } else if (cdt instanceof Coordinate) {
+                    coords.add(((Coordinate) cdt));
+                } else {
+                    //what should we do ?
+                }
             }
+
+            geometry = FilterGeometryUtils.GF.createLineString(coords.toArray(new Coordinate[coords.size()]));
         }
 
-        final LineString geometry = FilterGeometryUtils.GF.createLineString(coords.toArray(new Coordinate[coords.size()]));
-        geometry.setUserData(crs);
+        if (geometry != null) geometry.setUserData(crs);
         return geometry;
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_MultiLineString.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_MultiLineString.java
index 0b3c08e..03dd413 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_MultiLineString.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_MultiLineString.java
@@ -27,11 +27,15 @@ import org.opengis.filter.expression.Expression;
  * @since   2.0
  * @module
  */
-final class ST_MultiLineString extends AbstractGeomConstructor{
+final class ST_MultiLineString extends AbstractGeomConstructor {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 1756693505934851018L;
 
     public static final String NAME = "ST_MultiLineString";
 
-    public ST_MultiLineString(Expression[] parameters){
+    public ST_MultiLineString(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_MultiPoint.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_MultiPoint.java
index 666d5cb..51da090 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_MultiPoint.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_MultiPoint.java
@@ -28,10 +28,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_MultiPoint extends AbstractGeomConstructor {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 787499914563380171L;
 
     public static final String NAME = "ST_MultiPoint";
 
-    public ST_MultiPoint(Expression[] parameters){
+    public ST_MultiPoint(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_MultiPolygon.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_MultiPolygon.java
index fcf1910..959d49b 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_MultiPolygon.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_MultiPolygon.java
@@ -27,11 +27,15 @@ import org.opengis.filter.expression.Expression;
  * @since   2.0
  * @module
  */
-final class ST_MultiPolygon extends AbstractGeomConstructor{
+final class ST_MultiPolygon extends AbstractGeomConstructor {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -847780070815971604L;
 
     public static final String NAME = "ST_MultiPolygon";
 
-    public ST_MultiPolygon(Expression[] parameters){
+    public ST_MultiPolygon(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_NumGeometries.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_NumGeometries.java
index ce756c4..90fa9e0 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_NumGeometries.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_NumGeometries.java
@@ -33,10 +33,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_NumGeometries extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 3736987404066163773L;
 
     public static final String NAME = "ST_NumGeometries";
 
-    public ST_NumGeometries(Expression[] parameters) {
+    public ST_NumGeometries(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_NumInteriorRings.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_NumInteriorRings.java
index 2deb6d2..da743c5 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_NumInteriorRings.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_NumInteriorRings.java
@@ -35,10 +35,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_NumInteriorRings extends AbstractAccessorSpatialFunction<Polygon> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -7278238582506203440L;
 
     public static final String NAME = "ST_NumInteriorRings";
 
-    public ST_NumInteriorRings(Expression[] parameters) {
+    public ST_NumInteriorRings(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_NumPoints.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_NumPoints.java
index 1db8341..cd7bd63 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_NumPoints.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_NumPoints.java
@@ -33,10 +33,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_NumPoints extends AbstractAccessorSpatialFunction<LineString> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -5615941135387263521L;
 
     public static final String NAME = "ST_NumPoints";
 
-    public ST_NumPoints(Expression[] parameters) {
+    public ST_NumPoints(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Overlaps.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Overlaps.java
index 1691931..805aa70 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Overlaps.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Overlaps.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Overlaps extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -3322606303065731156L;
 
     public static final String NAME = "ST_Overlaps";
 
-    public ST_Overlaps(Expression[] parameters) {
+    public ST_Overlaps(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Perimeter.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Perimeter.java
index 583960e..ef5901b 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Perimeter.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Perimeter.java
@@ -36,10 +36,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Perimeter extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -1312027255077461307L;
 
     public static final String NAME = "ST_Perimeter";
 
-    public ST_Perimeter(Expression[] parameters) {
+    public ST_Perimeter(Expression... parameters) {
         super(parameters);
     }
 
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 8940612..30d7175 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
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.internal.filter.sqlmm;
 
+import java.math.BigDecimal;
 import org.apache.sis.feature.builder.AttributeTypeBuilder;
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.feature.builder.PropertyTypeBuilder;
@@ -24,6 +25,7 @@ import org.apache.sis.internal.feature.FeatureExpression;
 import org.apache.sis.internal.filter.FilterGeometryUtils;
 import org.apache.sis.referencing.CRS;
 import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.Point;
 import org.opengis.feature.FeatureType;
 import org.opengis.filter.expression.Expression;
@@ -48,6 +50,10 @@ import org.opengis.util.FactoryException;
  * @module
  */
 final class ST_Point extends NamedFunction implements FeatureExpression {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -6280773709322350835L;
 
     /**
      * Name of this function as defined by SQL/MM standard.
@@ -62,23 +68,25 @@ final class ST_Point extends NamedFunction implements FeatureExpression {
      *
      * @throws IllegalArgumentException if the number of arguments is less then two.
      */
-    ST_Point(final Expression[] parameters) {
+    ST_Point(final Expression... parameters) {
         super(parameters);
-        if (parameters.length < 2) {
-            throw new IllegalArgumentException("ST_Point function expect 2 or more parameters");
+        if (parameters.length < 1 || parameters.length > 4) {
+            throw new IllegalArgumentException("ST_Point function expect 1 to 4 parameters");
         }
 
-        if (this.parameters.size() > 2) {
-            Object cdt = this.parameters.get(2).evaluate(null);
-            if (cdt instanceof Number) {
-                try {
-                    constantCrs = CRS.forCode("EPSG:" + ((Number) cdt).intValue());
-                } catch (FactoryException ex) {
-                    warning(ex);
-                }
-            } else if (cdt instanceof CoordinateReferenceSystem) {
-                constantCrs = (CoordinateReferenceSystem) cdt;
-            }
+        int nbarg = this.parameters.size();
+        switch (nbarg) {
+            case 2:
+                constantCrs = toCrs(null, this.parameters.get(1));
+                break;
+            case 3:
+                constantCrs = toCrs(null, this.parameters.get(2));
+                break;
+            case 4:
+                constantCrs = toCrs(null, this.parameters.get(3));
+                break;
+            default:
+                break;
         }
     }
 
@@ -91,26 +99,59 @@ final class ST_Point extends NamedFunction implements FeatureExpression {
     }
 
     @Override
-    public Object evaluate(Object object) {
-        Number x = parameters.get(0).evaluate(object, Number.class);
-        Number y = parameters.get(1).evaluate(object, Number.class);
+    public Object evaluate(Object candidate) {
+
         CoordinateReferenceSystem crs = constantCrs;
-        if (crs == null && parameters.size() > 2) {
-            Object cdt = parameters.get(2).evaluate(object);
-            if (cdt instanceof Number) {
-                try {
-                    crs = CRS.forCode("EPSG:" + ((Number) cdt).intValue());
-                } catch (FactoryException ex) {
-                    warning(ex);
+        final int nbarg = parameters.size();
+        Geometry geom;
+        if (nbarg == 1) {
+            //WKB or WKT
+            geom = FilterGeometryUtils.toGeometry(candidate, parameters.get(0));
+
+        } else if (nbarg == 2) {
+            final Object arg0 = parameters.get(0).evaluate(candidate);
+            final Object arg1 = parameters.get(1).evaluate(candidate);
+            if (arg0 instanceof Number) {
+                // X,Y
+                final Number obj1 = (Number) arg0;
+                final Number obj2 = (Number) arg1;
+                geom = FilterGeometryUtils.GF.createPoint(new Coordinate(obj1.doubleValue(), obj2.doubleValue()));
+            } else {
+                //WKT/WKB + srid
+                geom = FilterGeometryUtils.toGeometry(candidate, parameters.get(0));
+                if (crs == null) {
+                    crs = toCrs(candidate, parameters.get(1));
                 }
-            } else if (cdt instanceof CoordinateReferenceSystem) {
-                crs = (CoordinateReferenceSystem) cdt;
             }
+        } else if (nbarg == 3) {
+            final Number obj1 = parameters.get(0).evaluate(candidate, Number.class);
+            final Number obj2 = parameters.get(1).evaluate(candidate, Number.class);
+            final Object obj3 = parameters.get(2).evaluate(candidate);
+            geom = FilterGeometryUtils.GF.createPoint(new Coordinate(obj1.doubleValue(), obj2.doubleValue()));
+            if (obj3 instanceof Float || obj3 instanceof Double || obj3 instanceof BigDecimal) {
+                // Z
+                geom.getCoordinate().z = ((Number) obj3).doubleValue();
+            } else {
+                // srid
+                if (crs == null) {
+                    crs = toCrs(candidate, parameters.get(2));
+                }
+            }
+        } else if (nbarg == 4) {
+            final Number obj1 = parameters.get(0).evaluate(candidate, Number.class);
+            final Number obj2 = parameters.get(1).evaluate(candidate, Number.class);
+            final Number obj3 = parameters.get(2).evaluate(candidate, Number.class);
+            geom = FilterGeometryUtils.GF.createPoint(new Coordinate(obj1.doubleValue(), obj2.doubleValue(), obj3.doubleValue()));
+            if (crs == null) {
+                crs = toCrs(candidate, parameters.get(3));
+            }
+        } else {
+            //should not happen,constructor prevents it
+            geom = null;
         }
 
-        final Point point = FilterGeometryUtils.GF.createPoint(new Coordinate(x.doubleValue(), y.doubleValue()));
-        point.setUserData(crs);
-        return point;
+        if (geom != null) geom.setUserData(crs);
+        return geom;
     }
 
     @Override
@@ -125,4 +166,18 @@ final class ST_Point extends NamedFunction implements FeatureExpression {
         return atb;
     }
 
+    private CoordinateReferenceSystem toCrs(Object candidate, Expression exp) {
+        Object cdt = exp.evaluate(candidate);
+        if (cdt instanceof Number) {
+            try {
+                cdt = CRS.forCode("EPSG:" + ((Number) cdt).intValue());
+            } catch (FactoryException ex) {
+                warning(ex);
+            }
+        } else if (cdt instanceof CoordinateReferenceSystem) {
+            return (CoordinateReferenceSystem) cdt;
+        }
+        return null;
+    }
+
 }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_PointN.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_PointN.java
index aec35ee..e5c7530 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_PointN.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_PointN.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_PointN extends AbstractAccessorSpatialFunction<LineString> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 6209252271398378085L;
 
     public static final String NAME = "ST_PointN";
 
-    public ST_PointN(Expression[] parameters) {
+    public ST_PointN(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_PointOnSurface.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_PointOnSurface.java
index d683875..20d0c16 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_PointOnSurface.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_PointOnSurface.java
@@ -37,10 +37,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_PointOnSurface extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 4583128428102106294L;
 
     public static final String NAME = "ST_PointOnSurface";
 
-    public ST_PointOnSurface(Expression[] parameters) {
+    public ST_PointOnSurface(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Polygon.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Polygon.java
index 4cc0c6d..c490649 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Polygon.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Polygon.java
@@ -31,10 +31,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Polygon extends AbstractGeomConstructor {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 852966071102079242L;
 
     public static final String NAME = "ST_Polygon";
 
-    public ST_Polygon(Expression[] parameters){
+    public ST_Polygon(Expression... parameters){
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Relate.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Relate.java
index 71b6202..0d28272 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Relate.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Relate.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Relate extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 5219117092935978607L;
 
     public static final String NAME = "ST_Relate";
 
-    public ST_Relate(Expression[] parameters) {
+    public ST_Relate(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_SRID.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_SRID.java
index 29b822e..11023b6 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_SRID.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_SRID.java
@@ -33,10 +33,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_SRID extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -9096441878310687365L;
 
     public static final String NAME = "ST_SRID";
 
-    public ST_SRID(Expression[] parameters) {
+    public ST_SRID(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Simplify.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Simplify.java
index 7cb09ea..9aa2402 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Simplify.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Simplify.java
@@ -67,7 +67,7 @@ final class ST_Simplify extends NamedFunction implements FeatureExpression {
      *
      * @throws IllegalArgumentException if the number of arguments is not equal to 2.
      */
-    ST_Simplify(final Expression[] parameters) {
+    ST_Simplify(final Expression... parameters) {
         super(parameters);
         ArgumentChecks.ensureExpectedCount("parameters", 2, parameters.length);
     }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_SimplifyPreserveTopology.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_SimplifyPreserveTopology.java
index e264326..42c65f9 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_SimplifyPreserveTopology.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_SimplifyPreserveTopology.java
@@ -67,7 +67,7 @@ final class ST_SimplifyPreserveTopology extends NamedFunction implements Feature
      *
      * @throws IllegalArgumentException if the number of arguments is not equal to 2.
      */
-    ST_SimplifyPreserveTopology(final Expression[] parameters) {
+    ST_SimplifyPreserveTopology(final Expression... parameters) {
         super(parameters);
         ArgumentChecks.ensureExpectedCount("parameters", 2, parameters.length);
     }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_StartPoint.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_StartPoint.java
index 039136b..d66c619 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_StartPoint.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_StartPoint.java
@@ -37,10 +37,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_StartPoint extends AbstractAccessorSpatialFunction<LineString> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -3584681263405936434L;
 
     public static final String NAME = "ST_StartPoint";
 
-    public ST_StartPoint(Expression[] parameters) {
+    public ST_StartPoint(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_SymDifference.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_SymDifference.java
index 3c49b1b..e64bb18 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_SymDifference.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_SymDifference.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_SymDifference extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 8791170084255971187L;
 
     public static final String NAME = "ST_SymDifference";
 
-    public ST_SymDifference(Expression[] parameters) {
+    public ST_SymDifference(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToGeomColl.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToGeomColl.java
similarity index 76%
rename from core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToGeomColl.java
rename to core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToGeomColl.java
index 5adef19..a8768de 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToGeomColl.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToGeomColl.java
@@ -14,14 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.filter.sqlmm.todo;
+package org.apache.sis.internal.filter.sqlmm;
 
-import org.apache.sis.internal.filter.sqlmm.AbstractAccessorSpatialFunction;
 import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.GeometryCollection;
 import java.text.ParseException;
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.feature.builder.PropertyTypeBuilder;
+import org.apache.sis.internal.feature.jts.JTSMapping;
 import org.opengis.feature.FeatureType;
 import org.opengis.filter.expression.Expression;
 
@@ -34,11 +34,15 @@ import org.opengis.filter.expression.Expression;
  * @since   2.0
  * @module
  */
-public final class ST_ToGeomColl extends AbstractAccessorSpatialFunction<Geometry> {
+final class ST_ToGeomColl extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -4026503261668900371L;
 
     public static final String NAME = "ST_ToGeomColl";
 
-    public ST_ToGeomColl(Expression[] parameters) {
+    public ST_ToGeomColl(Expression... parameters) {
         super(parameters);
     }
 
@@ -54,14 +58,14 @@ public final class ST_ToGeomColl extends AbstractAccessorSpatialFunction<Geometr
 
     @Override
     public Object execute(Geometry geom, Object... params) throws ParseException {
-        final Geometry env = MappingUtils.convertType(geom, GeometryCollection.class);
-        env.setSRID(geom.getSRID());
-        return env;
+        return JTSMapping.convertType(geom, GeometryCollection.class);
     }
 
     @Override
     public PropertyTypeBuilder expectedType(FeatureType valueType, FeatureTypeBuilder addTo) {
-        return addTo.addAttribute(Geometry.class).setName(NAME);
+        return addTo.addAttribute(Geometry.class)
+                .setCRS(expectedCrs(valueType, parameters.get(0)))
+                .setName(NAME);
     }
 
 }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToLineString.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToLineString.java
similarity index 76%
rename from core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToLineString.java
rename to core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToLineString.java
index cbcbec6..0c487cc 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToLineString.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToLineString.java
@@ -14,14 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.filter.sqlmm.todo;
+package org.apache.sis.internal.filter.sqlmm;
 
-import org.apache.sis.internal.filter.sqlmm.AbstractAccessorSpatialFunction;
 import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.LineString;
 import java.text.ParseException;
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.feature.builder.PropertyTypeBuilder;
+import org.apache.sis.internal.feature.jts.JTSMapping;
 import org.opengis.feature.FeatureType;
 import org.opengis.filter.expression.Expression;
 
@@ -34,11 +34,15 @@ import org.opengis.filter.expression.Expression;
  * @since   2.0
  * @module
  */
-public final class ST_ToLineString extends AbstractAccessorSpatialFunction<Geometry> {
+final class ST_ToLineString extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 5061161379544404715L;
 
     public static final String NAME = "ST_ToLineString";
 
-    public ST_ToLineString(Expression[] parameters) {
+    public ST_ToLineString(Expression... parameters) {
         super(parameters);
     }
 
@@ -54,14 +58,14 @@ public final class ST_ToLineString extends AbstractAccessorSpatialFunction<Geome
 
     @Override
     public Object execute(Geometry geom, Object... params) throws ParseException {
-        final Geometry env = MappingUtils.convertType(geom, LineString.class);
-        env.setSRID(geom.getSRID());
-        return env;
+        return JTSMapping.convertType(geom, LineString.class);
     }
 
     @Override
     public PropertyTypeBuilder expectedType(FeatureType valueType, FeatureTypeBuilder addTo) {
-        return addTo.addAttribute(Geometry.class).setName(NAME);
+        return addTo.addAttribute(Geometry.class)
+                .setCRS(expectedCrs(valueType, parameters.get(0)))
+                .setName(NAME);
     }
 
 }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToMultiLine.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToMultiLine.java
similarity index 75%
rename from core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToMultiLine.java
rename to core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToMultiLine.java
index edd8aa5..ed665a1 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToMultiLine.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToMultiLine.java
@@ -14,14 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.filter.sqlmm.todo;
+package org.apache.sis.internal.filter.sqlmm;
 
-import org.apache.sis.internal.filter.sqlmm.AbstractAccessorSpatialFunction;
 import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.MultiLineString;
 import java.text.ParseException;
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.feature.builder.PropertyTypeBuilder;
+import org.apache.sis.internal.feature.jts.JTSMapping;
 import org.opengis.feature.FeatureType;
 import org.opengis.filter.expression.Expression;
 
@@ -34,11 +34,15 @@ import org.opengis.filter.expression.Expression;
  * @since   2.0
  * @module
  */
-public final class ST_ToMultiLine extends AbstractAccessorSpatialFunction<Geometry> {
+final class ST_ToMultiLine extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 4516671077052073740L;
 
     public static final String NAME = "ST_ToMultiLine";
 
-    public ST_ToMultiLine(Expression[] parameters) {
+    public ST_ToMultiLine(Expression... parameters) {
         super(parameters);
     }
 
@@ -54,14 +58,14 @@ public final class ST_ToMultiLine extends AbstractAccessorSpatialFunction<Geomet
 
     @Override
     public Object execute(Geometry geom, Object... params) throws ParseException {
-        final Geometry env = MappingUtils.convertType(geom, MultiLineString.class);
-        env.setSRID(geom.getSRID());
-        return env;
+        return JTSMapping.convertType(geom, MultiLineString.class);
     }
 
     @Override
     public PropertyTypeBuilder expectedType(FeatureType valueType, FeatureTypeBuilder addTo) {
-        return addTo.addAttribute(MultiLineString.class).setName(NAME);
+        return addTo.addAttribute(MultiLineString.class)
+                .setCRS(expectedCrs(valueType, parameters.get(0)))
+                .setName(NAME);
     }
 
 }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToMultiPoint.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToMultiPoint.java
similarity index 76%
rename from core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToMultiPoint.java
rename to core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToMultiPoint.java
index f3265f6..ec680ce 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToMultiPoint.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToMultiPoint.java
@@ -14,14 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.filter.sqlmm.todo;
+package org.apache.sis.internal.filter.sqlmm;
 
-import org.apache.sis.internal.filter.sqlmm.AbstractAccessorSpatialFunction;
 import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.MultiPoint;
 import java.text.ParseException;
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.feature.builder.PropertyTypeBuilder;
+import org.apache.sis.internal.feature.jts.JTSMapping;
 import org.opengis.feature.FeatureType;
 import org.opengis.filter.expression.Expression;
 
@@ -34,11 +34,15 @@ import org.opengis.filter.expression.Expression;
  * @since   2.0
  * @module
  */
-public final class ST_ToMultiPoint extends AbstractAccessorSpatialFunction<Geometry> {
+final class ST_ToMultiPoint extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -2683987052895075949L;
 
     public static final String NAME = "ST_ToMultiPoint";
 
-    public ST_ToMultiPoint(Expression[] parameters) {
+    public ST_ToMultiPoint(Expression... parameters) {
         super(parameters);
     }
 
@@ -54,14 +58,14 @@ public final class ST_ToMultiPoint extends AbstractAccessorSpatialFunction<Geome
 
     @Override
     public Object execute(Geometry geom, Object... params) throws ParseException {
-        final Geometry env = MappingUtils.convertType(geom, MultiPoint.class);
-        env.setSRID(geom.getSRID());
-        return env;
+        return JTSMapping.convertType(geom, MultiPoint.class);
     }
 
     @Override
     public PropertyTypeBuilder expectedType(FeatureType valueType, FeatureTypeBuilder addTo) {
-        return addTo.addAttribute(MultiPoint.class).setName(NAME);
+        return addTo.addAttribute(MultiPoint.class)
+                .setCRS(expectedCrs(valueType, parameters.get(0)))
+                .setName(NAME);
     }
 
 }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToMultiPolygon.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToMultiPolygon.java
similarity index 75%
rename from core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToMultiPolygon.java
rename to core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToMultiPolygon.java
index 48caf60..ce712a3 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToMultiPolygon.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToMultiPolygon.java
@@ -14,14 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.filter.sqlmm.todo;
+package org.apache.sis.internal.filter.sqlmm;
 
-import org.apache.sis.internal.filter.sqlmm.AbstractAccessorSpatialFunction;
 import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.MultiPolygon;
 import java.text.ParseException;
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.feature.builder.PropertyTypeBuilder;
+import org.apache.sis.internal.feature.jts.JTSMapping;
 import org.opengis.feature.FeatureType;
 import org.opengis.filter.expression.Expression;
 
@@ -34,11 +34,15 @@ import org.opengis.filter.expression.Expression;
  * @since   2.0
  * @module
  */
-public final class ST_ToMultiPolygon extends AbstractAccessorSpatialFunction<Geometry> {
+final class ST_ToMultiPolygon extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 4190767609852261562L;
 
     public static final String NAME = "ST_ToMultiPolygon";
 
-    public ST_ToMultiPolygon(Expression[] parameters) {
+    public ST_ToMultiPolygon(Expression... parameters) {
         super(parameters);
     }
 
@@ -54,14 +58,14 @@ public final class ST_ToMultiPolygon extends AbstractAccessorSpatialFunction<Geo
 
     @Override
     public Object execute(Geometry geom, Object... params) throws ParseException {
-        final Geometry env = MappingUtils.convertType(geom, MultiPolygon.class);
-        env.setSRID(geom.getSRID());
-        return env;
+        return JTSMapping.convertType(geom, MultiPolygon.class);
     }
 
     @Override
     public PropertyTypeBuilder expectedType(FeatureType valueType, FeatureTypeBuilder addTo) {
-        return addTo.addAttribute(MultiPolygon.class).setName(NAME);
+        return addTo.addAttribute(MultiPolygon.class)
+                .setCRS(expectedCrs(valueType, parameters.get(0)))
+                .setName(NAME);
     }
 
 }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToPoint.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToPoint.java
similarity index 76%
rename from core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToPoint.java
rename to core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToPoint.java
index 3b92b7b..397b3c0 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToPoint.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToPoint.java
@@ -14,14 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.filter.sqlmm.todo;
+package org.apache.sis.internal.filter.sqlmm;
 
-import org.apache.sis.internal.filter.sqlmm.AbstractAccessorSpatialFunction;
 import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.Point;
 import java.text.ParseException;
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.feature.builder.PropertyTypeBuilder;
+import org.apache.sis.internal.feature.jts.JTSMapping;
 import org.opengis.feature.FeatureType;
 import org.opengis.filter.expression.Expression;
 
@@ -34,11 +34,15 @@ import org.opengis.filter.expression.Expression;
  * @since   2.0
  * @module
  */
-public final class ST_ToPoint extends AbstractAccessorSpatialFunction<Geometry> {
+final class ST_ToPoint extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -2553595500105961498L;
 
     public static final String NAME = "ST_ToPoint";
 
-    public ST_ToPoint(Expression[] parameters) {
+    public ST_ToPoint(Expression... parameters) {
         super(parameters);
     }
 
@@ -54,14 +58,14 @@ public final class ST_ToPoint extends AbstractAccessorSpatialFunction<Geometry>
 
     @Override
     public Object execute(Geometry geom, Object... params) throws ParseException {
-        final Geometry env = MappingUtils.convertType(geom, Point.class);
-        env.setSRID(geom.getSRID());
-        return env;
+        return JTSMapping.convertType(geom, Point.class);
     }
 
     @Override
     public PropertyTypeBuilder expectedType(FeatureType valueType, FeatureTypeBuilder addTo) {
-        return addTo.addAttribute(Point.class).setName(NAME);
+        return addTo.addAttribute(Point.class)
+                .setCRS(expectedCrs(valueType, parameters.get(0)))
+                .setName(NAME);
     }
 
 }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToPolygon.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToPolygon.java
similarity index 76%
rename from core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToPolygon.java
rename to core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToPolygon.java
index d495501..eb610f0 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_ToPolygon.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_ToPolygon.java
@@ -14,14 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.filter.sqlmm.todo;
+package org.apache.sis.internal.filter.sqlmm;
 
-import org.apache.sis.internal.filter.sqlmm.AbstractAccessorSpatialFunction;
 import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.Polygon;
 import java.text.ParseException;
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.feature.builder.PropertyTypeBuilder;
+import org.apache.sis.internal.feature.jts.JTSMapping;
 import org.opengis.feature.FeatureType;
 import org.opengis.filter.expression.Expression;
 
@@ -34,11 +34,15 @@ import org.opengis.filter.expression.Expression;
  * @since   2.0
  * @module
  */
-public final class ST_ToPolygon extends AbstractAccessorSpatialFunction<Geometry> {
+final class ST_ToPolygon extends AbstractAccessorSpatialFunction<Geometry> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -6316093689932320348L;
 
     public static final String NAME = "ST_ToPolygon";
 
-    public ST_ToPolygon(Expression[] parameters) {
+    public ST_ToPolygon(Expression... parameters) {
         super(parameters);
     }
 
@@ -54,14 +58,14 @@ public final class ST_ToPolygon extends AbstractAccessorSpatialFunction<Geometry
 
     @Override
     public Object execute(Geometry geom, Object... params) throws ParseException {
-        final Geometry env = MappingUtils.convertType(geom, Polygon.class);
-        env.setSRID(geom.getSRID());
-        return env;
+        return JTSMapping.convertType(geom, Polygon.class);
     }
 
     @Override
     public PropertyTypeBuilder expectedType(FeatureType valueType, FeatureTypeBuilder addTo) {
-        return addTo.addAttribute(Polygon.class).setName(NAME);
+        return addTo.addAttribute(Polygon.class)
+                .setCRS(expectedCrs(valueType, parameters.get(0)))
+                .setName(NAME);
     }
 
 }
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Touches.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Touches.java
index da02b37..6b2cac5 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Touches.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Touches.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Touches extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 35544493787096847L;
 
     public static final String NAME = "ST_Touches";
 
-    public ST_Touches(Expression[] parameters) {
+    public ST_Touches(Expression... parameters) {
         super(parameters);
     }
 
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 726f2a4..e55bc8b 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
@@ -107,7 +107,7 @@ final class ST_Transform extends NamedFunction implements FeatureExpression {
      * @throws IllegalArgumentException if the number of arguments is not equal to 2.
      * @throws FactoryException if CRS can not be constructed from the second expression.
      */
-    ST_Transform(final Expression[] parameters) throws FactoryException {
+    ST_Transform(final Expression... parameters) throws FactoryException {
         super(parameters);
         ArgumentChecks.ensureExpectedCount("parameters", 2, parameters.length);
         final Expression crs = parameters[1];
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Union.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Union.java
index 6d678d7..e23caa0 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Union.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Union.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Union extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 1984636364819136687L;
 
     public static final String NAME = "ST_Union";
 
-    public ST_Union(Expression[] parameters) {
+    public ST_Union(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Within.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Within.java
index 1578ee4..849b76b 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Within.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Within.java
@@ -34,10 +34,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_Within extends AbstractBinarySpatialFunction {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -4474212706955109548L;
 
     public static final String NAME = "ST_Within";
 
-    public ST_Within(Expression[] parameters) {
+    public ST_Within(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_X.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_X.java
index 06c74e3..0f894e6 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_X.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_X.java
@@ -33,10 +33,14 @@ import org.opengis.filter.expression.Expression;
  * @module
  */
 final class ST_X extends AbstractAccessorSpatialFunction<Point> {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 143569120333779562L;
 
     public static final String NAME = "ST_X";
 
-    public ST_X(Expression[] parameters) {
+    public ST_X(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_XFromBinary.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_XFromBinary.java
index 447f857..0e7e2c7 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_XFromBinary.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_XFromBinary.java
@@ -39,7 +39,12 @@ import org.opengis.filter.expression.Expression;
  */
 abstract class ST_XFromBinary extends AbstractSpatialFunction {
 
-    public ST_XFromBinary(Expression[] parameters) {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 8111450596023441499L;
+
+    public ST_XFromBinary(Expression... parameters) {
         super(parameters);
     }
 
@@ -91,6 +96,7 @@ abstract class ST_XFromBinary extends AbstractSpatialFunction {
     public static final class BdMPoly extends ST_XFromBinary {
 
         public static final String NAME = "ST_BdMPolyFromWKB";
+        private static final long serialVersionUID = -5763967468534517956L;
 
         public BdMPoly(Expression[] parameters) {
             super(parameters);
@@ -134,6 +140,7 @@ abstract class ST_XFromBinary extends AbstractSpatialFunction {
     public static final class BdPoly extends ST_XFromBinary {
 
         public static final String NAME = "ST_BdPolyFromWKB";
+        private static final long serialVersionUID = 6661949194256216330L;
 
         public BdPoly(Expression[] parameters) {
             super(parameters);
@@ -176,6 +183,7 @@ abstract class ST_XFromBinary extends AbstractSpatialFunction {
     public static final class GeomColl extends ST_XFromBinary {
 
         public static final String NAME = "ST_GeomCollFromWKB";
+        private static final long serialVersionUID = -1229981535753136679L;
 
         public GeomColl(Expression[] parameters) {
             super(parameters);
@@ -201,6 +209,7 @@ abstract class ST_XFromBinary extends AbstractSpatialFunction {
     public static final class Geom extends ST_XFromBinary {
 
         public static final String NAME = "ST_GeomFromWKB";
+        private static final long serialVersionUID = -1428672188136390056L;
 
         public Geom(Expression[] parameters) {
             super(parameters);
@@ -226,6 +235,7 @@ abstract class ST_XFromBinary extends AbstractSpatialFunction {
     public static final class Line extends ST_XFromBinary {
 
         public static final String NAME = "ST_LineFromWKB";
+        private static final long serialVersionUID = -4525486088596088088L;
 
         public Line(Expression[] parameters) {
             super(parameters);
@@ -251,6 +261,7 @@ abstract class ST_XFromBinary extends AbstractSpatialFunction {
     public static final class MLine extends ST_XFromBinary {
 
         public static final String NAME = "ST_MLineFromWKB";
+        private static final long serialVersionUID = 1733897936536015735L;
 
         public MLine(Expression[] parameters) {
             super(parameters);
@@ -276,6 +287,7 @@ abstract class ST_XFromBinary extends AbstractSpatialFunction {
     public static final class MPoint extends ST_XFromBinary {
 
         public static final String NAME = "ST_MPointFromWKB";
+        private static final long serialVersionUID = 1725448922596814788L;
 
         public MPoint(Expression[] parameters) {
             super(parameters);
@@ -301,6 +313,7 @@ abstract class ST_XFromBinary extends AbstractSpatialFunction {
     public static final class MPoly extends ST_XFromBinary {
 
         public static final String NAME = "ST_MPolyFromWKB";
+        private static final long serialVersionUID = 8180295093331098160L;
 
         public MPoly(Expression[] parameters) {
             super(parameters);
@@ -326,6 +339,7 @@ abstract class ST_XFromBinary extends AbstractSpatialFunction {
     public static final class Point extends ST_XFromBinary {
 
         public static final String NAME = "ST_PointFromWKB";
+        private static final long serialVersionUID = 6307946926253919188L;
 
         public Point(Expression[] parameters) {
             super(parameters);
@@ -351,6 +365,7 @@ abstract class ST_XFromBinary extends AbstractSpatialFunction {
     public static final class Poly extends ST_XFromBinary {
 
         public static final String NAME = "ST_PolyFromWKB";
+        private static final long serialVersionUID = 3729779304169979534L;
 
         public Poly(Expression[] parameters) {
             super(parameters);
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_XFromGML.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_XFromGML.java
index 0dea7f1..f79e3c3 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_XFromGML.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_XFromGML.java
@@ -37,7 +37,12 @@ import org.opengis.filter.expression.Expression;
  */
 abstract class ST_XFromGML extends AbstractSpatialFunction {
 
-    public ST_XFromGML(Expression[] parameters) {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 6113283783777989678L;
+
+    public ST_XFromGML(Expression... parameters) {
         super(parameters);
     }
 
@@ -93,6 +98,7 @@ abstract class ST_XFromGML extends AbstractSpatialFunction {
     public static final class GeomColl extends ST_XFromGML {
 
         public static final String NAME = "ST_GeomCollFromGML";
+        private static final long serialVersionUID = 2729025080212643888L;
 
         public GeomColl(Expression[] parameters) {
             super(parameters);
@@ -117,6 +123,7 @@ abstract class ST_XFromGML extends AbstractSpatialFunction {
     public static final class Geom extends ST_XFromGML {
 
         public static final String NAME = "ST_GeomFromGML";
+        private static final long serialVersionUID = -2967969861402168905L;
 
         public Geom(Expression[] parameters) {
             super(parameters);
@@ -142,6 +149,7 @@ abstract class ST_XFromGML extends AbstractSpatialFunction {
     public static final class Line extends ST_XFromGML {
 
         public static final String NAME = "ST_LineFromGML";
+        private static final long serialVersionUID = 2939373456076304217L;
 
         public Line(Expression[] parameters) {
             super(parameters);
@@ -167,6 +175,7 @@ abstract class ST_XFromGML extends AbstractSpatialFunction {
     public static final class MLine extends ST_XFromGML {
 
         public static final String NAME = "ST_MLineFromGML";
+        private static final long serialVersionUID = -6449667109261980974L;
 
         public MLine(Expression[] parameters) {
             super(parameters);
@@ -192,6 +201,7 @@ abstract class ST_XFromGML extends AbstractSpatialFunction {
     public static final class MPoint extends ST_XFromGML {
 
         public static final String NAME = "ST_MPointFromGML";
+        private static final long serialVersionUID = 268946482386292257L;
 
         public MPoint(Expression[] parameters) {
             super(parameters);
@@ -217,6 +227,7 @@ abstract class ST_XFromGML extends AbstractSpatialFunction {
     public static final class MPoly extends ST_XFromGML {
 
         public static final String NAME = "ST_MPolyFromGML";
+        private static final long serialVersionUID = 3505318747927007728L;
 
         public MPoly(Expression[] parameters) {
             super(parameters);
@@ -241,6 +252,7 @@ abstract class ST_XFromGML extends AbstractSpatialFunction {
     public static final class Point extends ST_XFromGML {
 
         public static final String NAME = "ST_PointFromGML";
+        private static final long serialVersionUID = -1032773543624102657L;
 
         public Point(Expression[] parameters) {
             super(parameters);
@@ -266,6 +278,7 @@ abstract class ST_XFromGML extends AbstractSpatialFunction {
     public static final class Poly extends ST_XFromGML {
 
         public static final String NAME = "ST_PolyFromGML";
+        private static final long serialVersionUID = 7305807862301697831L;
 
         public Poly(Expression[] parameters) {
             super(parameters);
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_XFromText.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_XFromText.java
index fde7086..2aede56 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_XFromText.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_XFromText.java
@@ -39,7 +39,12 @@ import org.opengis.filter.expression.Expression;
  */
 abstract class ST_XFromText extends AbstractSpatialFunction {
 
-    public ST_XFromText(Expression[] parameters) {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -9046918207193451904L;
+
+    public ST_XFromText(Expression... parameters) {
         super(parameters);
     }
 
@@ -91,6 +96,7 @@ abstract class ST_XFromText extends AbstractSpatialFunction {
     public static final class BdMPoly extends ST_XFromText {
 
         public static final String NAME = "ST_BdMPolyFromText";
+        private static final long serialVersionUID = 9014831950657428233L;
 
         public BdMPoly(Expression[] parameters) {
             super(parameters);
@@ -134,6 +140,7 @@ abstract class ST_XFromText extends AbstractSpatialFunction {
     public static final class BdPoly extends ST_XFromText {
 
         public static final String NAME = "ST_BdPolyFromText";
+        private static final long serialVersionUID = -5743188370723944952L;
 
         public BdPoly(Expression[] parameters) {
             super(parameters);
@@ -176,6 +183,7 @@ abstract class ST_XFromText extends AbstractSpatialFunction {
     public static final class GeomColl extends ST_XFromText {
 
         public static final String NAME = "ST_GeomCollFromText";
+        private static final long serialVersionUID = 8816234645129212298L;
 
         public GeomColl(Expression[] parameters) {
             super(parameters);
@@ -201,6 +209,7 @@ abstract class ST_XFromText extends AbstractSpatialFunction {
     public static final class Geom extends ST_XFromText {
 
         public static final String NAME = "ST_GeomFromText";
+        private static final long serialVersionUID = -1627156125717985980L;
 
         public Geom(Expression[] parameters) {
             super(parameters);
@@ -226,6 +235,7 @@ abstract class ST_XFromText extends AbstractSpatialFunction {
     public static final class Line extends ST_XFromText {
 
         public static final String NAME = "ST_LineFromText";
+        private static final long serialVersionUID = -6384733422127389790L;
 
         public Line(Expression[] parameters) {
             super(parameters);
@@ -251,6 +261,7 @@ abstract class ST_XFromText extends AbstractSpatialFunction {
     public static final class MLine extends ST_XFromText {
 
         public static final String NAME = "ST_MLineFromText";
+        private static final long serialVersionUID = -8797802130317419443L;
 
         public MLine(Expression[] parameters) {
             super(parameters);
@@ -276,6 +287,7 @@ abstract class ST_XFromText extends AbstractSpatialFunction {
     public static final class MPoint extends ST_XFromText {
 
         public static final String NAME = "ST_MPointFromText";
+        private static final long serialVersionUID = 5037254027906574270L;
 
         public MPoint(Expression[] parameters) {
             super(parameters);
@@ -302,6 +314,7 @@ abstract class ST_XFromText extends AbstractSpatialFunction {
     public static final class MPoly extends ST_XFromText {
 
         public static final String NAME = "ST_MPolyFromText";
+        private static final long serialVersionUID = 5914267165283411013L;
 
         public MPoly(Expression[] parameters) {
             super(parameters);
@@ -327,6 +340,7 @@ abstract class ST_XFromText extends AbstractSpatialFunction {
     public static final class Point extends ST_XFromText {
 
         public static final String NAME = "ST_PointFromText";
+        private static final long serialVersionUID = -5265959153677337532L;
 
         public Point(Expression[] parameters) {
             super(parameters);
@@ -352,6 +366,7 @@ abstract class ST_XFromText extends AbstractSpatialFunction {
     public static final class Poly extends ST_XFromText {
 
         public static final String NAME = "ST_PolyFromText";
+        private static final long serialVersionUID = -2502891009213433036L;
 
         public Poly(Expression[] parameters) {
             super(parameters);
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Y.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Y.java
index fde489d..e7e9e5b 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Y.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Y.java
@@ -34,9 +34,14 @@ import org.opengis.filter.expression.Expression;
  */
 final class ST_Y extends AbstractAccessorSpatialFunction<Point> {
 
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -6063954169922560196L;
+
     public static final String NAME = "ST_Y";
 
-    public ST_Y(Expression[] parameters) {
+    public ST_Y(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Z.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Z.java
index a14a0d2..c65eeb7 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Z.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/ST_Z.java
@@ -34,9 +34,14 @@ import org.opengis.filter.expression.Expression;
  */
 final class ST_Z extends AbstractAccessorSpatialFunction<Point> {
 
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 8600571279426234278L;
+
     public static final String NAME = "ST_Z";
 
-    public ST_Z(Expression[] parameters) {
+    public ST_Z(Expression... parameters) {
         super(parameters);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_LineString.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_LineString.java
deleted file mode 100644
index e6e19b1..0000000
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_LineString.java
+++ /dev/null
@@ -1,49 +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.internal.filter.sqlmm.todo;
-
-import org.apache.sis.internal.filter.sqlmm.AbstractGeomConstructor;
-import org.locationtech.jts.geom.LineString;
-import org.opengis.filter.expression.Expression;
-
-/**
- * SQL/MM, ISO/IEC 13249-3:2011, ST_LineString. <br>
- *
- * @author Johann Sorel (Geomatys)
- * @version 2.0
- * @since   2.0
- * @module
- */
-public final class ST_LineString extends AbstractGeomConstructor {
-
-    public static final String NAME = "ST_LineString";
-
-    public ST_LineString(Expression[] parameters){
-        super(parameters);
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-    @Override
-    protected Class<LineString> getExpectedClass() {
-        return LineString.class;
-    }
-
-}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_Point.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_Point.java
deleted file mode 100644
index 20cced9..0000000
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/sqlmm/todo/ST_Point.java
+++ /dev/null
@@ -1,131 +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.internal.filter.sqlmm.todo;
-
-import org.apache.sis.internal.filter.sqlmm.AbstractSpatialFunction;
-import org.locationtech.jts.geom.Coordinate;
-import org.locationtech.jts.geom.Geometry;
-import org.locationtech.jts.io.ParseException;
-import java.math.BigDecimal;
-import org.apache.sis.feature.builder.FeatureTypeBuilder;
-import org.apache.sis.feature.builder.PropertyTypeBuilder;
-import org.apache.sis.internal.filter.FilterGeometryUtils;
-import org.locationtech.jts.geom.Point;
-import org.opengis.feature.FeatureType;
-import org.opengis.filter.expression.Expression;
-
-/**
- * SQL/MM, ISO/IEC 13249-3:2011, ST_Point. <br>
- *
- * @author Johann Sorel (Geomatys)
- * @version 2.0
- * @since   2.0
- * @module
- */
-public final class ST_Point extends AbstractSpatialFunction{
-
-    public static final String NAME = "ST_Point";
-
-    public ST_Point(Expression[] parameters){
-        super(parameters);
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-    @Override
-    protected int getMinParams() {
-        return 1;
-    }
-
-    @Override
-    protected int getMaxParams() {
-        return 4;
-    }
-
-    public String getSyntax() {
-        return "ST_Point( x ,y [,z] [,srid] ) "
-          + "or ST_Point( wkt [,srid] ) "
-          + "or ST_Point( wkb [,srid] )";
-    }
-
-    @Override
-    public Object evaluate(Object candidate) {
-        final int nbarg = children.size();
-        final Geometry geom;
-        if(nbarg == 1){
-            try {
-                //WKB or WKT
-                geom = OrientSpatialUtilities.toGeometry(children.get(0).evaluate(context, candidate));
-            } catch (ParseException ex) {
-                throw new OException(ex.getMessage(), ex);
-            }
-
-        }else if(nbarg == 2){
-            final Object arg0 = children.get(0).evaluate(context, candidate);
-            final Object arg1 = children.get(1).evaluate(context, candidate);
-            if(arg0 instanceof Number){
-                // X,Y
-                final Number obj1 = (Number) arg0;
-                final Number obj2 = (Number) arg1;
-                geom = FilterGeometryUtils.GF.createPoint(new Coordinate(obj1.doubleValue(), obj2.doubleValue()));
-            }else{
-                //WKT/WKB + srid
-                try {
-                    //WKB or WKT
-                    geom = OrientSpatialUtilities.toGeometry(arg0);
-                } catch (ParseException ex) {
-                    throw new OException(ex.getMessage(), ex);
-                }
-                geom.setSRID(((Number)arg1).intValue());
-            }
-
-        }else if(nbarg == 3){
-            final Number obj1 = (Number) children.get(0).evaluate(context, candidate);
-            final Number obj2 = (Number) children.get(1).evaluate(context, candidate);
-            final Number obj3 = (Number) children.get(2).evaluate(context, candidate);
-            geom = FilterGeometryUtils.GF.createPoint(new Coordinate(obj1.doubleValue(), obj2.doubleValue()));
-            if(obj3 instanceof Float || obj3 instanceof Double || obj3 instanceof BigDecimal){
-                // Z
-                geom.getCoordinate().z = obj3.doubleValue();
-            }else{
-                // srid
-                geom.setSRID(obj3.intValue());
-            }
-
-        }else if(nbarg == 4){
-            final Number obj1 = (Number) children.get(0).evaluate(context, candidate);
-            final Number obj2 = (Number) children.get(1).evaluate(context, candidate);
-            final Number obj3 = (Number) children.get(2).evaluate(context, candidate);
-            geom = FilterGeometryUtils.GF.createPoint(new Coordinate(obj1.doubleValue(), obj2.doubleValue(), obj3.doubleValue()));
-            geom.setSRID( ((Number) children.get(3).evaluate(context, candidate) ).intValue() );
-
-        }else{
-            throw new OException("Unexpected number of arguments : "+children.size());
-        }
-
-        return geom;
-    }
-
-    @Override
-    public PropertyTypeBuilder expectedType(FeatureType valueType, FeatureTypeBuilder addTo) {
-        return addTo.addAttribute(Point.class).setName(NAME);
-    }
-
-}
diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/SQLMMTest.java b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/SQLMMTest.java
similarity index 94%
rename from core/sis-feature/src/test/java/org/apache/sis/internal/filter/SQLMMTest.java
rename to core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/SQLMMTest.java
index c437032..ffd1f10 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/SQLMMTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/SQLMMTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.filter;
+package org.apache.sis.internal.filter.sqlmm;
 
 import java.util.Arrays;
 import org.opengis.feature.Feature;
@@ -259,19 +259,6 @@ public final strictfp class SQLMMTest extends TestCase {
 
     @Test
     public void ST_Intersects() throws Exception {
-        try {
-            new ST_Intersects(null, null);
-            fail("ST_Intersects operator should not accept null parameters");
-        } catch (NullArgumentException e) {
-            // expected behavior
-        }
-
-        try {
-            new ST_Intersects(null, factory.literal(new GeneralEnvelope(2)));
-            fail("ST_Intersects operator should not accept null parameters");
-        } catch (NullArgumentException e) {
-            // expected behavior
-        }
 
         final Coordinate start = new Coordinate(0, 0.1);
         final Coordinate second = new Coordinate(1.2, 0.2);
@@ -282,8 +269,8 @@ public final strictfp class SQLMMTest extends TestCase {
         final Literal lring = factory.literal(ring);
         ST_Intersects st = new ST_Intersects(factory.literal(geometryFactory.createPoint(new Coordinate(2, 4))), lring);
         // Ensure argument nullity does not modify behavior
-        assertFalse("Unexpected intersection", st.evaluate(null));
-        assertFalse("Unexpected intersection", st.evaluate(new Object()));
+        assertFalse("Unexpected intersection", (Boolean) st.evaluate(null));
+        assertFalse("Unexpected intersection", (Boolean) st.evaluate(new Object()));
 
         // Border should intersect
         final Feature f = mock();
@@ -291,10 +278,10 @@ public final strictfp class SQLMMTest extends TestCase {
         f.setPropertyValue(P_NAME, point);
         final PropertyName geomName = factory.property(P_NAME);
         st = new ST_Intersects(geomName, lring);
-        assertTrue("Border point should intersect triangle", st.evaluate(f));
+        assertTrue("Border point should intersect triangle", (Boolean) st.evaluate(f));
         // Ensure inverting expression does not modify behavior.
         st = new ST_Intersects(lring, geomName);
-        assertTrue("Border point should intersect triangle", st.evaluate(f));
+        assertTrue("Border point should intersect triangle", (Boolean) st.evaluate(f));
 
         // Ensure CRS conversion works as expected (see package-info).
         // Missing
@@ -311,8 +298,8 @@ public final strictfp class SQLMMTest extends TestCase {
         final Geometry nadPoint = JTS.transform(point, CRS.findOperation(crs84, nadUtm, null));
         f.setPropertyValue(P_NAME, nadPoint);
         ring.setUserData(crs84);
-        assertTrue("Intersection should be found when CRS are compatible", new ST_Intersects(geomName, lring).evaluate(f));
-        assertTrue("Intersection should be found when CRS are compatible", new ST_Intersects(factory.literal(nadPoint), lring).evaluate(null));
+        assertTrue("Intersection should be found when CRS are compatible", (Boolean) new ST_Intersects(geomName, lring).evaluate(f));
+        assertTrue("Intersection should be found when CRS are compatible", (Boolean) new ST_Intersects(factory.literal(nadPoint), lring).evaluate(null));
 
         // Common base CRS
         final ProjectedCRS utm00 = CommonCRS.WGS84.universal(0, 0);
@@ -320,8 +307,8 @@ public final strictfp class SQLMMTest extends TestCase {
         final ProjectedCRS utm78 = CommonCRS.WGS84.universal(7, 8);
         final Geometry pointUtm78 = JTS.transform(ring, CRS.findOperation(crs84, utm78, null));
         f.setPropertyValue(P_NAME, pointUtm78);
-        assertTrue("Intersection should be found when CRS are compatible", new ST_Intersects(geomName, factory.literal(ringUtm00)).evaluate(f));
-        assertTrue("Intersection should be found when CRS are compatible", new ST_Intersects(factory.literal(pointUtm78), factory.literal(ringUtm00)).evaluate(null));
+        assertTrue("Intersection should be found when CRS are compatible", (Boolean) new ST_Intersects(geomName, factory.literal(ringUtm00)).evaluate(f));
+        assertTrue("Intersection should be found when CRS are compatible", (Boolean) new ST_Intersects(factory.literal(pointUtm78), factory.literal(ringUtm00)).evaluate(null));
     }
 
     /**
diff --git a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
index 6ccacf2..3058a84 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
@@ -61,7 +61,7 @@ import org.junit.runners.Suite;
     org.apache.sis.filter.LikeFunctionTest.class,
     org.apache.sis.filter.SpatialFunctionTest.class,
     org.apache.sis.filter.TemporalFunctionTest.class,
-    org.apache.sis.internal.filter.SQLMMTest.class,
+    org.apache.sis.internal.filter.sqlmm.SQLMMTest.class,
     org.apache.sis.internal.feature.AttributeConventionTest.class,
     org.apache.sis.internal.feature.j2d.ShapePropertiesTest.class,
     org.apache.sis.internal.feature.Java2DTest.class,


Mime
View raw message