This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 6aa28f8  Modify the JTS factory class for building JTS Polygon more 
directly, and complete javadoc.
6aa28f8 is described below

commit 6aa28f899b162add0d7e6bd5a603d1dd8ccbf355
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Sat Jan 18 18:04:11 2020 +0100

    Modify the JTS factory class for building JTS Polygon more directly, and 
complete javadoc.
---
 .../java/org/apache/sis/internal/feature/ESRI.java |  20 +--
 .../apache/sis/internal/feature/Geometries.java    |   7 +-
 .../java/org/apache/sis/internal/feature/JTS.java  | 144 +++++++++++++--------
 .../org/apache/sis/internal/feature/Java2D.java    |  32 +++--
 .../sis/internal/feature/j2d/package-info.java     |   2 +-
 .../org/apache/sis/internal/feature/jts/JTS.java   |  62 +++++----
 6 files changed, 161 insertions(+), 106 deletions(-)

diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java 
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java
index db06990..87a3a05 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java
@@ -18,29 +18,28 @@ package org.apache.sis.internal.feature;
 
 import java.nio.ByteBuffer;
 import java.util.Iterator;
-
 import com.esri.core.geometry.Geometry;
 import com.esri.core.geometry.Envelope2D;
 import com.esri.core.geometry.MultiPath;
+import com.esri.core.geometry.MultiVertexGeometry;
 import com.esri.core.geometry.Polyline;
 import com.esri.core.geometry.Polygon;
 import com.esri.core.geometry.Point;
 import com.esri.core.geometry.Point2D;
 import com.esri.core.geometry.Point3D;
+import com.esri.core.geometry.WkbImportFlags;
 import com.esri.core.geometry.WktImportFlags;
 import com.esri.core.geometry.WktExportFlags;
+import com.esri.core.geometry.OperatorImportFromWkb;
 import com.esri.core.geometry.OperatorImportFromWkt;
 import com.esri.core.geometry.OperatorExportToWkt;
 import com.esri.core.geometry.OperatorCentroid2D;
-
 import org.apache.sis.geometry.GeneralEnvelope;
-import org.apache.sis.math.Vector;
 import org.apache.sis.setup.GeometryLibrary;
+import org.apache.sis.math.Vector;
 import org.apache.sis.util.Classes;
 import org.apache.sis.util.Debug;
 
-import com.esri.core.geometry.*;
-
 
 /**
  * Centralizes some usages of ESRI geometry API by Apache SIS.
@@ -48,6 +47,7 @@ import com.esri.core.geometry.*;
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
+ * @author  Alexis Manin (Geomatys)
  * @version 1.1
  * @since   0.7
  * @module
@@ -257,17 +257,19 @@ add:    for (;;) {
     }
 
     /**
-     * Parses the given WKT.
+     * Parses the given Well Known Text (WKT).
      */
     @Override
     public Geometry parseWKT(final String wkt) {
         return 
OperatorImportFromWkt.local().execute(WktImportFlags.wktImportDefaults, 
Geometry.Type.Unknown, wkt, null);
     }
 
+    /**
+     * Reads the given Well Known Binary (WKB).
+     */
     @Override
-    public Geometry parseWKB(byte[] source) {
-        final OperatorImportFromWkb op = OperatorImportFromWkb.local();
-        return op.execute(WkbImportFlags.wkbImportDefaults, 
Geometry.Type.Unknown, ByteBuffer.wrap(source), null);
+    public Geometry parseWKB(final ByteBuffer data) {
+        return 
OperatorImportFromWkb.local().execute(WkbImportFlags.wkbImportDefaults, 
Geometry.Type.Unknown, data, null);
     }
 
     /**
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
 
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
index d040593..a36c871 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.internal.feature;
 
+import java.nio.ByteBuffer;
 import java.util.Iterator;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
@@ -242,6 +243,9 @@ public abstract class Geometries<G> {
      * and returns {@code true}. Otherwise returns {@code false}. The default 
implementation returns
      * {@code false} because only a few geometry implementations can store CRS 
information.
      *
+     * <p>This method should be invoked only for newly created geometries. If 
the geometry library supports
+     * user objects (e.g. JTS), there is no guarantees that this method will 
not overwrite user setting.</p>
+     *
      * @see #tryTransform(Object, CoordinateOperation, 
CoordinateReferenceSystem)
      */
     boolean trySetCoordinateReferenceSystem(Object geometry, 
CoordinateReferenceSystem crs) {
@@ -422,12 +426,13 @@ public abstract class Geometries<G> {
 
     /**
      * Reads the given bytes as a Well Known Binary (WKB) encoded geometry.
+     * Whether this method changes the buffer position or not is 
implementation-dependent.
      *
      * @param  data  the binary data in WKB format. Can not be null.
      * @return decoded geometry (never {@code null}).
      * @throws Exception if the WKB can not be parsed. The exception sub-class 
depends on the implementation.
      */
-    public abstract G parseWKB(byte[] data) throws Exception;
+    public abstract G parseWKB(ByteBuffer data) throws Exception;
 
     /**
      * Creates a two-dimensional point from the given coordinate. If the CRS 
is geographic, then the
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java 
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java
index d296c5b..2ea8abc 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java
@@ -21,6 +21,7 @@ import java.util.List;
 import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.nio.ByteBuffer;
 
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.referencing.operation.CoordinateOperation;
@@ -30,6 +31,8 @@ import org.opengis.util.FactoryException;
 import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.math.Vector;
 import org.apache.sis.setup.GeometryLibrary;
+import org.apache.sis.internal.util.Strings;
+import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.Classes;
 import org.apache.sis.util.Debug;
 
@@ -55,6 +58,7 @@ import org.locationtech.jts.io.WKTReader;
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
+ * @author  Alexis Manin (Geomatys)
  * @version 1.1
  * @since   0.7
  * @module
@@ -75,7 +79,7 @@ final class JTS extends Geometries<Geometry> {
     }
 
     /**
-     * Parses the given WKT.
+     * Parses the given Well Known Text (WKT).
      *
      * @return the geometry object for the given WKT.
      * @throws ParseException if the WKT can not be parsed.
@@ -85,9 +89,30 @@ final class JTS extends Geometries<Geometry> {
         return new WKTReader(factory).read(wkt);
     }
 
+    /**
+     * Reads the given Well Known Binary (WKB).
+     * This implementation does not change the buffer position.
+     */
     @Override
-    public Geometry parseWKB(byte[] source) throws ParseException {
-        return new WKBReader(factory).read(source);
+    public Geometry parseWKB(final ByteBuffer data) throws ParseException {
+        byte[] array;
+        if (data.hasArray()) {
+            /*
+             * Try to use the underlying array without copy if possible.
+             * Copy only if the position or length does not match.
+             */
+            array = data.array();
+            int lower = data.arrayOffset();
+            int upper = data.limit() + lower;
+            lower += data.position();
+            if (lower != 0 || upper != array.length) {
+                array = Arrays.copyOfRange(array, lower, upper);
+            }
+        } else {
+            array = new byte[data.remaining()];
+            data.get(array);
+        }
+        return new WKBReader(factory).read(array);
     }
 
     /**
@@ -177,9 +202,8 @@ final class JTS extends Geometries<Geometry> {
 
     /**
      * If the given geometry is an implementation of this library, returns its 
coordinate reference system.
-     * Otherwise returns {@code null}.
-     *
-     * @see #tryTransform(Object, CoordinateOperation, 
CoordinateReferenceSystem)
+     * This method overwrites any previous user object. This is okay for the 
context in which Apache SIS
+     * uses this method, which is only for newly created geometries.
      */
     @Override
     final CoordinateReferenceSystem tryGetCoordinateReferenceSystem(final 
Object geometry) throws FactoryException {
@@ -190,6 +214,11 @@ final class JTS extends Geometries<Geometry> {
         }
     }
 
+    /**
+     * If the given geometry is an implementation of this library, sets its 
coordinate reference system.
+     *
+     * @see #tryTransform(Object, CoordinateOperation, 
CoordinateReferenceSystem)
+     */
     @Override
     final boolean trySetCoordinateReferenceSystem(final Object geometry, final 
CoordinateReferenceSystem crs) {
         if (geometry instanceof Geometry) {
@@ -259,7 +288,7 @@ final class JTS extends Geometries<Geometry> {
             throw new UnsupportedOperationException(unsupported(dimension));
         }
         final List<Coordinate> coordinates = new ArrayList<>(32);
-        final List<LineString> lines = new ArrayList<>();
+        final List<Geometry> lines = new ArrayList<>();
         for (final Vector v : coords) {
             if (v != null) {
                 final int size = v.size();
@@ -276,17 +305,14 @@ final class JTS extends Geometries<Geometry> {
                         coordinates.add(c);
                     } else {
                         if (is3D) i++;
-                        toLineString(coordinates, lines);
+                        toLineString(coordinates, lines, polygon);
                         coordinates.clear();
                     }
                 }
             }
         }
-        toLineString(coordinates, lines);
-        if (polygon) {
-            return toPolygon(toGeometry(lines));    // TODO: create polygon 
directly instead.
-        }
-        return toGeometry(lines);
+        toLineString(coordinates, lines, polygon);
+        return toGeometry(lines, polygon);
     }
 
     /**
@@ -295,64 +321,80 @@ final class JTS extends Geometries<Geometry> {
      *
      * @param  geometries  the polygons or linear rings to put in a 
multi-polygons.
      * @throws ClassCastException if an element in the array is not a JTS 
geometry.
+     * @throws IllegalArgumentException if an element is a non-closed linear 
string.
      */
     @Override
     public MultiPolygon createMultiPolygon(final Object[] geometries) {
         final Polygon[] polygons = new Polygon[geometries.length];
         for (int i=0; i<geometries.length; i++) {
-            polygons[i] = toPolygon((Geometry) unwrap(geometries[i]));
-        }
-        return factory.createMultiPolygon(polygons);
-    }
-
-    private Polygon toPolygon(Geometry polyline) throws 
IllegalArgumentException {
-        if (polyline instanceof Polygon) {
-            return (Polygon) polyline;
-        }
-        Polygon result = null;
-        if (polyline instanceof LinearRing) {
-            result = factory.createPolygon((LinearRing) polyline);
-        } else if (polyline instanceof LineString) {
-            final LineString myLine = (LineString) polyline;
-            if (myLine.getEndPoint().equals(myLine.getStartPoint())) {
-                result = factory.createPolygon(myLine.getCoordinateSequence());
+            final Object polyline = unwrap(geometries[i]);
+            final Polygon polygon;
+            if (polyline instanceof Polygon) {
+                polygon = (Polygon) polyline;
+            } else if (polyline instanceof LinearRing) {
+                polygon = factory.createPolygon((LinearRing) polyline);
+                copyMetadata((Geometry) polyline, polygon);
+            } else if (polyline instanceof LineString) {
+                // Let JTS throws an exception with its own error message if 
the ring is not valid.
+                polygon = factory.createPolygon(((LineString) 
polyline).getCoordinateSequence());
+                copyMetadata((Geometry) polyline, polygon);
+            } else {
+                throw new 
ClassCastException(Errors.format(Errors.Keys.IllegalArgumentClass_3,
+                        Strings.bracket("geometries", i), Polygon.class, 
Classes.getClass(polyline)));
             }
+            polygons[i] = polygon;
         }
-        if (result == null) {
-            throw new IllegalArgumentException("Input is not a closed line.");
-        }
-        copyMetadata(polyline, result);
-        return result;
+        return factory.createMultiPolygon(polygons);
     }
 
     /**
      * Makes a line string or linear ring from the given coordinates, and adds 
the line string to the given list.
+     * If the {@code polygon} argument is {@code true}, then this method 
creates polygons instead of line strings.
      * If the given coordinates array is empty, then this method does nothing.
      * This method does not modify the given coordinates list.
      */
-    private void toLineString(final List<Coordinate> coordinates, final 
List<LineString> addTo) {
+    private void toLineString(final List<Coordinate> coordinates, final 
List<Geometry> addTo, final boolean polygon) {
         final int s = coordinates.size();
         if (s >= 2) {
-            final LineString line;
             final Coordinate[] ca = coordinates.toArray(new Coordinate[s]);
-            if (ca[0].equals2D(ca[s-1])) {
-                line = factory.createLinearRing(ca);        // Throws an 
exception if s < 4.
+            final Geometry geom;
+            if (polygon) {
+                geom = factory.createPolygon(ca);
+            } else if (ca[0].equals2D(ca[s-1])) {
+                geom = factory.createLinearRing(ca);        // Throws an 
exception if s < 4.
             } else {
-                line = factory.createLineString(ca);        // Throws an 
exception if contains duplicated point.
+                geom = factory.createLineString(ca);        // Throws an 
exception if contains duplicated point.
             }
-            addTo.add(line);
+            addTo.add(geom);
         }
     }
 
     /**
-     * Returns the given list of line string as a single geometry.
+     * Returns the given list of polygons or line strings as a single geometry.
+     *
+     * @param  lines  the polygons or lines strings.
+     * @return {@code true} if the given list contains {@link Polygon} 
instances, or
+     *         {@code false} if it contains {@link LineString} instances.
+     * @throws ArrayStoreException if the geometries in the given list are not 
instances
+     *         of the type specified by the {@code polygon} argument.
      */
-    private Geometry toGeometry(final List<LineString> lines) {
+    @SuppressWarnings("SuspiciousToArrayCall")      // Type controlled by 
`polygon`.
+    private Geometry toGeometry(final List<Geometry> lines, final boolean 
polygon) {
         final int s = lines.size();
         switch (s) {
-            case 0:  return factory.createLinearRing((Coordinate[]) null);     
 // Creates an empty linear ring.
-            case 1:  return lines.get(0);
-            default: return factory.createMultiLineString(lines.toArray(new 
LineString[s]));
+            case 0:  {
+                // Create an empty polygon or linear ring.
+                return polygon ? factory.createPolygon   ((Coordinate[]) null)
+                               : factory.createLinearRing((Coordinate[]) null);
+            }
+            case 1: {
+                return lines.get(0);
+            }
+            default: {
+                // An ArrayStoreException here would be a bug in our use of 
`polygon` boolean.
+                return polygon ? factory.createMultiPolygon   
(lines.toArray(new Polygon   [s]))
+                               : 
factory.createMultiLineString(lines.toArray(new LineString[s]));
+            }
         }
     }
 
@@ -367,14 +409,14 @@ final class JTS extends Geometries<Geometry> {
             return null;
         }
         final List<Coordinate> coordinates = new ArrayList<>();
-        final List<LineString> lines = new ArrayList<>();
+        final List<Geometry> lines = new ArrayList<>();
 add:    for (;;) {
             if (next instanceof Point) {
                 final Coordinate pt = ((Point) next).getCoordinate();
                 if (!Double.isNaN(pt.x) && !Double.isNaN(pt.y)) {
                     coordinates.add(pt);
                 } else {
-                    toLineString(coordinates, lines);
+                    toLineString(coordinates, lines, false);
                     coordinates.clear();
                 }
             } else {
@@ -386,7 +428,7 @@ add:    for (;;) {
                         lines.add(ls);
                     } else {
                         coordinates.addAll(Arrays.asList(ls.getCoordinates()));
-                        toLineString(coordinates, lines);
+                        toLineString(coordinates, lines, false);
                         coordinates.clear();
                     }
                 }
@@ -398,8 +440,8 @@ add:    for (;;) {
             do if (!polylines.hasNext()) break add;
             while ((next = polylines.next()) == null);
         }
-        toLineString(coordinates, lines);
-        return toGeometry(lines);
+        toLineString(coordinates, lines, false);
+        return toGeometry(lines, false);
     }
 
     /**
@@ -429,7 +471,7 @@ add:    for (;;) {
      * @see #tryGetCoordinateReferenceSystem(Object)
      */
     @Override
-    final Geometry tryTransform(final Object geometry, final 
CoordinateOperation operation, final CoordinateReferenceSystem targetCRS)
+    Geometry tryTransform(final Object geometry, final CoordinateOperation 
operation, final CoordinateReferenceSystem targetCRS)
             throws FactoryException, TransformException
     {
         if (geometry instanceof Geometry) {
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java 
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java
index 6d6e1d6..5a67ad3 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java
@@ -18,6 +18,7 @@ package org.apache.sis.internal.feature;
 
 import java.util.List;
 import java.util.Iterator;
+import java.nio.ByteBuffer;
 import java.awt.Shape;
 import java.awt.geom.Line2D;
 import java.awt.geom.Path2D;
@@ -42,6 +43,7 @@ import org.apache.sis.util.UnsupportedImplementationException;
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
+ * @author  Alexis Manin (Geomatys)
  * @version 1.1
  * @since   0.7
  * @module
@@ -127,6 +129,11 @@ final class Java2D extends Geometries<Shape> {
                 case 0:  return ArraysExt.EMPTY_DOUBLE;
                 case 1:  return coordinates.get(0);
                 default: {
+                    /*
+                     * Concatenate the coordinates of all polygons in a single 
array. We lost the distinction
+                     * between the different polygons, which is why this 
method should not be used except for
+                     * testing.
+                     */
                     final double[] tgt = new 
double[coordinates.stream().mapToInt((a) -> a.length).sum()];
                     int p = 0;
                     for (final double[] src : coordinates) {
@@ -168,7 +175,7 @@ final class Java2D extends Geometries<Shape> {
      * @param  length  initial capacity.
      * @return an initially empty path of the given type.
      */
-    private Path2D createPath(final boolean isFloat, final int length) {
+    private static Path2D createPath(final boolean isFloat, final int length) {
         return isFloat ? new Path2D.Float (Path2D.WIND_NON_ZERO, length)
                        : new Path2D.Double(Path2D.WIND_NON_ZERO, length);
     }
@@ -202,6 +209,7 @@ final class Java2D extends Geometries<Shape> {
             }
         }
         /*
+         * Shortcut (for performance reason) when building a single line 
segment.
          * Note: Point2D is not an instance of Shape, so we can not make a 
special case for it.
          */
         length /= BIDIMENSIONAL;
@@ -218,30 +226,27 @@ final class Java2D extends Geometries<Shape> {
                 return path;
             }
         }
+        /*
+         * General case if we could not use a shortcut.
+         */
         final Path2D path = createPath(isFloat, length);
-        double startX = Double.NaN, startY = Double.NaN;
-        double  lastX = Double.NaN,  lastY = Double.NaN;
         boolean lineTo = false;
         for (final Vector v : coordinates) {
             final int size = v.size();
             for (int i=0; i<size;) {
                 final double x = v.doubleValue(i++);
                 final double y = v.doubleValue(i++);
-                if (Double.isNaN(startX)) {
-                    startX = x;
-                    startY = y;
-                }
                 if (Double.isNaN(x) || Double.isNaN(y)) {
-                    if (lastX == startX && lastY == startY) path.closePath();
+                    if (polygon) {
+                        path.closePath();
+                    }
                     lineTo = false;
-                    startX = startY = Double.NaN;
                 } else if (lineTo) {
                     path.lineTo(x, y);
                 } else {
                     path.moveTo(x, y);
                     lineTo = true;
                 }
-                lastX = x; lastY = y;
             }
         }
         if (polygon) {
@@ -335,15 +340,18 @@ add:    for (;;) {
     }
 
     /**
-     * Parses the given WKT.
+     * Well Known Text (WKT) parsing not supported with Java2D.
      */
     @Override
     public Shape parseWKT(final String wkt) {
         throw new UnsupportedImplementationException(unsupported("parseWKT"));
     }
 
+    /**
+     * Well Known Binary (WKB) reading not supported with Java2D.
+     */
     @Override
-    public Shape parseWKB(byte[] source) {
+    public Shape parseWKB(ByteBuffer data) {
         throw new UnsupportedImplementationException(unsupported("parseWKB"));
     }
 }
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/package-info.java
 
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/package-info.java
index 747ae56..ed904d7 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/package-info.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/j2d/package-info.java
@@ -24,7 +24,7 @@
  * may change in incompatible ways in any future version without notice.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
  *
  * @see org.apache.sis.internal.referencing.j2d
  *
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/JTS.java 
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/JTS.java
index 86813e1..9937e79 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/JTS.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/JTS.java
@@ -17,29 +17,26 @@
 package org.apache.sis.internal.feature.jts;
 
 import java.util.Map;
-import java.util.Optional;
-
+import org.opengis.metadata.Identifier;
+import org.opengis.util.FactoryException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
-import org.opengis.util.FactoryException;
-
-import org.apache.sis.geometry.Envelope2D;
-import org.apache.sis.internal.system.Loggers;
-import org.apache.sis.internal.util.Constants;
-import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.util.Static;
 import org.apache.sis.util.Utilities;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Errors;
-
+import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
+import org.apache.sis.geometry.Envelope2D;
+import org.apache.sis.internal.system.Loggers;
+import org.apache.sis.internal.util.Constants;
+import org.apache.sis.referencing.IdentifiedObjects;
 import org.locationtech.jts.geom.Envelope;
 import org.locationtech.jts.geom.Geometry;
 
-import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
-
 
 /**
  * Utilities for Java Topology Suite (JTS) objects.
@@ -50,7 +47,8 @@ import static 
org.apache.sis.util.ArgumentChecks.ensureNonNull;
  * For example we may replace it by a more general mechanism working also on 
other geometry libraries.</p>
  *
  * @author  Johann Sorel (Geomatys)
- * @version 1.0
+ * @author  Alexis Manin (Geomatys)
+ * @version 1.1
  * @since   1.0
  * @module
  */
@@ -107,27 +105,27 @@ public final class JTS extends Static {
         return null;
     }
 
-    public static Optional<CoordinateReferenceSystem> 
setCoordinateReferenceSystem(final Geometry target, final 
CoordinateReferenceSystem crs) {
-        ensureNonNull("Target geometry", target);
-        final Object ud = target.getUserData();
-        if (ud == null) {
-            // By security, we reset SRID in case old CRS was defined this way.
-            target.setSRID(0);
-            target.setUserData(crs);
-            return Optional.empty();
-        } else if (ud instanceof CoordinateReferenceSystem) {
-            target.setUserData(crs);
-            return Optional.of((CoordinateReferenceSystem) ud);
-        } else if (ud instanceof Map) {
-            final Map asMap = (Map) ud;
-            // In case user-data contains other useful data, we don't switch 
from map to CRS. We also reset SRID.
-            final Object oldVal = asMap.put(CRS_KEY, crs);
-            // By security, we reset SRID in case old CRS was defined this way.
-            if (oldVal == null) {
-                target.setSRID(0);
-            }
+    /**
+     * Sets the Coordinate Reference System (CRS) in the specified geometry. 
This method overwrite any previous
+     * user data; it should be invoked only when the geometry is known to not 
store any other information.
+     * In current Apache SIS usage, this method is invoked only for newly 
created geometries.
+     *
+     * <p>This method also sets the JTS SRID to EPSG code if such code can be 
found. For performance reasons
+     * this method does not perform a full scan of EPSG database if the CRS 
does not provide an EPSG code.</p>
+     *
+     * @param  target  the geometry where to store coordinate reference system 
information.
+     * @param  crs     the CRS to store, or {@code null}.
+     */
+    public static void setCoordinateReferenceSystem(final Geometry target, 
final CoordinateReferenceSystem crs) {
+        target.setUserData(crs);
+        int epsg = 0;
+        final Identifier id = IdentifiedObjects.getIdentifier(crs, 
Citations.EPSG);
+        if (id != null) try {
+            epsg = Integer.parseInt(id.getCode());
+        } catch (NumberFormatException e) {
+            // Ignore. Note: this is also the exception if id.getCode() is 
null.
         }
-        throw new IllegalArgumentException("Cannot modify input geometry, 
because user-data does not comply with SIS convention (should be a map or null, 
but was "+ud.getClass().getCanonicalName()+").");
+        target.setSRID(epsg);
     }
 
     /**

Reply via email to