This is an automated email from the ASF dual-hosted git repository.
jsorel 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 7bdaab6a29 Decode OGR vector layers, rebuild FeatureTypes
7bdaab6a29 is described below
commit 7bdaab6a292822f9c7700c4cfc99f26fa8b1e0c3
Author: jsorel <[email protected]>
AuthorDate: Wed Oct 9 10:55:36 2024 +0200
Decode OGR vector layers, rebuild FeatureTypes
---
.../org.apache.sis.feature/main/module-info.java | 1 +
optional/build.gradle.kts | 2 +
.../org.apache.sis.storage.DataStoreProvider | 2 +-
.../main/module-info.java | 4 +
.../main/org/apache/sis/storage/gdal/GDAL.java | 269 +++++++++++++++++++++
.../org/apache/sis/storage/gdal/GDALStore.java | 5 +-
.../org/apache/sis/storage/gdal/OGRFeatureSet.java | 184 ++++++++++++++
.../org/apache/sis/storage/gdal/OGRFieldType.java | 84 +++++++
.../apache/sis/storage/gdal/OGRwkbByteOrder.java | 36 +++
.../sis/storage/gdal/OGRwkbGeometryType.java | 185 ++++++++++++++
.../apache/sis/storage/gdal/OgrGeometryReader.java | 206 ++++++++++++++++
.../apache/sis/storage/gdal/OgrSpliterator.java | 133 ++++++++++
.../main/org/apache/sis/storage/gdal/Opener.java | 2 +-
.../org/apache/sis/storage/gdal/SpatialRef.java | 13 +
14 files changed, 1123 insertions(+), 3 deletions(-)
diff --git a/endorsed/src/org.apache.sis.feature/main/module-info.java
b/endorsed/src/org.apache.sis.feature/main/module-info.java
index a99f398169..0fa39a382d 100644
--- a/endorsed/src/org.apache.sis.feature/main/module-info.java
+++ b/endorsed/src/org.apache.sis.feature/main/module-info.java
@@ -55,6 +55,7 @@ module org.apache.sis.feature {
org.apache.sis.storage.shapefile, // In the "incubator"
sub-project.
org.apache.sis.portrayal,
org.apache.sis.portrayal.map, // In the "incubator"
sub-project.
+ org.apache.sis.storage.gdal, // In the "optional"
sub-project.
org.apache.sis.gui; // In the "optional"
sub-project.
exports org.apache.sis.geometry.wrapper to
diff --git a/optional/build.gradle.kts b/optional/build.gradle.kts
index dbcd427a82..79fd1f326b 100644
--- a/optional/build.gradle.kts
+++ b/optional/build.gradle.kts
@@ -50,6 +50,8 @@ dependencies {
// Mandatory dependencies
api (libs.units)
api (libs.geoapi)
+ api (libs.jts.core) // Should be an
optional dependency.
+ api (libs.esri.geometry) // Idem.
implementation(libs.jaxb.api) // Transitive dependency.
runtimeOnly (libs.jaxb.impl)
api (files(File(pathToFX, "javafx.base.jar")))
diff --git
a/optional/src/org.apache.sis.storage.gdal/main/META-INF.services/org.apache.sis.storage.DataStoreProvider
b/optional/src/org.apache.sis.storage.gdal/main/META-INF.services/org.apache.sis.storage.DataStoreProvider
index 25f274232b..fe0f6d43f6 100644
---
a/optional/src/org.apache.sis.storage.gdal/main/META-INF.services/org.apache.sis.storage.DataStoreProvider
+++
b/optional/src/org.apache.sis.storage.gdal/main/META-INF.services/org.apache.sis.storage.DataStoreProvider
@@ -1,4 +1,4 @@
# Workaround for Maven bug https://issues.apache.org/jira/browse/MNG-7855
# The content of this file is automatically derived from module-info.class
file.
# Should be used only if the JAR file was on class-path rather than
module-path.
-org.apache.sis.storage.gdal.GdalStoreProvider
+org.apache.sis.storage.gdal.GDALStoreProvider
diff --git a/optional/src/org.apache.sis.storage.gdal/main/module-info.java
b/optional/src/org.apache.sis.storage.gdal/main/module-info.java
index e4d87b9584..c7c98de106 100644
--- a/optional/src/org.apache.sis.storage.gdal/main/module-info.java
+++ b/optional/src/org.apache.sis.storage.gdal/main/module-info.java
@@ -52,6 +52,10 @@ module org.apache.sis.storage.gdal {
requires transitive org.apache.sis.referencing;
requires transitive org.apache.sis.storage;
+ // Optional dependencies to be provided by user.
+ requires static esri.geometry.api;
+ requires static org.locationtech.jts;
+
exports org.apache.sis.storage.gdal;
provides org.apache.sis.storage.DataStoreProvider
diff --git
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/GDAL.java
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/GDAL.java
index c70763fc39..cf6d50abd9 100644
---
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/GDAL.java
+++
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/GDAL.java
@@ -274,6 +274,183 @@ final class GDAL extends NativeFunctions {
*/
final MethodHandle adviseRead;
+ /**
+ * <abbr>GDAL</abbr> {@code CPLErr GDALDatasetGetLayerCount(Pointer hDS)}.
+ * Get the number of layers in this dataset.
+ */
+ final MethodHandle datasetGetLayerCount;
+
+ /**
+ * <abbr>GDAL</abbr> {@code CPLErr GDALDatasetGetLayer(Pointer hDS, int
index)}.
+ * Fetch a layer by index.
+ */
+ final MethodHandle datasetGetLayer;
+
+ /**
+ * <abbr>OGR</abbr> {@code Pointer CPLErr OGR_L_GetLayerDefn(Pointer hDS)}.
+ * Fetch the schema information for this layer.
+ */
+ final MethodHandle ogrLayerGetLayerDefn;
+
+ /**
+ * <abbr>OGR</abbr> {@code Pointer CPLErr OGR_L_GetName(Pointer hDS)}.
+ * Return the layer name.
+ */
+ final MethodHandle ogrLayerGetName;
+
+ /**
+ * <abbr>OGR</abbr> {@code GIntBig CPL_DLL
OGR_L_GetFeatureCount(OGRLayerH, int)}.
+ * Fetch the feature count in this layer.
+ */
+ final MethodHandle ogrLayerGetFeatureCount;
+
+ /**
+ * <abbr>OGR</abbr> {@code OGRErr CPL_DLL OGR_L_GetExtent(OGRLayerH,
OGREnvelope *, int)}.
+ * Fetch spatial extent.
+ */
+ final MethodHandle ogrLayerGetExtent;
+
+ /**
+ * <abbr>OGR</abbr> {@code OGRFeatureH CPL_DLL
OGR_L_GetNextFeature(OGRLayerH) CPL_WARN_UNUSED_RESULT}.
+ * Fetch the next available feature from this layer.
+ */
+ final MethodHandle ogrLayerGetNextFeature;
+
+ /**
+ * <abbr>OGR</abbr> {@code GIntBig CPL_DLL OGR_F_GetFID(OGRFeatureH)}.
+ * Get feature identifier.
+ */
+ final MethodHandle ogrFeatureGetFid;
+
+ /**
+ * <abbr>OGR</abbr> {@code int CPL_DLL
OGR_F_GetFieldAsInteger(OGRFeatureH, int)}.
+ * Fetch field value as integer.
+ */
+ final MethodHandle ogrFeatureGetFieldAsInteger;
+
+ /**
+ * <abbr>OGR</abbr> {@code GIntBig CPL_DLL
OGR_F_GetFieldAsInteger64(OGRFeatureH, int)}.
+ * Fetch field value as integer 64 bit.
+ */
+ final MethodHandle ogrFeatureGetFieldAsInteger64;
+
+ /**
+ * <abbr>OGR</abbr> {@code double CPL_DLL
OGR_F_GetFieldAsDouble(OGRFeatureH, int)}.
+ * Fetch field value as a double.
+ */
+ final MethodHandle ogrFeatureGetFieldAsDouble;
+
+ /**
+ * <abbr>OGR</abbr> {@code const char CPL_DLL
*OGR_F_GetFieldAsString(OGRFeatureH, int)}.
+ * Fetch field value as a string.
+ */
+ final MethodHandle ogrFeatureGetFieldAsString;
+
+ /**
+ * <abbr>OGR</abbr> {@code OGRGeometryH OGR_F_GetGeometryRef(OGRFeatureH
hFeat)}.
+ * Fetch a handle to feature geometry.
+ */
+ final MethodHandle ogrFeatureGetGeometryRef;
+
+ /**
+ * <abbr>OGR</abbr> {@code void OGR_F_Destroy(OGRFeatureH hFeat)}.
+ * Destroy feature.
+ */
+ final MethodHandle ogrFeatureDestroy;
+
+ /**
+ * <abbr>OGR</abbr> {@code void OGR_DS_Destroy(OGRDataSourceH hDS)}.
+ * Closes opened datasource and releases allocated resources.
+ */
+ final MethodHandle ogrDataSourceDestroy;
+
+ /**
+ * <abbr>OGR</abbr> {@code const char * OGR_G_GetGeometryName(OGRGeometryH
hGeom)}.
+ * Fetch WKT name for geometry type.
+ */
+ final MethodHandle ogrGeometryGetGeometryName;
+
+ /**
+ * <abbr>OGR</abbr> {@code int CPL_DLL OGR_G_GetPoints(OGRGeometryH hGeom,
void *pabyX, int nXStride,
+ * void *pabyY, int nYStride, void
*pabyZ, int nZStride);}.
+ * Returns all points of line string.
+ */
+ final MethodHandle ogrGeometryGetPoints;
+
+ /**
+ * <abbr>OGR</abbr> {@code int OGR_G_GetPointCount(OGRGeometryH hGeom)}.
+ * Fetch number of points from a Point or a LineString/LinearRing geometry.
+ */
+ final MethodHandle ogrGeometryGetPointCount;
+
+ /**
+ * <abbr>OGR</abbr> {@code int OGR_G_GetGeometryCount(OGRGeometryH hGeom)}.
+ * Fetch the number of elements in a geometry or number of geometries in
container.
+ */
+ final MethodHandle ogrGeometryGetGeometryCount;
+
+ /**
+ * <abbr>OGR</abbr> {@code OGRGeometryH OGR_G_GetGeometryRef(OGRGeometryH
hGeom, int iSubGeom)}.
+ * Fetch geometry from a geometry container.
+ */
+ final MethodHandle ogrGeometryGetGeometryRef;
+
+ /**
+ * <abbr>OGR</abbr> {@code Pointer CPLErr OGR_FD_GetFieldCount(Pointer
hDS)}.
+ * Fetch number of fields on the passed feature definition.
+ */
+ final MethodHandle ogrFeatureDefinitionGetFieldCount;
+
+ /**
+ * <abbr>OGR</abbr> {@code Pointer CPLErr OGR_FD_GetFieldDefn(Pointer
hDS)}.
+ * Fetch field definition of the passed feature definition.
+ */
+ final MethodHandle ogrFeatureDefinitionGetFieldDefinition;
+
+ /**
+ * <abbr>OGR</abbr> {@code int CPLErr OGR_Fld_GetType(Pointer hDS, int
index)}.
+ * Fetch type of this field.
+ */
+ final MethodHandle ogrFeatureDefinitionGetFieldType;
+
+ /**
+ * <abbr>OGR</abbr> {@code Pointer CPLErr OGR_Fld_GetNameRef(Pointer hDS)}.
+ * Fetch name of this field.
+ */
+ final MethodHandle ogrFeatureDefinitionGetFieldName;
+
+ /**
+ * <abbr>OGR</abbr> {@code int CPLErr OGR_FD_GetGeomFieldCount(Pointer
hDS)}.
+ * Fetch number of geometry fields on this feature.
+ */
+ final MethodHandle ogrFeatureDefinitionGetGeomFieldCount;
+
+ /**
+ * <abbr>OGR</abbr> {@code OGRGeomFieldDefnH
OGR_FD_GetGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField)}.
+ * Fetch geometry field definition of the passed feature definition.
+ */
+ final MethodHandle ogrFeatureDefinitionGetGeomFieldDefinition;
+
+ /**
+ * <abbr>OGR</abbr> {@code int CPLErr OGR_Fld_GetType(Pointer hDS, int
index)}.
+ * Fetch geometry type of this field.
+ */
+ final MethodHandle ogrFeatureDefinitionGetGeomFieldType;
+
+ /**
+ * <abbr>OGR</abbr> {@code OGRwkbGeometryType CPL_DLL OGR_GFld_GetType(
OGRGeomFieldDefnH )}.
+ * Fetch name of this field.
+ */
+ final MethodHandle ogrFeatureDefinitionGetGeomFieldName;
+
+ /**
+ * <abbr>OGR</abbr> {@code OGRSpatialReferenceH CPL_DLL
OGR_GFld_GetSpatialRef(OGRGeomFieldDefnH)}.
+ * Fetch spatial reference system of this field.
+ */
+ final MethodHandle ogrFeatureDefinitionGetGeomFieldSpatialRef;
+
+
+
/**
* Creates the handles for all <abbr>GDAL</abbr> functions which will be
needed.
*
@@ -288,6 +465,7 @@ final class GDAL extends NativeFunctions {
final var acceptPointerReturnInt =
FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS);
final var acceptTwoPtrsReturnDouble =
FunctionDescriptor.of(ValueLayout.JAVA_DOUBLE, ValueLayout.ADDRESS,
ValueLayout.ADDRESS);
final var acceptTwoPtrsReturnPointer =
FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS,
ValueLayout.ADDRESS);
+ final var acceptPointerAndIntReturnPointer =
FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS,
ValueLayout.JAVA_INT);
// Memory management
free = lookup("VSIFree",
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS));
@@ -394,6 +572,97 @@ final class GDAL extends NativeFunctions {
ValueLayout.JAVA_INT, // GDALDataType eBDataType
ValueLayout.ADDRESS)); // CSLConstList papszOptions
+ // Dataset layer API
+ datasetGetLayerCount = lookup("GDALDatasetGetLayerCount",
acceptPointerReturnInt);
+
+ datasetGetLayer = lookup("GDALDatasetGetLayer",
acceptPointerAndIntReturnPointer);
+
+ // OGR API
+ ogrLayerGetLayerDefn = lookup("OGR_L_GetLayerDefn",
acceptPointerReturnPointer);
+
+ ogrLayerGetName = lookup("OGR_L_GetName", acceptPointerReturnPointer);
+
+ ogrLayerGetFeatureCount = lookup("OGR_L_GetFeatureCount",
FunctionDescriptor.of(
+ ValueLayout.JAVA_LONG,
+ ValueLayout.ADDRESS,
+ ValueLayout.JAVA_INT)); //flag to force computtion
+
+ ogrLayerGetExtent = lookup("OGR_L_GetExtent", FunctionDescriptor.of(
+ ValueLayout.JAVA_INT,
+ ValueLayout.ADDRESS,
+ ValueLayout.ADDRESS,
+ ValueLayout.JAVA_INT));
+
+ ogrLayerGetNextFeature = lookup("OGR_L_GetNextFeature",
acceptPointerReturnPointer);
+
+ ogrFeatureGetFid = lookup("OGR_F_GetFID", FunctionDescriptor.of(
+ ValueLayout.JAVA_LONG,
+ ValueLayout.ADDRESS));
+
+ ogrFeatureDefinitionGetFieldCount = lookup("OGR_FD_GetFieldCount",
acceptPointerReturnInt);
+
+ ogrFeatureDefinitionGetFieldDefinition = lookup("OGR_FD_GetFieldDefn",
acceptPointerAndIntReturnPointer);
+
+ ogrFeatureDefinitionGetFieldType = lookup("OGR_Fld_GetType",
acceptPointerReturnInt);
+
+ ogrFeatureDefinitionGetFieldName = lookup("OGR_Fld_GetNameRef",
acceptPointerReturnPointer);
+
+ ogrFeatureDefinitionGetGeomFieldCount =
lookup("OGR_FD_GetGeomFieldCount", acceptPointerReturnInt);
+
+ ogrFeatureDefinitionGetGeomFieldDefinition =
lookup("OGR_FD_GetGeomFieldDefn", acceptPointerAndIntReturnPointer);
+
+ ogrFeatureDefinitionGetGeomFieldType = lookup("OGR_GFld_GetType",
acceptPointerReturnInt);
+
+ ogrFeatureDefinitionGetGeomFieldName = lookup("OGR_GFld_GetNameRef",
acceptPointerReturnPointer);
+
+ ogrFeatureDefinitionGetGeomFieldSpatialRef =
lookup("OGR_GFld_GetSpatialRef", acceptPointerReturnPointer);
+
+ ogrFeatureGetFieldAsInteger = lookup("OGR_F_GetFieldAsInteger",
FunctionDescriptor.of(
+ ValueLayout.JAVA_INT,
+ ValueLayout.ADDRESS,
+ ValueLayout.JAVA_INT));
+
+ ogrFeatureGetFieldAsInteger64 = lookup("OGR_F_GetFieldAsInteger64",
FunctionDescriptor.of(
+ ValueLayout.JAVA_LONG,
+ ValueLayout.ADDRESS,
+ ValueLayout.JAVA_INT));
+
+ ogrFeatureGetFieldAsDouble = lookup("OGR_F_GetFieldAsDouble",
FunctionDescriptor.of(
+ ValueLayout.JAVA_DOUBLE,
+ ValueLayout.ADDRESS,
+ ValueLayout.JAVA_INT));
+
+ ogrFeatureGetFieldAsString = lookup("OGR_F_GetFieldAsString",
FunctionDescriptor.of(
+ ValueLayout.ADDRESS,
+ ValueLayout.ADDRESS,
+ ValueLayout.JAVA_INT));
+
+ ogrFeatureGetGeometryRef = lookup("OGR_F_GetGeometryRef",
acceptPointerReturnPointer);
+
+ ogrFeatureDestroy = lookup("OGR_F_Destroy",
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS));
+
+ ogrDataSourceDestroy = lookup("OGR_DS_Destroy",
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS));
+
+ ogrGeometryGetGeometryName = lookup("OGR_G_GetGeometryName",
acceptPointerReturnPointer);
+
+ ogrGeometryGetPoints = lookup("OGR_G_GetPoints",
FunctionDescriptor.of(
+ ValueLayout.JAVA_INT,
+ ValueLayout.ADDRESS,
+ ValueLayout.ADDRESS,
+ ValueLayout.JAVA_INT,
+ ValueLayout.ADDRESS,
+ ValueLayout.JAVA_INT,
+ ValueLayout.ADDRESS,
+ ValueLayout.JAVA_INT));
+
+ ogrGeometryGetPointCount = lookup("OGR_G_GetPointCount",
acceptPointerReturnInt);
+
+ ogrGeometryGetGeometryCount = lookup("OGR_G_GetGeometryCount",
acceptPointerReturnInt);
+
+ ogrGeometryGetGeometryRef = lookup("OGR_G_GetGeometryRef",
acceptPointerAndIntReturnPointer);
+
+
+
// Set error handling first in order to redirect initialization
warnings.
setErrorHandler(null);
diff --git
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/GDALStore.java
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/GDALStore.java
index 748dc7d15c..2aa49d6ccb 100644
---
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/GDALStore.java
+++
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/GDALStore.java
@@ -50,6 +50,7 @@ import org.apache.sis.util.privy.Constants;
import org.apache.sis.util.privy.UnmodifiableArrayList;
import org.apache.sis.util.iso.DefaultNameFactory;
import org.apache.sis.system.Cleaners;
+import org.apache.sis.util.ArraysExt;
/**
@@ -373,7 +374,9 @@ public class GDALStore extends DataStore implements
Aggregate {
if (subdatasets != null && !subdatasets.isEmpty()) {
components = subdatasets;
} else {
- components =
UnmodifiableArrayList.wrap(TiledResource.groupBySizeAndType(this, gdal,
handle()));
+ final TiledResource[] rasters =
TiledResource.groupBySizeAndType(this, gdal, handle());
+ final OGRFeatureSet[] vectors =
OGRFeatureSet.listVectors(this, gdal, handle());
+ components =
UnmodifiableArrayList.wrap(ArraysExt.concatenate(new Resource[0], rasters,
vectors));
}
} finally {
ErrorHandler.throwOnFailure(this, "components");
diff --git
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OGRFeatureSet.java
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OGRFeatureSet.java
new file mode 100644
index 0000000000..639f108e2f
--- /dev/null
+++
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OGRFeatureSet.java
@@ -0,0 +1,184 @@
+/*
+ * 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.storage.gdal;
+
+import java.lang.foreign.Arena;
+import java.lang.foreign.MemorySegment;
+import java.nio.DoubleBuffer;
+import java.util.Optional;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.sis.feature.builder.AttributeRole;
+import org.apache.sis.feature.builder.AttributeTypeBuilder;
+import org.apache.sis.feature.builder.FeatureTypeBuilder;
+import org.apache.sis.feature.privy.AttributeConvention;
+import org.apache.sis.geometry.GeneralEnvelope;
+import org.apache.sis.referencing.crs.AbstractCRS;
+import org.apache.sis.referencing.cs.AxesConvention;
+import org.apache.sis.storage.AbstractFeatureSet;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.panama.NativeFunctions;
+import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.MultiLineString;
+import org.locationtech.jts.geom.MultiPolygon;
+import org.locationtech.jts.geom.Polygon;
+import org.opengis.feature.Feature;
+import org.opengis.feature.FeatureType;
+import org.opengis.geometry.Envelope;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+final class OGRFeatureSet extends AbstractFeatureSet {
+
+ final GDALStore store;
+ final GDAL gdal;
+ final MemorySegment dataset;
+ final MemorySegment layer;
+
+ //computed after a getType() call
+ FeatureType type;
+ CoordinateReferenceSystem crs;
+ String[] fields;
+ String[] geomFields;
+ OGRFieldType[] fieldEncs;
+
+ OGRFeatureSet(final GDALStore store, final GDAL gdal, final MemorySegment
dataset, MemorySegment layer) {
+ super(store);
+ this.store = store;
+ this.gdal = gdal;
+ this.dataset = dataset;
+ this.layer = layer;
+ }
+
+ @Override
+ public synchronized FeatureType getType() throws DataStoreException {
+ if (type != null) return type;
+
+ try {
+ final MemorySegment driver = (MemorySegment)
gdal.getDatasetDriver.invokeExact(dataset);
+ final String driverName = NativeFunctions.toString((MemorySegment)
gdal.getName.invokeExact(driver));
+
+ final MemorySegment layerDef = (MemorySegment)
gdal.ogrLayerGetLayerDefn.invokeExact(layer);
+ final String name = NativeFunctions.toString( ((MemorySegment)
gdal.ogrLayerGetName.invokeExact(layer)));
+
+ final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
+
ftb.addAttribute(Long.class).setName(AttributeConvention.IDENTIFIER_PROPERTY);
+ ftb.setName(name);
+
+ // List feature type fields
+ fields = new
String[(int)gdal.ogrFeatureDefinitionGetFieldCount.invokeExact(layerDef)];
+ fieldEncs = new OGRFieldType[fields.length];
+ for (int i = 0 ; i<fields.length; i++) {
+ final MemorySegment fieldDef = (MemorySegment)
gdal.ogrFeatureDefinitionGetFieldDefinition.invokeExact(layerDef,i);
+ final OGRFieldType type = OGRFieldType.valueOf((int)
gdal.ogrFeatureDefinitionGetFieldType.invokeExact(fieldDef));
+ final String fieldName = NativeFunctions.toString(
(MemorySegment)gdal.ogrFeatureDefinitionGetFieldName.invokeExact(fieldDef));
+ final Class<?> valueClass = type.getJavaClass();
+ ftb.addAttribute(valueClass).setName(fieldName);
+ fields[i] = fieldName;
+ fieldEncs[i] = type;
+ }
+
+ // List geometric feature type fields
+ geomFields = new String[(int)
gdal.ogrFeatureDefinitionGetGeomFieldCount.invokeExact(layerDef)];
+ for(int i=0; i<geomFields.length; i++) {
+ final MemorySegment ogrGeomFieldDefnH = (MemorySegment)
gdal.ogrFeatureDefinitionGetGeomFieldDefinition.invokeExact(layerDef,i);
+ final OGRwkbGeometryType typrgeom =
OGRwkbGeometryType.valueOf( (int)
gdal.ogrFeatureDefinitionGetGeomFieldType.invokeExact(ogrGeomFieldDefnH));
+ geomFields[i] =
NativeFunctions.toString((MemorySegment)gdal.ogrFeatureDefinitionGetGeomFieldName.invokeExact(ogrGeomFieldDefnH));
+ if(geomFields[i].isEmpty()) geomFields[i] = "geometry"+i;
+
+ //read CRS
+ final MemorySegment crsRef = (MemorySegment)
gdal.ogrFeatureDefinitionGetGeomFieldSpatialRef.invokeExact(ogrGeomFieldDefnH);
+ final SpatialRef spatialRef =
SpatialRef.createWithHandle(store, gdal, crsRef);
+ crs = spatialRef.parseCRS("listVectors");
+ //force longitude first
+ crs =
((AbstractCRS)crs).forConvention(AxesConvention.RIGHT_HANDED);
+
+ Class<?> geomClass = typrgeom.getJavaClass();
+ if (driverName.toLowerCase().contains("shapefile")) {
+ //OGR Hack : shapefile geometry type is not correctly
detected
+ //this seems to be because ogr shp driver do not make a
difference betwen geom types
+ //https://code.djangoproject.com/ticket/7218
+ if (Polygon.class.equals(geomClass)) geomClass =
MultiPolygon.class;
+ if (LineString.class.equals(geomClass)) geomClass =
MultiLineString.class;
+ }
+
+ final AttributeTypeBuilder<?> attBuilder =
ftb.addAttribute(geomClass).setName(geomFields[i]).setCRS(crs);
+ if (i == 0)
attBuilder.addRole(AttributeRole.DEFAULT_GEOMETRY); // first geometry as
default
+ }
+ type = ftb.build();
+ } catch (Throwable e) {
+ throw GDAL.propagate(e);
+ }
+ return type;
+ }
+
+ @Override
+ public Optional<Envelope> getEnvelope() throws DataStoreException {
+ // use ogr provided envelope
+ try (Arena arena = Arena.ofConfined()) {
+ final MemorySegment extent = arena.allocate(8*4);
+ int error = (int) gdal.ogrLayerGetExtent.invokeExact(layer,
extent, 1);
+ if (error != 0) {
+ throw new DataStoreException("Failed to calculate envelope for
type "+ getIdentifier().get());
+ }
+ final DoubleBuffer db = extent.asByteBuffer().asDoubleBuffer();
+ final GeneralEnvelope env = new GeneralEnvelope(crs);
+ env.setRange(0, db.get(0), db.get(1));
+ env.setRange(1, db.get(2), db.get(3));
+ return Optional.of(env);
+ } catch (Throwable e) {
+ throw GDAL.propagate(e);
+ }
+ }
+
+ public long getCount() throws DataStoreException {
+ try {
+ final Long nb = (Long)
gdal.ogrLayerGetFeatureCount.invokeExact(layer, 1);
+ return nb != null ? nb : -1;
+ } catch (Throwable e) {
+ throw GDAL.propagate(e);
+ }
+ }
+
+ @Override
+ public Stream<Feature> features(boolean parallel) throws
DataStoreException {
+ final OgrSpliterator ite = new OgrSpliterator(this, getType());
+ return StreamSupport.stream(ite, parallel);
+ }
+
+ /**
+ * Returns featuresets found.
+ *
+ * @throws DataStoreException if an error occurred.
+ */
+ static OGRFeatureSet[] listVectors(final GDALStore parent, final GDAL
gdal, final MemorySegment dataset)
+ throws DataStoreException {
+ try {
+ final OGRFeatureSet[] array = new OGRFeatureSet[(int)
gdal.datasetGetLayerCount.invokeExact(dataset)];
+ for (int iLayer = 0; iLayer < array.length ; iLayer++) {
+ final MemorySegment layer = (MemorySegment)
gdal.datasetGetLayer.invokeExact(dataset, iLayer);
+ array[iLayer] = new OGRFeatureSet(parent, gdal, dataset,
layer);
+ }
+ return array;
+ } catch (Throwable e) {
+ throw GDAL.propagate(e);
+ }
+ }
+}
diff --git
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OGRFieldType.java
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OGRFieldType.java
new file mode 100644
index 0000000000..9559127e58
--- /dev/null
+++
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OGRFieldType.java
@@ -0,0 +1,84 @@
+/*
+ * 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.storage.gdal;
+
+/**
+ *
+ * @author Hilmi Bouallegue (Geomatys)
+ */
+enum OGRFieldType {
+ /** Simple 32bit integer */
+ OFTInteger(Integer.class),
+ /** List of 32bit integers */
+ OFTIntegerList(Object.class),
+ /** Double Precision floating point */
+ OFTReal(Double.class),
+ /** List of doubles */
+ OFTRealList(Object.class),
+ /** String of ASCII chars */
+ OFTString(String.class),
+ /** Array of strings */
+ OFTStringList(Object.class),
+ /** deprecated */
+ OFTWideString(String.class),
+ /** deprecated */
+ OFTWideStringList(Object.class),
+ /** Raw Binary data */
+ OFTBinary(Object.class),
+ /** Date */
+ OFTDate(Object.class),
+ /** Time */
+ OFTTime(Object.class),
+ /** Date and Time */
+ OFTDateTime(Object.class),
+ /** Single 64bit integer */
+ OFTInteger64(Long.class),
+ /** List of 64bit integers */
+ OFTInteger64List(Object.class),
+ OFTMaxType(Object.class);
+
+ private final Class javaClass;
+
+ OGRFieldType(Class javaClass){
+ this.javaClass =javaClass;
+ }
+
+ public Class getJavaClass(){
+ return javaClass;
+ }
+
+ public static OGRFieldType valueOf(int value) {
+ switch (value) {
+ case 0 : return OFTInteger;
+ case 1 : return OFTIntegerList;
+ case 2 : return OFTReal;
+ case 3 : return OFTRealList;
+ case 4 : return OFTString;
+ case 5 : return OFTStringList;
+ case 6 : return OFTWideString;
+ case 7 : return OFTWideStringList;
+ case 8 : return OFTBinary;
+ case 9 : return OFTDate;
+ case 10 : return OFTTime;
+ case 11 : return OFTDateTime;
+ case 12 : return OFTInteger64;
+ case 13 : return OFTInteger64List;
+ }
+ throw new IllegalArgumentException("Unknown type " + value);
+ }
+
+}
diff --git
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OGRwkbByteOrder.java
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OGRwkbByteOrder.java
new file mode 100644
index 0000000000..6cacfa2312
--- /dev/null
+++
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OGRwkbByteOrder.java
@@ -0,0 +1,36 @@
+/*
+ * 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.storage.gdal;
+
+/**
+ *
+ * @author Hilmi Bouallegue (Geomatys)
+ */
+enum OGRwkbByteOrder {
+ /** MSB/Sun/Motoroloa: Most Significant Byte First. */
+ wkbXDR,
+ /** LSB/Intel/Vax: Least Significant Byte First. */
+ wkbNDR;
+
+ public static OGRwkbByteOrder valueOf(int value) {
+ switch (value) {
+ case 0 : return wkbXDR;
+ case 1 : return wkbNDR;
+ }
+ throw new IllegalArgumentException("Unknown type " + value);
+ }
+}
diff --git
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OGRwkbGeometryType.java
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OGRwkbGeometryType.java
new file mode 100644
index 0000000000..5f81883227
--- /dev/null
+++
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OGRwkbGeometryType.java
@@ -0,0 +1,185 @@
+/*
+ * 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.storage.gdal;
+
+import org.locationtech.jts.geom.*;
+
+
+/**
+ *
+ * @author Hilmi Bouallegue (Geomatys)
+ */
+public enum OGRwkbGeometryType {
+ wkbUnknown(Geometry.class),
+ wkbPoint(Point.class),
+ wkbLineString(LineString.class),
+ wkbPolygon(Polygon.class),
+ wkbMultiPoint(MultiPoint.class),
+ wkbMultiLineString(MultiLineString.class),
+ wkbMultiPolygon(MultiPolygon.class),
+ wkbGeometryCollection(GeometryCollection.class),
+ wkbCircularString(Geometry.class),
+ wkbCompoundCurve(Geometry.class),
+ wkbCurvePolygon(Geometry.class),
+ wkbMultiCurve(Geometry.class),
+ wkbMultiSurface(Geometry.class),
+ wkbCurve(Geometry.class),
+ wkbSurface(Geometry.class),
+ wkbPolyhedralSurface(Geometry.class),
+ wkbTIN(Geometry.class),
+ wkbTriangle(Geometry.class),
+ wkbNone(Geometry.class),
+ wkbLinearRing(Geometry.class),
+ wkbCircularStringZ(Geometry.class),
+ wkbCompoundCurveZ(Geometry.class),
+ wkbCurvePolygonZ(Geometry.class),
+ wkbMultiCurveZ(Geometry.class),
+ wkbMultiSurfaceZ(Geometry.class),
+ wkbCurveZ(Geometry.class),
+ wkbSurfaceZ(Geometry.class),
+ wkbPolyhedralSurfaceZ(Geometry.class),
+ wkbTINZ(Geometry.class),
+ wkbTriangleZ(Geometry.class),
+ wkbPointM(Geometry.class),
+ wkbLineStringM(Geometry.class),
+ wkbPolygonM(Geometry.class),
+ wkbMultiPointM(Geometry.class),
+ wkbMultiLineStringM(Geometry.class),
+ wkbMultiPolygonM(Geometry.class),
+ wkbGeometryCollectionM(Geometry.class),
+ wkbCircularStringM(Geometry.class),
+ wkbCompoundCurveM(Geometry.class),
+ wkbCurvePolygonM(Geometry.class),
+ wkbMultiCurveM(Geometry.class),
+ wkbMultiSurfaceM(Geometry.class),
+ wkbCurveM(Geometry.class),
+ wkbSurfaceM(Geometry.class),
+ wkbPolyhedralSurfaceM(Geometry.class),
+ wkbTINM(Geometry.class),
+ wkbTriangleM(Geometry.class),
+ wkbPointZM(Geometry.class),
+ wkbLineStringZM(Geometry.class),
+ wkbPolygonZM(Geometry.class),
+ wkbMultiPointZM(Geometry.class),
+ wkbMultiLineStringZM(Geometry.class),
+ wkbMultiPolygonZM(Geometry.class),
+ wkbGeometryCollectionZM(Geometry.class),
+ wkbCircularStringZM(Geometry.class),
+ wkbCompoundCurveZM(Geometry.class),
+ wkbCurvePolygonZM(Geometry.class),
+ wkbMultiCurveZM(Geometry.class),
+ wkbMultiSurfaceZM(Geometry.class),
+ wkbCurveZM(Geometry.class),
+ wkbSurfaceZM(Geometry.class),
+ wkbPolyhedralSurfaceZM(Geometry.class),
+ wkbTINZM(Geometry.class),
+ wkbTriangleZM(Geometry.class),
+ wkbPoint25D(Geometry.class),
+ wkbLineString25D(Geometry.class),
+ wkbPolygon25D(Geometry.class),
+ wkbMultiPoint25D(Geometry.class),
+ wkbMultiLineString25D(Geometry.class),
+ wkbMultiPolygon25D(Geometry.class),
+ wkbGeometryCollection25D(Geometry.class);
+
+ private final Class javaClass;
+
+ OGRwkbGeometryType(Class javaClass){
+ this.javaClass =javaClass;
+ }
+
+ public Class getJavaClass(){
+ return javaClass;
+ }
+
+ public static OGRwkbGeometryType valueOf(int value) {
+ switch (value) {
+ case 0 : return wkbUnknown;
+ case 1 : return wkbPoint;
+ case 2 : return wkbLineString;
+ case 3 : return wkbPolygon;
+ case 4 : return wkbMultiPoint;
+ case 5 : return wkbMultiLineString;
+ case 6 : return wkbMultiPolygon;
+ case 7 : return wkbGeometryCollection;
+ case 8 : return wkbCircularString;
+ case 9 : return wkbCompoundCurve;
+ case 10 : return wkbCurvePolygon;
+ case 11 : return wkbMultiCurve;
+ case 12 : return wkbMultiSurface;
+ case 13 : return wkbCurve;
+ case 14 : return wkbSurface;
+ case 15 : return wkbPolyhedralSurface;
+ case 16 : return wkbTIN;
+ case 17 : return wkbTriangle;
+ case 18 : return wkbNone;
+ case 19 : return wkbLinearRing;
+ case 20 : return wkbCircularStringZ;
+ case 21 : return wkbCompoundCurveZ;
+ case 22 : return wkbCurvePolygonZ;
+ case 23 : return wkbMultiCurveZ;
+ case 24 : return wkbMultiSurfaceZ;
+ case 25 : return wkbCurveZ;
+ case 26 : return wkbSurfaceZ;
+ case 27 : return wkbPolyhedralSurfaceZ;
+ case 28 : return wkbTINZ;
+ case 29 : return wkbTriangleZ;
+ case 30 : return wkbPointM;
+ case 31 : return wkbLineStringM;
+ case 32 : return wkbPolygonM;
+ case 33 : return wkbMultiPointM;
+ case 34 : return wkbMultiLineStringM;
+ case 35 : return wkbMultiPolygonM;
+ case 36 : return wkbGeometryCollectionM;
+ case 37 : return wkbCircularStringM;
+ case 38 : return wkbCompoundCurveM;
+ case 39 : return wkbCurvePolygonM;
+ case 40 : return wkbMultiCurveM;
+ case 41 : return wkbMultiSurfaceM;
+ case 42 : return wkbCurveM;
+ case 43 : return wkbSurfaceM;
+ case 44 : return wkbPolyhedralSurfaceM;
+ case 45 : return wkbTINM;
+ case 46 : return wkbTriangleM;
+ case 47 : return wkbPointZM;
+ case 48 : return wkbLineStringZM;
+ case 49 : return wkbPolygonZM;
+ case 50 : return wkbMultiPointZM;
+ case 51 : return wkbMultiLineStringZM;
+ case 52 : return wkbMultiPolygonZM;
+ case 53 : return wkbGeometryCollectionZM;
+ case 54 : return wkbCircularStringZM;
+ case 55 : return wkbCompoundCurveZM;
+ case 56 : return wkbCurvePolygonZM;
+ case 57 : return wkbMultiCurveZM;
+ case 58 : return wkbMultiSurfaceZM;
+ case 59 : return wkbCurveZM;
+ case 60 : return wkbSurfaceZM;
+ case 61 : return wkbPolyhedralSurfaceZM;
+ case 62 : return wkbTINZM;
+ case 63 : return wkbTriangleZM;
+ case 64 : return wkbPoint25D;
+ case 65 : return wkbLineString25D;
+ case 66 : return wkbPolygon25D;
+ case 67 : return wkbMultiPoint25D;
+ case 68 : return wkbMultiLineString25D;
+ case 69 : return wkbMultiPolygon25D;
+ case 70 : return wkbGeometryCollection25D;
+ }
+ throw new IllegalArgumentException("Unknown type " + value);
+ }
+}
diff --git
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OgrGeometryReader.java
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OgrGeometryReader.java
new file mode 100644
index 0000000000..2bbe4aade8
--- /dev/null
+++
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OgrGeometryReader.java
@@ -0,0 +1,206 @@
+/*
+ * 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.storage.gdal;
+
+import java.lang.foreign.Arena;
+import java.lang.foreign.MemorySegment;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.panama.NativeFunctions;
+import org.locationtech.jts.geom.CoordinateSequence;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.GeometryFactory;
+import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.LinearRing;
+import org.locationtech.jts.geom.Polygon;
+import org.locationtech.jts.geom.impl.PackedCoordinateSequence;
+
+/**
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+final class OgrGeometryReader implements AutoCloseable {
+
+ private static final GeometryFactory GF = new GeometryFactory();
+ //reuse direct buffer for better performances
+ private MemorySegment px;
+ private MemorySegment py;
+ private ByteBuffer bufferx;
+ private ByteBuffer buffery;
+
+ private final Arena arena = Arena.ofConfined();
+ private final GDAL gdal;
+
+ OgrGeometryReader(GDAL gdal) {
+ this.gdal = gdal;
+ }
+
+ private void resizeBuffer(int nbPoint){
+ final int size = nbPoint*2*8;
+ if (px == null || px.byteSize() < size) {
+ px = arena.allocate(size);
+ py = px.asSlice(8);
+ bufferx = px.asByteBuffer();
+ buffery = py.asByteBuffer();
+ }
+ }
+
+ public Geometry toGeometry(MemorySegment ogrGeom) throws
DataStoreException {
+ if (ogrGeom == null) return null;
+
+ try {
+ MemorySegment NULL = MemorySegment.ofAddress(0);
+ final String type = NativeFunctions.toString(
(MemorySegment)gdal.ogrGeometryGetGeometryName.invokeExact(ogrGeom));
+
+ switch (type) {
+ case "POINT" : {
+ final double[] coords = new double[2];
+ resizeBuffer(1);
+ final int returnedNbPoints = (int)
gdal.ogrGeometryGetPoints.invokeExact(ogrGeom,px,16,py,16,NULL,0);
+
+ bufferx.position(0);
+
bufferx.order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer().get(coords);
+
+ final CoordinateSequence cs = new
PackedCoordinateSequence.Double(coords,2,0);
+ return GF.createPoint(cs);
+ }
+ case "MULTIPOINT" : {
+ final int nbPoint = (int)
gdal.ogrGeometryGetPointCount.invokeExact(ogrGeom);
+ final double[] coords = new double[nbPoint*2];
+ if (nbPoint != 0) {
+ resizeBuffer(nbPoint);
+ final int returnedNbPoints = (int)
gdal.ogrGeometryGetPoints.invokeExact(ogrGeom,px,16,py,16,NULL,0);
+
+ bufferx.position(0);
+
bufferx.order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer().get(coords);
+ }
+ final CoordinateSequence cs = new
PackedCoordinateSequence.Double(coords,2,0);
+ return GF.createMultiPoint(cs);
+ }
+ case "LINESTRING" : {
+ final int nbPoint = (int)
gdal.ogrGeometryGetPointCount.invokeExact(ogrGeom);
+ final double[] coords = new double[nbPoint*2];
+ resizeBuffer(nbPoint);
+ final int returnedNbPoints = (int)
gdal.ogrGeometryGetPoints.invokeExact(ogrGeom,px,16,py,16,NULL,0);
+
+ bufferx.position(0);
+
bufferx.order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer().get(coords);
+
+ if (nbPoint==1) {
+ //duplicate first point, JTS need at least 2
coordinates
+ final double[] cp = new
double[]{coords[0],coords[1],coords[0],coords[1]};
+ final CoordinateSequence cs = new
PackedCoordinateSequence.Double(cp,2,0);
+ return GF.createLineString(cs);
+ } else {
+ final CoordinateSequence cs = new
PackedCoordinateSequence.Double(coords,2,0);
+ return GF.createLineString(cs);
+ }
+ }
+ case "LINEARRING" : {
+ final int nbPoint = (int)
gdal.ogrGeometryGetPointCount.invokeExact(ogrGeom);
+ double[] coords = new double[(nbPoint+1)*2];
+ resizeBuffer(nbPoint+1);
+ final int returnedNbPoints = (int)
gdal.ogrGeometryGetPoints.invokeExact(ogrGeom,px,16,py,16,NULL,0);
+
+ bufferx.position(0);
+
bufferx.order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer().get(coords,0,nbPoint*2);
+
+ //JTS needs at least 3+1 points
+ if (coords.length<8) {
+ double[] cs = Arrays.copyOf(coords, 8);
+ for(int i=nbPoint;i<4;i++){
+ cs[i*2+0] = coords[0];
+ cs[i*2+1] = coords[1];
+ }
+ coords = cs;
+ }
+
+ //duplicate first to last point this is a JTS constraint
+ coords[coords.length-2] = coords[0];
+ coords[coords.length-1] = coords[1];
+
+ final CoordinateSequence cs = new
PackedCoordinateSequence.Double(coords,2,0);
+ return GF.createLinearRing(cs);
+ }
+ case "MULTILINESTRING" : {
+ final int nbGeom = (int)
gdal.ogrGeometryGetGeometryCount.invokeExact(ogrGeom);
+ final LineString[] children = new LineString[nbGeom];
+ for (int i=0;i<nbGeom;i++) {
+ final MemorySegment sub = (MemorySegment)
gdal.ogrGeometryGetGeometryRef.invokeExact(ogrGeom, i);
+ children[i] = (LineString) toGeometry(sub);
+ }
+ return GF.createMultiLineString(children);
+ }
+ case "POLYGON" : {
+ final int nbGeom = (int)
gdal.ogrGeometryGetGeometryCount.invokeExact(ogrGeom);
+ //first is the exterior ring, next ones are the interiors
+ LinearRing exterior = null;
+ final LinearRing[] interiors = new LinearRing[nbGeom-1];
+ for (int i=0;i<nbGeom;i++) {
+ final MemorySegment sub = (MemorySegment)
gdal.ogrGeometryGetGeometryRef.invokeExact(ogrGeom, i);
+ if (i==0) exterior = (LinearRing) toGeometry(sub);
+ else interiors[i-1] = (LinearRing) toGeometry(sub);
+ }
+ return GF.createPolygon(exterior,interiors);
+ }
+ case "MULTIPOLYGON" : {
+ final int nbGeom = (int)
gdal.ogrGeometryGetGeometryCount.invokeExact(ogrGeom);
+ final Polygon[] children = new Polygon[nbGeom];
+ for (int i=0;i<nbGeom;i++) {
+ final MemorySegment sub = (MemorySegment)
gdal.ogrGeometryGetGeometryRef.invokeExact(ogrGeom, i);
+ children[i] = (Polygon) toGeometry(sub);
+ }
+ return GF.createMultiPolygon(children);
+ }
+ case "GEOMETRYCOLLECTION" : {
+ final int nbGeom = (int)
gdal.ogrGeometryGetGeometryCount.invokeExact(ogrGeom);
+ final Geometry[] children = new Geometry[nbGeom];
+ for (int i=0;i<nbGeom;i++) {
+ final MemorySegment sub = (MemorySegment)
gdal.ogrGeometryGetGeometryRef.invokeExact(ogrGeom, i);
+ children[i] = toGeometry(sub);
+ }
+ return GF.createGeometryCollection(children);
+ }
+ case "GEOMETRY" :
+ case "CIRCULARSTRING" :
+ case "COMPOUNDCURVE" :
+ case "CURVEPOLYGON" :
+ case "MULTICURVE" :
+ case "MULTISURFACE" :
+ case "CURVE" :
+ case "SURFACE" :
+ case "POLYHEDRALSURFACE" :
+ case "TIN" :
+ case "TRIANGLE" :
+ default : {
+ throw new DataStoreException("Unsupported geometry type
"+type);
+ }
+ }
+ } catch (Throwable e) {
+ throw GDAL.propagate(e);
+ }
+
+ }
+
+ @Override
+ public void close() {
+ arena.close();
+ }
+
+}
diff --git
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OgrSpliterator.java
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OgrSpliterator.java
new file mode 100644
index 0000000000..a293d52327
--- /dev/null
+++
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/OgrSpliterator.java
@@ -0,0 +1,133 @@
+/*
+ * 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.storage.gdal;
+
+import java.lang.foreign.MemorySegment;
+import java.util.Spliterator;
+import java.util.function.Consumer;
+import org.apache.sis.feature.privy.AttributeConvention;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.panama.NativeFunctions;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.MultiLineString;
+import org.locationtech.jts.geom.MultiPolygon;
+import org.locationtech.jts.geom.Polygon;
+import org.opengis.feature.AttributeType;
+import org.opengis.feature.Feature;
+import org.opengis.feature.FeatureType;
+
+
+/**
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+final class OgrSpliterator implements Spliterator<Feature>{
+
+ private final OGRFeatureSet fs;
+ private final OgrGeometryReader geomReader;
+ private final FeatureType type;
+ private boolean closed = false;
+ private final GDAL gdal;
+
+ OgrSpliterator(OGRFeatureSet fs, FeatureType type) throws
DataStoreException {
+ this.fs = fs;
+ this.type = type;
+ gdal = fs.gdal;
+ geomReader = new OgrGeometryReader(gdal);
+ }
+
+ @Override
+ public Spliterator<Feature> trySplit() {
+ return null;
+ }
+
+ @Override
+ public long estimateSize() {
+ return Long.MAX_VALUE;
+ }
+
+ @Override
+ public int characteristics() {
+ return NONNULL;
+ }
+
+ @Override
+ public boolean tryAdvance(Consumer<? super Feature> action) {
+ //Reading the features of the layer
+ try {
+ final MemorySegment featurePt = (MemorySegment)
gdal.ogrLayerGetNextFeature.invokeExact(fs.layer);
+ if (featurePt == null || featurePt.address() == 0L) {
+ return false;
+ }
+
+ final Feature feature = type.newInstance();
+ feature.setPropertyValue(AttributeConvention.IDENTIFIER, (long)
gdal.ogrFeatureGetFid.invokeExact(featurePt));
+ //Loop for all the features of the layer
+ for (int i = 0; i < fs.fields.length; i++) {
+ OGRFieldType fieldType = fs.fieldEncs[i];
+ String propName = fs.fields[i];
+ if (fieldType == OGRFieldType.OFTInteger) {
+ feature.setPropertyValue(propName, (int)
gdal.ogrFeatureGetFieldAsInteger.invokeExact(featurePt, i));
+ } else if (fieldType == OGRFieldType.OFTInteger64) {
+ feature.setPropertyValue(propName, (long)
gdal.ogrFeatureGetFieldAsInteger64.invokeExact(featurePt, i));
+ } else if (fieldType == OGRFieldType.OFTReal) {
+ feature.setPropertyValue(propName, (double)
gdal.ogrFeatureGetFieldAsDouble.invokeExact(featurePt, i));
+ } else if (fieldType == OGRFieldType.OFTString) {
+ feature.setPropertyValue(propName,
NativeFunctions.toString( (MemorySegment)
gdal.ogrFeatureGetFieldAsString.invokeExact(featurePt, i)));
+ } else {
+ feature.setPropertyValue(propName,
NativeFunctions.toString( (MemorySegment)
gdal.ogrFeatureGetFieldAsString.invokeExact(featurePt, i)));
+ }
+ }
+ // read geometry
+ if (fs.geomFields.length > 0) {
+ //TODO loop on all geometries
+ final MemorySegment ogrGeom = (MemorySegment)
gdal.ogrFeatureGetGeometryRef.invokeExact(featurePt);
+ Geometry geom = geomReader.toGeometry(ogrGeom);
+ final AttributeType geomType = (AttributeType)
type.getProperty(fs.geomFields[0]);
+
+ //shapefile mix LineString with MultiLineString and Polygon
with MultiPolygon, but not JTS
+ if (geom instanceof LineString) {
+ final MultiLineString ml =
geom.getFactory().createMultiLineString(new LineString[]{(LineString) geom});
+ ml.setUserData(geom.getUserData());
+ geom = ml;
+ } else if (geom instanceof Polygon) {
+ final MultiPolygon mp =
geom.getFactory().createMultiPolygon(new Polygon[]{(Polygon) geom});
+ mp.setUserData(geom.getUserData());
+ geom = mp;
+ }
+ geom.setUserData(fs.crs);
+ feature.setPropertyValue(fs.geomFields[0], geom);
+ }
+ //release memory
+ gdal.ogrFeatureDestroy.invokeExact(featurePt);
+
+ action.accept(feature);
+ return true;
+ } catch (Throwable e) {
+ throw GDAL.propagate(e);
+ }
+ }
+
+ public synchronized void close() {
+ if (closed) {
+ return;
+ }
+ closed = true;
+ }
+
+}
diff --git
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/Opener.java
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/Opener.java
index 4b737797ec..59b699c11a 100644
---
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/Opener.java
+++
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/Opener.java
@@ -69,7 +69,7 @@ final class Opener implements Runnable {
* @throws DataStoreException if <var>GDAL</var> cannot open the data set.
*/
Opener(final GDALStoreProvider owner, final String url, final String...
allowedDrivers) throws DataStoreException {
- this(owner, url, new OpenFlag[] {OpenFlag.RASTER, OpenFlag.SHARED},
allowedDrivers, null, null);
+ this(owner, url, new OpenFlag[] {OpenFlag.RASTER, OpenFlag.VECTOR,
OpenFlag.SHARED}, allowedDrivers, null, null);
}
/**
diff --git
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/SpatialRef.java
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/SpatialRef.java
index 912c6a1707..813108973c 100644
---
a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/SpatialRef.java
+++
b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/SpatialRef.java
@@ -97,6 +97,19 @@ final class SpatialRef {
return new SpatialRef(owner, gdal, handle);
}
+ /**
+ * Creates a new instance.
+ *
+ * @param owner the dataset which is providing the <abbr>CRS</abbr>
definition.
+ * @param gdal sets of handles for invoking <abbr>GDAL</abbr>
functions.
+ * @param spatialRefHandle pointer to native SpatialRef.
+ * @return wrapper for the <abbr>CRS</abbr> definition provided by
<abbr>GDAL</abbr>, or {@code null} if none.
+ * @throws DataStoreException if an error occurred while fetching
information from <abbr>GDAL</abbr>.
+ */
+ static SpatialRef createWithHandle(final GDALStore owner, final GDAL gdal,
final MemorySegment spatialRefHandle) throws DataStoreException {
+ return new SpatialRef(owner, gdal, spatialRefHandle);
+ }
+
/**
* Parses the <abbr>CRS</abbr> of the data set by parsing its
<abbr>WKT</abbr> representation.
* This method must be invoked from a method synchronized on {@link
GDALStore}.