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

asf-gitbox-commits 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 454665b5ad feat(Shapefile): generate an identifier when none exist
454665b5ad is described below

commit 454665b5ad3124c07bdcd084859bb63a3f4a3eac
Author: jsorel <[email protected]>
AuthorDate: Mon May 4 15:49:00 2026 +0200

    feat(Shapefile): generate an identifier when none exist
---
 .../sis/storage/shapefile/ShapefileStore.java      | 40 ++++++++++++++++++----
 1 file changed, 33 insertions(+), 7 deletions(-)

diff --git 
a/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java
 
b/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java
index 49748eb474..c0a913a23f 100644
--- 
a/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java
+++ 
b/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java
@@ -41,6 +41,7 @@ import java.util.OptionalLong;
 import java.util.Set;
 import java.util.Spliterator;
 import java.util.Spliterators;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.function.Consumer;
@@ -296,7 +297,7 @@ public final class ShapefileStore extends DataStore 
implements WritableFeatureSe
     private final class AsFeatureSet extends AbstractFeatureSet implements 
WritableFeatureSet {
 
         private final Rectangle2D.Double filter;
-        private final Set<String> dbfProperties;
+        private final Set<String> readProperties;
         private final boolean readShp;
         private Charset charset;
 
@@ -321,14 +322,25 @@ public final class ShapefileStore extends DataStore 
implements WritableFeatureSe
             super(null);
             this.readShp = readShp;
             this.filter = filter;
-            this.dbfProperties = properties;
+            this.readProperties = properties;
         }
 
         /**
          * @return true if this view reads all data without any filter.
          */
         private boolean isDefaultView() {
-            return filter == null && dbfProperties == null && readShp;
+            return filter == null && readProperties == null && readShp;
+        }
+
+        /**
+         * @return true if a feature id must be created.
+         * @throws DataStoreException
+         */
+        private boolean mustGenerateId() throws DataStoreException {
+            getType();
+            if (idField != null) return false;
+            if (readProperties == null) return true;
+            return readProperties.contains(AttributeConvention.IDENTIFIER);
         }
 
         /**
@@ -399,16 +411,16 @@ public final class ShapefileStore extends DataStore 
implements WritableFeatureSe
                         this.dbfHeader = header;
                         boolean hasId = false;
 
-                        if (dbfProperties == null) {
+                        if (readProperties == null) {
                             dbfPropertiesIndex = new int[header.fields.length];
                         } else {
-                            dbfPropertiesIndex = new int[dbfProperties.size()];
+                            dbfPropertiesIndex = new 
int[readProperties.size()];
                         }
 
                         int idx=0;
                         for (int i = 0; i < header.fields.length; i++) {
                             final DBFField field = header.fields[i];
-                            if (dbfProperties != null && 
!dbfProperties.contains(field.fieldName)) {
+                            if (readProperties != null && 
!readProperties.contains(field.fieldName)) {
                                 //skip unwanted fields
                                 continue;
                             }
@@ -433,6 +445,13 @@ public final class ShapefileStore extends DataStore 
implements WritableFeatureSe
                     throw new DataStoreException("DBF file is missing.");
                 }
 
+                //create a computed identifier field
+                if (readProperties == null && idField == null) {
+                    ftb.addAttribute(Integer.class)
+                       .setName(AttributeConvention.IDENTIFIER_PROPERTY)
+                       .addRole(AttributeRole.IDENTIFIER_COMPONENT);
+                }
+
                 type = ftb.build();
             }
             return type;
@@ -484,6 +503,9 @@ public final class ShapefileStore extends DataStore 
implements WritableFeatureSe
             }
             final int geomSrid = srid;
 
+            final boolean generateId = mustGenerateId();
+            final AtomicInteger nextId = new AtomicInteger();
+
             final Spliterator spliterator;
             if (readShp && dbfPropertiesIndex.length > 0) {
                 //read both shp and dbf
@@ -508,6 +530,8 @@ public final class ShapefileStore extends DataStore 
implements WritableFeatureSe
                             for (int i = 0; i < dbfPropertiesIndex.length; 
i++) {
                                 
next.setPropertyValue(header.fields[dbfPropertiesIndex[i]].fieldName, 
dbfRecord[i]);
                             }
+                            if (generateId) 
next.setPropertyValue(AttributeConvention.IDENTIFIER, nextId.getAndIncrement());
+
                             action.accept(next);
                             return true;
                         } catch (IOException ex) {
@@ -529,6 +553,7 @@ public final class ShapefileStore extends DataStore 
implements WritableFeatureSe
                                 shpRecord.geometry.setSRID(geomSrid);
                             }
                             next.setPropertyValue(GEOMETRY_NAME, 
shpRecord.geometry);
+                            if (generateId) 
next.setPropertyValue(AttributeConvention.IDENTIFIER, nextId.getAndIncrement());
                             action.accept(next);
                             return true;
                         } catch (IOException ex) {
@@ -549,6 +574,7 @@ public final class ShapefileStore extends DataStore 
implements WritableFeatureSe
                             for (int i = 0; i < dbfPropertiesIndex.length; 
i++) {
                                 
next.setPropertyValue(header.fields[dbfPropertiesIndex[i]].fieldName, 
dbfRecord[i]);
                             }
+                            if (generateId) 
next.setPropertyValue(AttributeConvention.IDENTIFIER, nextId.getAndIncrement());
                             action.accept(next);
                             return true;
                         } catch (IOException ex) {
@@ -621,7 +647,7 @@ public final class ShapefileStore extends DataStore 
implements WritableFeatureSe
                     }
 
                     //if link fields are referenced, add target fields
-                    if (properties.contains(AttributeConvention.IDENTIFIER)) 
simpleSelection &= !properties.add(idField);
+                    if (properties.contains(AttributeConvention.IDENTIFIER) && 
idField != null) simpleSelection &= !properties.add(idField);
                     if (properties.contains(AttributeConvention.GEOMETRY)) 
simpleSelection &= !properties.add(GEOMETRY_NAME);
                     if (properties.contains(AttributeConvention.ENVELOPE)) 
simpleSelection &= !properties.add(GEOMETRY_NAME);
                 }

Reply via email to