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 e520c8b28d Formatting and bug fix in the setting of the buffer limit 
and the use of the Geopackage SRID.
e520c8b28d is described below

commit e520c8b28dbeeb6a85a25ed651048509c47022f5
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Sat Jun 15 20:23:01 2024 +0200

    Formatting and bug fix in the setting of the buffer limit and the use of 
the Geopackage SRID.
---
 .../sis/storage/sql/feature/GeometryGetter.java    | 57 +++++++++++-----------
 1 file changed, 28 insertions(+), 29 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/GeometryGetter.java
 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/GeometryGetter.java
index 78c9596451..3aa316295e 100644
--- 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/GeometryGetter.java
+++ 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/GeometryGetter.java
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.storage.sql.feature;
 
-import java.util.OptionalInt;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.sql.ResultSet;
@@ -24,6 +23,7 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.geometry.wrapper.GeometryWrapper;
 import org.apache.sis.geometry.wrapper.Geometries;
 import org.apache.sis.storage.DataStoreContentException;
+import org.apache.sis.util.resources.Errors;
 
 
 /**
@@ -52,7 +52,6 @@ import org.apache.sis.storage.DataStoreContentException;
  * @param <G> the type of geometry objects created by the factory.
  * @param <V> the type of geometry objects returned by this getter.
  *
- *
  * @see org.apache.sis.storage.sql.postgis.RasterGetter
  */
 final class GeometryGetter<G, V extends G> extends ValueGetter<V> {
@@ -109,46 +108,46 @@ final class GeometryGetter<G, V extends G> extends 
ValueGetter<V> {
         final byte[] wkb = encoding.getBytes(source, columnIndex);
         if (wkb == null) return null;
         ByteBuffer buffer = ByteBuffer.wrap(wkb);
-
-        // Possible Geopackage header 
https://www.geopackage.org/spec140/index.html#gpb_spec
-        int gpkgSrid = -1;
-        if (wkb.length > 2 && wkb[0] == 'G' && wkb[1] == 'P') {
-            // Remove the header.
-            final int version = wkb[2] & 0xFF; // 8-bit unsigned integer, 0 = 
version 1
+        /*
+         * The bytes should describe a geometry encoded in Well Known Binary 
(WKB) format,
+         * but this implementation accepts also the Geopackage geometry 
encoding:
+         *
+         *     https://www.geopackage.org/spec140/index.html#gpb_spec
+         *
+         * This is still a geometry in WKB format, but preceded by a header of 
at least two 32-bits integers.
+         */
+        int gpkgSrid = 0;       // ≤0 means "no CRS" as of 
`stmts.fetchCRS(int)` contract.
+        if (wkb.length > 2*Integer.BYTES && wkb[0] == 'G' && wkb[1] == 'P') {
+            final int version = Byte.toUnsignedInt(wkb[2]);     // 8-bit 
unsigned integer, 0 = version 1
             if (version != 0) {
-                throw new DataStoreContentException("Only version 1 of 
Geopackage WKB is supported");
+                throw new 
DataStoreContentException(Errors.forLocale(stmts.getLocale())
+                        .getString(Errors.Keys.UnsupportedFormatVersion_2, 
"Geopackage", version));
             }
-            final int flags = wkb[3];
-            final boolean bigEndian = (flags & 0b1) == 0;
-            final int envelopeType = (flags & 0b1110) >> 1;
-            final boolean isEmpty = (flags & 0b10000) != 0;
+            final int     flags        = wkb[3];
+            final boolean bigEndian    = (flags & 0b000001) == 0;
+            final int     envelopeType = (flags & 0b001110) >> 1;
+            final boolean isEmpty      = (flags & 0b010000) != 0;
             final boolean extendedType = (flags & 0b100000) != 0;
-
             buffer.order(bigEndian ? ByteOrder.BIG_ENDIAN : 
ByteOrder.LITTLE_ENDIAN);
-            gpkgSrid = buffer.asIntBuffer().get(1);
+            gpkgSrid = buffer.getInt(Integer.BYTES);
             // Skip header and envelope.
             final int offset;
             switch (envelopeType) {
-                case 0 : offset = 8; break;
-                case 1 : offset = 8 + 4 * Double.BYTES; break;
-                case 2 :
-                case 3 : offset = 8 + 6 * Double.BYTES; break;
-                case 4 : offset = 8 + 8 * Double.BYTES; break;
-                default : throw new DataStoreContentException("Invalid 
envelope type");
+                case 0: offset = 2*Integer.BYTES;                  break;   // 
No envelope.
+                case 1: offset = 2*Integer.BYTES + 4*Double.BYTES; break;   // 
2D envelope.
+                case 2:                                                     // 
3D envelope with Z.
+                case 3: offset = 2*Integer.BYTES + 6*Double.BYTES; break;   // 
3D envelope with M.
+                case 4: offset = 2*Integer.BYTES + 8*Double.BYTES; break;   // 
4D envelope.
+                default: throw new 
DataStoreContentException(Errors.forLocale(stmts.getLocale())
+                            .getString(Errors.Keys.UnexpectedValueInElement_2, 
"envelope contents indicator"));
             }
-            buffer = buffer.position(offset).limit(wkb.length-offset).slice();
+            buffer = buffer.position(offset).slice();
             // Result of slice is in BIG_ENDIAN.
         }
-
         final GeometryWrapper geom = geometryFactory.parseWKB(buffer);
         CoordinateReferenceSystem crs = defaultCRS;
         if (stmts != null) {
-            final OptionalInt srid = geom.getSRID();
-            if (srid.isPresent()) {
-                crs = stmts.fetchCRS(srid.getAsInt());
-            } else if (gpkgSrid != -1) {
-                crs = stmts.fetchCRS(srid.getAsInt());
-            }
+            crs = stmts.fetchCRS(geom.getSRID().orElse(gpkgSrid));
         }
         if (crs != null) {
             geom.setCoordinateReferenceSystem(crs);

Reply via email to