You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2023/11/06 11:38:09 UTC
(sis) 01/01: Merge branch 'geoapi-3.1'
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/sis.git
commit fafbe8a7b643a4994eb5fe2917721e380d381af2
Merge: ed9308d56c 2bffeac5a6
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Mon Nov 6 12:37:23 2023 +0100
Merge branch 'geoapi-3.1'
endorsed/build.gradle.kts | 3 +-
.../org.apache.sis.feature/main/module-info.java | 1 +
.../grid/BandAggregateGridCoverageTest.java | 4 +-
.../coverage/grid/ConvertedGridCoverageTest.java | 6 +-
.../coverage/grid/DimensionalityReductionTest.java | 2 +-
.../sis/coverage/grid/GridCoverage2DTest.java | 4 +-
.../sis/coverage/grid/GridCoverageBuilderTest.java | 2 +-
.../sis/coverage/grid/GridDerivationTest.java | 8 +-
.../apache/sis/coverage/grid/GridExtentTest.java | 2 +-
.../apache/sis/coverage/grid/GridGeometryTest.java | 8 +-
.../coverage/grid/ResampledGridCoverageTest.java | 8 +-
.../sis/coverage/grid/ReshapedImageTest.java | 6 +-
.../coverage/grid/TranslatedGridCoverageTest.java | 2 +-
.../apache/sis/feature/EnvelopeOperationTest.java | 2 +-
.../apache/sis/feature/FeatureOperationsTest.java | 6 +-
.../feature/builder/FeatureTypeBuilderTest.java | 8 +-
.../feature/internal/AttributeConventionTest.java | 2 +-
.../sis/filter/BinarySpatialFilterTestCase.java | 4 +-
.../apache/sis/filter/sqlmm/RegistryTestCase.java | 4 +-
.../org/apache/sis/filter/sqlmm/SQLMMTest.java | 2 +-
.../sis/geometry/wrapper/GeometriesTestCase.java | 4 +-
.../org/apache/sis/image/ResamplingGridTest.java | 4 +-
.../apache/sis/metadata/MetadataCopierTest.java | 4 +-
.../apache/sis/metadata/MetadataStandardTest.java | 6 +-
.../apache/sis/metadata/PropertyAccessorTest.java | 14 +-
.../sis/metadata/PropertyInformationTest.java | 2 +-
.../org/apache/sis/metadata/SpecialCasesTest.java | 6 +-
.../sis/metadata/sql/IdentifierGeneratorTest.java | 1 -
.../sis/metadata/sql/MetadataWriterTest.java | 4 +-
.../xml/bind/fra/DirectReferenceSystemTest.java | 4 +-
.../apache/sis/geometry/AbstractEnvelopeTest.java | 6 +-
.../org/apache/sis/geometry/ArrayEnvelopeTest.java | 4 +-
.../apache/sis/geometry/CoordinateFormatTest.java | 6 +-
.../org/apache/sis/geometry/Envelope2DTest.java | 2 +-
.../org/apache/sis/geometry/EnvelopesTest.java | 2 +-
.../sis/geometry/GeneralDirectPositionTest.java | 2 +-
.../apache/sis/geometry/GeneralEnvelopeTest.java | 4 +-
.../apache/sis/geometry/ImmutableEnvelopeTest.java | 2 +-
.../org/apache/sis/geometry/SubEnvelopeTest.java | 2 +-
.../org/apache/sis/geometry/TransformTestCase.java | 8 +-
.../sis/geometry/WraparoundAdjustmentTest.java | 4 +-
.../sis/referencing/AuthorityFactoriesTest.java | 4 +-
.../test/org/apache/sis/referencing/CRSTest.java | 6 +-
.../sis/referencing/GeodesicsOnEllipsoidTest.java | 2 +-
.../sis/referencing/GeodeticCalculatorTest.java | 2 +-
.../sis/referencing/IdentifiedObjectsTest.java | 2 +-
.../sis/referencing/StandardDefinitionsTest.java | 10 +-
.../sis/referencing/crs/AbstractCRSTest.java | 4 +-
.../referencing/crs/DefaultCompoundCRSTest.java | 4 +-
.../sis/referencing/crs/DefaultDerivedCRSTest.java | 4 +-
.../referencing/crs/DefaultEngineeringCRSTest.java | 2 +-
.../sis/referencing/crs/DefaultImageCRSTest.java | 4 +-
.../referencing/crs/DefaultProjectedCRSTest.java | 2 +-
.../referencing/crs/DefaultTemporalCRSTest.java | 2 +-
.../apache/sis/referencing/crs/HardCodedCRS.java | 4 +-
.../sis/referencing/crs/HardCodedCRSTest.java | 2 +-
.../datum/DefaultTemporalDatumTest.java | 2 +-
.../sis/referencing/datum/HardCodedDatum.java | 4 +-
.../referencing/factory/AuthorityFactoryMock.java | 2 +
.../factory/MultiAuthoritiesFactoryTest.java | 6 +-
.../internal/ServicesForMetadataTest.java | 2 +-
.../operation/CoordinateOperationFinderTest.java | 4 +-
.../DefaultConcatenatedOperationTest.java | 4 +-
.../operation/DefaultConversionTest.java | 12 +-
.../operation/DefaultTransformationTest.java | 8 +-
.../operation/HardCodedConversions.java | 2 +
.../builder/LinearTransformBuilderTest.java | 6 +-
.../operation/builder/LinearizerTest.java | 4 +-
.../operation/provider/GeographicOffsetsTest.java | 2 +-
.../transform/AbridgedMolodenskyTransformTest.java | 4 +-
.../transform/CoordinateSystemTransformTest.java | 2 +-
.../transform/DefaultMathTransformFactoryTest.java | 8 +-
.../InterpolatedGeocentricTransformTest.java | 2 +-
.../transform/MathTransformFactoryBase.java | 2 +
.../transform/MolodenskyTransformTest.java | 4 +-
.../transform/TransformSeparatorTest.java | 6 +-
.../transform/WraparoundTransformTest.java | 2 +-
.../sis/referencing/util/AxesMapperTest.java | 2 +-
.../sis/referencing/util/AxisDirectionsTest.java | 4 +-
.../referencing/util/CoordinateOperationsTest.java | 10 +-
.../referencing/util/DefinitionVerifierTest.java | 10 +-
.../util/EllipsoidalHeightCombinerTest.java | 8 +-
.../apache/sis/referencing/util/FormulasTest.java | 2 +-
.../referencing/util/ReferencingUtilitiesTest.java | 4 +-
.../sis/referencing/util/WKTUtilitiesTest.java | 4 +-
.../referencing/util/WraparoundApplicatorTest.java | 3 +-
.../main/module-info.java | 2 +-
.../apache/sis/storage/geotiff/Compression.java | 241 ++++++++
.../{GeoTiffOption.java => FormatModifier.java} | 39 +-
.../apache/sis/storage/geotiff/GeoTiffStore.java | 66 +-
.../sis/storage/geotiff/GeoTiffStoreProvider.java | 16 +-
.../org/apache/sis/storage/geotiff/IOBase.java | 6 +-
.../org/apache/sis/storage/geotiff/Reader.java | 6 +-
.../org/apache/sis/storage/geotiff/Writer.java | 80 ++-
.../sis/storage/geotiff/base/Compression.java | 15 +-
.../apache/sis/storage/geotiff/base/Predictor.java | 41 +-
.../storage/geotiff/inflater/CopyFromBytes.java | 91 ++-
.../geotiff/inflater/HorizontalPredictor.java | 4 +-
.../sis/storage/geotiff/inflater/Inflater.java | 2 +-
.../storage/geotiff/inflater/PredictorChannel.java | 2 +
.../storage/geotiff/writer/CompressionChannel.java | 116 ++++
.../geotiff/writer/HorizontalPredictor.java | 390 ++++++++++++
.../sis/storage/geotiff/writer/PixelChannel.java | 60 ++
.../storage/geotiff/writer/PredictorChannel.java | 86 +++
.../sis/storage/geotiff/writer/TileMatrix.java | 185 ++++--
.../org/apache/sis/storage/geotiff/writer/ZIP.java | 120 ++++
.../org/apache/sis/storage/geotiff/WriterTest.java | 76 +--
.../storage/sql/feature/GeometryGetterTest.java | 2 +-
.../sql/feature/SelectionClauseWriterTest.java | 2 +-
.../sql/feature/TemporalValueGetterTest.java | 4 +-
.../sis/storage/sql/postgis/PostgresTest.java | 2 +-
.../org.apache.sis.storage/main/module-info.java | 1 +
.../main/org/apache/sis/io/stream/ChannelData.java | 4 +
.../apache/sis/io/stream/ChannelDataOutput.java | 10 +
.../sis/io/stream/ChannelImageOutputStream.java | 14 +
.../apache/sis/io/stream/FileCacheByteChannel.java | 5 +-
.../apache/sis/io/stream/HyperRectangleWriter.java | 361 ++++++++---
.../apache/sis/io/stream/RewindableLineReader.java | 2 +-
.../org/apache/sis/storage/StorageConnector.java | 141 +++--
.../main/org/apache/sis/storage/csv/Store.java | 6 +-
.../apache/sis/storage/wkt/FirstKeywordPeek.java | 4 +-
.../org/apache/sis/storage/CoverageQueryTest.java | 2 +-
.../org/apache/sis/storage/CoverageSubsetTest.java | 2 +-
.../aggregate/BandAggregateGridResourceTest.java | 2 +-
.../sis/storage/base/MemoryGridResourceTest.java | 2 +-
.../sis/storage/esri/BSQConsistencyTest.java | 2 +-
.../apache/sis/storage/esri/WritableStoreTest.java | 2 +-
.../src/org.apache.sis.util/main/module-info.java | 1 +
.../main/org/apache/sis/util/ArgumentChecks.java | 22 +-
.../org/apache/sis/util/resources/Vocabulary.java | 5 +
.../sis/util/resources/Vocabulary.properties | 1 +
.../sis/util/resources/Vocabulary_fr.properties | 1 +
.../main/module-info.java | 2 +
.../sis/storage/shapefile/ShapefileProvider.java | 82 +++
.../sis/storage/shapefile/ShapefileStore.java | 385 ++++++++++++
.../apache/sis/storage/shapefile/dbf/DBFField.java | 120 ++++
.../sis/storage/shapefile/dbf/DBFFieldEncoder.java | 206 +++++++
.../sis/storage/shapefile/dbf/DBFHeader.java | 78 +++
.../sis/storage/shapefile/dbf/DBFReader.java | 87 +++
.../sis/storage/shapefile/dbf/DBFRecord.java} | 20 +-
.../shapefile/shp/ShapeGeometryEncoder.java | 677 +++++++++++++++++++++
.../sis/storage/shapefile/shp/ShapeHeader.java | 113 ++++
.../sis/storage/shapefile/shp/ShapeReader.java | 66 ++
.../sis/storage/shapefile/shp/ShapeRecord.java | 78 +++
.../sis/storage/shapefile/shp/ShapeType.java | 89 +++
.../sis/storage/shapefile/shp/ShapeWriter.java | 65 ++
.../sis/storage/shapefile/shx/IndexReader.java | 66 ++
.../sis/storage/shapefile/ShapefileStoreTest.java | 90 +++
.../sis/storage/shapefile/dbf/DBFIOTest.java | 104 ++++
.../apache/sis/storage/shapefile/multipoint.cpg | 1 +
.../apache/sis/storage/shapefile/multipoint.dbf | Bin 0 -> 88 bytes
.../apache/sis/storage/shapefile/multipoint.prj | 1 +
.../apache/sis/storage/shapefile/multipoint.shp | Bin 0 -> 260 bytes
.../apache/sis/storage/shapefile/multipoint.shx | Bin 0 -> 116 bytes
.../org/apache/sis/storage/shapefile/point.cpg | 1 +
.../org/apache/sis/storage/shapefile/point.dbf | Bin 0 -> 434 bytes
.../org/apache/sis/storage/shapefile/point.prj | 1 +
.../org/apache/sis/storage/shapefile/point.shp | Bin 0 -> 156 bytes
.../org/apache/sis/storage/shapefile/point.shx | Bin 0 -> 116 bytes
.../org/apache/sis/storage/shapefile/polygon.cpg | 1 +
.../org/apache/sis/storage/shapefile/polygon.dbf | Bin 0 -> 88 bytes
.../org/apache/sis/storage/shapefile/polygon.prj | 1 +
.../org/apache/sis/storage/shapefile/polygon.shp | Bin 0 -> 456 bytes
.../org/apache/sis/storage/shapefile/polygon.shx | Bin 0 -> 116 bytes
.../org/apache/sis/storage/shapefile/polyline.cpg | 1 +
.../org/apache/sis/storage/shapefile/polyline.dbf | Bin 0 -> 88 bytes
.../org/apache/sis/storage/shapefile/polyline.prj | 1 +
.../org/apache/sis/storage/shapefile/polyline.shp | Bin 0 -> 328 bytes
.../org/apache/sis/storage/shapefile/polyline.shx | Bin 0 -> 116 bytes
.../sis/storage/shapefile/shp/ShapeIOTest.java | 319 ++++++++++
.../apache/sis/gui/coverage/CoverageCanvasApp.java | 4 +-
.../org/apache/sis/gui/coverage/GridViewApp.java | 4 +-
172 files changed, 4715 insertions(+), 556 deletions(-)
diff --cc endorsed/src/org.apache.sis.referencing/test/org/apache/sis/geometry/AbstractEnvelopeTest.java
index 7495875e05,4b14655648..57d0622432
--- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/geometry/AbstractEnvelopeTest.java
+++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/geometry/AbstractEnvelopeTest.java
@@@ -32,10 -31,8 +31,11 @@@ import static org.junit.Assert.*
import static org.opengis.test.Validators.validate;
import static org.apache.sis.referencing.Assertions.assertContains;
import static org.apache.sis.referencing.Assertions.assertDisjoint;
+ import static org.apache.sis.referencing.crs.HardCodedCRS.WGS84;
+// Specific to the main branch:
+import static org.apache.sis.test.GeoapiAssert.PENDING_NEXT_GEOAPI_RELEASE;
+
/**
* Tests the methods defined in the {@link AbstractEnvelope} class.
diff --cc endorsed/src/org.apache.sis.util/main/module-info.java
index 3394402ebf,afebada7be..29dc1fd8dd
--- a/endorsed/src/org.apache.sis.util/main/module-info.java
+++ b/endorsed/src/org.apache.sis.util/main/module-info.java
@@@ -127,6 -127,8 +127,7 @@@ module org.apache.sis.util
org.apache.sis.storage.netcdf,
org.apache.sis.storage.geotiff,
org.apache.sis.storage.earthobservation,
+ org.apache.sis.storage.shapefile, // In the "incubator" sub-project.
- org.apache.sis.cql, // In the "incubator" sub-project.
org.apache.sis.portrayal,
org.apache.sis.cloud.aws,
org.apache.sis.console,
diff --cc incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java
index 0000000000,33c46f120d..04774dfc66
mode 000000,100644..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
@@@ -1,0 -1,385 +1,385 @@@
+ /*
+ * 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.shapefile;
+
+ import java.io.IOException;
+ import java.nio.ByteBuffer;
+ import java.nio.channels.SeekableByteChannel;
+ import java.nio.channels.WritableByteChannel;
+ import java.nio.charset.Charset;
+ import java.nio.charset.StandardCharsets;
+ import java.nio.file.Files;
+ import java.nio.file.Path;
+ import java.nio.file.StandardOpenOption;
+ import java.util.Iterator;
+ import java.util.Optional;
+ import java.util.Spliterator;
+ import java.util.Spliterators;
+ import java.util.concurrent.locks.ReadWriteLock;
+ import java.util.concurrent.locks.ReentrantReadWriteLock;
+ import java.util.function.Consumer;
+ import java.util.function.Predicate;
+ import java.util.function.UnaryOperator;
+ import java.util.stream.Stream;
+ import java.util.stream.StreamSupport;
+ import org.opengis.geometry.Envelope;
+ import org.opengis.metadata.Metadata;
+ import org.opengis.parameter.ParameterValueGroup;
+ import org.opengis.referencing.crs.CoordinateReferenceSystem;
+ import org.opengis.util.FactoryException;
+ import org.opengis.util.GenericName;
+ 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.io.stream.ChannelDataInput;
+ import org.apache.sis.io.stream.ChannelDataOutput;
+ import org.apache.sis.io.stream.IOUtilities;
+ import org.apache.sis.parameter.Parameters;
+ import org.apache.sis.referencing.CRS;
+ import org.apache.sis.referencing.CommonCRS;
+ import org.apache.sis.storage.AbstractFeatureSet;
+ import org.apache.sis.storage.DataStore;
+ import org.apache.sis.storage.DataStoreException;
+ import org.apache.sis.storage.FeatureSet;
+ import org.apache.sis.storage.Query;
+ import org.apache.sis.storage.UnsupportedQueryException;
+ import org.apache.sis.storage.WritableFeatureSet;
+ import org.apache.sis.storage.shapefile.cpg.CpgFiles;
+ import org.apache.sis.storage.shapefile.dbf.DBFField;
+ import org.apache.sis.storage.shapefile.dbf.DBFHeader;
+ import org.apache.sis.storage.shapefile.dbf.DBFReader;
+ import org.apache.sis.storage.shapefile.dbf.DBFRecord;
+ import org.apache.sis.storage.shapefile.shp.ShapeGeometryEncoder;
+ import org.apache.sis.storage.shapefile.shp.ShapeHeader;
+ import org.apache.sis.storage.shapefile.shp.ShapeReader;
+ import org.apache.sis.storage.shapefile.shp.ShapeRecord;
+ import org.apache.sis.util.collection.BackingStoreException;
+
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.feature.Feature;
-import org.opengis.feature.FeatureType;
++// Specific to the main branch:
++import org.apache.sis.feature.AbstractFeature;
++import org.apache.sis.feature.DefaultFeatureType;
+
+
+ /**
+ * Shapefile datastore.
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+ public final class ShapefileStore extends DataStore implements FeatureSet {
+
+ private static final String GEOMETRY_NAME = "geometry";
+
+ private final Path shpPath;
+ private final ShpFiles files;
+ /**
+ * Internal class to inherit AbstractFeatureSet.
+ */
+ private final AsFeatureSet featureSetView = new AsFeatureSet();
- private FeatureType type;
++ private DefaultFeatureType type;
+ private Charset charset;
+
+ /**
+ * Lock to control read and write operations.
+ */
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+ public ShapefileStore(Path path) {
+ this.shpPath = path;
+ this.files = new ShpFiles(shpPath);
+ }
+
+ @Override
+ public Optional<ParameterValueGroup> getOpenParameters() {
+ final Parameters parameters = Parameters.castOrWrap(ShapefileProvider.PARAMETERS_DESCRIPTOR.createValue());
+ parameters.parameter(ShapefileProvider.LOCATION).setValue(shpPath.toUri());
+ return Optional.of(parameters);
+ }
+
+ @Override
+ public void close() throws DataStoreException {
+ }
+
+
+ /*
+ Redirect FeatureSet interface to View
+ */
+ @Override
+ public Optional<GenericName> getIdentifier() throws DataStoreException {
+ return featureSetView.getIdentifier();
+ }
+
+ @Override
+ public Metadata getMetadata() throws DataStoreException {
+ return featureSetView.getMetadata();
+ }
+
+ @Override
- public FeatureType getType() throws DataStoreException {
++ public DefaultFeatureType getType() throws DataStoreException {
+ return featureSetView.getType();
+ }
+
+ @Override
+ public FeatureSet subset(Query query) throws UnsupportedQueryException, DataStoreException {
+ return featureSetView.subset(query);
+ }
+
+ @Override
- public Stream<Feature> features(boolean parallel) throws DataStoreException {
++ public Stream<AbstractFeature> features(boolean parallel) throws DataStoreException {
+ return featureSetView.features(parallel);
+ }
+
+ @Override
+ public Optional<Envelope> getEnvelope() throws DataStoreException {
+ return featureSetView.getEnvelope();
+ }
+
+ private class AsFeatureSet extends AbstractFeatureSet implements WritableFeatureSet {
+
+ private AsFeatureSet() {
+ super(null);
+ }
+
+ @Override
- public synchronized FeatureType getType() throws DataStoreException {
++ public synchronized DefaultFeatureType getType() throws DataStoreException {
+ if (type == null) {
+ if (!Files.isRegularFile(shpPath)) {
+ throw new DataStoreException("Shape files do not exist. Update FeatureType first to initialize this empty datastore");
+ }
+
+ final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
+ ftb.setName(files.baseName);
+
+ //read shp header to obtain geometry type
+ final Class geometryClass;
+ try (final ShapeReader reader = new ShapeReader(ShpFiles.openReadChannel(shpPath))) {
+ final ShapeHeader header = reader.getHeader();
+ geometryClass = ShapeGeometryEncoder.getEncoder(header.shapeType).getValueClass();
+ } catch (IOException ex) {
+ throw new DataStoreException("Failed to parse shape file header.", ex);
+ }
+
+ //read prj file for projection
+ final Path prjFile = files.getPrj(false);
+ final CoordinateReferenceSystem crs;
+ if (prjFile != null) {
+ try {
+ crs = CRS.fromWKT(Files.readString(prjFile, StandardCharsets.UTF_8));
+ } catch (IOException | FactoryException ex) {
+ throw new DataStoreException("Failed to parse prj file.", ex);
+ }
+ } else {
+ //shapefile often do not have a .prj, mostly those are in CRS:84.
+ //we do not raise an error otherwise we would not be able to read a lot of data.
+ crs = CommonCRS.WGS84.normalizedGeographic();
+ }
+
+ ftb.addAttribute(geometryClass).setName(GEOMETRY_NAME).setCRS(crs).addRole(AttributeRole.DEFAULT_GEOMETRY);
+
+ //read cpg for dbf file charset
+ final Path cpgFile = files.getCpg(false);
+ if (cpgFile != null) {
+ try (final SeekableByteChannel channel = Files.newByteChannel(cpgFile, StandardOpenOption.READ)) {
+ charset = CpgFiles.read(channel);
+ } catch (IOException ex) {
+ throw new DataStoreException("Failed to parse cpg file.", ex);
+ }
+ } else {
+ charset = StandardCharsets.UTF_8;
+ }
+
+ //read dbf for attributes
+ final Path dbfFile = files.getDbf(false);
+ if (dbfFile != null) {
+ try (DBFReader reader = new DBFReader(ShpFiles.openReadChannel(dbfFile), charset)) {
+ final DBFHeader header = reader.getHeader();
+ boolean hasId = false;
+ for (DBFField field : header.fields) {
+ final AttributeTypeBuilder atb = ftb.addAttribute(field.getEncoder().getValueClass()).setName(field.fieldName);
+ //no official but 'id' field is common
+ if (!hasId && "id".equalsIgnoreCase(field.fieldName) || "identifier".equalsIgnoreCase(field.fieldName)) {
+ atb.addRole(AttributeRole.IDENTIFIER_COMPONENT);
+ hasId = true;
+ }
+ }
+ } catch (IOException ex) {
+ throw new DataStoreException("Failed to parse dbf file header.", ex);
+ }
+ } else {
+ throw new DataStoreException("DBF file is missing.");
+ }
+
+ type = ftb.build();
+ }
+ return type;
+ }
+
+ @Override
- public Stream<Feature> features(boolean parallel) throws DataStoreException {
- final FeatureType type = getType();
++ public Stream<AbstractFeature> features(boolean parallel) throws DataStoreException {
++ final DefaultFeatureType type = getType();
+ final ShapeReader shpreader;
+ final DBFReader dbfreader;
+ try {
+ shpreader = new ShapeReader(ShpFiles.openReadChannel(files.shpFile));
+ dbfreader = new DBFReader(ShpFiles.openReadChannel(files.getDbf(false)), charset);
+ } catch (IOException ex) {
+ throw new DataStoreException("Faild to open shp and dbf files.", ex);
+ }
+ final DBFHeader header = dbfreader.getHeader();
+
+ final Spliterator spliterator = new Spliterators.AbstractSpliterator(Long.MAX_VALUE, Spliterator.ORDERED) {
+ @Override
+ public boolean tryAdvance(Consumer action) {
+ try {
+ final ShapeRecord shpRecord = shpreader.next();
+ if (shpRecord == null) return false;
+ final DBFRecord dbfRecord = dbfreader.next();
- final Feature next = type.newInstance();
++ final AbstractFeature next = type.newInstance();
+ next.setPropertyValue(GEOMETRY_NAME, shpRecord.geometry);
+ for (int i = 0; i < header.fields.length; i++) {
+ next.setPropertyValue(header.fields[i].fieldName, dbfRecord.fields[i]);
+ }
+ action.accept(next);
+ return true;
+ } catch (IOException ex) {
+ throw new BackingStoreException(ex.getMessage(), ex);
+ }
+ }
+ };
- final Stream<Feature> stream = StreamSupport.stream(spliterator, false);
++ final Stream<AbstractFeature> stream = StreamSupport.stream(spliterator, false);
+ return stream.onClose(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ shpreader.close();
+ dbfreader.close();
+ } catch (IOException ex) {
+ throw new BackingStoreException(ex.getMessage(), ex);
+ }
+ }
+ });
+
+ }
+
+ @Override
- public void updateType(FeatureType newType) throws DataStoreException {
++ public void updateType(DefaultFeatureType newType) throws DataStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
- public void add(Iterator<? extends Feature> features) throws DataStoreException {
++ public void add(Iterator<? extends AbstractFeature> features) throws DataStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
- public void removeIf(Predicate<? super Feature> filter) throws DataStoreException {
++ public void removeIf(Predicate<? super AbstractFeature> filter) throws DataStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
- public void replaceIf(Predicate<? super Feature> filter, UnaryOperator<Feature> updater) throws DataStoreException {
++ public void replaceIf(Predicate<? super AbstractFeature> filter, UnaryOperator<AbstractFeature> updater) throws DataStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+
+ /**
+ * Manipulate the different shape files.
+ */
+ private static class ShpFiles {
+
+ private final String baseName;
+ private final boolean baseUpper;
+ private final Path shpFile;
+ private Path shxFile;
+ private Path dbfFile;
+ private Path prjFile;
+ private Path cpgFile;
+
+ public ShpFiles(Path shpFile) {
+ this.shpFile = shpFile;
+ final String fileName = shpFile.getFileName().toString();
+ baseUpper = Character.isUpperCase(fileName.codePointAt(fileName.length()-1));
+ this.baseName = IOUtilities.filenameWithoutExtension(fileName);
+ shxFile = findSibling("shx");
+ dbfFile = findSibling("dbf");
+ prjFile = findSibling("prj");
+ cpgFile = findSibling("cpg");
+ }
+
+ /**
+ * @param create true to create the path even if file do not exist.
+ * @return file if it exist or create is true, null otherwise
+ */
+ public Path getShx(boolean create) {
+ if (create && shxFile == null) {
+ return shpFile.getParent().resolve(baseName + "." + (baseUpper ? "SHX" : "shx"));
+ }
+ return shxFile;
+ }
+
+ /**
+ * @param create true to create the path even if file do not exist.
+ * @return file if it exist or create is true, null otherwise
+ */
+ public Path getDbf(boolean create) {
+ if (create && dbfFile == null) {
+ return shpFile.getParent().resolve(baseName + "." + (baseUpper ? "DBF" : "dbf"));
+ }
+ return dbfFile;
+ }
+
+ /**
+ * @param create true to create the path even if file do not exist.
+ * @return file if it exist or create is true, null otherwise
+ */
+ public Path getPrj(boolean create) {
+ if (create && prjFile == null) {
+ return shpFile.getParent().resolve(baseName + "." + (baseUpper ? "PRJ" : "prj"));
+ }
+ return prjFile;
+ }
+
+ /**
+ * @param create true to create the path even if file do not exist.
+ * @return file if it exist or create is true, null otherwise
+ */
+ public Path getCpg(boolean create) {
+ if (create && cpgFile == null) {
+ return shpFile.getParent().resolve(baseName + "." + (baseUpper ? "CPG" : "cpg"));
+ }
+ return cpgFile;
+ }
+
+ private Path findSibling(String extension) {
+ Path candidate = shpFile.getParent().resolve(baseName + "." + extension);
+ if (java.nio.file.Files.isRegularFile(candidate)) return candidate;
+ candidate = shpFile.getParent().resolve(baseName + "." + extension.toUpperCase());
+ if (java.nio.file.Files.isRegularFile(candidate)) return candidate;
+ return null;
+ }
+
+ private static ChannelDataInput openReadChannel(Path path) throws IOException {
+ final SeekableByteChannel channel = Files.newByteChannel(path, StandardOpenOption.READ);
+ return new ChannelDataInput(path.getFileName().toString(), channel, ByteBuffer.allocate(8192), false);
+ }
+
+ private static ChannelDataOutput openWriteChannel(Path path) throws IOException, IllegalArgumentException, DataStoreException {
+ final WritableByteChannel wbc = Files.newByteChannel(path, StandardOpenOption.WRITE);
+ return new ChannelDataOutput(path.getFileName().toString(), wbc, ByteBuffer.allocate(8000));
+ }
+ }
+
+ }
diff --cc incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/ShapefileStoreTest.java
index 0000000000,0cdb00b890..9eb5e07bea
mode 000000,100644..100644
--- a/incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/ShapefileStoreTest.java
+++ b/incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/ShapefileStoreTest.java
@@@ -1,0 -1,90 +1,90 @@@
+ /*
+ * 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.shapefile;
+
+ import java.net.URISyntaxException;
+ import java.net.URL;
+ import java.nio.file.Paths;
+ import java.time.LocalDate;
+ import java.util.Iterator;
+ import java.util.stream.Stream;
+ import static org.junit.jupiter.api.Assertions.*;
+ import org.apache.sis.storage.DataStoreException;
+ import org.junit.Test;
+ import org.locationtech.jts.geom.Point;
+
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.feature.AttributeType;
-import org.opengis.feature.Feature;
-import org.opengis.feature.FeatureType;
++// Specific to the main branch:
++import org.apache.sis.feature.AbstractFeature;
++import org.apache.sis.feature.DefaultFeatureType;
++import org.apache.sis.feature.DefaultAttributeType;
+
+
+ /**
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+ public class ShapefileStoreTest {
+
+ @Test
+ public void testStream() throws URISyntaxException, DataStoreException {
+ final URL url = ShapefileStoreTest.class.getResource("/org/apache/sis/storage/shapefile/point.shp");
+ final ShapefileStore store = new ShapefileStore(Paths.get(url.toURI()));
+
+ //check feature type
- final FeatureType type = store.getType();
++ final DefaultFeatureType type = store.getType();
+ assertEquals("point", type.getName().toString());
+ assertEquals(9, type.getProperties(true).size());
+ assertNotNull(type.getProperty("sis:identifier"));
+ assertNotNull(type.getProperty("sis:envelope"));
+ assertNotNull(type.getProperty("sis:geometry"));
- final var geomProp = (AttributeType) type.getProperty("geometry");
- final var idProp = (AttributeType) type.getProperty("id");
- final var textProp = (AttributeType) type.getProperty("text");
- final var integerProp = (AttributeType) type.getProperty("integer");
- final var floatProp = (AttributeType) type.getProperty("float");
- final var dateProp = (AttributeType) type.getProperty("date");
++ final var geomProp = (DefaultAttributeType) type.getProperty("geometry");
++ final var idProp = (DefaultAttributeType) type.getProperty("id");
++ final var textProp = (DefaultAttributeType) type.getProperty("text");
++ final var integerProp = (DefaultAttributeType) type.getProperty("integer");
++ final var floatProp = (DefaultAttributeType) type.getProperty("float");
++ final var dateProp = (DefaultAttributeType) type.getProperty("date");
+ assertEquals(Point.class, geomProp.getValueClass());
+ assertEquals(Long.class, idProp.getValueClass());
+ assertEquals(String.class, textProp.getValueClass());
+ assertEquals(Long.class, integerProp.getValueClass());
+ assertEquals(Double.class, floatProp.getValueClass());
+ assertEquals(LocalDate.class, dateProp.getValueClass());
+
- try (Stream<Feature> stream = store.features(false)) {
- Iterator<Feature> iterator = stream.iterator();
++ try (Stream<AbstractFeature> stream = store.features(false)) {
++ Iterator<AbstractFeature> iterator = stream.iterator();
+ assertTrue(iterator.hasNext());
- Feature feature1 = iterator.next();
++ AbstractFeature feature1 = iterator.next();
+ assertEquals(1L, feature1.getPropertyValue("id"));
+ assertEquals("text1", feature1.getPropertyValue("text"));
+ assertEquals(10L, feature1.getPropertyValue("integer"));
+ assertEquals(20.0, feature1.getPropertyValue("float"));
+ assertEquals(LocalDate.of(2023, 10, 27), feature1.getPropertyValue("date"));
+ Point pt1 = (Point) feature1.getPropertyValue("geometry");
+
+ assertTrue(iterator.hasNext());
- Feature feature2 = iterator.next();
++ AbstractFeature feature2 = iterator.next();
+ assertEquals(2L, feature2.getPropertyValue("id"));
+ assertEquals("text2", feature2.getPropertyValue("text"));
+ assertEquals(40L, feature2.getPropertyValue("integer"));
+ assertEquals(60.0, feature2.getPropertyValue("float"));
+ assertEquals(LocalDate.of(2023, 10, 28), feature2.getPropertyValue("date"));
+ Point pt2 = (Point) feature2.getPropertyValue("geometry");
+
+ assertFalse(iterator.hasNext());
+ }
+ }
+ }