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 2026/08/15 15:41:51 UTC
(sis) 01/01: Merge branch 'geoapi-3.1'. The DGGS module has been temporarily excluded because it depends on the geometry module, which is available only in the GeoAPI 3.1/4.0 branches.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/sis.git
commit b8782f10292d86e5b153801e7e37d6d110144663
Merge: 1b04543131 b7f39770a2
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Sat Aug 15 13:37:45 2026 +0200
Merge branch 'geoapi-3.1'.
The DGGS module has been temporarily excluded because it depends on the
geometry module, which is available only in the GeoAPI 3.1/4.0 branches.
.../apache/sis/buildtools/gradle/Dependency.java | 2 +-
.../org/apache/sis/console/HelpCommandTest.java | 1 +
.../org.apache.sis.feature/main/module-info.java | 1 +
.../sis/coverage/grid/ClippedGridCoverage.java | 4 +-
.../apache/sis/coverage/grid/GridCRSBuilder.java | 156 +++---
.../org/apache/sis/coverage/grid/GridCoverage.java | 17 +-
.../apache/sis/coverage/grid/GridCoverage2D.java | 100 ++--
.../sis/coverage/grid/GridCoverageBuilder.java | 6 +-
.../apache/sis/coverage/grid/GridDerivation.java | 2 +-
.../org/apache/sis/coverage/grid/GridExtent.java | 136 ++---
.../org/apache/sis/coverage/grid/GridGeometry.java | 43 +-
.../apache/sis/coverage/grid/ImageRenderer.java | 121 +----
.../apache/sis/coverage/grid/SliceGeometry.java | 3 +-
.../org/apache/sis/feature/AbstractFeature.java | 7 +-
.../org/apache/sis/feature/internal/Resources.java | 15 +
.../sis/feature/internal/Resources.properties | 3 +
.../sis/feature/internal/Resources_fr.properties | 3 +
.../internal/shared/AttributeConvention.java | 6 +-
.../main/org/apache/sis/image/BandSelectImage.java | 4 +-
.../apache/sis/image/BandedSampleConverter.java | 6 +-
.../main/org/apache/sis/image/ComputedImage.java | 12 +-
.../main/org/apache/sis/image/ImageLayout.java | 38 +-
.../main/org/apache/sis/image/ImageOverlay.java | 2 +-
.../org/apache/sis/image/MultiSourcePrefetch.java | 5 +-
.../main/org/apache/sis/image/PlanarImage.java | 128 ++---
.../main/org/apache/sis/image/PrefetchedImage.java | 4 +-
.../org/apache/sis/image/SourceAlignedImage.java | 2 +-
.../apache/sis/image/WritableComputedImage.java | 8 +-
.../org/apache/sis/image/internal/Summarizer.java | 275 +++++++++++
.../apache/sis/image/internal}/package-info.java | 11 +-
.../image/internal/shared/BatchComputedImage.java | 27 +-
.../image/internal/shared/ColorModelFactory.java | 54 +-
.../image/internal/shared/DeferredProperty.java | 47 +-
.../sis/image/internal/shared/ImageUtilities.java | 36 +-
.../sis/image/internal/shared/RasterFactory.java | 21 +-
.../sis/image/internal/shared/ReshapedImage.java | 115 ++++-
.../image/internal/shared/ScaledColorSpace.java | 13 +-
.../sis/image/internal/shared/TileOpExecutor.java | 7 +-
.../sis/image/internal/shared/TiledImage.java | 6 +-
.../image/internal/shared/WritableTiledImage.java | 16 +-
...ervableImage.java => WritableUntiledImage.java} | 272 ++++++++--
.../apache/sis/coverage/grid/GridExtentTest.java | 57 ++-
.../coverage/grid/ResampledGridCoverageTest.java | 6 +-
.../test/org/apache/sis/image/ImageLayoutTest.java | 9 +
.../test/org/apache/sis/image/TiledImageMock.java | 71 ++-
.../image/internal/shared/ReshapedImageTest.java | 5 +-
.../org/apache/sis/metadata/AbstractMetadata.java | 6 +-
.../main/org/apache/sis/metadata/CacheKey.java | 9 +-
.../org/apache/sis/metadata/MetadataCopier.java | 2 +-
.../org/apache/sis/metadata/MetadataStandard.java | 393 ++++++++++-----
.../org/apache/sis/metadata/MetadataVisitor.java | 15 +-
.../apache/sis/metadata/ModifiableMetadata.java | 46 +-
.../org/apache/sis/metadata/PropertyAccessor.java | 3 +-
.../main/org/apache/sis/metadata/Pruner.java | 4 +-
.../main/org/apache/sis/metadata/StateChanger.java | 2 +-
.../main/org/apache/sis/metadata/TreeNode.java | 10 +-
.../apache/sis/metadata/UnresolvedTypePolicy.java} | 40 +-
.../apache/sis/metadata/internal/Resources.java | 5 +
.../sis/metadata/internal/Resources.properties | 1 +
.../sis/metadata/internal/Resources_fr.properties | 1 +
.../sis/metadata/internal/shared/Merger.java | 88 +++-
.../iso/extent/DefaultGeographicBoundingBox.java | 2 +-
.../main/org/apache/sis/metadata/package-info.java | 2 +-
.../sis/metadata/sql/internal/shared/Dialect.java | 43 +-
.../metadata/sql/internal/shared/SQLBuilder.java | 11 +-
.../sis/metadata/sql/internal/shared/Supports.java | 7 +-
.../org/apache/sis/util/iso/DefaultRecordType.java | 2 +-
.../apache/sis/xml/bind/cat/CodeListAdapter.java | 2 +-
.../test/org/apache/sis/metadata/HashCodeTest.java | 4 +-
.../apache/sis/metadata/InformationMapTest.java | 1 +
.../apache/sis/metadata/MetadataStandardTest.java | 28 +-
.../test/org/apache/sis/metadata/NameMapTest.java | 1 +
.../test/org/apache/sis/metadata/PrunerTest.java | 1 +
.../org/apache/sis/metadata/SpecialCasesTest.java | 1 +
.../apache/sis/metadata/TreeNodeChildrenTest.java | 2 +-
.../test/org/apache/sis/metadata/TypeMapTest.java | 1 +
.../sis/metadata/internal/shared/MergerTest.java | 24 +-
.../org/apache/sis/map/coverage/RenderingData.java | 24 +-
.../apache/sis/map/coverage/RenderingDataTest.java | 256 ++++++++++
.../main/org/apache/sis/geometry/Envelopes.java | 51 +-
.../org/apache/sis/parameter/MatrixParameters.java | 2 +-
.../sis/referencing/datum/DatumOrEnsemble.java | 2 +-
.../operation/CoordinateOperationContext.java | 6 +-
.../operation/CoordinateOperationFinder.java | 32 +-
.../referencing/operation/SubOperationInfo.java | 40 +-
.../operation/provider/DatumShiftMethod.java | 6 +-
.../transform/AbstractLinearTransform.java | 7 +-
.../operation/transform/PassThroughTransform.java | 6 +-
.../operation/transform/TransformJoiner.java | 11 +-
.../org/apache/sis/storage/geotiff/DataSubset.java | 2 +-
.../org/apache/sis/storage/netcdf/base/Axis.java | 23 +-
.../apache/sis/storage/netcdf/base/Variable.java | 7 +
.../sis/storage/netcdf/ucar/VariableWrapper.java | 22 +-
.../sis/storage/sql/feature/SelectionClause.java | 11 +-
.../storage/sql/feature/SelectionClauseWriter.java | 6 +-
.../sis/storage/sql/postgis/RasterReader.java | 4 +-
.../org/apache/sis/storage/sql/SQLStoreTest.java | 2 +-
.../org/apache/sis/storage/gpx/MetadataTest.java | 8 +-
.../org/apache/sis/storage/gpx/ReaderTest.java | 85 +++-
.../org.apache.sis.storage/main/module-info.java | 6 +-
.../main/org/apache/sis/storage/DataStore.java | 4 +-
.../main/org/apache/sis/storage/FeatureQuery.java | 4 +-
.../main/org/apache/sis/storage/Resource.java | 4 +-
.../org/apache/sis/storage/esri/RasterStore.java | 13 +-
.../sis/storage/event/CascadedStoreEvent.java | 2 +-
.../apache/sis/storage/event/StoreListener.java | 6 +-
.../apache/sis/storage/event/StoreListeners.java | 16 +-
.../sis/storage/metadata/MetadataBuilder.java | 2 +-
.../sis/storage/tiling/ArtificiallyTiledImage.java | 261 ++++++++++
.../apache/sis/storage/tiling/ImageTileMatrix.java | 2 +-
.../apache/sis/storage/tiling/TileReadEvent.java | 63 ++-
.../sis/storage/tiling/TiledDeferredImage.java | 2 +-
.../sis/storage/tiling/TiledGridCoverage.java | 10 +-
.../storage/tiling/TiledGridCoverageResource.java | 547 +++++++++++++++++----
.../org/apache/sis/storage/DataStoreTestCase.java | 4 +-
.../sis/storage/event/StoreListenersTest.java | 6 +-
.../main/org/apache/sis/math/Statistics.java | 3 +
.../main/org/apache/sis/util/Classes.java | 9 +-
.../sis/util/collection/WeakValueHashMap.java | 4 +-
.../apache/sis/util/internal/shared/Numerics.java | 2 +-
.../main/org/apache/sis/util/resources/Errors.java | 5 +
.../apache/sis/util/resources/Errors.properties | 1 +
.../apache/sis/util/resources/Errors_fr.properties | 1 +
.../sis/util/resources/IndexedResourceBundle.java | 14 +-
.../org/apache/sis/util/resources/Messages.java | 5 +
.../apache/sis/util/resources/Messages.properties | 1 +
.../sis/util/resources/Messages_fr.properties | 3 +-
.../org/apache/sis/util/resources/Vocabulary.java | 25 +-
.../sis/util/resources/Vocabulary.properties | 5 +-
.../sis/util/resources/Vocabulary_fr.properties | 7 +-
.../apache/sis/util/collection/RangeSetTest.java | 4 +-
incubator/build.gradle.kts | 19 +-
.../coveragejson/binding/CategoryEncoding.java | 82 ---
.../storage/coveragejson/binding/Dictionary.java | 73 ---
.../sis/storage/coveragejson/binding/I18N.java | 125 -----
.../storage/coveragejson/binding/Parameters.java | 78 ---
.../sis/storage/coveragejson/binding/Ranges.java | 74 ---
.../org.apache.sis.storage.DataStoreProvider | 0
.../main/module-info.java | 27 +-
.../storage/coveragejson/CoverageJsonStore.java | 17 +-
.../coveragejson/CoverageJsonStoreProvider.java | 0
.../sis/storage/coveragejson/CoverageResource.java | 18 +-
.../sis/storage/coveragejson/binding/Axe.java | 9 +-
.../sis/storage/coveragejson/binding/Axes.java | 16 +-
.../sis/storage/coveragejson/binding/Category.java | 10 +-
.../coveragejson/binding/CategoryEncoding.java} | 16 +-
.../sis/storage/coveragejson/binding/Coverage.java | 47 +-
.../coveragejson/binding/CoverageCollection.java | 10 +-
.../coveragejson/binding/CoverageJsonObject.java | 37 +-
.../sis/storage/coveragejson/binding/Domain.java | 7 +-
.../coveragejson/binding/GeographicCRS.java | 7 +-
.../sis/storage/coveragejson/binding/I18N.java | 77 +++
.../storage/coveragejson/binding/IdentifierRS.java | 10 +-
.../sis/storage/coveragejson/binding/NdArray.java | 7 +-
.../coveragejson/binding/ObservedProperty.java | 9 +-
.../storage/coveragejson/binding/Parameter.java | 7 +-
.../coveragejson/binding/ParameterGroup.java | 7 +-
.../storage/coveragejson/binding/ProjectedCRS.java | 7 +-
.../binding/ReferenceSystemConnection.java | 9 +-
.../sis/storage/coveragejson/binding/Symbol.java | 9 +-
.../coveragejson/binding/TargetConcept.java | 9 +-
.../storage/coveragejson/binding/TemporalRS.java | 7 +-
.../sis/storage/coveragejson/binding/TileSet.java | 9 +-
.../storage/coveragejson/binding/TiledNdArray.java | 9 +-
.../sis/storage/coveragejson/binding/Unit.java | 9 +-
.../storage/coveragejson/binding/VerticalCRS.java | 7 +-
.../storage/coveragejson/binding/package-info.java | 0
.../sis/storage/coveragejson/package-info.java | 0
.../org/apache/sis/storage/geojson/GeoJSON.java | 165 +++++++
.../apache/sis/storage/geojson/GeoJSONMapper.java | 479 ++++++++++++++++++
.../storage/geojson/binding/GeoJSONFeature.java | 318 ++++++++++++
.../geojson/binding/GeoJSONFeatureCollection.java | 322 ++++++++++++
.../storage/geojson/binding/GeoJSONGeometry.java | 134 +++++
.../geojson/binding/GeoJSONGeometryCollection.java | 84 ++++
.../storage/geojson/binding/GeoJSONLineString.java | 85 ++++
.../geojson/binding/GeoJSONMultiLineString.java | 85 ++++
.../storage/geojson/binding/GeoJSONMultiPoint.java | 85 ++++
.../geojson/binding/GeoJSONMultiPolygon.java | 85 ++++
.../sis/storage/geojson/binding/GeoJSONObject.java | 104 ++++
.../sis/storage/geojson/binding/GeoJSONPoint.java | 88 ++++
.../storage/geojson/binding/GeoJSONPolygon.java | 85 ++++
.../geojson/binding/JSONFGCircularString.java | 88 ++++
.../geojson/binding/JSONFGCompoundCurve.java | 88 ++++
.../storage/geojson/binding/JSONFGCoordRefSys.java | 131 +++++
.../geojson/binding/JSONFGCurvePolygon.java | 89 ++++
.../storage/geojson/binding/JSONFGMeasures.java | 123 +++++
.../storage/geojson/binding/JSONFGMultiCurve.java | 89 ++++
.../geojson/binding/JSONFGMultiPolyhedron.java | 85 ++++
.../storage/geojson/binding/JSONFGMultiPrism.java | 85 ++++
.../geojson/binding/JSONFGMultiSurface.java | 88 ++++
.../storage/geojson/binding/JSONFGPolyhedron.java | 86 ++++
.../sis/storage/geojson/binding/JSONFGPrism.java | 127 +++++
.../sis/storage/geojson/binding/JSONFGTime.java | 124 +++++
.../sis/storage/geojson}/binding/package-info.java | 8 +-
.../sis/storage/json/DataTransferObject.java | 100 ++++
.../movingfeature/binding/MFCoordRefSys.java | 110 +++++
.../movingfeature/binding/MFMovingFeature.java | 277 +++++++++++
.../binding/MFMovingFeatureCollection.java | 270 ++++++++++
.../binding/MFMovingGeometryBase.java | 101 ++++
.../binding/MFMovingGeometryCollection.java | 93 ++++
.../movingfeature/binding/MFMovingLineString.java | 87 ++++
.../movingfeature/binding/MFMovingPoint.java | 86 ++++
.../movingfeature/binding/MFMovingPointCloud.java | 89 ++++
.../movingfeature/binding/MFMovingPolygon.java | 88 ++++
.../movingfeature/binding/MFOrientation.java | 103 ++++
.../movingfeature/binding/MFTemporalGeometry.java | 128 +++++
.../binding/MFTemporalPrimitiveGeometry.java | 152 ++++++
.../binding/MFTemporalPropertyGroup.java | 94 ++++
.../binding/MFTemporalPropertyValue.java | 186 +++++++
.../movingfeature}/binding/package-info.java | 7 +-
.../main/org/apache/sis/storage/ogcjson/Link.java | 280 +++++++++++
.../apache/sis/storage/ogcjson}/package-info.java | 6 +-
.../coveragejson/CoverageJsonStoreTest.java | 0
.../storage/coveragejson/binding/BindingTest.java | 69 +--
.../sis/storage/coveragejson/binding/LICENSE.md | 0
.../storage/coveragejson/binding/axe_bounds.json | 0
.../storage/coveragejson/binding/axe_polygon.json | 0
.../storage/coveragejson/binding/axe_regular.json | 0
.../storage/coveragejson/binding/axe_tuples.json | 0
.../binding/coverage_vertical_profile.json | 0
.../binding/coverage_vertical_profile_nocs.json | 0
.../coveragejson/binding/coveragecollection.json | 0
.../storage/coveragejson/binding/domain_grid.json | 0
.../coveragejson/binding/domain_trajectory.json | 0
.../coveragejson/binding/domaintype_grid.json | 0
.../binding/domaintype_multipoint.json | 0
.../binding/domaintype_multipointseries.json | 0
.../binding/domaintype_multipolygon.json | 0
.../binding/domaintype_multipolygonseries.json | 0
.../coveragejson/binding/domaintype_point.json | 0
.../binding/domaintype_pointseries.json | 0
.../coveragejson/binding/domaintype_polygon.json | 0
.../binding/domaintype_polygonseries.json | 0
.../coveragejson/binding/domaintype_section.json | 0
.../binding/domaintype_trajectory.json | 0
.../binding/domaintype_vertical_profile.json | 0
.../binding/geographiccrs_longlat.json | 0
.../binding/geographiccrs_longlatheight.json | 0
.../sis/storage/coveragejson/binding/ndarray.json | 0
.../binding/parameter_categoricaldata.json | 0
.../binding/parameter_continuousdata.json | 0
.../binding/parametergroup_uncertainty.json | 0
.../binding/parametergroup_vectorquantity.json | 0
.../binding/projectedcrs_britishnationalgrid.json | 0
.../binding/reference_system_connection.json | 0
.../storage/coveragejson/binding/temporalrs.json | 0
.../storage/coveragejson/binding/tiledndarray.json | 0
.../coveragejson/binding/verticalcrs_navd88.json | 0
.../sis/storage/coveragejson/coverage_xyzt.json | 0
.../sis/storage/geojson/binding/BindingTest.java} | 15 +-
.../storage/geojson/binding/geojson_feature.json | 10 +
.../geojson/binding/geojson_featurecollection.json | 48 ++
.../binding/geojson_geometrycollection.json | 13 +
.../geojson/binding/geojson_linestring.json | 7 +
.../geojson/binding/geojson_multilinestring.json | 13 +
.../geojson/binding/geojson_multipoint.json | 7 +
.../geojson/binding/geojson_multipolygon.json | 30 ++
.../sis/storage/geojson/binding/geojson_point.json | 4 +
.../storage/geojson/binding/geojson_polygon.json | 12 +
.../binding/jsonfg_circularstring_measures.json | 13 +
.../binding/jsonfg_circularstring_no_measures.json | 8 +
.../binding/jsonfg_compoundcurve_measures.json | 25 +
.../binding/jsonfg_compoundcurve_no_measures.json | 20 +
.../geojson/binding/jsonfg_coordrefsys.json | 18 +
.../binding/jsonfg_curvepolygon_measures.json | 20 +
.../binding/jsonfg_curvepolygon_no_measures.json | 15 +
.../storage/geojson/binding/jsonfg_feature.json | 49 ++
.../jsonfg_geometrycollection_measures.json | 21 +
.../jsonfg_geometrycollection_no_measures.json | 16 +
.../binding/jsonfg_linestring_measures.json | 12 +
.../binding/jsonfg_linestring_no_measures.json | 7 +
.../binding/jsonfg_multicurve_measures.json | 25 +
.../binding/jsonfg_multicurve_no_measures.json | 20 +
.../binding/jsonfg_multilinestring_measures.json | 18 +
.../jsonfg_multilinestring_no_measures.json | 13 +
.../binding/jsonfg_multipoint_measures.json | 12 +
.../binding/jsonfg_multipoint_no_measures.json | 7 +
.../binding/jsonfg_multipolygon_measures.json | 35 ++
.../binding/jsonfg_multipolygon_no_measures.json | 30 ++
.../binding/jsonfg_multipolyhedron_measures.json | 23 +
.../jsonfg_multipolyhedron_no_measures.json | 18 +
.../binding/jsonfg_multiprism_measures.json | 27 +
.../binding/jsonfg_multiprism_no_measures.json | 22 +
.../binding/jsonfg_multisurface_measures.json | 37 ++
.../binding/jsonfg_multisurface_no_measures.json | 32 ++
.../geojson/binding/jsonfg_point_measures.json | 9 +
.../geojson/binding/jsonfg_point_no_measures.json | 4 +
.../geojson/binding/jsonfg_polygon_measures.json | 17 +
.../binding/jsonfg_polygon_no_measures.json | 12 +
.../binding/jsonfg_polyhedron_measures.json | 21 +
.../binding/jsonfg_polyhedron_no_measures.json | 16 +
.../geojson/binding/jsonfg_prism_measures.json | 22 +
.../geojson/binding/jsonfg_prism_no_measures.json | 17 +
.../storage/geojson/binding/jsonfg_time_date.json | 15 +
.../geojson/binding/jsonfg_time_interval.json | 18 +
.../binding/jsonfg_time_interval_open_end.json | 18 +
.../binding/jsonfg_time_interval_open_start.json | 18 +
.../geojson/binding/jsonfg_time_timestamp.json | 15 +
.../sis/storage/json/AbstractBindingTest.java | 76 +++
.../movingfeature/binding/BindingTest.java} | 15 +-
netbeans-project/ivy.xml | 3 +
netbeans-project/nbproject/project.properties | 2 +-
.../apache/sis/gui/coverage/CoverageCanvas.java | 211 ++------
.../apache/sis/gui/coverage/CoverageControls.java | 2 +-
.../apache/sis/gui/coverage/CoverageExplorer.java | 2 +-
.../org/apache/sis/gui/coverage/GridControls.java | 2 +-
.../main/org/apache/sis/gui/coverage/GridView.java | 2 +-
.../apache/sis/gui/coverage/RectangleMerger.java | 111 +++++
.../sis/gui/coverage/StyledRenderingData.java | 5 +
.../apache/sis/gui/coverage/TileReadListener.java | 327 ++++++++++++
.../org/apache/sis/gui/dataset/WindowHandler.java | 2 +-
.../org/apache/sis/gui/internal/LogHandler.java | 2 +-
.../apache/sis/gui/internal/ShapeConverter.java | 5 +-
.../org/apache/sis/gui/map/EvanescentPane.java | 1 +
.../main/org/apache/sis/gui/map/MapCanvas.java | 40 +-
.../main/org/apache/sis/gui/map/MultiCanvas.java | 2 +-
.../org/apache/sis/gui/map/ValuesFormatter.java | 7 +-
.../org/apache/sis/gui/map/ValuesUnderCursor.java | 2 +-
.../org/apache/sis/storage/gdal/TiledResource.java | 16 +-
319 files changed, 10574 insertions(+), 1979 deletions(-)
diff --cc buildSrc/src/main/java/org/apache/sis/buildtools/gradle/Dependency.java
index 3eb4604a65,4bcec1da8c..5a668b537e
--- a/buildSrc/src/main/java/org/apache/sis/buildtools/gradle/Dependency.java
+++ b/buildSrc/src/main/java/org/apache/sis/buildtools/gradle/Dependency.java
@@@ -76,7 -78,8 +76,7 @@@ public final class Dependency
Map.entry("storage.gsf", "storage:sis-gsf"),
Map.entry("storage.gdal", "storage:sis-gdal"),
Map.entry("storage.geopackage", "storage:sis-geopackage"),
- Map.entry("storage.coveragejson", "storage:sis-coveragejson"),
+ Map.entry("storage.json", "storage:sis-json"),
- Map.entry("portrayal.map", "core:sis-portrayal-map"),
Map.entry("webapp", "application:sis-webapp")
);
diff --cc endorsed/src/org.apache.sis.feature/main/module-info.java
index ef37ed8ccb,3ba6d33f15..87168cb542
--- a/endorsed/src/org.apache.sis.feature/main/module-info.java
+++ b/endorsed/src/org.apache.sis.feature/main/module-info.java
@@@ -69,8 -68,11 +69,9 @@@ module org.apache.sis.feature
org.apache.sis.storage.sql,
org.apache.sis.storage.netcdf,
org.apache.sis.storage.shapefile, // In the "incubator" sub-project.
+ org.apache.sis.storage.json, // In the "incubator" sub-project.
- org.apache.sis.referencing.dggs, // In the "incubator" sub-project.
org.apache.sis.storage.gdal, // In the "optional" sub-project.
org.apache.sis.portrayal,
- org.apache.sis.portrayal.map, // In the "incubator" sub-project.
org.apache.sis.gui; // In the "optional" sub-project.
exports org.apache.sis.geometry.wrapper to
diff --cc endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCRSBuilder.java
index 0425941c15,7ebf7e57a3..4217928a76
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCRSBuilder.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCRSBuilder.java
@@@ -67,11 -66,14 +66,14 @@@ import org.apache.sis.util.logging.Logg
import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.util.collection.Containers;
import org.apache.sis.util.collection.BackingStoreException;
+ import org.apache.sis.util.internal.shared.Numerics;
import org.apache.sis.util.iso.Types;
import org.apache.sis.measure.Units;
+ import org.apache.sis.util.resources.Errors;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.referencing.ObjectDomain;
-import org.opengis.coordinate.MismatchedDimensionException;
+// Specific to the main branch:
+import org.opengis.referencing.datum.Datum;
++import org.opengis.geometry.MismatchedDimensionException;
/**
diff --cc endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/AbstractFeature.java
index 31b84f7e15,17408ae4a8..c41c7b7a0c
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/AbstractFeature.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/AbstractFeature.java
@@@ -569,13 -531,13 +564,13 @@@ public abstract class AbstractFeature i
* @param property name of the property for which to get a characteristic.
* @param characteristic name of the characteristic of the property of the given name.
* @return default value of the specified characteristic on the specified property.
-- * @throws PropertyNotFoundException if the {@code property} argument is not the name of a property.
++ * @throws IllegalArgumentException if the {@code property} argument is not the name of a property.
*/
final Optional<?> getDefaultCharacteristicValue(final String property, final String characteristic) {
- final PropertyType p = type.getProperty(property);
- if (p instanceof AttributeType<?>) {
- return Optional.ofNullable(((AttributeType<?>) p).characteristics().get(characteristic))
- .map(AttributeType::getDefaultValue);
+ final AbstractIdentifiedType p = type.getProperty(property);
+ if (p instanceof DefaultAttributeType<?>) {
+ return Optional.ofNullable(((DefaultAttributeType<?>) p).characteristics().get(characteristic))
+ .map(DefaultAttributeType::getDefaultValue);
}
return Optional.empty();
}
diff --cc endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/shared/AttributeConvention.java
index f6131f6227,395db909dc..ef66b1d810
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/shared/AttributeConvention.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/shared/AttributeConvention.java
@@@ -284,7 -290,7 +284,7 @@@ public final class AttributeConvention
* @param feature the feature instance from which to get the <abbr>CRS</abbr> of an attribute.
* @param property name of the property for which to get the <abbr>CRS</abbr>.
* @return the Coordinate Reference System characteristic of the specified property, or {@code null} if none.
-- * @throws PropertyNotFoundException if the {@code property} argument is not the name of a property of the given feature.
++ * @throws IllegalArgumentException if the {@code property} argument is not the name of a property of the given feature.
* @throws ClassCastException if {@link #CRS_CHARACTERISTIC} has been found but is associated
* to an object which is not a {@link CoordinateReferenceSystem} instance.
*
@@@ -332,7 -338,7 +332,7 @@@
* @param feature the feature instance from which to get the maximal length of an attribute.
* @param property the name of the property for which to get the maximal length.
* @return the maximal length characteristic of the specified property, or {@code null} if none.
-- * @throws PropertyNotFoundException if the {@code property} argument is not the name of a property of the given feature.
++ * @throws IllegalArgumentException if the {@code property} argument is not the name of a property of the given feature.
* @throws ClassCastException if {@link #MAXIMAL_LENGTH_CHARACTERISTIC} has been found but is associated
* to an object which is not an {@link Integer} instance.
*
@@@ -390,10 -396,27 +390,10 @@@
* @param property name of the property for which to get the characteristic.
* @param characteristic name of the characteristic from which to get the value or default value.
* @return the value or default value of the specified characteristic in the specified property, or {@code null} if none.
-- * @throws PropertyNotFoundException if the {@code property} argument is not the name of a property of the given feature.
++ * @throws IllegalArgumentException if the {@code property} argument is not the name of a property of the given feature.
*/
- private static Object getCharacteristic(final Feature feature, final String property, final String characteristic) {
- if (feature instanceof AbstractFeature) {
- return ((AbstractFeature) feature).getCharacteristicValue(property, characteristic).orElse(null);
- }
- final Property attribute = feature.getProperty(property);
- if (attribute instanceof Attribute<?>) {
- final Attribute<?> at = ((Attribute<?>) attribute).characteristics().get(characteristic);
- if (at != null) {
- final Object value = at.getValue();
- if (value != null) {
- return value;
- }
- }
- final AttributeType<?> type = ((Attribute<?>) attribute).getType().characteristics().get(characteristic);
- if (type != null) {
- return type.getDefaultValue();
- }
- }
- return null;
+ private static Object getCharacteristic(final AbstractFeature feature, final String property, final String characteristic) {
+ return feature.getCharacteristicValue(property, characteristic).orElse(null);
}
/**
diff --cc endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/internal/shared/MergerTest.java
index d419b2d3e2,9c79d7677b..09c66d15eb
--- a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/internal/shared/MergerTest.java
+++ b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/internal/shared/MergerTest.java
@@@ -111,10 -114,10 +111,10 @@@ public final class MergerTest extends T
assertSetEquals(List.of(StandardCharsets.UTF_16, StandardCharsets.UTF_8),
target.getLocalesAndCharsets().values());
- final Iterator<ContentInformation> it = target.getContentInfo().iterator();
- final ImageDescription image = (ImageDescription) it.next();
- final FeatureCatalogueDescription features = (FeatureCatalogueDescription) it.next();
- final DefaultCoverageDescription coverage = (DefaultCoverageDescription) it.next();
+ final Iterator<ContentInformation> it = target.getContentInfo().iterator();
+ final var image = assertInstanceOf(ImageDescription.class, it.next());
+ final var features = assertInstanceOf(FeatureCatalogueDescription.class, it.next());
- final var coverage = assertInstanceOf(CoverageDescription.class, it.next());
++ final var coverage = assertInstanceOf(DefaultCoverageDescription.class, it.next());
assertFalse(it.hasNext());
assertEquals(ImagingCondition.CLOUD, image .getImagingCondition());
diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
index 69c93aedb1,c692d2cbca..62e545cbc5
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
@@@ -31,10 -31,10 +31,13 @@@ import org.apache.sis.referencing.inter
import org.apache.sis.referencing.operation.matrix.Matrices;
import org.apache.sis.referencing.operation.matrix.MatrixSIS;
import org.apache.sis.referencing.operation.transform.MathTransforms;
+ import org.apache.sis.measure.NumberRange;
+ import org.apache.sis.util.Classes;
+ import org.apache.sis.util.internal.shared.Strings;
+// Specific to the main branch:
+import org.apache.sis.referencing.crs.DefaultParametricCRS;
+
/**
* Information about the operation from a source component to a target component in {@code CompoundCRS} instances.
diff --cc endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SelectionClause.java
index 8a1b2ad0d2,fb0355910e..e1299735df
--- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SelectionClause.java
+++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SelectionClause.java
@@@ -181,10 -190,17 +181,17 @@@ public final class SelectionClause exte
}
/**
- * Writes a literal value, or marks this SQL as invalid if the value cannot be formatted.
+ * Writes a literal value, or marks this <abbr>SQL</abbr> as invalid if the value cannot be formatted.
+ * The value can be {@code null}, a character string, a Boolean, a number, a temporal object,
+ * a geographic bounding box or an envelope. If the given object cannot be formatted,
+ * then this clause is {@linkplain #invalidate() marked as invalid}.
*/
final void appendLiteral(final Object value) {
- if (value instanceof GeographicBoundingBox) {
+ if (value == null) {
+ append(NULL);
+ } else if (value instanceof CharSequence) {
- appendLiteralOrPattern(value.toString());
++ appendValue(value.toString());
+ } else if (value instanceof GeographicBoundingBox) {
appendGeometry(null, new GeneralEnvelope((GeographicBoundingBox) value));
} else if (value instanceof Envelope) {
appendGeometry(null, (Envelope) value);
diff --cc endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SelectionClauseWriter.java
index 386016294c,114a2fff87..52c88c92b4
--- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SelectionClauseWriter.java
+++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SelectionClauseWriter.java
@@@ -83,8 -87,8 +83,8 @@@ public class SelectionClauseWriter exte
setFilterHandler(ComparisonOperatorName.PROPERTY_IS_GREATER_THAN_OR_EQUAL_TO, new Comparison(" >= "));
setFilterHandler(ComparisonOperatorName.PROPERTY_IS_LESS_THAN, new Comparison(" < "));
setFilterHandler(ComparisonOperatorName.PROPERTY_IS_LESS_THAN_OR_EQUAL_TO, new Comparison(" <= "));
- setFilterHandler(ComparisonOperatorName.PROPERTY_IS_BETWEEN, (f,sql) -> {
- setFilterHandler(ComparisonOperatorName.valueOf(FunctionNames.PROPERTY_IS_BETWEEN), (f, sql) -> {
- final var filter = (BetweenComparisonOperator<Feature>) f;
++ setFilterHandler(ComparisonOperatorName.PROPERTY_IS_BETWEEN, (f, sql) -> {
+ final var filter = (BetweenComparisonOperator<AbstractFeature>) f;
/* Nothing to append */ if (write(sql, filter.getExpression())) return;
sql.append(" BETWEEN "); if (write(sql, filter.getLowerBoundary())) return;
sql.append(" AND "); write(sql, filter.getUpperBoundary());
diff --cc endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/SQLStoreTest.java
index d7741d7460,e0f04f8e94..c090a2ac23
--- a/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/SQLStoreTest.java
+++ b/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/SQLStoreTest.java
@@@ -446,10 -451,10 +446,10 @@@ public final class SQLStoreTest extend
*/
final Object[] result;
final FeatureSet cities = dataset.findResource("Cities");
- try (Stream<Feature> features = cities.subset(query).features(false)) {
+ try (Stream<AbstractFeature> features = cities.subset(query).features(false)) {
result = features.map(f -> f.getPropertyValue("native_name")).toArray();
}
- assertSetEquals(Arrays.asList("Montréal", "Québec"), Arrays.asList(result));
+ assertSetEquals(List.of("Montréal", "Québec"), Arrays.asList(result));
}
/**
diff --cc endorsed/src/org.apache.sis.storage.xml/test/org/apache/sis/storage/gpx/ReaderTest.java
index ffedca3a5e,56fcd3e904..0e44121b2e
--- a/endorsed/src/org.apache.sis.storage.xml/test/org/apache/sis/storage/gpx/ReaderTest.java
+++ b/endorsed/src/org.apache.sis.storage.xml/test/org/apache/sis/storage/gpx/ReaderTest.java
@@@ -95,8 -105,9 +105,9 @@@ public final class ReaderTest extends T
*/
private static void assertEnvelopeEquals(final double xmin, final double xmax,
final double ymin, final double ymax,
- final Envelope actual)
- final Feature f)
++ final AbstractFeature f)
{
+ final Envelope actual = assertInstanceOf(Envelope.class, f.getPropertyValue("sis:envelope"));
assertEquals(2, actual.getDimension(), "dimension");
assertEquals(actual.getMinimum(0), xmin, "xmin");
assertEquals(actual.getMaximum(0), xmax, "xmax");
@@@ -207,10 -255,10 +255,10 @@@
@Test
public void testWayPoint100() throws DataStoreException {
try (Store reader = create(TestData.V1_0, TestData.WAYPOINT)) {
- verifyAlmostEmptyMetadata((Metadata) reader.getMetadata());
+ verifyAlmostEmptyMetadata(getMetadata(reader));
assertEquals(StoreProvider.V1_0, reader.getVersion());
- try (Stream<Feature> features = reader.features(false)) {
- final Iterator<Feature> it = features.iterator();
+ try (Stream<AbstractFeature> features = reader.features(false)) {
+ final Iterator<AbstractFeature> it = features.iterator();
verifyPoint(it.next(), 0, false);
verifyPoint(it.next(), 1, false);
verifyPoint(it.next(), 2, false);
@@@ -227,10 -275,10 +275,10 @@@
@Test
public void testWayPoint110() throws DataStoreException {
try (Store reader = create(TestData.V1_1, TestData.WAYPOINT)) {
- verifyAlmostEmptyMetadata((Metadata) reader.getMetadata());
+ verifyAlmostEmptyMetadata(getMetadata(reader));
assertEquals(StoreProvider.V1_1, reader.getVersion());
- try (Stream<Feature> features = reader.features(false)) {
- final Iterator<Feature> it = features.iterator();
+ try (Stream<AbstractFeature> features = reader.features(false)) {
+ final Iterator<AbstractFeature> it = features.iterator();
verifyPoint(it.next(), 0, true);
verifyPoint(it.next(), 1, true);
verifyPoint(it.next(), 2, true);
@@@ -247,10 -295,10 +295,10 @@@
@Test
public void testRoute100() throws DataStoreException {
try (Store reader = create(TestData.V1_0, TestData.ROUTE)) {
- verifyAlmostEmptyMetadata((Metadata) reader.getMetadata());
+ verifyAlmostEmptyMetadata(getMetadata(reader));
assertEquals(StoreProvider.V1_0, reader.getVersion());
- try (Stream<Feature> features = reader.features(false)) {
- final Iterator<Feature> it = features.iterator();
+ try (Stream<AbstractFeature> features = reader.features(false)) {
+ final Iterator<AbstractFeature> it = features.iterator();
verifyRoute(it.next(), false, 1);
verifyEmpty(it.next(), "rtept");
assertFalse(it.hasNext());
@@@ -352,10 -400,10 +400,10 @@@
@Test
public void testTrack100() throws DataStoreException {
try (Store reader = create(TestData.V1_0, TestData.TRACK)) {
- verifyAlmostEmptyMetadata((Metadata) reader.getMetadata());
+ verifyAlmostEmptyMetadata(getMetadata(reader));
assertEquals(StoreProvider.V1_0, reader.getVersion());
- try (Stream<Feature> features = reader.features(false)) {
- final Iterator<Feature> it = features.iterator();
+ try (Stream<AbstractFeature> features = reader.features(false)) {
+ final Iterator<AbstractFeature> it = features.iterator();
verifyTrack(it.next(), false, 1);
verifyEmpty(it.next(), "trkseg");
assertFalse(it.hasNext());
@@@ -371,10 -419,10 +419,10 @@@
@Test
public void testTrack110() throws DataStoreException {
try (Store reader = create(TestData.V1_1, TestData.TRACK)) {
- verifyAlmostEmptyMetadata((Metadata) reader.getMetadata());
+ verifyAlmostEmptyMetadata(getMetadata(reader));
assertEquals(StoreProvider.V1_1, reader.getVersion());
- try (Stream<Feature> features = reader.features(false)) {
- final Iterator<Feature> it = features.iterator();
+ try (Stream<AbstractFeature> features = reader.features(false)) {
+ final Iterator<AbstractFeature> it = features.iterator();
verifyTrack(it.next(), true, 3);
verifyEmpty(it.next(), "trkseg");
assertFalse(it.hasNext());
@@@ -586,16 -634,17 +634,17 @@@
* @throws DataStoreException if reader failed to be created or failed at reading.
*/
@Test
+ @SuppressWarnings("ConvertToTryWithResources")
public void testConcurrentReads() throws DataStoreException {
try (Store reader = createFromURL()) {
- final Stream<Feature> f1 = reader.features(false);
- final Iterator<Feature> i1 = f1.iterator();
+ final Stream<AbstractFeature> f1 = reader.features(false);
+ final Iterator<AbstractFeature> i1 = f1.iterator();
verifyRoute(i1.next(), true, 3);
- final Stream<Feature> f2 = reader.features(false);
- final Iterator<Feature> i2 = f2.iterator();
+ final Stream<AbstractFeature> f2 = reader.features(false);
+ final Iterator<AbstractFeature> i2 = f2.iterator();
verifyEmpty(i1.next(), "rtept");
- final Stream<Feature> f3 = reader.features(false);
- final Iterator<Feature> i3 = f3.iterator();
+ final Stream<AbstractFeature> f3 = reader.features(false);
+ final Iterator<AbstractFeature> i3 = f3.iterator();
verifyRoute(i2.next(), true, 3);
verifyRoute(i3.next(), true, 3);
verifyEmpty(i3.next(), "rtept");
diff --cc endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java
index 63b6b1b81f,b780a79674..9c5845162a
--- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java
+++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java
@@@ -622,7 -621,7 +622,7 @@@ public class FeatureQuery extends Quer
* @param builder the builder where to add the property.
* @return whether the property has been successfully added.
* @throws InvalidFilterValueException if {@linkplain #expression} is invalid.
-- * @throws PropertyNotFoundException if the property was not found in {@code builder.source()}.
++ * @throws IllegalArgumentException if the property was not found in {@code builder.source()}.
* @throws UnconvertibleObjectException if the property default value cannot be converted to the expected type.
*/
final boolean addTo(final FeatureProjectionBuilder builder) {
@@@ -788,7 -787,7 +788,7 @@@
* @param sourceType the feature type to project.
* @param locale locale for error messages, or {@code null} for the default locale.
* @throws InvalidFilterValueException if an {@linkplain NamedExpression#expression expression} is invalid.
-- * @throws PropertyNotFoundException if a property referenced by an expression was not found in {@code sourceType}.
++ * @throws IllegalArgumentException if a property referenced by an expression was not found in {@code sourceType}.
* @throws UnconvertibleObjectException if a property default value cannot be converted to the expected type.
* @throws UnsupportedOperationException if there is an attempt to rename a property which is used by an operation.
*/
diff --cc incubator/src/org.apache.sis.storage.json/main/org/apache/sis/storage/geojson/GeoJSON.java
index 0000000000,d805dfbcef..ee2b202e19
mode 000000,100644..100644
--- a/incubator/src/org.apache.sis.storage.json/main/org/apache/sis/storage/geojson/GeoJSON.java
+++ b/incubator/src/org.apache.sis.storage.json/main/org/apache/sis/storage/geojson/GeoJSON.java
@@@ -1,0 -1,165 +1,165 @@@
+ /*
+ * 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.geojson;
+
+ import java.util.List;
+ import java.util.Map.Entry;
++import org.apache.sis.feature.AbstractFeature;
++import org.apache.sis.feature.DefaultFeatureType;
+ import org.apache.sis.feature.builder.AttributeRole;
+ import org.apache.sis.feature.builder.FeatureTypeBuilder;
+ import org.apache.sis.feature.internal.shared.AttributeConvention;
+ import org.apache.sis.storage.DataStoreException;
+ import org.apache.sis.storage.geojson.binding.GeoJSONFeature;
+ import org.apache.sis.storage.geojson.binding.GeoJSONGeometry;
+ import org.apache.sis.storage.geojson.binding.GeoJSONGeometryCollection;
+ import org.apache.sis.storage.geojson.binding.GeoJSONLineString;
+ import org.apache.sis.storage.geojson.binding.GeoJSONMultiLineString;
+ import org.apache.sis.storage.geojson.binding.GeoJSONMultiPoint;
+ import org.apache.sis.storage.geojson.binding.GeoJSONMultiPolygon;
+ import org.apache.sis.storage.geojson.binding.GeoJSONPoint;
+ import org.apache.sis.storage.geojson.binding.GeoJSONPolygon;
+ import org.locationtech.jts.geom.Coordinate;
+ import org.locationtech.jts.geom.CoordinateXY;
+ import org.locationtech.jts.geom.CoordinateXYZM;
+ 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.Point;
+ import org.locationtech.jts.geom.Polygon;
-import org.opengis.feature.Feature;
-import org.opengis.feature.FeatureType;
+
+ /**
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+ public final class GeoJSON {
+
+ private static final GeometryFactory GF = new GeometryFactory();
+
+ private GeoJSON() {
+
+ }
+
- public static Feature fromGeoJSON(GeoJSONFeature json, FeatureType type) throws DataStoreException {
++ public static AbstractFeature fromGeoJSON(GeoJSONFeature json, DefaultFeatureType type) throws DataStoreException {
+
+ final GeoJSONGeometry jsongeom = json.getGeometry();
+ Geometry geom = null;
+ if (jsongeom != null) {
+ geom = fromGeoJSON(jsongeom);
+ }
+
+ if (type == null) {
+ final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
+ ftb.setName("geojson");
+
+ if (json.getId() != null) {
+ ftb.addAttribute(json.getId().getClass()).setName(AttributeConvention.IDENTIFIER_PROPERTY).addRole(AttributeRole.IDENTIFIER_COMPONENT);
+ }
+ if (geom != null) {
+ ftb.addAttribute(geom.getClass()).setName(AttributeConvention.GEOMETRY_PROPERTY).addRole(AttributeRole.DEFAULT_GEOMETRY);
+ }
+ for (Entry<String,Object> entry : json.getProperties().entrySet()) {
+ ftb.addAttribute(entry.getValue().getClass()).setName(entry.getKey());
+ }
+ type = ftb.build();
+ }
+
- final Feature feature = type.newInstance();
++ final AbstractFeature feature = type.newInstance();
+
+ if (json.getId() != null) {
+ feature.setPropertyValue(AttributeConvention.IDENTIFIER, json.getId());
+ }
+
+ if (geom != null) {
+ feature.setPropertyValue(AttributeConvention.GEOMETRY, geom);
+ }
+
+ for (Entry<String,Object> entry : json.getProperties().entrySet()) {
+ feature.setPropertyValue(entry.getKey(), entry.getValue());
+ }
+ return feature;
+ }
+
+ public static Geometry fromGeoJSON(GeoJSONGeometry geom) throws DataStoreException {
+ if (geom instanceof GeoJSONPoint json) {
+ return GF.createPoint(toCoordinate(json.getCoordinates()));
+ } else if (geom instanceof GeoJSONLineString json) {
+ return GF.createLineString(toCoordinates(json.getCoordinates()));
+ } else if (geom instanceof GeoJSONPolygon json) {
+ return toPolygon(json.getCoordinates());
+ } else if (geom instanceof GeoJSONMultiPoint json) {
+ final List<List<Double>> coordinates = json.getCoordinates();
+ final Point[] points = new Point[coordinates.size()];
+ for (int i = 0; i < points.length; i++) {
+ points[i] = GF.createPoint(toCoordinate(coordinates.get(i)));
+ }
+ return GF.createMultiPoint(points);
+ } else if (geom instanceof GeoJSONMultiLineString json) {
+ final List<List<List<Double>>> coordinates = json.getCoordinates();
+ final LineString[] lines = new LineString[coordinates.size()];
+ for (int i = 0; i < lines.length; i++) {
+ lines[i] = GF.createLineString(toCoordinates(coordinates.get(i)));
+ }
+ return GF.createMultiLineString(lines);
+ } else if (geom instanceof GeoJSONMultiPolygon json) {
+ final List<List<List<List<Double>>>> coordinates = json.getCoordinates();
+ final Polygon[] polygons = new Polygon[coordinates.size()];
+ for (int i = 0; i < polygons.length; i++) {
+ polygons[i] = toPolygon(coordinates.get(i));
+ }
+ return GF.createMultiPolygon(polygons);
+ } else if (geom instanceof GeoJSONGeometryCollection json) {
+ final List<GeoJSONGeometry> geometries = json.getGeometries();
+ final Geometry[] children = new Geometry[geometries.size()];
+ for (int i = 0; i < children.length; i++) {
+ children[i] = fromGeoJSON(geometries.get(i));
+ }
+ return GF.createGeometryCollection(children);
+ } else {
+ throw new DataStoreException("Geometry not supported " + geom);
+ }
+ }
+
+ private static Polygon toPolygon(List<List<List<Double>>> rings) throws DataStoreException {
+ final LinearRing shell = GF.createLinearRing(toCoordinates(rings.get(0)));
+ final LinearRing[] holes = new LinearRing[rings.size() - 1];
+ for (int i = 0; i < holes.length; i++) {
+ holes[i] = GF.createLinearRing(toCoordinates(rings.get(i + 1)));
+ }
+ return GF.createPolygon(shell, holes);
+ }
+
+ private static Coordinate[] toCoordinates(List<List<Double>> positions) throws DataStoreException {
+ final Coordinate[] coords = new Coordinate[positions.size()];
+ for (int i = 0; i < coords.length; i++) {
+ coords[i] = toCoordinate(positions.get(i));
+ }
+ return coords;
+ }
+
+ private static Coordinate toCoordinate(List<Double> coordinates) throws DataStoreException {
+ final int size = coordinates.size();
+ switch (size) {
+ case 2 : return new CoordinateXY(coordinates.get(0), coordinates.get(1));
+ case 3 : return new Coordinate(coordinates.get(0), coordinates.get(1), coordinates.get(2));
+ case 4 : return new CoordinateXYZM(coordinates.get(0), coordinates.get(1), coordinates.get(2), coordinates.get(3));
+ default : throw new DataStoreException("Geometry " + size + "not supported");
+ }
+ }
+
+ }
diff --cc incubator/src/org.apache.sis.storage.json/main/org/apache/sis/storage/geojson/GeoJSONMapper.java
index 0000000000,f480f04d6e..65bc1df0f6
mode 000000,100644..100644
--- a/incubator/src/org.apache.sis.storage.json/main/org/apache/sis/storage/geojson/GeoJSONMapper.java
+++ b/incubator/src/org.apache.sis.storage.json/main/org/apache/sis/storage/geojson/GeoJSONMapper.java
@@@ -1,0 -1,481 +1,479 @@@
+ /*
+ * 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.geojson;
+
+ import java.util.ArrayList;
+ import java.util.Iterator;
+ import java.util.LinkedHashMap;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.function.Predicate;
+ import java.util.stream.Collectors;
+ import java.util.stream.Stream;
++import org.apache.sis.feature.AbstractFeature;
++import org.apache.sis.feature.AbstractIdentifiedType;
++import org.apache.sis.feature.AbstractOperation;
++import org.apache.sis.feature.DefaultAttributeType;
++import org.apache.sis.feature.DefaultFeatureType;
+ import org.apache.sis.feature.internal.shared.AttributeConvention;
+ import org.apache.sis.referencing.IdentifiedObjects;
+ import org.apache.sis.storage.DataStoreException;
+ import org.apache.sis.storage.FeatureSet;
+ import org.apache.sis.storage.geojson.binding.GeoJSONFeature;
+ import org.apache.sis.storage.geojson.binding.GeoJSONFeatureCollection;
+ import org.apache.sis.storage.geojson.binding.GeoJSONGeometry;
+ import org.apache.sis.storage.geojson.binding.GeoJSONGeometryCollection;
+ import org.apache.sis.storage.geojson.binding.GeoJSONLineString;
+ import org.apache.sis.storage.geojson.binding.GeoJSONMultiLineString;
+ import org.apache.sis.storage.geojson.binding.GeoJSONMultiPoint;
+ import org.apache.sis.storage.geojson.binding.GeoJSONMultiPolygon;
+ import org.apache.sis.storage.geojson.binding.GeoJSONPoint;
+ import org.apache.sis.storage.geojson.binding.GeoJSONPolygon;
+ import org.locationtech.jts.geom.CoordinateSequence;
+ import org.locationtech.jts.geom.Envelope;
+ import org.locationtech.jts.geom.Geometry;
+ import org.locationtech.jts.geom.GeometryCollection;
+ import org.locationtech.jts.geom.LineString;
+ import org.locationtech.jts.geom.MultiLineString;
+ import org.locationtech.jts.geom.MultiPoint;
+ import org.locationtech.jts.geom.MultiPolygon;
+ import org.locationtech.jts.geom.Point;
+ import org.locationtech.jts.geom.Polygon;
-import org.opengis.feature.AttributeType;
-import org.opengis.feature.Feature;
-import org.opengis.feature.FeatureType;
-import org.opengis.feature.IdentifiedType;
-import org.opengis.feature.Operation;
-import org.opengis.feature.PropertyNotFoundException;
-import org.opengis.feature.PropertyType;
+ import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+ /**
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+ public final class GeoJSONMapper {
+
+ private boolean bboxOnCollection = false;
+ private boolean bboxOnFeature = false;
+ private boolean bboxOnGeometry = false;
+ private boolean includeFeatureId = true;
+ private boolean includeTypeOnFeature = false;
+ private boolean includeTypeOnCollection = false;
+ private boolean includeCoordRefSysOnCollection = false;
+ private boolean includeCoordRefSysOnFeature = false;
+ private boolean includeCoordRefSysOnGeometry = false;
+
+ public void setBboxOnCollection(boolean bboxOnCollection) {
+ this.bboxOnCollection = bboxOnCollection;
+ }
+
+ public boolean isBboxOnCollection() {
+ return bboxOnCollection;
+ }
+
+ public void setBboxOnFeature(boolean bboxOnFeature) {
+ this.bboxOnFeature = bboxOnFeature;
+ }
+
+ public boolean isBboxOnFeature() {
+ return bboxOnFeature;
+ }
+
+ public void setBboxOnGeometry(boolean bboxOnGeometry) {
+ this.bboxOnGeometry = bboxOnGeometry;
+ }
+
+ public boolean isBboxOnGeometry() {
+ return bboxOnGeometry;
+ }
+
+ public void setIncludeFeatureId(boolean includeFeatureId) {
+ this.includeFeatureId = includeFeatureId;
+ }
+
+ public boolean isIncludeFeatureId() {
+ return includeFeatureId;
+ }
+
+ public void setIncludeTypeOnFeature(boolean includeTypeOnFeature) {
+ this.includeTypeOnFeature = includeTypeOnFeature;
+ }
+
+ public boolean isIncludeTypeOnFeature() {
+ return includeTypeOnFeature;
+ }
+
+ public void setIncludeTypeOnCollection(boolean includeTypeOnCollection) {
+ this.includeTypeOnCollection = includeTypeOnCollection;
+ }
+
+ public boolean isIncludeTypeOnCollection() {
+ return includeTypeOnCollection;
+ }
+
+ public void setIncludeCoordRefSysOnCollection(boolean includeCoordRefSysOnCollection) {
+ this.includeCoordRefSysOnCollection = includeCoordRefSysOnCollection;
+ }
+
+ public boolean isIncludeCoordRefSysOnCollection() {
+ return includeCoordRefSysOnCollection;
+ }
+
+ public void setIncludeCoordRefSysOnFeature(boolean includeCoordRefSysOnFeature) {
+ this.includeCoordRefSysOnFeature = includeCoordRefSysOnFeature;
+ }
+
+ public boolean isIncludeCoordRefSysOnFeature() {
+ return includeCoordRefSysOnFeature;
+ }
+
+ public void setIncludeCoordRefSysOnGeometry(boolean includeCoordRefSysOnGeometry) {
+ this.includeCoordRefSysOnGeometry = includeCoordRefSysOnGeometry;
+ }
+
+ public boolean isIncludeCoordRefSysOnGeometry() {
+ return includeCoordRefSysOnGeometry;
+ }
+
- public GeoJSONFeature transform(Feature feature) throws DataStoreException {
- final FeatureType type = feature.getType();
++ public GeoJSONFeature transform(AbstractFeature feature) throws DataStoreException {
++ final DefaultFeatureType type = feature.getType();
+
+ final GeoJSONFeature gf = new GeoJSONFeature();
+
+ if (includeTypeOnFeature) {
+ gf.setFeatureType(getTypeName(type));
+ }
+
+ if (includeFeatureId && feature.getType().hasProperty(AttributeConvention.IDENTIFIER)) { // TODO: should be determined in advance.
+ Object id = feature.getPropertyValue(AttributeConvention.IDENTIFIER);
+ if (id != null) {
+ gf.setId(id);
+ }
+ }
+ if (includeCoordRefSysOnFeature) {
+ gf.setCoordRefSys(getCoordRefSys(type));
+ }
+
+ if (feature.getType().hasProperty(AttributeConvention.GEOMETRY)) { // TODO: should be determined in advance.
+ Object geom = feature.getPropertyValue(AttributeConvention.GEOMETRY);
+ if (geom instanceof Geometry g) {
+ GeoJSONGeometry json = transform(g);
+ gf.setGeometry(json);
+
+ if (bboxOnFeature) {
+ Envelope env = g.getEnvelopeInternal();
+ if (env != null && !env.isNull()) {
+ final List<Double> bbox = new ArrayList<>();
+ bbox.add(env.getMinX());
+ bbox.add(env.getMinY());
+ bbox.add(env.getMaxX());
+ bbox.add(env.getMaxY());
+ gf.setBbox(bbox);
+ }
+ }
+ }
+ }
+
+ final Map<String,Object> properties = new LinkedHashMap();
+ gf.setProperties(properties);
- for (PropertyType pt : type.getProperties(true)) {
++ for (AbstractIdentifiedType pt : type.getProperties(true)) {
+ if (AttributeConvention.contains(pt.getName())) continue;
- if (pt instanceof AttributeType) {
++ if (pt instanceof DefaultAttributeType) {
+ final String name = pt.getName().toString();
+ final Object value = feature.getPropertyValue(name);
+ properties.put(name, value);
+ }
+ }
+
+ return gf;
+ }
+
+ public GeoJSONFeatureCollection transform(FeatureSet features) throws DataStoreException {
- final FeatureType type = features.getType();
++ final DefaultFeatureType type = features.getType();
+
+ final GeoJSONFeatureCollection cl = new GeoJSONFeatureCollection();
+ final List<GeoJSONFeature> lst = new ArrayList<>();
- try (Stream<Feature> stream = features.features(false)) {
- final Iterator<Feature> ite = stream.iterator();
++ try (Stream<AbstractFeature> stream = features.features(false)) {
++ final Iterator<AbstractFeature> ite = stream.iterator();
+ while (ite.hasNext()) {
+ lst.add(transform(ite.next()));
+ }
+ }
+
+ cl.setFeatures(lst);
+
+ if (includeTypeOnCollection) {
+ cl.setFeatureType(getTypeName(type));
+ }
+ if (includeCoordRefSysOnCollection) {
+ cl.setCoordRefSys(getCoordRefSys(type));
+ }
+ if (bboxOnCollection) {
+ org.opengis.geometry.Envelope env = features.getEnvelope().orElse(null);
+ if (env != null) {
+ final List<Double> bbox = new ArrayList<>();
+ bbox.add(env.getMinimum(0));
+ bbox.add(env.getMinimum(1));
+ bbox.add(env.getMaximum(0));
+ bbox.add(env.getMaximum(1));
+ cl.setBbox(bbox);
+ }
+ }
+
+ return cl;
+ }
+
+ public GeoJSONGeometry transform(Geometry geom) throws DataStoreException {
+
+ final GeoJSONGeometry res;
+ if (geom instanceof Point cdt) {
+ final GeoJSONPoint json = new GeoJSONPoint();
+ CoordinateSequence cs = cdt.getCoordinateSequence();
+ json.setCoordinates(toList(cs).get(0));
+ res = json;
+ } else if (geom instanceof LineString cdt) {
+ final GeoJSONLineString json = new GeoJSONLineString();
+ CoordinateSequence cs = cdt.getCoordinateSequence();
+ json.setCoordinates(toList(cs));
+ res = json;
+ } else if (geom instanceof Polygon cdt) {
+ final GeoJSONPolygon json = new GeoJSONPolygon();
+ final List<List<List<Double>>> lst = new ArrayList<>();
+ lst.add(toList(cdt.getExteriorRing().getCoordinateSequence()));
+ for (int i = 0, n = cdt.getNumInteriorRing(); i < n; i++) {
+ lst.add(toList(cdt.getInteriorRingN(i).getCoordinateSequence()));
+ }
+ json.setCoordinates(lst);
+ res = json;
+ } else if (geom instanceof MultiPoint cdt) {
+ final GeoJSONMultiPoint json = new GeoJSONMultiPoint();
+ final List<List<Double>> lst = new ArrayList<>();
+ for (int i = 0, n = cdt.getNumGeometries(); i < n; i++) {
+ lst.add(toList(((Point)cdt.getGeometryN(i)).getCoordinateSequence()).get(0));
+ }
+ json.setCoordinates(lst);
+ res = json;
+ } else if (geom instanceof MultiLineString cdt) {
+ final GeoJSONMultiLineString json = new GeoJSONMultiLineString();
+ final List<List<List<Double>>> lst = new ArrayList<>();
+ for (int i = 0, n = cdt.getNumGeometries(); i < n; i++) {
+ lst.add(toList(((LineString)cdt.getGeometryN(i)).getCoordinateSequence()));
+ }
+ json.setCoordinates(lst);
+ res = json;
+ } else if (geom instanceof MultiPolygon cdt) {
+ final GeoJSONMultiPolygon json = new GeoJSONMultiPolygon();
+ final List<List<List<List<Double>>>> lst = new ArrayList<>();
+ for (int i = 0, n = cdt.getNumGeometries(); i < n; i++) {
+ final Polygon pl = (Polygon) cdt.getGeometryN(i);
+ final List<List<List<Double>>> sublst = new ArrayList<>();
+ sublst.add(toList(pl.getExteriorRing().getCoordinateSequence()));
+ for (int j = 0, k = pl.getNumInteriorRing(); j < k; j++) {
+ sublst.add(toList(pl.getInteriorRingN(j).getCoordinateSequence()));
+ }
+ lst.add(sublst);
+ }
+ json.setCoordinates(lst);
+ res = json;
+ } else if (geom instanceof GeometryCollection cdt) {
+ final GeoJSONGeometryCollection json = new GeoJSONGeometryCollection();
+ final List<GeoJSONGeometry> geometries = new ArrayList<>();
+ for (int i = 0, n = cdt.getNumGeometries(); i < n; i++) {
+ final Geometry pl = (Geometry) cdt.getGeometryN(i);
+ geometries.add(transform(pl));
+ }
+ json.setGeometries(geometries);
+ res = json;
+ } else {
+ throw new DataStoreException("Geometry not supported yet " + geom);
+ }
+
+ if (bboxOnGeometry) {
+ Envelope env = geom.getEnvelopeInternal();
+ if (env != null && !env.isNull()) {
+ final List<Double> bbox = new ArrayList<>();
+ bbox.add(env.getMinX());
+ bbox.add(env.getMinY());
+ bbox.add(env.getMaxX());
+ bbox.add(env.getMaxY());
+ res.setBbox(bbox);
+ }
+ }
+
+ if (includeCoordRefSysOnGeometry) {
+ Object userData = geom.getUserData();
+ if (userData instanceof CoordinateReferenceSystem crs) {
+ res.setCoordRefSys(getCoordRefSys(crs));
+ }
+ }
+
+ return res;
+ }
+
+ private List<List<Double>> toList(CoordinateSequence cs) throws DataStoreException {
+ final int dim = cs.getDimension();
+ final int size = cs.size();
+ final List<List<Double>> lst = new ArrayList<>(size);
+ switch (dim) {
+ case 2 : {
+ for (int i = 0; i < size; i++) {
+ lst.add(List.of(cs.getOrdinate(i, 0), cs.getOrdinate(i, 1)));
+ }
+ } break;
+ case 3 : {
+ for (int i = 0; i < size; i++) {
+ lst.add(List.of(cs.getOrdinate(i, 0), cs.getOrdinate(i, 1), cs.getOrdinate(i, 2)));
+ }
+ } break;
+ case 4 : {
+ for (int i = 0; i < size; i++) {
+ lst.add(List.of(cs.getOrdinate(i, 0), cs.getOrdinate(i, 1), cs.getOrdinate(i, 2), cs.getOrdinate(i, 3)));
+ }
+ } break;
+ default: throw new DataStoreException("Unexpected coordinate sequence dimension " + dim);
+ }
+ return lst;
+ }
+
- private static String getTypeName(FeatureType type) {
++ private static String getTypeName(DefaultFeatureType type) {
+ return type.getName().toString();
+ }
+
+ /**
+ * Returns the 'coordRefSys' value to use for the given feature type: a plain CRS
+ * identifier URI {@link String}, per the common encoding used by real JSON-FG producers
+ * (see JSON-FG version 1.0.0, {@code coordrefsys.json}).
+ */
- private static Object getCoordRefSys(FeatureType ft) {
++ private static Object getCoordRefSys(DefaultFeatureType ft) {
+ final CoordinateReferenceSystem crs = getCRS(ft);
+ return getCoordRefSys(crs);
+ }
+
+ private static Object getCoordRefSys(CoordinateReferenceSystem crs) {
+ if (crs == null) return null;
+ return IdentifiedObjects.getIdentifierOrName(crs);
+ }
+
+
+ /**
+ * Extract the coordinate reference system associated to the primary geometry
+ * of input data type.
+ *
+ * @implNote
- * Primary geometry is determined using {@link #getDefaultGeometry(org.opengis.feature.FeatureType) }.
++ * Primary geometry is determined using {@link #getDefaultGeometry(DefaultFeatureType)}.
+ *
+ * @param type The data type to extract reference system from.
+ * @return The CRS associated to the default geometry of this data type, or
+ * a null value if we cannot determine what is the primary geometry of the
+ * data type. Note that a null value is also returned if a geometry property
+ * is found, but no CRS characteristics is associated with it.
+ */
- private static CoordinateReferenceSystem getCRS(FeatureType type){
++ private static CoordinateReferenceSystem getCRS(DefaultFeatureType type){
+ try {
+ return getCRS(getDefaultGeometry(type));
+ } catch (IllegalArgumentException|IllegalStateException ex) {
+ //no default geometry property
+ return null;
+ }
+ }
+
+ /**
+ * Extract CRS characteristic if it exist.
+ *
+ * @param type
+ * @return CoordinateReferenceSystem or null
+ */
- private static CoordinateReferenceSystem getCRS(PropertyType type){
++ private static CoordinateReferenceSystem getCRS(AbstractIdentifiedType type){
+ return getCharacteristicValue(type, AttributeConvention.CRS, null);
+ }
+
+ /**
+ * Extract characteristic value if it exist.
+ *
+ * @param <T> expected value class
+ * @param type base type to search in
+ * @param charName characteristic name
+ * @param defaulValue default value if characteristic is missing or null.
+ * @return characteristic value or default value is not found
+ */
- private static <T> T getCharacteristicValue(PropertyType type, String charName, T defaulValue){
- while(type instanceof Operation){
- type = (PropertyType) ((Operation)type).getResult();
++ private static <T> T getCharacteristicValue(AbstractIdentifiedType type, String charName, T defaulValue){
++ while(type instanceof AbstractOperation){
++ type = (AbstractIdentifiedType) ((AbstractOperation)type).getResult();
+ }
- if(type instanceof AttributeType){
- final AttributeType at = (AttributeType) ((AttributeType)type).characteristics().get(charName);
++ if(type instanceof DefaultAttributeType){
++ final DefaultAttributeType at = (DefaultAttributeType) ((DefaultAttributeType)type).characteristics().get(charName);
+ if(at!=null){
+ T val = (T) at.getDefaultValue();
+ return val==null ? defaulValue : val;
+ }
+ }
+ return defaulValue;
+ }
+
+ /**
+ * Search for the main geometric property in the given type. We'll search
+ * for an SIS convention first (see
+ * {@link AttributeConvention#GEOMETRY_PROPERTY}. If no convention is set on
+ * the input type, we'll check if it contains a single geometric property.
+ * If it's the case, we return it. Otherwise (no or multiple geometries), we
+ * throw an exception.
+ *
+ * @param type The data type to search into.
+ * @return The main geometric property we've found.
- * @throws PropertyNotFoundException If no geometric property is available
++ * @throws IllegalArgumentException If no geometric property is available
+ * in the given type.
+ * @throws IllegalStateException If no convention is set (see
+ * {@link AttributeConvention#GEOMETRY_PROPERTY}), and we've found more than
+ * one geometry.
+ */
- private static PropertyType getDefaultGeometry(final FeatureType type) throws PropertyNotFoundException, IllegalStateException {
- PropertyType geometry;
++ private static AbstractIdentifiedType getDefaultGeometry(final DefaultFeatureType type) throws IllegalArgumentException, IllegalStateException {
++ AbstractIdentifiedType geometry;
+ try {
+ geometry = type.getProperty(AttributeConvention.GEOMETRY);
- } catch (PropertyNotFoundException e) {
++ } catch (IllegalArgumentException e) {
+ try {
+ geometry = searchForGeometry(type);
+ } catch (RuntimeException e2) {
+ e2.addSuppressed(e);
+ throw e2;
+ }
+ }
+ return geometry;
+ }
+
+ /**
+ * Search for a geometric attribute outside SIS conventions. More accurately,
+ * we expect the given type to have a single geometry attribute. If many are
+ * found, an exception is thrown.
+ *
+ * @param type The data type to search into.
+ * @return The only geometric property we've found.
- * @throws PropertyNotFoundException If no geometric property is available in
++ * @throws IllegalArgumentException If no geometric property is available in
+ * the given type.
+ * @throws IllegalStateException If we've found more than one geometry.
+ */
- private static PropertyType searchForGeometry(final FeatureType type) throws PropertyNotFoundException, IllegalStateException {
- final Predicate<IdentifiedType> isNotConvention = p -> !AttributeConvention.contains(p.getName());
- final List<? extends PropertyType> geometries = type.getProperties(true).stream()
++ private static AbstractIdentifiedType searchForGeometry(final DefaultFeatureType type) throws IllegalArgumentException, IllegalStateException {
++ final Predicate<AbstractIdentifiedType> isNotConvention = p -> !AttributeConvention.contains(p.getName());
++ final List<? extends AbstractIdentifiedType> geometries = type.getProperties(true).stream()
+ .filter(isNotConvention)
+ .filter(AttributeConvention::isGeometryAttribute)
+ .collect(Collectors.toList());
+
+ if (geometries.size() < 1) {
- throw new PropertyNotFoundException("No geometric property can be found outside of sis convention.");
++ throw new IllegalArgumentException("No geometric property can be found outside of sis convention.");
+ } else if (geometries.size() > 1) {
+ throw new IllegalStateException("Multiple geometries found. We don't know which one to select.");
+ } else {
+ return geometries.get(0);
+ }
+ }
+
+ }
diff --cc netbeans-project/ivy.xml
index 9e591bf630,4e265323ba..9be4d52407
--- a/netbeans-project/ivy.xml
+++ b/netbeans-project/ivy.xml
@@@ -39,5 -38,10 +39,8 @@@
<dependency org="gov.nist.math" name="jama" rev="1.0.3"/>
<dependency org="net.sf.geographiclib" name="GeographicLib-Java" rev="2.0"/>
<dependency org="org.xerial" name="sqlite-jdbc" rev="3.45.1.0"/>
- <dependency org="org.xerial" name="sqlite-jdbc" rev="3.45.1.0"/>
- <dependency org="org.xerial" name="sqlite-jdbc" rev="3.45.1.0"/>
+ <dependency org="com.fasterxml.jackson.core" name="jackson-core" rev="2.22.1"/>
+ <dependency org="com.fasterxml.jackson.core" name="jackson-annotations" rev="2.22"/>
+ <dependency org="com.fasterxml.jackson.core" name="jackson-databind" rev="2.22.1"/>
</dependencies>
</ivy-module>