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/08/18 14:44:19 UTC
[sis] 03/03: Merge branch 'geoapi-4.0' into geoapi-3.1. This merge modularizes the Apache SIS project (JPMS) and migrates the build system from Maven to Gradle.
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-3.1
in repository https://gitbox.apache.org/repos/asf/sis.git
commit 8474e339bcab8574640c33bc02724f9595b25821
Merge: e46d2afe80 a4b030f6f5
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Fri Aug 18 16:41:51 2023 +0200
Merge branch 'geoapi-4.0' into geoapi-3.1.
This merge modularizes the Apache SIS project (JPMS)
and migrates the build system from Maven to Gradle.
https://github.com/apache/sis/pull/37
https://issues.apache.org/jira/browse/SIS-582
.gitignore | 12 +-
NOTICE | 8 +-
application/pom.xml | 137 -
application/sis-console/pom.xml | 151 -
.../main/java/org/apache/sis/console/Command.java | 285 --
.../java/org/apache/sis/console/CommandRunner.java | 352 ---
.../org.apache.sis.setup.InstallationResources | 3 -
application/sis-javafx/doc/readme.txt | 17 -
application/sis-javafx/pom.xml | 304 --
application/sis-javafx/src/main/artifact/LICENSE | 1 -
application/sis-javafx/src/main/artifact/NOTICE | 1 -
application/sis-javafx/src/main/artifact/bin/sis | 30 -
.../sis-javafx/src/main/artifact/bin/sis.bat | 27 -
application/sis-javafx/src/main/artifact/bin/sisfx | 45 -
.../sis-javafx/src/main/artifact/bin/sisfx.bat | 36 -
.../org/apache/sis/internal/gui/Resources.java | 585 ----
.../apache/sis/internal/gui/Resources.properties | 98 -
.../sis/internal/gui/Resources_fr.properties | 103 -
.../org/apache/sis/internal/setup/FXFinder.java | 439 ---
.../org.apache.sis.setup.InstallationResources | 3 -
application/sis-openoffice/pom.xml | 184 --
.../org/apache/sis/openoffice/Registration.java | 115 -
.../org/apache/sis/openoffice/XReferencing.java | 145 -
.../org/apache/sis/openoffice/package-info.java | 31 -
.../src/main/unopkg/build-instruction.html | 119 -
application/sis-webapp/pom.xml | 57 -
.../org/apache/sis/services/OSGiActivator.java | 87 -
.../src/main/webapp/META-INF/context.xml | 26 -
buildSrc/build.gradle.kts | 87 +
.../org/apache/sis/buildtools/book/Assembler.java | 568 ++++
.../apache/sis/buildtools/book/BookException.java | 37 +
.../org/apache/sis/buildtools/book/Characters.java | 49 +
.../apache/sis/buildtools/book/CodeColorizer.java | 414 +++
.../org/apache/sis/buildtools}/book/GEOAPI.lst | 0
.../main/org/apache/sis/buildtools}/book/OGC.lst | 0
.../main/org/apache/sis/buildtools}/book/SIS.lst | 0
.../org/apache/sis/buildtools}/book/XML_PREFIX.lst | 0
.../apache/sis/buildtools/book/package-info.java | 55 +
.../org/apache/sis/buildtools/doclet/Doclet.java | 139 +
.../org/apache/sis/buildtools/doclet/Include.java | 129 +
.../org/apache/sis/buildtools/doclet/Rewriter.java | 247 ++
.../org/apache/sis/buildtools/doclet/Taglet.java | 192 ++
.../apache/sis/buildtools/doclet/package-info.java | 27 +
.../apache/sis/buildtools/gradle/Assembler.java | 131 +
.../apache/sis/buildtools/gradle/BuildHelper.java | 180 ++
.../apache/sis/buildtools/gradle/Conventions.java | 192 ++
.../apache/sis/buildtools/gradle/Dependency.java | 271 ++
.../apache/sis/buildtools/gradle/JavaMaker.java | 118 +
.../sis/buildtools/gradle/ModularCompilation.java | 283 ++
.../apache/sis/buildtools/gradle/ModularJAR.java | 176 ++
.../sis/buildtools/gradle/ModularJavadoc.java | 200 ++
.../sis/buildtools/gradle/ModularPublishing.java | 79 +
.../apache/sis/buildtools/gradle/ModularTest.java | 260 ++
.../sis/buildtools/gradle/SISBuildException.java | 37 +
.../org/apache/sis/buildtools/gradle/UnoPkg.java | 215 ++
.../apache/sis/buildtools/gradle/ZipWriter.java | 286 ++
.../apache/sis/buildtools/gradle/package-info.java | 30 +
.../org/apache/sis/buildtools/maven/Element.java | 73 +
.../org/apache/sis/buildtools/maven/Generator.java | 239 ++
.../apache/sis/buildtools/maven/package-info.java | 30 +
.../sis/buildtools/maven/workaround/Argument.java | 100 +
.../maven/workaround/ProxyGenerator.java | 279 ++
.../buildtools/maven/workaround/package-info.java | 38 +
.../resources/IndexedResourceCompiler.java | 792 +++++
.../sis/buildtools/resources/package-info.java | 26 +
.../resources/IndexedResourceCompilerTest.java | 65 +
cloud/pom.xml | 122 -
cloud/sis-cloud-aws/pom.xml | 97 -
.../sis/cloud/aws/internal/Resources.properties | 29 -
.../sis/cloud/aws/internal/Resources_fr.properties | 34 -
.../services/java.nio.file.spi.FileSystemProvider | 1 -
core/pom.xml | 199 --
core/sis-build-helper/pom.xml | 150 -
.../src/main/ant/prepare-release.xml | 44 -
.../org/apache/sis/internal/book/Assembler.java | 568 ----
.../apache/sis/internal/book/BookException.java | 37 -
.../org/apache/sis/internal/book/Characters.java | 49 -
.../apache/sis/internal/book/CodeColorizer.java | 414 ---
.../org/apache/sis/internal/book/package-info.java | 55 -
.../org/apache/sis/internal/doclet/Doclet.java | 205 --
.../org/apache/sis/internal/doclet/Include.java | 129 -
.../org/apache/sis/internal/doclet/Rewriter.java | 250 --
.../org/apache/sis/internal/doclet/Taglet.java | 192 --
.../apache/sis/internal/doclet/package-info.java | 27 -
.../org/apache/sis/internal/maven/Assembler.java | 270 --
.../org/apache/sis/internal/maven/Filenames.java | 111 -
.../apache/sis/internal/maven/JarCollector.java | 282 --
.../apache/sis/internal/maven/package-info.java | 33 -
.../org/apache/sis/internal/unopkg/JavaMaker.java | 148 -
.../org/apache/sis/internal/unopkg/UnoPkg.java | 295 --
.../apache/sis/internal/unopkg/package-info.java | 87 -
.../util/resources/IndexedResourceCompiler.java | 663 ----
.../util/resources/ResourceCompilerException.java | 48 -
.../sis/util/resources/ResourceCompilerMojo.java | 283 --
.../org/apache/sis/util/resources/package-info.txt | 2 -
.../src/main/javadoc/overview.html | 32 -
.../META-INF/m2e/lifecycle-mapping-metadata.xml | 17 -
.../util/resources/ResourceCompilerMojoTest.java | 51 -
core/sis-cql/pom.xml | 145 -
.../main/antlr4/org/apache/sis/internal/cql/CQL.g4 | 298 --
core/sis-feature/pom.xml | 190 --
.../org/apache/sis/feature/AbstractAttribute.java | 504 ---
.../apache/sis/feature/DefaultAttributeType.java | 371 ---
.../org/apache/sis/feature/DefaultFeatureType.java | 945 ------
.../apache/sis/feature/builder/TypeBuilder.java | 576 ----
.../apache/sis/filter/DefaultFilterFactory.java | 1144 -------
.../sis/internal/coverage/CompoundTransform.java | 216 --
.../org/apache/sis/internal/feature/Resources.java | 679 ----
.../sis/internal/feature/Resources.properties | 109 -
.../sis/internal/feature/Resources_fr.properties | 114 -
.../internal/filter/sqlmm/FunctionWithSRID.java | 235 --
.../java/org/apache/sis/feature/Assertions.java | 206 --
core/sis-metadata/pom.xml | 189 --
.../sis/internal/jaxb/AdapterReplacement.java | 73 -
.../apache/sis/internal/jaxb/TypeRegistration.java | 267 --
.../sis/internal/jaxb/geometry/ObjectFactory.java | 105 -
.../sis/internal/jaxb/gml/SC_VerticalCRS.java | 142 -
.../sis/internal/metadata/MetadataTypes.java | 103 -
.../sis/internal/metadata/ReferencingServices.java | 306 --
.../apache/sis/internal/metadata/Resources.java | 216 --
.../sis/internal/metadata/Resources.properties | 30 -
.../sis/internal/metadata/Resources_fr.properties | 35 -
.../sis/internal/metadata/ServicesForUtility.java | 170 -
.../sis/internal/metadata/TemporalUtilities.java | 146 -
.../sis/internal/metadata/sql/Initializer.java | 470 ---
.../sis/internal/metadata/sql/LocalDataSource.java | 457 ---
.../sis/internal/simple/CitationConstant.java | 242 --
.../org/apache/sis/internal/xml/XmlUtilities.java | 336 --
.../org/apache/sis/metadata/MetadataStandard.java | 1108 -------
.../org/apache/sis/metadata/TreeTableView.java | 221 --
.../sis/metadata/iso/extent/DefaultExtent.java | 392 ---
.../iso/extent/DefaultGeographicBoundingBox.java | 789 -----
.../iso/extent/DefaultSpatialTemporalExtent.java | 230 --
.../metadata/iso/extent/DefaultTemporalExtent.java | 286 --
.../metadata/iso/extent/DefaultVerticalExtent.java | 377 ---
.../apache/sis/metadata/iso/extent/Extents.java | 777 -----
.../apache/sis/metadata/sql/MetadataSource.java | 1284 --------
.../org/apache/sis/util/iso/DefaultRecordType.java | 503 ---
.../org/apache/sis/util/iso/RecordDefinition.java | 268 --
.../org/apache/sis/xml/TransformingReader.java | 427 ---
.../src/main/java/org/apache/sis/xml/XML.java | 710 -----
core/sis-metadata/src/main/javadoc/overview.html | 32 -
.../org.apache.sis.internal.jaxb.TypeRegistration | 1 -
.../org.apache.sis.internal.util.MetadataServices | 1 -
.../META-INF/services/org.opengis.util.NameFactory | 3 -
.../org/apache/sis/metadata/sql/Contents.sql | 100 -
.../sis/internal/metadata/AxisDirectionsTest.txt | 3 -
.../java/org/apache/sis/metadata/Assertions.java | 228 --
.../apache/sis/metadata/MetadataStandardTest.java | 373 ---
.../org/apache/sis/metadata/iso/APIVerifier.java | 247 --
.../sis/metadata/iso/DefaultMetadataTest.java | 291 --
.../sis/metadata/iso/extent/ExtentsTest.java | 214 --
.../sis/metadata/sql/MetadataFallbackVerifier.java | 144 -
.../java/org/apache/sis/test/sql/TestDatabase.java | 311 --
core/sis-portrayal/pom.xml | 151 -
core/sis-referencing-by-identifiers/pom.xml | 154 -
.../apache/sis/internal/gazetteer/Resources.java | 301 --
.../sis/internal/gazetteer/Resources.properties | 43 -
.../sis/internal/gazetteer/Resources_fr.properties | 48 -
.../referencing/gazetteer/GazetteerFactory.java | 105 -
core/sis-referencing/pom.xml | 215 --
.../org/apache/sis/geometry/CoordinateFormat.java | 1864 -----------
.../internal/jaxb/referencing/SC_VerticalCRS.java | 89 -
.../sis/internal/referencing/DatabaseListener.java | 72 -
.../sis/internal/referencing/ReferencingTypes.java | 75 -
.../apache/sis/internal/referencing/Resources.java | 795 -----
.../sis/internal/referencing/Resources.properties | 132 -
.../internal/referencing/Resources_fr.properties | 137 -
.../internal/referencing/ServicesForMetadata.java | 537 ----
.../java/org/apache/sis/io/wkt/WKTDictionary.java | 1124 -------
.../org/apache/sis/parameter/TensorParameters.java | 840 -----
.../apache/sis/referencing/AuthorityFactories.java | 251 --
.../main/java/org/apache/sis/referencing/CRS.java | 1489 ---------
.../java/org/apache/sis/referencing/CommonCRS.java | 2052 ------------
.../apache/sis/referencing/NamedIdentifier.java | 572 ----
.../sis/referencing/crs/DefaultCompoundCRS.java | 661 ----
.../sis/referencing/crs/DefaultTemporalCRS.java | 525 ----
.../referencing/factory/GeodeticObjectFactory.java | 1727 ----------
.../referencing/factory/sql/EPSGDataAccess.java | 3320 --------------------
.../sis/referencing/factory/sql/EPSGFactory.java | 544 ----
.../sis/referencing/factory/sql/EPSGInstaller.java | 311 --
.../factory/sql/InstallationScriptProvider.java | 381 ---
.../sis/referencing/factory/sql/package-info.java | 92 -
.../operation/AbstractCoordinateOperation.java | 1204 -------
.../referencing/operation/SubOperationInfo.java | 383 ---
.../referencing/operation/matrix/MatrixSIS.java | 815 -----
.../transform/AbridgedMolodenskyTransform2D.java | 108 -
.../operation/transform/DatumShiftTransform.java | 338 --
.../transform/DefaultMathTransformFactory.java | 1784 -----------
.../transform/EllipsoidToCentricTransform.java | 1045 ------
.../operation/transform/MathTransformProvider.java | 124 -
.../sis-referencing/src/main/javadoc/overview.html | 32 -
...org.apache.sis.internal.jaxb.AdapterReplacement | 3 -
.../org.apache.sis.internal.jaxb.TypeRegistration | 3 -
...pache.sis.internal.metadata.ReferencingServices | 1 -
...rg.apache.sis.internal.metadata.sql.Initializer | 3 -
...org.opengis.referencing.crs.CRSAuthorityFactory | 4 -
.../org.opengis.referencing.crs.CRSFactory | 3 -
.../org.opengis.referencing.cs.CSAuthorityFactory | 3 -
.../services/org.opengis.referencing.cs.CSFactory | 3 -
...opengis.referencing.datum.DatumAuthorityFactory | 3 -
.../org.opengis.referencing.datum.DatumFactory | 3 -
...g.operation.CoordinateOperationAuthorityFactory | 3 -
...eferencing.operation.CoordinateOperationFactory | 3 -
...ngis.referencing.operation.MathTransformFactory | 3 -
...g.opengis.referencing.operation.OperationMethod | 80 -
.../java/org/apache/sis/io/wkt/WKTParserTest.java | 697 ----
.../org/apache/sis/referencing/Assertions.java | 538 ----
.../transform/DefaultMathTransformFactoryTest.java | 402 ---
...g.opengis.referencing.operation.OperationMethod | 3 -
core/sis-utility/pom.xml | 139 -
.../sis/internal/converter/ConverterRegistry.java | 608 ----
.../sis/internal/converter/NumberConverter.java | 186 --
.../sis/internal/converter/SystemRegistry.java | 231 --
.../sis/internal/converter/package-info.java | 45 -
.../org/apache/sis/internal/system/Loggers.java | 224 --
.../sis/internal/system/OptionalDependency.java | 89 -
.../org/apache/sis/internal/system/Reflect.java | 106 -
.../org/apache/sis/internal/system/Shutdown.java | 208 --
.../sis/internal/system/SupervisorMBean.java | 56 -
.../apache/sis/internal/system/SystemListener.java | 154 -
.../org/apache/sis/internal/system/Threads.java | 103 -
.../org/apache/sis/internal/util/CodeLists.java | 162 -
.../apache/sis/internal/util/MetadataServices.java | 208 --
.../java/org/apache/sis/io/CompoundFormat.java | 544 ----
.../org/apache/sis/measure/LinearConverter.java | 470 ---
.../src/main/java/org/apache/sis/setup/About.java | 811 -----
.../java/org/apache/sis/setup/Configuration.java | 150 -
.../apache/sis/setup/InstallationResources.java | 223 --
.../sis/util/DefaultInternationalString.java | 405 ---
.../apache/sis/util/SimpleInternationalString.java | 129 -
.../org/apache/sis/util/collection/RangeSet.java | 1653 ----------
.../resources/ResourceInternationalString.java | 196 --
core/sis-utility/src/main/javadoc/overview.html | 47 -
.../services/javax.measure.spi.ServiceProvider | 3 -
.../services/org.apache.sis.util.ObjectConverter | 45 -
endorsed/build.gradle.kts | 392 +++
.../services/java.nio.file.spi.FileSystemProvider | 4 +
.../org.apache.sis.cloud.aws/main/module-info.java | 38 +
.../apache/sis/cloud/aws/internal/Resources.java | 0
.../sis/cloud/aws/internal/Resources.properties | 29 +
.../sis/cloud/aws/internal/Resources_en.java | 0
.../sis/cloud/aws/internal/Resources_fr.java | 0
.../sis/cloud/aws/internal/Resources_fr.properties | 34 +
.../sis/cloud/aws/internal/package-info.java | 0
.../org/apache/sis/cloud/aws/s3/BucketStore.java | 0
.../apache/sis/cloud/aws/s3/CachedByteChannel.java | 0
.../apache/sis/cloud/aws/s3/ClientFileSystem.java | 0
.../org/apache/sis/cloud/aws/s3/DerivedList.java | 0
.../org/apache/sis/cloud/aws/s3/FileService.java | 0
.../main}/org/apache/sis/cloud/aws/s3/KeyPath.java | 0
.../apache/sis/cloud/aws/s3/KeyPathMatcher.java | 0
.../apache/sis/cloud/aws/s3/ObjectAttributes.java | 0
.../org/apache/sis/cloud/aws/s3/PathIterator.java | 0
.../org/apache/sis/cloud/aws/s3/package-info.java | 0
.../sis/cloud/aws/s3/ClientFileSystemTest.java | 0
.../sis/cloud/aws/s3/KeyPathMatcherTest.java | 0
.../org/apache/sis/cloud/aws/s3/KeyPathTest.java | 0
.../org.apache.sis.setup.InstallationResources | 4 +
.../org.apache.sis.console/main/module-info.java | 37 +
.../main}/org/apache/sis/console/AboutCommand.java | 0
.../main}/org/apache/sis/console/CRSCommand.java | 0
.../main/org/apache/sis/console/Command.java | 285 ++
.../main/org/apache/sis/console/CommandRunner.java | 352 +++
.../org/apache/sis/console/Commands.properties | 0
.../org/apache/sis/console/Commands_en.properties | 0
.../org/apache/sis/console/Commands_fr.properties | 0
.../apache/sis/console/FormattedOutputCommand.java | 0
.../main}/org/apache/sis/console/HelpCommand.java | 0
.../org/apache/sis/console/IdentifierCommand.java | 0
.../apache/sis/console/IdentifierState.properties | 0
.../sis/console/IdentifierState_en.properties | 0
.../sis/console/IdentifierState_fr.properties | 0
.../sis/console/InvalidCommandException.java | 0
.../apache/sis/console/InvalidOptionException.java | 0
.../org/apache/sis/console/Messages.properties | 0
.../org/apache/sis/console/Messages_en.properties | 0
.../org/apache/sis/console/Messages_fr.properties | 0
.../org/apache/sis/console/MetadataCommand.java | 0
.../org/apache/sis/console/MimeTypeCommand.java | 0
.../main}/org/apache/sis/console/Option.java | 0
.../org/apache/sis/console/Options.properties | 0
.../org/apache/sis/console/Options_en.properties | 0
.../org/apache/sis/console/Options_fr.properties | 0
.../main}/org/apache/sis/console/OutputFormat.java | 0
.../apache/sis/console/ResourcesDownloader.java | 0
.../org/apache/sis/console/TransformCommand.java | 0
.../main}/org/apache/sis/console/package-info.java | 0
.../org/apache/sis/console/AboutCommandTest.java | 0
.../org/apache/sis/console/CRSCommandTest.java | 0
.../org/apache/sis/console/CommandRunnerTest.java | 0
.../org/apache/sis/console/HelpCommandTest.java | 0
.../apache/sis/console/MetadataCommandTest.java | 0
.../apache/sis/console/MimeTypeCommandTest.java | 0
.../org.apache.sis.feature/main/module-info.java | 80 +
.../org/apache/sis/coverage/BandedCoverage.java | 0
.../main}/org/apache/sis/coverage/Category.java | 0
.../org/apache/sis/coverage/CategoryList.java | 0
.../org/apache/sis/coverage/ConvertedCategory.java | 0
.../org/apache/sis/coverage/ConvertedRange.java | 0
.../org/apache/sis/coverage/CoverageCombiner.java | 0
.../coverage/IllegalSampleDimensionException.java | 0
.../coverage/MismatchedCoverageRangeException.java | 0
.../org/apache/sis/coverage/RegionOfInterest.java | 0
.../org/apache/sis/coverage/SampleDimension.java | 0
.../org/apache/sis/coverage/SampleRangeFormat.java | 0
.../coverage/SubspaceNotSpecifiedException.java | 0
.../main}/org/apache/sis/coverage/ToNaN.java | 0
.../coverage/grid/BandAggregateGridCoverage.java | 0
.../sis/coverage/grid/BufferedGridCoverage.java | 0
.../sis/coverage/grid/ConvertedGridCoverage.java | 0
.../coverage/grid/CoordinateOperationFinder.java | 0
.../apache/sis/coverage/grid/DefaultEvaluator.java | 0
.../sis/coverage/grid/DerivedGridCoverage.java | 0
.../apache/sis/coverage/grid/DimensionReducer.java | 0
.../sis/coverage/grid/DimensionalityReduction.java | 0
.../sis/coverage/grid/DisjointExtentException.java | 0
.../apache/sis/coverage/grid/DomainLinearizer.java | 0
.../apache/sis/coverage/grid/EvaluatorWrapper.java | 0
.../coverage/grid/FractionalGridCoordinates.java | 0
.../apache/sis/coverage/grid/GridClippingMode.java | 0
.../sis/coverage/grid/GridCoordinatesView.java | 0
.../org/apache/sis/coverage/grid/GridCoverage.java | 0
.../apache/sis/coverage/grid/GridCoverage2D.java | 0
.../sis/coverage/grid/GridCoverageBuilder.java | 0
.../sis/coverage/grid/GridCoverageProcessor.java | 0
.../apache/sis/coverage/grid/GridDerivation.java | 0
.../org/apache/sis/coverage/grid/GridExtent.java | 0
.../apache/sis/coverage/grid/GridExtentCRS.java | 0
.../org/apache/sis/coverage/grid/GridGeometry.java | 0
.../apache/sis/coverage/grid/GridOrientation.java | 0
.../apache/sis/coverage/grid/GridRoundingMode.java | 0
.../grid/IllegalGridGeometryException.java | 0
.../apache/sis/coverage/grid/ImageRenderer.java | 0
.../grid/IncompleteGridGeometryException.java | 0
.../apache/sis/coverage/grid/PixelTranslation.java | 0
.../sis/coverage/grid/ReducedGridCoverage.java | 0
.../sis/coverage/grid/ResampledGridCoverage.java | 0
.../apache/sis/coverage/grid/ReshapedImage.java | 0
.../apache/sis/coverage/grid/SliceGeometry.java | 0
.../sis/coverage/grid/TranslatedGridCoverage.java | 0
.../org/apache/sis/coverage/grid/package-info.java | 0
.../org/apache/sis/coverage/package-info.java | 0
.../apache/sis/feature/AbstractAssociation.java | 0
.../org/apache/sis/feature/AbstractAttribute.java | 504 +++
.../org/apache/sis/feature/AbstractFeature.java | 0
.../apache/sis/feature/AbstractIdentifiedType.java | 0
.../org/apache/sis/feature/AbstractOperation.java | 0
.../org/apache/sis/feature/AssociationView.java | 0
.../org/apache/sis/feature/AttributeView.java | 0
.../org/apache/sis/feature/CharacteristicMap.java | 0
.../apache/sis/feature/CharacteristicTypeMap.java | 0
.../org/apache/sis/feature/CommonParentFinder.java | 0
.../apache/sis/feature/DefaultAssociationRole.java | 0
.../apache/sis/feature/DefaultAttributeType.java | 371 +++
.../org/apache/sis/feature/DefaultFeatureType.java | 945 ++++++
.../main}/org/apache/sis/feature/DenseFeature.java | 0
.../org/apache/sis/feature/EnvelopeOperation.java | 0
.../apache/sis/feature/ExpressionOperation.java | 0
.../org/apache/sis/feature/FeatureFormat.java | 0
.../sis/feature/FeatureOperationException.java | 0
.../org/apache/sis/feature/FeatureOperations.java | 0
.../main}/org/apache/sis/feature/Features.java | 0
.../main}/org/apache/sis/feature/Field.java | 0
.../main}/org/apache/sis/feature/FieldType.java | 0
.../sis/feature/FoliationRepresentation.java | 0
.../sis/feature/GroupAsPolylineOperation.java | 0
.../sis/feature/InvalidFeatureException.java | 0
.../org/apache/sis/feature/LinkOperation.java | 0
.../apache/sis/feature/MultiValuedAssociation.java | 0
.../apache/sis/feature/MultiValuedAttribute.java | 0
.../org/apache/sis/feature/NamedFeatureType.java | 0
.../org/apache/sis/feature/OperationResult.java | 0
.../org/apache/sis/feature/PropertySingleton.java | 0
.../main}/org/apache/sis/feature/PropertyView.java | 0
.../apache/sis/feature/SingletonAssociation.java | 0
.../org/apache/sis/feature/SingletonAttribute.java | 0
.../org/apache/sis/feature/SparseFeature.java | 0
.../apache/sis/feature/StringJoinOperation.java | 0
.../main}/org/apache/sis/feature/Validator.java | 0
.../main}/org/apache/sis/feature/benchmarks.html | 0
.../feature/builder/AssociationRoleBuilder.java | 0
.../apache/sis/feature/builder/AttributeRole.java | 0
.../sis/feature/builder/AttributeTypeBuilder.java | 0
.../feature/builder/CharacteristicTypeBuilder.java | 0
.../sis/feature/builder/FeatureTypeBuilder.java | 0
.../sis/feature/builder/OperationWrapper.java | 0
.../sis/feature/builder/PropertyTypeBuilder.java | 0
.../apache/sis/feature/builder/RemoveOnlyList.java | 0
.../apache/sis/feature/builder/TypeBuilder.java | 576 ++++
.../apache/sis/feature/builder/package-info.java | 0
.../main}/org/apache/sis/feature/package-info.java | 0
.../org/apache/sis/filter/ArithmeticFunction.java | 0
.../org/apache/sis/filter/AssociationValue.java | 0
.../org/apache/sis/filter/BinaryFunction.java | 0
.../apache/sis/filter/BinaryGeometryFilter.java | 0
.../org/apache/sis/filter/BinarySpatialFilter.java | 0
.../main}/org/apache/sis/filter/Capabilities.java | 0
.../org/apache/sis/filter/ComparisonFilter.java | 0
.../org/apache/sis/filter/ConvertFunction.java | 0
.../apache/sis/filter/DefaultFilterFactory.java | 1144 +++++++
.../org/apache/sis/filter/DefaultSortProperty.java | 0
.../org/apache/sis/filter/DistanceFilter.java | 0
.../org/apache/sis/filter/IdentifierFilter.java | 0
.../org/apache/sis/filter/LeafExpression.java | 0
.../main}/org/apache/sis/filter/LikeFilter.java | 0
.../main}/org/apache/sis/filter/LogicalFilter.java | 0
.../main}/org/apache/sis/filter/Optimization.java | 0
.../main}/org/apache/sis/filter/PropertyValue.java | 0
.../org/apache/sis/filter/TemporalFilter.java | 0
.../main}/org/apache/sis/filter/UnaryFunction.java | 0
.../main}/org/apache/sis/filter/package-info.java | 0
.../main}/org/apache/sis/image/AnnotatedImage.java | 0
.../org/apache/sis/image/BandAggregateImage.java | 0
.../org/apache/sis/image/BandSelectImage.java | 0
.../org/apache/sis/image/BandSharedRaster.java | 0
.../main}/org/apache/sis/image/BandSharing.java | 0
.../main}/org/apache/sis/image/BandedIterator.java | 0
.../apache/sis/image/BandedSampleConverter.java | 0
.../main}/org/apache/sis/image/Colorizer.java | 0
.../main}/org/apache/sis/image/ComputedImage.java | 0
.../main}/org/apache/sis/image/ComputedTiles.java | 0
.../main}/org/apache/sis/image/DataType.java | 0
.../main}/org/apache/sis/image/ErrorAction.java | 0
.../main}/org/apache/sis/image/ErrorHandler.java | 0
.../main}/org/apache/sis/image/ImageAdapter.java | 0
.../main}/org/apache/sis/image/ImageCombiner.java | 0
.../main}/org/apache/sis/image/ImageProcessor.java | 0
.../main}/org/apache/sis/image/Interpolation.java | 0
.../org/apache/sis/image/LanczosInterpolation.java | 0
.../main}/org/apache/sis/image/MaskImage.java | 0
.../main}/org/apache/sis/image/MaskedImage.java | 0
.../org/apache/sis/image/MultiSourceImage.java | 0
.../org/apache/sis/image/MultiSourceLayout.java | 0
.../org/apache/sis/image/MultiSourcePrefetch.java | 0
.../main}/org/apache/sis/image/PixelIterator.java | 0
.../main}/org/apache/sis/image/PlanarImage.java | 0
.../sis/image/PositionalConsistencyImage.java | 0
.../org/apache/sis/image/PrefetchedImage.java | 0
.../main}/org/apache/sis/image/RecoloredImage.java | 0
.../main}/org/apache/sis/image/ResampledImage.java | 0
.../main}/org/apache/sis/image/ResamplingGrid.java | 0
.../org/apache/sis/image/SourceAlignedImage.java | 0
.../org/apache/sis/image/StatisticsCalculator.java | 0
.../main}/org/apache/sis/image/TileCache.java | 0
.../main}/org/apache/sis/image/TransferType.java | 0
.../main}/org/apache/sis/image/Transferer.java | 0
.../main}/org/apache/sis/image/UserProperties.java | 0
.../main}/org/apache/sis/image/Visualization.java | 0
.../apache/sis/image/WritableComputedImage.java | 0
.../apache/sis/image/WritablePixelIterator.java | 0
.../main}/org/apache/sis/image/package-info.java | 0
.../org/apache/sis/index/tree/NodeIterator.java | 0
.../main}/org/apache/sis/index/tree/PointTree.java | 0
.../org/apache/sis/index/tree/PointTreeNode.java | 0
.../org/apache/sis/index/tree/QuadTreeNode.java | 0
.../org/apache/sis/index/tree/package-info.java | 0
.../sis/internal/coverage/CommonDomainFinder.java | 0
.../sis/internal/coverage/CompoundTransform.java | 217 ++
.../internal/coverage/CompoundTransformOf1D.java | 0
.../sis/internal/coverage/MultiSourceArgument.java | 0
.../sis/internal/coverage/RangeArgument.java | 0
.../sis/internal/coverage/RepeatedTransform.java | 0
.../sis/internal/coverage/SampleDimensions.java | 0
.../internal/coverage/j2d/BatchComputedImage.java | 0
.../internal/coverage/j2d/ColorModelBuilder.java | 0
.../internal/coverage/j2d/ColorModelFactory.java | 0
.../sis/internal/coverage/j2d/ColorModelType.java | 0
.../sis/internal/coverage/j2d/ColorsForRange.java | 0
.../internal/coverage/j2d/DeferredProperty.java | 0
.../sis/internal/coverage/j2d/FillValues.java | 0
.../sis/internal/coverage/j2d/ImageLayout.java | 0
.../sis/internal/coverage/j2d/ImageUtilities.java | 0
.../coverage/j2d/MultiBandsIndexColorModel.java | 0
.../sis/internal/coverage/j2d/ObservableImage.java | 0
.../sis/internal/coverage/j2d/RasterFactory.java | 0
.../internal/coverage/j2d/SampleModelFactory.java | 0
.../internal/coverage/j2d/ScaledColorModel.java | 0
.../internal/coverage/j2d/ScaledColorSpace.java | 0
.../internal/coverage/j2d/TileErrorHandler.java | 0
.../sis/internal/coverage/j2d/TileOpExecutor.java | 0
.../sis/internal/coverage/j2d/TilePlaceholder.java | 0
.../sis/internal/coverage/j2d/TiledImage.java | 0
.../internal/coverage/j2d/WritableTiledImage.java | 0
.../sis/internal/coverage/j2d/package-info.java | 0
.../apache/sis/internal/coverage/package-info.java | 0
.../sis/internal/feature/AbstractGeometry.java | 0
.../sis/internal/feature/AttributeConvention.java | 0
.../sis/internal/feature/FeatureExpression.java | 0
.../sis/internal/feature/FeatureUtilities.java | 0
.../apache/sis/internal/feature/Geometries.java | 0
.../sis/internal/feature/GeometryFactories.java | 0
.../apache/sis/internal/feature/GeometryType.java | 0
.../sis/internal/feature/GeometryWithCRS.java | 0
.../sis/internal/feature/GeometryWrapper.java | 0
.../apache/sis/internal/feature/InstantList.java | 0
.../sis/internal/feature/MovingFeatures.java | 0
.../org/apache/sis/internal/feature/Resources.java | 679 ++++
.../sis/internal/feature/Resources.properties | 109 +
.../apache/sis/internal/feature/Resources_en.java | 0
.../apache/sis/internal/feature/Resources_fr.java | 0
.../sis/internal/feature/Resources_fr.properties | 114 +
.../internal/feature/SpatialOperationContext.java | 0
.../sis/internal/feature/StandardGeometries.java | 0
.../apache/sis/internal/feature/esri/Factory.java | 0
.../apache/sis/internal/feature/esri/Wrapper.java | 0
.../sis/internal/feature/esri/package-info.java | 0
.../feature/j2d/DecimatedPathIterator.java | 0
.../sis/internal/feature/j2d/DecimatedShape.java | 0
.../sis/internal/feature/j2d/EmptyShape.java | 0
.../apache/sis/internal/feature/j2d/Factory.java | 0
.../apache/sis/internal/feature/j2d/FlatShape.java | 0
.../sis/internal/feature/j2d/MultiPolylines.java | 0
.../sis/internal/feature/j2d/PathBuilder.java | 0
.../sis/internal/feature/j2d/PointWrapper.java | 0
.../apache/sis/internal/feature/j2d/Polygon.java | 0
.../apache/sis/internal/feature/j2d/Polyline.java | 0
.../sis/internal/feature/j2d/ShapeProperties.java | 0
.../sis/internal/feature/j2d/ShapeWrapper.java | 0
.../apache/sis/internal/feature/j2d/Wrapper.java | 0
.../sis/internal/feature/j2d/package-info.java | 0
.../apache/sis/internal/feature/jts/Factory.java | 0
.../sis/internal/feature/jts/FilteringContext.java | 0
.../feature/jts/GeometryCoordinateTransform.java | 0
.../internal/feature/jts/GeometryTransform.java | 0
.../org/apache/sis/internal/feature/jts/JTS.java | 0
.../feature/jts/PackedCoordinateSequence.java | 0
.../jts/PackedCoordinateSequenceFactory.java | 0
.../internal/feature/jts/PathIteratorAdapter.java | 0
.../sis/internal/feature/jts/ShapeAdapter.java | 0
.../sis/internal/feature/jts/ShapeConverter.java | 0
.../apache/sis/internal/feature/jts/Wrapper.java | 0
.../sis/internal/feature/jts/package-info.java | 0
.../apache/sis/internal/feature/package-info.java | 0
.../apache/sis/internal/filter/CopyVisitor.java | 0
.../apache/sis/internal/filter/EditVisitor.java | 0
.../apache/sis/internal/filter/FunctionNames.java | 0
.../sis/internal/filter/FunctionRegister.java | 0
.../sis/internal/filter/GeometryConverter.java | 0
.../main}/org/apache/sis/internal/filter/Node.java | 0
.../sis/internal/filter/SortByComparator.java | 0
.../org/apache/sis/internal/filter/Visitor.java | 0
.../org/apache/sis/internal/filter/XPath.java | 0
.../apache/sis/internal/filter/package-info.java | 0
.../internal/filter/sqlmm/FunctionDescription.java | 0
.../internal/filter/sqlmm/FunctionWithSRID.java | 235 ++
.../internal/filter/sqlmm/GeometryConstructor.java | 0
.../sis/internal/filter/sqlmm/GeometryParser.java | 0
.../sis/internal/filter/sqlmm/OneGeometry.java | 0
.../apache/sis/internal/filter/sqlmm/Registry.java | 0
.../apache/sis/internal/filter/sqlmm/SQLMM.java | 0
.../sis/internal/filter/sqlmm/ST_FromBinary.java | 0
.../sis/internal/filter/sqlmm/ST_FromText.java | 0
.../apache/sis/internal/filter/sqlmm/ST_Point.java | 0
.../sis/internal/filter/sqlmm/ST_Transform.java | 0
.../sis/internal/filter/sqlmm/SpatialFunction.java | 0
.../sis/internal/filter/sqlmm/TwoGeometries.java | 0
.../sis/internal/filter/sqlmm/package-info.java | 0
.../internal/processing/image/CompoundFuture.java | 0
.../internal/processing/image/TiledProcess.java | 0
.../internal/processing/image/package-info.java | 0
.../sis/internal/processing/isoline/Fragments.java | 0
.../sis/internal/processing/isoline/Isolines.java | 0
.../sis/internal/processing/isoline/Joiner.java | 0
.../internal/processing/isoline/Parallelized.java | 0
.../processing/isoline/PolylineBuffer.java | 0
.../internal/processing/isoline/PolylineStage.java | 0
.../sis/internal/processing/isoline/Result.java | 0
.../sis/internal/processing/isoline/Tracer.java | 0
.../internal/processing/isoline/package-info.java | 0
.../org/apache/sis/coverage/CategoryListTest.java | 0
.../org/apache/sis/coverage/CategoryTest.java | 0
.../apache/sis/coverage/CoverageCombinerTest.java | 0
.../apache/sis/coverage/SampleDimensionTest.java | 0
.../apache/sis/coverage/SampleRangeFormatTest.java | 0
.../grid/BandAggregateGridCoverageTest.java | 0
.../coverage/grid/BufferedGridCoverageTest.java | 0
.../coverage/grid/ConvertedGridCoverageTest.java | 0
.../coverage/grid/DimensionalityReductionTest.java | 0
.../grid/FractionalGridCoordinatesTest.java | 0
.../sis/coverage/grid/GridCoverage2DTest.java | 0
.../sis/coverage/grid/GridCoverageBuilderTest.java | 0
.../sis/coverage/grid/GridDerivationTest.java | 0
.../apache/sis/coverage/grid/GridExtentTest.java | 0
.../apache/sis/coverage/grid/GridGeometryTest.java | 0
.../sis/coverage/grid/GridOrientationTest.java | 0
.../sis/coverage/grid/PixelTranslationTest.java | 0
.../coverage/grid/ResampledGridCoverageTest.java | 0
.../sis/coverage/grid/ReshapedImageTest.java | 0
.../coverage/grid/TranslatedGridCoverageTest.java | 0
.../apache/sis/feature/AbstractFeatureTest.java | 0
.../apache/sis/feature/AbstractOperationTest.java | 0
.../test/org/apache/sis/feature/Assertions.java | 206 ++
.../apache/sis/feature/CharacteristicMapTest.java | 0
.../sis/feature/CharacteristicTypeMapTest.java | 0
.../org/apache/sis/feature/CustomAttribute.java | 0
.../sis/feature/DefaultAssociationRoleTest.java | 0
.../sis/feature/DefaultAttributeTypeTest.java | 0
.../apache/sis/feature/DefaultFeatureTypeTest.java | 0
.../org/apache/sis/feature/DenseFeatureTest.java | 0
.../apache/sis/feature/EnvelopeOperationTest.java | 0
.../org/apache/sis/feature/FeatureFormatTest.java | 0
.../apache/sis/feature/FeatureMemoryBenchmark.java | 0
.../apache/sis/feature/FeatureOperationsTest.java | 0
.../org/apache/sis/feature/FeatureTestCase.java | 0
.../test}/org/apache/sis/feature/FeaturesTest.java | 0
.../sis/feature/GroupAsPolylineOperationTest.java | 0
.../org/apache/sis/feature/LinkOperationTest.java | 0
.../sis/feature/MultiValuedAttributeTest.java | 0
.../test}/org/apache/sis/feature/NoOperation.java | 0
.../apache/sis/feature/PropertySingletonTest.java | 0
.../sis/feature/SingletonAssociationTest.java | 0
.../apache/sis/feature/SingletonAttributeTest.java | 0
.../org/apache/sis/feature/SparseFeatureTest.java | 0
.../sis/feature/StringJoinOperationTest.java | 0
.../builder/AssociationRoleBuilderTest.java | 0
.../feature/builder/AttributeTypeBuilderTest.java | 0
.../builder/CharacteristicTypeBuilderTest.java | 0
.../feature/builder/FeatureTypeBuilderTest.java | 0
.../apache/sis/filter/ArithmeticFunctionTest.java | 0
.../sis/filter/BinarySpatialFilterTestCase.java | 0
.../filter/BinarySpatialFilterUsingESRI_Test.java | 0
.../filter/BinarySpatialFilterUsingJTS_Test.java | 0
.../BinarySpatialFilterUsingJava2D_Test.java | 0
.../org/apache/sis/filter/CapabilitiesTest.java | 0
.../apache/sis/filter/ComparisonFilterTest.java | 0
.../apache/sis/filter/IdentifierFilterTest.java | 0
.../org/apache/sis/filter/LeafExpressionTest.java | 0
.../org/apache/sis/filter/LikeFilterTest.java | 0
.../org/apache/sis/filter/LogicalFilterTest.java | 0
.../test}/org/apache/sis/filter/PeriodLiteral.java | 0
.../org/apache/sis/filter/TemporalFilterTest.java | 0
.../test}/org/apache/sis/filter/XPathTest.java | 0
.../apache/sis/image/BandAggregateImageTest.java | 0
.../org/apache/sis/image/BandSelectImageTest.java | 0
.../org/apache/sis/image/BandedIteratorTest.java | 0
.../sis/image/BandedSampleConverterTest.java | 0
.../org/apache/sis/image/ComputedImageTest.java | 0
.../test}/org/apache/sis/image/DataTypeTest.java | 0
.../org/apache/sis/image/ImageCombinerTest.java | 0
.../org/apache/sis/image/ImageProcessorTest.java | 0
.../test}/org/apache/sis/image/ImageTestCase.java | 0
.../org/apache/sis/image/InterpolationTest.java | 0
.../org/apache/sis/image/LinearIteratorTest.java | 0
.../org/apache/sis/image/MaskedImageTest.java | 0
.../org/apache/sis/image/PixelIteratorTest.java | 0
.../org/apache/sis/image/PlanarImageTest.java | 0
.../org/apache/sis/image/ResampledImageTest.java | 0
.../org/apache/sis/image/ResamplingGridTest.java | 0
.../apache/sis/image/StatisticsCalculatorTest.java | 0
.../test}/org/apache/sis/image/TestViewer.java | 0
.../test}/org/apache/sis/image/TiledImageMock.java | 0
.../apache/sis/index/tree/PointTreeNodeTest.java | 0
.../org/apache/sis/index/tree/PointTreeTest.java | 0
.../sis/internal/coverage/RangeArgumentTest.java | 0
.../coverage/j2d/ColorModelBuilderTest.java | 0
.../sis/internal/coverage/j2d/ImageLayoutTest.java | 0
.../internal/coverage/j2d/ImageUtilitiesTest.java | 0
.../coverage/j2d/SampleModelFactoryTest.java | 0
.../coverage/j2d/ScaledColorSpaceTest.java | 0
.../internal/feature/AttributeConventionTest.java | 0
.../sis/internal/feature/GeometriesTestCase.java | 0
.../sis/internal/feature/GeometryTypeTest.java | 0
.../internal/feature/StandardGeometriesTest.java | 0
.../sis/internal/feature/esri/FactoryTest.java | 0
.../sis/internal/feature/j2d/FactoryTest.java | 0
.../sis/internal/feature/j2d/FlatShapeTest.java | 0
.../internal/feature/j2d/ShapePropertiesTest.java | 0
.../sis/internal/feature/jts/FactoryTest.java | 0
.../apache/sis/internal/feature/jts/JTSTest.java | 0
.../sis/internal/feature/jts/ShapeAdapterTest.java | 0
.../internal/feature/jts/ShapeConverterTest.java | 0
.../sis/internal/filter/CopyVisitorTest.java | 0
.../sis/internal/filter/FilterFactoryMock.java | 0
.../apache/sis/internal/filter/FunctionMock.java | 0
.../sis/internal/filter/FunctionNamesTest.java | 0
.../sis/internal/filter/ValueReferenceMock.java | 0
.../internal/filter/sqlmm/RegistryTestCase.java | 0
.../filter/sqlmm/RegistryUsingESRI_Test.java | 0
.../filter/sqlmm/RegistryUsingJTS_Test.java | 0
.../filter/sqlmm/RegistryUsingJava2D_Test.java | 0
.../sis/internal/filter/sqlmm/SQLMMTest.java | 0
.../internal/processing/isoline/IsolinesTest.java | 0
.../internal/processing/isoline/StepsViewer.java | 0
.../apache/sis/test/feature/FeatureComparator.java | 0
.../org/apache/sis/test/feature/package-info.java | 0
.../org.apache.sis.internal.jaxb.TypeRegistration | 4 +
.../org.apache.sis.internal.util.MetadataServices | 4 +
.../META-INF/services/org.opengis.util.NameFactory | 4 +
.../org.apache.sis.metadata/main/module-info.java | 190 ++
.../sis/internal/jaxb/AdapterReplacement.java | 73 +
.../org/apache/sis/internal/jaxb/Context.java | 0
.../apache/sis/internal/jaxb/FilterByVersion.java | 0
.../sis/internal/jaxb/FinalClassExtensions.java | 0
.../sis/internal/jaxb/IdentifierMapAdapter.java | 0
.../sis/internal/jaxb/IdentifierMapEntry.java | 0
.../sis/internal/jaxb/ModifiableIdentifierMap.java | 0
.../sis/internal/jaxb/NonMarshalledAuthority.java | 0
.../sis/internal/jaxb/SpecializedIdentifier.java | 0
.../apache/sis/internal/jaxb/TypeRegistration.java | 267 ++
.../sis/internal/jaxb/UseLegacyMetadata.java | 0
.../sis/internal/jaxb/cat/CodeListAdapter.java | 0
.../apache/sis/internal/jaxb/cat/CodeListUID.java | 0
.../apache/sis/internal/jaxb/cat/EnumAdapter.java | 0
.../apache/sis/internal/jaxb/cat/package-info.java | 0
.../sis/internal/jaxb/code/CI_DateTypeCode.java | 0
.../internal/jaxb/code/CI_OnLineFunctionCode.java | 0
.../jaxb/code/CI_PresentationFormCode.java | 0
.../apache/sis/internal/jaxb/code/CI_RoleCode.java | 0
.../internal/jaxb/code/CI_TelephoneTypeCode.java | 0
.../org/apache/sis/internal/jaxb/code/DCPList.java | 0
.../sis/internal/jaxb/code/DQM_ValueStructure.java | 0
.../jaxb/code/DQ_EvaluationMethodTypeCode.java | 0
.../internal/jaxb/code/DS_AssociationTypeCode.java | 0
.../internal/jaxb/code/DS_InitiativeTypeCode.java | 0
.../internal/jaxb/code/MD_CellGeometryCode.java | 0
.../internal/jaxb/code/MD_CharacterSetCode.java | 0
.../internal/jaxb/code/MD_ClassificationCode.java | 0
.../jaxb/code/MD_CoverageContentTypeCode.java | 0
.../sis/internal/jaxb/code/MD_DatatypeCode.java | 0
.../jaxb/code/MD_DimensionNameTypeCode.java | 0
.../jaxb/code/MD_GeometricObjectTypeCode.java | 0
.../jaxb/code/MD_ImagingConditionCode.java | 0
.../sis/internal/jaxb/code/MD_KeywordTypeCode.java | 0
.../jaxb/code/MD_MaintenanceFrequencyCode.java | 0
.../internal/jaxb/code/MD_MediumFormatCode.java | 0
.../sis/internal/jaxb/code/MD_MediumNameCode.java | 0
.../sis/internal/jaxb/code/MD_ObligationCode.java | 0
.../jaxb/code/MD_PixelOrientationCode.java | 0
.../sis/internal/jaxb/code/MD_ProgressCode.java | 0
.../sis/internal/jaxb/code/MD_RestrictionCode.java | 0
.../sis/internal/jaxb/code/MD_ScopeCode.java | 0
.../code/MD_SpatialRepresentationTypeCode.java | 0
.../internal/jaxb/code/MD_TopicCategoryCode.java | 0
.../internal/jaxb/code/MD_TopologyLevelCode.java | 0
.../sis/internal/jaxb/code/MI_BandDefinition.java | 0
.../sis/internal/jaxb/code/MI_ContextCode.java | 0
.../internal/jaxb/code/MI_GeometryTypeCode.java | 0
.../internal/jaxb/code/MI_ObjectiveTypeCode.java | 0
.../internal/jaxb/code/MI_OperationTypeCode.java | 0
.../jaxb/code/MI_PolarisationOrientationCode.java | 0
.../sis/internal/jaxb/code/MI_PriorityCode.java | 0
.../sis/internal/jaxb/code/MI_SequenceCode.java | 0
.../jaxb/code/MI_TransferFunctionTypeCode.java | 0
.../sis/internal/jaxb/code/MI_TriggerCode.java | 0
.../sis/internal/jaxb/code/SV_CouplingType.java | 0
.../internal/jaxb/code/SV_ParameterDirection.java | 0
.../sis/internal/jaxb/code/package-info.java | 0
.../sis/internal/jaxb/gco/CharSequenceAdapter.java | 0
.../apache/sis/internal/jaxb/gco/GO_Boolean.java | 0
.../sis/internal/jaxb/gco/GO_CharacterString.java | 0
.../apache/sis/internal/jaxb/gco/GO_DateTime.java | 0
.../apache/sis/internal/jaxb/gco/GO_Decimal.java | 0
.../apache/sis/internal/jaxb/gco/GO_Distance.java | 0
.../sis/internal/jaxb/gco/GO_GenericName.java | 0
.../apache/sis/internal/jaxb/gco/GO_Integer.java | 0
.../apache/sis/internal/jaxb/gco/GO_Integer64.java | 0
.../apache/sis/internal/jaxb/gco/GO_Measure.java | 0
.../internal/jaxb/gco/GO_MultiplicityRange.java | 0
.../org/apache/sis/internal/jaxb/gco/GO_Real.java | 0
.../apache/sis/internal/jaxb/gco/GO_Record.java | 0
.../sis/internal/jaxb/gco/GO_RecordType.java | 0
.../apache/sis/internal/jaxb/gco/GO_Temporal.java | 0
.../org/apache/sis/internal/jaxb/gco/GO_URL.java | 0
.../sis/internal/jaxb/gco/GO_UnlimitedInteger.java | 0
.../jaxb/gco/InternationalStringAdapter.java | 0
.../jaxb/gco/InternationalStringConverter.java | 0
.../apache/sis/internal/jaxb/gco/Multiplicity.java | 0
.../sis/internal/jaxb/gco/MultiplicityRange.java | 0
.../apache/sis/internal/jaxb/gco/NameValue.java | 0
.../internal/jaxb/gco/ObjectIdentification.html | 0
.../sis/internal/jaxb/gco/ObjectReference.java | 0
.../apache/sis/internal/jaxb/gco/PropertyType.java | 0
.../sis/internal/jaxb/gco/StringAdapter.java | 0
.../apache/sis/internal/jaxb/gco/URIAdapter.java | 0
.../apache/sis/internal/jaxb/gco/UnitAdapter.java | 0
.../sis/internal/jaxb/gco/UnlimitedInteger.java | 0
.../apache/sis/internal/jaxb/gco/package-info.java | 0
.../org/apache/sis/internal/jaxb/gcx/Anchor.java | 0
.../org/apache/sis/internal/jaxb/gcx/FileName.java | 0
.../apache/sis/internal/jaxb/gcx/MimeFileType.java | 0
.../sis/internal/jaxb/gcx/MimeFileTypeAdapter.java | 0
.../apache/sis/internal/jaxb/gcx/package-info.java | 0
.../sis/internal/jaxb/geometry/GM_Object.java | 0
.../sis/internal/jaxb/geometry/ObjectFactory.java | 104 +
.../sis/internal/jaxb/geometry/package-info.java | 0
.../sis/internal/jaxb/gmi/LE_ProcessStep.java | 0
.../apache/sis/internal/jaxb/gmi/LE_Source.java | 0
.../org/apache/sis/internal/jaxb/gmi/MI_Band.java | 0
.../internal/jaxb/gmi/MI_CoverageDescription.java | 0
.../sis/internal/jaxb/gmi/MI_Georectified.java | 0
.../sis/internal/jaxb/gmi/MI_Georeferenceable.java | 0
.../sis/internal/jaxb/gmi/MI_ImageDescription.java | 0
.../apache/sis/internal/jaxb/gmi/MI_Metadata.java | 0
.../apache/sis/internal/jaxb/gmi/package-info.java | 0
.../sis/internal/jaxb/gml/CodeListAdapter.java | 0
.../apache/sis/internal/jaxb/gml/DateAdapter.java | 0
.../apache/sis/internal/jaxb/gml/GMLAdapter.java | 0
.../org/apache/sis/internal/jaxb/gml/Measure.java | 0
.../apache/sis/internal/jaxb/gml/MeasureList.java | 0
.../sis/internal/jaxb/gml/SC_VerticalCRS.java | 143 +
.../apache/sis/internal/jaxb/gml/TM_Primitive.java | 0
.../apache/sis/internal/jaxb/gml/TimeInstant.java | 0
.../apache/sis/internal/jaxb/gml/TimePeriod.java | 0
.../sis/internal/jaxb/gml/TimePeriodBound.java | 0
.../internal/jaxb/gml/UniversalTimeAdapter.java | 0
.../apache/sis/internal/jaxb/gml/package-info.java | 0
.../apache/sis/internal/jaxb/gts/TM_Duration.java | 0
.../sis/internal/jaxb/gts/TM_PeriodDuration.java | 0
.../apache/sis/internal/jaxb/gts/package-info.java | 0
.../org/apache/sis/internal/jaxb/lan/Country.java | 0
.../apache/sis/internal/jaxb/lan/LanguageCode.java | 0
.../sis/internal/jaxb/lan/LocaleAdapter.java | 0
.../sis/internal/jaxb/lan/LocaleAndCharset.java | 0
.../jaxb/lan/LocalisedCharacterString.java | 0
.../apache/sis/internal/jaxb/lan/OtherLocales.java | 0
.../apache/sis/internal/jaxb/lan/PT_FreeText.java | 0
.../apache/sis/internal/jaxb/lan/PT_Locale.java | 0
.../apache/sis/internal/jaxb/lan/TextGroup.java | 0
.../apache/sis/internal/jaxb/lan/package-info.java | 0
.../sis/internal/jaxb/metadata/CI_Address.java | 0
.../sis/internal/jaxb/metadata/CI_Citation.java | 0
.../sis/internal/jaxb/metadata/CI_Contact.java | 0
.../apache/sis/internal/jaxb/metadata/CI_Date.java | 0
.../internal/jaxb/metadata/CI_OnlineResource.java | 0
.../sis/internal/jaxb/metadata/CI_Party.java | 0
.../internal/jaxb/metadata/CI_Responsibility.java | 0
.../jaxb/metadata/CI_ResponsibleParty.java | 0
.../sis/internal/jaxb/metadata/CI_Series.java | 0
.../sis/internal/jaxb/metadata/CI_Telephone.java | 0
.../internal/jaxb/metadata/DQM_BasicMeasure.java | 0
.../internal/jaxb/metadata/DQM_Description.java | 0
.../sis/internal/jaxb/metadata/DQM_Measure.java | 0
.../sis/internal/jaxb/metadata/DQM_Parameter.java | 0
.../jaxb/metadata/DQM_SourceReference.java | 0
.../sis/internal/jaxb/metadata/DQ_DataQuality.java | 0
.../sis/internal/jaxb/metadata/DQ_Element.java | 0
.../jaxb/metadata/DQ_EvaluationMethod.java | 0
.../jaxb/metadata/DQ_MeasureReference.java | 0
.../jaxb/metadata/DQ_PositionalAccuracy.java | 0
.../sis/internal/jaxb/metadata/DQ_Result.java | 0
.../DQ_StandaloneQualityReportInformation.java | 0
.../sis/internal/jaxb/metadata/EX_Extent.java | 0
.../jaxb/metadata/EX_GeographicExtent.java | 0
.../internal/jaxb/metadata/EX_TemporalExtent.java | 0
.../internal/jaxb/metadata/EX_VerticalExtent.java | 0
.../sis/internal/jaxb/metadata/LE_Algorithm.java | 0
.../jaxb/metadata/LE_NominalResolution.java | 0
.../jaxb/metadata/LE_ProcessStepReport.java | 0
.../sis/internal/jaxb/metadata/LE_Processing.java | 0
.../sis/internal/jaxb/metadata/LI_Lineage.java | 0
.../sis/internal/jaxb/metadata/LI_ProcessStep.java | 0
.../sis/internal/jaxb/metadata/LI_Source.java | 0
.../jaxb/metadata/MD_AggregateInformation.java | 0
.../metadata/MD_ApplicationSchemaInformation.java | 0
.../jaxb/metadata/MD_AssociatedResource.java | 0
.../internal/jaxb/metadata/MD_AttributeGroup.java | 0
.../internal/jaxb/metadata/MD_BrowseGraphic.java | 0
.../sis/internal/jaxb/metadata/MD_Constraints.java | 0
.../jaxb/metadata/MD_ContentInformation.java | 0
.../jaxb/metadata/MD_DataIdentification.java | 0
.../jaxb/metadata/MD_DigitalTransferOptions.java | 0
.../sis/internal/jaxb/metadata/MD_Dimension.java | 0
.../internal/jaxb/metadata/MD_Distribution.java | 0
.../sis/internal/jaxb/metadata/MD_Distributor.java | 0
.../metadata/MD_ExtendedElementInformation.java | 0
.../internal/jaxb/metadata/MD_FeatureTypeInfo.java | 0
.../sis/internal/jaxb/metadata/MD_Format.java | 0
.../jaxb/metadata/MD_GeometricObjects.java | 0
.../internal/jaxb/metadata/MD_Identification.java | 0
.../sis/internal/jaxb/metadata/MD_Identifier.java | 0
.../internal/jaxb/metadata/MD_KeywordClass.java | 0
.../sis/internal/jaxb/metadata/MD_Keywords.java | 0
.../jaxb/metadata/MD_MaintenanceInformation.java | 0
.../sis/internal/jaxb/metadata/MD_Medium.java | 0
.../sis/internal/jaxb/metadata/MD_Metadata.java | 0
.../metadata/MD_MetadataExtensionInformation.java | 0
.../internal/jaxb/metadata/MD_MetadataScope.java | 0
.../metadata/MD_PortrayalCatalogueReference.java | 0
.../internal/jaxb/metadata/MD_RangeDimension.java | 0
.../internal/jaxb/metadata/MD_Releasability.java | 0
.../jaxb/metadata/MD_RepresentativeFraction.java | 0
.../sis/internal/jaxb/metadata/MD_Resolution.java | 0
.../sis/internal/jaxb/metadata/MD_Scope.java | 0
.../jaxb/metadata/MD_ScopeDescription.java | 0
.../jaxb/metadata/MD_SpatialRepresentation.java | 0
.../jaxb/metadata/MD_StandardOrderProcess.java | 0
.../sis/internal/jaxb/metadata/MD_Usage.java | 0
.../jaxb/metadata/MI_AcquisitionInformation.java | 0
.../jaxb/metadata/MI_EnvironmentalRecord.java | 0
.../sis/internal/jaxb/metadata/MI_Event.java | 0
.../apache/sis/internal/jaxb/metadata/MI_GCP.java | 0
.../jaxb/metadata/MI_GeolocationInformation.java | 0
.../sis/internal/jaxb/metadata/MI_Instrument.java | 0
.../sis/internal/jaxb/metadata/MI_Objective.java | 0
.../sis/internal/jaxb/metadata/MI_Operation.java | 0
.../apache/sis/internal/jaxb/metadata/MI_Plan.java | 0
.../sis/internal/jaxb/metadata/MI_Platform.java | 0
.../internal/jaxb/metadata/MI_PlatformPass.java | 0
.../jaxb/metadata/MI_RangeElementDescription.java | 0
.../internal/jaxb/metadata/MI_RequestedDate.java | 0
.../sis/internal/jaxb/metadata/MI_Requirement.java | 0
.../sis/internal/jaxb/metadata/MX_DataFile.java | 0
.../internal/jaxb/metadata/RS_ReferenceSystem.java | 0
.../internal/jaxb/metadata/SV_CoupledResource.java | 0
.../jaxb/metadata/SV_OperationChainMetadata.java | 0
.../jaxb/metadata/SV_OperationMetadata.java | 0
.../sis/internal/jaxb/metadata/SV_Parameter.java | 0
.../sis/internal/jaxb/metadata/package-info.java | 0
.../internal/jaxb/metadata/replace/Parameter.java | 0
.../jaxb/metadata/replace/QualityParameter.java | 0
.../jaxb/metadata/replace/RS_Identifier.java | 0
.../metadata/replace/ReferenceSystemMetadata.java | 0
.../internal/jaxb/metadata/replace/SensorType.java | 0
.../jaxb/metadata/replace/ServiceParameter.java | 0
.../jaxb/metadata/replace/package-info.java | 0
.../org/apache/sis/internal/jaxb/package-info.java | 0
.../apache/sis/internal/metadata/AxisNames.java | 0
.../apache/sis/internal/metadata/Dependencies.java | 0
.../apache/sis/internal/metadata/ExcludedSet.java | 0
.../apache/sis/internal/metadata/Identifiers.java | 0
.../internal/metadata/ImplementationHelper.java | 0
.../org/apache/sis/internal/metadata/Merger.java | 0
.../sis/internal/metadata/MetadataTypes.java | 104 +
.../apache/sis/internal/metadata/NameMeaning.java | 0
.../sis/internal/metadata/NameToIdentifier.java | 0
.../sis/internal/metadata/RecordSchemaSIS.java | 0
.../sis/internal/metadata/ReferencingServices.java | 306 ++
.../apache/sis/internal/metadata/Resources.java | 216 ++
.../sis/internal/metadata/Resources.properties | 30 +
.../apache/sis/internal/metadata/Resources_en.java | 0
.../apache/sis/internal/metadata/Resources_fr.java | 0
.../sis/internal/metadata/Resources_fr.properties | 35 +
.../sis/internal/metadata/ServicesForUtility.java | 170 +
.../sis/internal/metadata/TemporalUtilities.java | 146 +
.../internal/metadata/TransformationAccuracy.java | 0
.../internal/metadata/legacy/DateToTemporal.java | 0
.../metadata/legacy/LegacyPropertyAdapter.java | 0
.../internal/metadata/legacy/TemporalToDate.java | 0
.../sis/internal/metadata/legacy/package-info.java | 0
.../apache/sis/internal/metadata/package-info.java | 0
.../apache/sis/internal/metadata/sql/Dialect.java | 0
.../sis/internal/metadata/sql/Initializer.java | 466 +++
.../sis/internal/metadata/sql/LocalDataSource.java | 457 +++
.../sis/internal/metadata/sql/Reflection.java | 0
.../sis/internal/metadata/sql/SQLBuilder.java | 0
.../sis/internal/metadata/sql/SQLUtilities.java | 0
.../sis/internal/metadata/sql/ScriptRunner.java | 0
.../apache/sis/internal/metadata/sql/Syntax.java | 0
.../sis/internal/metadata/sql/TypeMapper.java | 0
.../sis/internal/metadata/sql/package-info.java | 0
.../sis/internal/simple/CitationConstant.java | 242 ++
.../sis/internal/simple/SimpleAttributeType.java | 0
.../apache/sis/internal/simple/SimpleCitation.java | 0
.../apache/sis/internal/simple/SimpleDuration.java | 0
.../apache/sis/internal/simple/SimpleExtent.java | 0
.../apache/sis/internal/simple/SimpleFormat.java | 0
.../internal/simple/SimpleIdentifiedObject.java | 0
.../sis/internal/simple/SimpleIdentifier.java | 0
.../apache/sis/internal/simple/SimpleMetadata.java | 0
.../apache/sis/internal/simple/package-info.java | 0
.../apache/sis/internal/xml/LegacyNamespaces.java | 0
.../sis/internal/xml/StreamWriterDelegate.java | 0
.../org/apache/sis/internal/xml/XmlUtilities.java | 336 ++
.../org/apache/sis/internal/xml/package-info.java | 0
.../org/apache/sis/metadata/AbstractMetadata.java | 0
.../main}/org/apache/sis/metadata/CacheKey.java | 0
.../main}/org/apache/sis/metadata/DomainRange.java | 0
.../main}/org/apache/sis/metadata/HashCode.java | 0
.../main}/org/apache/sis/metadata/IndexMap.java | 0
.../org/apache/sis/metadata/InformationMap.java | 0
.../sis/metadata/InvalidMetadataException.java | 0
.../org/apache/sis/metadata/KeyNamePolicy.java | 0
.../org/apache/sis/metadata/MetadataCopier.java | 0
.../org/apache/sis/metadata/MetadataFormat.java | 0
.../org/apache/sis/metadata/MetadataStandard.java | 1108 +++++++
.../org/apache/sis/metadata/MetadataVisitor.java | 0
.../sis/metadata/MetadataVisitorException.java | 0
.../apache/sis/metadata/ModifiableMetadata.java | 0
.../main}/org/apache/sis/metadata/NameMap.java | 0
.../main}/org/apache/sis/metadata/ObjectPair.java | 0
.../org/apache/sis/metadata/PropertyAccessor.java | 0
.../apache/sis/metadata/PropertyComparator.java | 0
.../apache/sis/metadata/PropertyInformation.java | 0
.../main}/org/apache/sis/metadata/PropertyMap.java | 0
.../main}/org/apache/sis/metadata/Pruner.java | 0
.../org/apache/sis/metadata/SpecialCases.java | 0
.../sis/metadata/StandardImplementation.java | 0
.../org/apache/sis/metadata/StateChanger.java | 0
.../org/apache/sis/metadata/TitleProperty.java | 0
.../main}/org/apache/sis/metadata/TreeNode.java | 0
.../org/apache/sis/metadata/TreeNodeChildren.java | 0
.../org/apache/sis/metadata/TreeTableView.java | 221 ++
.../main}/org/apache/sis/metadata/TypeMap.java | 0
.../org/apache/sis/metadata/TypeValuePolicy.java | 0
.../metadata/UnmodifiableMetadataException.java | 0
.../apache/sis/metadata/ValueExistencePolicy.java | 0
.../main}/org/apache/sis/metadata/ValueMap.java | 0
.../iso/DefaultApplicationSchemaInformation.java | 0
.../iso/DefaultExtendedElementInformation.java | 0
.../apache/sis/metadata/iso/DefaultIdentifier.java | 0
.../apache/sis/metadata/iso/DefaultMetadata.java | 0
.../iso/DefaultMetadataExtensionInformation.java | 0
.../sis/metadata/iso/DefaultMetadataScope.java | 0
.../iso/DefaultPortrayalCatalogueReference.java | 0
.../org/apache/sis/metadata/iso/ISOMetadata.java | 0
.../sis/metadata/iso/MetadataScopeAdapter.java | 0
.../sis/metadata/iso/OnlineResourceAdapter.java | 0
.../apache/sis/metadata/iso/URIStringAdapter.java | 0
.../acquisition/DefaultAcquisitionInformation.java | 0
.../acquisition/DefaultEnvironmentalRecord.java | 0
.../sis/metadata/iso/acquisition/DefaultEvent.java | 0
.../iso/acquisition/DefaultInstrument.java | 0
.../metadata/iso/acquisition/DefaultObjective.java | 0
.../metadata/iso/acquisition/DefaultOperation.java | 0
.../sis/metadata/iso/acquisition/DefaultPlan.java | 0
.../metadata/iso/acquisition/DefaultPlatform.java | 0
.../iso/acquisition/DefaultPlatformPass.java | 0
.../iso/acquisition/DefaultRequestedDate.java | 0
.../iso/acquisition/DefaultRequirement.java | 0
.../sis/metadata/iso/acquisition/package-info.java | 0
.../sis/metadata/iso/citation/AbstractParty.java | 0
.../sis/metadata/iso/citation/Citations.java | 0
.../sis/metadata/iso/citation/DefaultAddress.java | 0
.../sis/metadata/iso/citation/DefaultCitation.java | 0
.../metadata/iso/citation/DefaultCitationDate.java | 0
.../sis/metadata/iso/citation/DefaultContact.java | 0
.../metadata/iso/citation/DefaultIndividual.java | 0
.../iso/citation/DefaultOnlineResource.java | 0
.../metadata/iso/citation/DefaultOrganisation.java | 0
.../iso/citation/DefaultResponsibility.java | 0
.../iso/citation/DefaultResponsibleParty.java | 0
.../sis/metadata/iso/citation/DefaultSeries.java | 0
.../metadata/iso/citation/DefaultTelephone.java | 0
.../metadata/iso/citation/LegacyTelephones.java | 0
.../sis/metadata/iso/citation/package-info.java | 0
.../iso/constraint/DefaultConstraints.java | 0
.../iso/constraint/DefaultLegalConstraints.java | 0
.../iso/constraint/DefaultReleasability.java | 0
.../iso/constraint/DefaultSecurityConstraints.java | 0
.../sis/metadata/iso/constraint/package-info.java | 0
.../iso/content/AbstractContentInformation.java | 0
.../iso/content/DefaultAttributeGroup.java | 0
.../sis/metadata/iso/content/DefaultBand.java | 0
.../iso/content/DefaultCoverageDescription.java | 0
.../DefaultFeatureCatalogueDescription.java | 0
.../iso/content/DefaultFeatureTypeInfo.java | 0
.../iso/content/DefaultImageDescription.java | 0
.../iso/content/DefaultRangeDimension.java | 0
.../content/DefaultRangeElementDescription.java | 0
.../iso/content/DefaultSampleDimension.java | 0
.../sis/metadata/iso/content/package-info.java | 0
.../metadata/iso/distribution/DefaultDataFile.java | 0
.../DefaultDigitalTransferOptions.java | 0
.../iso/distribution/DefaultDistribution.java | 0
.../iso/distribution/DefaultDistributor.java | 0
.../metadata/iso/distribution/DefaultFormat.java | 0
.../metadata/iso/distribution/DefaultMedium.java | 0
.../distribution/DefaultStandardOrderProcess.java | 0
.../metadata/iso/distribution/package-info.java | 0
.../iso/extent/AbstractGeographicExtent.java | 0
.../iso/extent/DefaultBoundingPolygon.java | 0
.../sis/metadata/iso/extent/DefaultExtent.java | 392 +++
.../iso/extent/DefaultGeographicBoundingBox.java | 789 +++++
.../iso/extent/DefaultGeographicDescription.java | 0
.../iso/extent/DefaultSpatialTemporalExtent.java | 230 ++
.../metadata/iso/extent/DefaultTemporalExtent.java | 286 ++
.../metadata/iso/extent/DefaultVerticalExtent.java | 377 +++
.../apache/sis/metadata/iso/extent/Extents.java | 777 +++++
.../sis/metadata/iso/extent/package-info.java | 0
.../iso/identification/AbstractIdentification.java | 0
.../DefaultAggregateInformation.java | 0
.../identification/DefaultAssociatedResource.java | 0
.../iso/identification/DefaultBrowseGraphic.java | 0
.../iso/identification/DefaultCoupledResource.java | 0
.../identification/DefaultDataIdentification.java | 0
.../iso/identification/DefaultKeywordClass.java | 0
.../iso/identification/DefaultKeywords.java | 0
.../DefaultOperationChainMetadata.java | 0
.../identification/DefaultOperationMetadata.java | 0
.../DefaultRepresentativeFraction.java | 0
.../iso/identification/DefaultResolution.java | 0
.../DefaultServiceIdentification.java | 0
.../metadata/iso/identification/DefaultUsage.java | 0
.../metadata/iso/identification/OperationName.java | 0
.../metadata/iso/identification/package-info.java | 0
.../sis/metadata/iso/lineage/DefaultAlgorithm.java | 0
.../sis/metadata/iso/lineage/DefaultLineage.java | 0
.../iso/lineage/DefaultNominalResolution.java | 0
.../metadata/iso/lineage/DefaultProcessStep.java | 0
.../iso/lineage/DefaultProcessStepReport.java | 0
.../metadata/iso/lineage/DefaultProcessing.java | 0
.../sis/metadata/iso/lineage/DefaultSource.java | 0
.../sis/metadata/iso/lineage/package-info.java | 0
.../iso/maintenance/AttributeTypeAdapter.java | 0
.../maintenance/DefaultMaintenanceInformation.java | 0
.../sis/metadata/iso/maintenance/DefaultScope.java | 0
.../iso/maintenance/DefaultScopeDescription.java | 0
.../iso/maintenance/FeatureTypeAdapter.java | 0
.../iso/maintenance/LegacyFeatureType.java | 0
.../sis/metadata/iso/maintenance/package-info.java | 0
.../org/apache/sis/metadata/iso/package-info.java | 0
.../metadata/iso/quality/AbstractCompleteness.java | 0
.../iso/quality/AbstractDataEvaluation.java | 0
.../sis/metadata/iso/quality/AbstractElement.java | 0
.../iso/quality/AbstractLogicalConsistency.java | 0
.../metadata/iso/quality/AbstractMetaquality.java | 0
.../iso/quality/AbstractPositionalAccuracy.java | 0
.../sis/metadata/iso/quality/AbstractResult.java | 0
.../iso/quality/AbstractTemporalAccuracy.java | 0
.../iso/quality/AbstractTemporalQuality.java | 0
.../iso/quality/AbstractThematicAccuracy.java | 0
.../DefaultAbsoluteExternalPositionalAccuracy.java | 0
.../quality/DefaultAccuracyOfATimeMeasurement.java | 0
.../iso/quality/DefaultAggregationDerivation.java | 0
.../metadata/iso/quality/DefaultBasicMeasure.java | 0
.../iso/quality/DefaultCompletenessCommission.java | 0
.../iso/quality/DefaultCompletenessOmission.java | 0
.../iso/quality/DefaultConceptualConsistency.java | 0
.../metadata/iso/quality/DefaultConfidence.java | 0
.../iso/quality/DefaultConformanceResult.java | 0
.../iso/quality/DefaultCoverageResult.java | 0
.../metadata/iso/quality/DefaultDataQuality.java | 0
.../iso/quality/DefaultDescriptiveResult.java | 0
.../iso/quality/DefaultDomainConsistency.java | 0
.../iso/quality/DefaultEvaluationMethod.java | 0
.../DefaultEvaluationReportInformation.java | 0
.../iso/quality/DefaultFormatConsistency.java | 0
.../iso/quality/DefaultFullInspection.java | 0
.../DefaultGriddedDataPositionalAccuracy.java | 0
.../metadata/iso/quality/DefaultHomogeneity.java | 0
.../iso/quality/DefaultIndirectEvaluation.java | 0
.../iso/quality/DefaultMeasureDescription.java | 0
.../iso/quality/DefaultMeasureReference.java | 0
.../DefaultNonQuantitativeAttributeAccuracy.java | 0
...DefaultNonQuantitativeAttributeCorrectness.java | 0
.../iso/quality/DefaultQualityMeasure.java | 0
.../DefaultQuantitativeAttributeAccuracy.java | 0
.../iso/quality/DefaultQuantitativeResult.java | 0
.../DefaultRelativeInternalPositionalAccuracy.java | 0
.../iso/quality/DefaultRepresentativity.java | 0
.../iso/quality/DefaultSampleBasedInspection.java | 0
.../sis/metadata/iso/quality/DefaultScope.java | 0
.../iso/quality/DefaultSourceReference.java | 0
.../iso/quality/DefaultTemporalConsistency.java | 0
.../iso/quality/DefaultTemporalValidity.java | 0
.../DefaultThematicClassificationCorrectness.java | 0
.../iso/quality/DefaultTopologicalConsistency.java | 0
.../sis/metadata/iso/quality/DefaultUsability.java | 0
.../sis/metadata/iso/quality/ISOMetadata.java | 0
.../sis/metadata/iso/quality/package-info.java | 0
.../spatial/AbstractGeolocationInformation.java | 0
.../iso/spatial/AbstractSpatialRepresentation.java | 0
.../sis/metadata/iso/spatial/DefaultDimension.java | 0
.../sis/metadata/iso/spatial/DefaultGCP.java | 0
.../metadata/iso/spatial/DefaultGCPCollection.java | 0
.../iso/spatial/DefaultGeometricObjects.java | 0
.../metadata/iso/spatial/DefaultGeorectified.java | 0
.../iso/spatial/DefaultGeoreferenceable.java | 0
.../spatial/DefaultGridSpatialRepresentation.java | 0
.../DefaultVectorSpatialRepresentation.java | 0
.../sis/metadata/iso/spatial/package-info.java | 0
.../org/apache/sis/metadata/package-info.java | 0
.../org/apache/sis/metadata/sql/CacheKey.java | 0
.../apache/sis/metadata/sql/CachedStatement.java | 0
.../org/apache/sis/metadata/sql/Citations.sql | 0
.../main/org/apache/sis/metadata/sql/Contents.sql | 100 +
.../org/apache/sis/metadata/sql/Dispatcher.java | 0
.../sis/metadata/sql/IdentifierGenerator.java | 0
.../org/apache/sis/metadata/sql/Installer.java | 0
.../org/apache/sis/metadata/sql/LookupInfo.java | 0
.../main}/org/apache/sis/metadata/sql/Metadata.sql | 0
.../apache/sis/metadata/sql/MetadataFallback.java | 0
.../org/apache/sis/metadata/sql/MetadataProxy.java | 0
.../apache/sis/metadata/sql/MetadataSource.java | 1284 ++++++++
.../sis/metadata/sql/MetadataStoreException.java | 0
.../apache/sis/metadata/sql/MetadataWriter.java | 0
.../org/apache/sis/metadata/sql/Referencing.sql | 0
.../apache/sis/metadata/sql/TableHierarchy.java | 0
.../org/apache/sis/metadata/sql/package-info.java | 0
.../org/apache/sis/util/iso/AbstractFactory.java | 0
.../org/apache/sis/util/iso/AbstractName.java | 0
.../org/apache/sis/util/iso/DefaultLocalName.java | 0
.../org/apache/sis/util/iso/DefaultMemberName.java | 0
.../apache/sis/util/iso/DefaultNameFactory.java | 0
.../org/apache/sis/util/iso/DefaultNameSpace.java | 0
.../org/apache/sis/util/iso/DefaultRecord.java | 0
.../apache/sis/util/iso/DefaultRecordSchema.java | 0
.../org/apache/sis/util/iso/DefaultRecordType.java | 503 +++
.../org/apache/sis/util/iso/DefaultScopedName.java | 0
.../org/apache/sis/util/iso/DefaultTypeName.java | 0
.../org/apache/sis/util/iso/GlobalNameSpace.java | 0
.../main}/org/apache/sis/util/iso/Names.java | 0
.../org/apache/sis/util/iso/RecordDefinition.java | 268 ++
.../main}/org/apache/sis/util/iso/TypeNames.java | 0
.../main}/org/apache/sis/util/iso/Types.java | 0
.../org/apache/sis/util/iso/package-info.java | 0
.../main}/org/apache/sis/xml/IdentifiedObject.java | 0
.../main}/org/apache/sis/xml/IdentifierMap.java | 0
.../main}/org/apache/sis/xml/IdentifierSpace.java | 0
.../main}/org/apache/sis/xml/Implementation.java | 0
.../main}/org/apache/sis/xml/InputFactory.java | 0
.../main}/org/apache/sis/xml/LegacyCodes.java | 0
.../main}/org/apache/sis/xml/MarshalContext.java | 0
.../main}/org/apache/sis/xml/MarshallerPool.java | 0
.../main}/org/apache/sis/xml/Namespaces.java | 0
.../org/apache/sis/xml/NilInternationalString.java | 0
.../main}/org/apache/sis/xml/NilObject.java | 0
.../main}/org/apache/sis/xml/NilObjectHandler.java | 0
.../main}/org/apache/sis/xml/NilReason.java | 0
.../main}/org/apache/sis/xml/OutputFactory.java | 0
.../main}/org/apache/sis/xml/Pooled.java | 0
.../main}/org/apache/sis/xml/PooledMarshaller.java | 0
.../main}/org/apache/sis/xml/PooledTemplate.java | 0
.../org/apache/sis/xml/PooledUnmarshaller.java | 0
.../org/apache/sis/xml/ReferenceResolver.java | 0
.../main}/org/apache/sis/xml/RenameOnExport.lst | 0
.../main}/org/apache/sis/xml/RenameOnImport.lst | 0
.../main}/org/apache/sis/xml/TransformVersion.java | 0
.../main}/org/apache/sis/xml/TransformedEvent.java | 0
.../main}/org/apache/sis/xml/Transformer.java | 0
.../org/apache/sis/xml/TransformingNamespaces.java | 0
.../org/apache/sis/xml/TransformingReader.java | 427 +++
.../org/apache/sis/xml/TransformingWriter.java | 0
.../main}/org/apache/sis/xml/ValueConverter.java | 0
.../main}/org/apache/sis/xml/XLink.java | 0
.../main/org/apache/sis/xml/XML.java | 710 +++++
.../main}/org/apache/sis/xml/XPointer.java | 0
.../main}/org/apache/sis/xml/package-info.java | 0
.../main}/org/apache/sis/xml/readme.html | 0
.../internal/jaxb/IdentifierMapAdapterTest.java | 0
.../internal/jaxb/ModifiableIdentifierMapTest.java | 0
.../internal/jaxb/cat/CodeListMarshallingTest.java | 0
.../sis/internal/jaxb/cat/EnumAdapterTest.java | 0
.../sis/internal/jaxb/cat/EnumMarshallingTest.java | 0
.../sis/internal/jaxb/gco/MultiplicityTest.java | 0
.../sis/internal/jaxb/gco/PropertyTypeMock.java | 0
.../sis/internal/jaxb/gco/PropertyTypeTest.java | 0
.../sis/internal/jaxb/gco/StringAdapterTest.java | 0
.../apache/sis/internal/jaxb/gml/MeasureTest.java | 0
.../sis/internal/jaxb/gml/TimePeriodTest.java | 0
.../internal/jaxb/lan/FreeTextMarshallingTest.java | 0
.../sis/internal/jaxb/lan/LanguageCodeTest.java | 0
.../sis/internal/jaxb/lan/OtherLocalesTest.java | 0
.../sis/internal/jaxb/lan/PT_LocaleTest.java | 0
.../metadata/replace/QualityParameterTest.java | 0
.../metadata/replace/ServiceParameterTest.java | 0
.../sis/internal/metadata/AxisDirectionsTest.txt | 3 +
.../sis/internal/metadata/AxisNamesTest.java | 0
.../sis/internal/metadata/IdentifiersTest.java | 0
.../metadata/ImplementationHelperTest.java | 0
.../apache/sis/internal/metadata/MergerTest.java | 0
.../sis/internal/metadata/NameMeaningTest.java | 0
.../internal/metadata/sql/SQLUtilitiesTest.java | 0
.../internal/metadata/sql/ScriptRunnerTest.java | 0
.../sis/internal/metadata/sql/TypeMapperTest.java | 0
.../sis/internal/simple/SimpleIdentifierTest.java | 0
.../sis/internal/xml/DocumentComparatorTest.java | 0
.../apache/sis/internal/xml/XmlUtilitiesTest.java | 0
.../apache/sis/metadata/AbstractMetadataTest.java | 0
.../test/org/apache/sis/metadata/Assertions.java | 228 ++
.../org/apache/sis/metadata/HashCodeTest.java | 0
.../apache/sis/metadata/InformationMapTest.java | 0
.../apache/sis/metadata/MetadataCopierTest.java | 0
.../apache/sis/metadata/MetadataStandardTest.java | 373 +++
.../sis/metadata/ModifiableMetadataTest.java | 0
.../test}/org/apache/sis/metadata/NameMapTest.java | 0
.../apache/sis/metadata/PropertyAccessorTest.java | 0
.../sis/metadata/PropertyConsistencyCheck.java | 0
.../sis/metadata/PropertyInformationTest.java | 0
.../test}/org/apache/sis/metadata/PrunerTest.java | 0
.../org/apache/sis/metadata/SpecialCasesTest.java | 0
.../apache/sis/metadata/TreeNodeChildrenTest.java | 0
.../org/apache/sis/metadata/TreeNodeTest.java | 0
.../apache/sis/metadata/TreeTableFormatTest.java | 0
.../org/apache/sis/metadata/TreeTableViewTest.java | 0
.../test}/org/apache/sis/metadata/TypeMapTest.java | 0
.../org/apache/sis/metadata/ValueMapTest.java | 0
.../org/apache/sis/metadata/iso/APIVerifier.java | 247 ++
.../apache/sis/metadata/iso/AllMetadataTest.java | 0
.../sis/metadata/iso/CustomMetadataTest.java | 0
.../sis/metadata/iso/DefaultIdentifierTest.java | 0
.../sis/metadata/iso/DefaultMetadataTest.java | 292 ++
.../apache/sis/metadata/iso/api-changes.properties | 0
.../sis/metadata/iso/citation/CitationsTest.java | 0
.../iso/citation/DefaultCitationDateTest.java | 0
.../metadata/iso/citation/DefaultCitationTest.java | 0
.../metadata/iso/citation/DefaultContactTest.java | 0
.../iso/citation/DefaultResponsibilityTest.java | 0
.../metadata/iso/citation/HardCodedCitations.java | 0
.../constraint/DefaultLegalConstraintsTest.java | 0
.../sis/metadata/iso/content/DefaultBandTest.java | 0
.../sis/metadata/iso/extent/DefaultExtentTest.java | 0
.../extent/DefaultGeographicBoundingBoxTest.java | 0
.../sis/metadata/iso/extent/ExtentsTest.java | 215 ++
.../identification/DefaultBrowseGraphicTest.java | 0
.../identification/DefaultCoupledResourceTest.java | 0
.../DefaultDataIdentificationTest.java | 0
.../iso/identification/DefaultKeywordsTest.java | 0
.../DefaultRepresentativeFractionTest.java | 0
.../iso/identification/DefaultResolutionTest.java | 0
.../DefaultServiceIdentificationTest.java | 0
.../metadata/iso/lineage/DefaultLineageTest.java | 0
.../iso/lineage/DefaultProcessStepTest.java | 0
.../maintenance/DefaultScopeDescriptionTest.java | 0
.../metadata/iso/quality/AbstractElementTest.java | 0
.../quality/AbstractPositionalAccuracyTest.java | 0
.../iso/quality/DefaultDomainConsistencyTest.java | 0
.../iso/quality/DefaultEvaluationMethodTest.java | 0
.../iso/quality/DefaultQuantitativeResultTest.java | 0
.../sis/metadata/iso/quality/ScopeCodeTest.java | 0
.../iso/spatial/DefaultGeorectifiedTest.java | 0
.../sis/metadata/sql/IdentifierGeneratorTest.java | 0
.../sis/metadata/sql/MetadataFallbackVerifier.java | 144 +
.../sis/metadata/sql/MetadataSourceTest.java | 0
.../sis/metadata/sql/MetadataWriterTest.java | 0
.../org/apache/sis/metadata/xml/2007/Citation.xml | 0
.../org/apache/sis/metadata/xml/2007/Extent.xml | 0
.../org/apache/sis/metadata/xml/2007/Locales.xml | 0
.../org/apache/sis/metadata/xml/2007/Metadata.xml | 0
.../apache/sis/metadata/xml/2007/Multiplicity.xml | 0
.../sis/metadata/xml/2007/PositionalAccuracy.xml | 0
.../apache/sis/metadata/xml/2007/ProcessStep.xml | 0
.../metadata/xml/2007/ServiceIdentification.xml | 0
.../org/apache/sis/metadata/xml/2016/Citation.xml | 0
.../org/apache/sis/metadata/xml/2016/Extent.xml | 0
.../org/apache/sis/metadata/xml/2016/Locales.xml | 0
.../org/apache/sis/metadata/xml/2016/Metadata.xml | 0
.../apache/sis/metadata/xml/2016/Multiplicity.xml | 0
.../sis/metadata/xml/2016/PositionalAccuracy.xml | 0
.../apache/sis/metadata/xml/2016/ProcessStep.xml | 0
.../metadata/xml/2016/ServiceIdentification.xml | 0
.../sis/metadata/xml/SchemaComplianceTest.java | 0
.../org/apache/sis/metadata/xml/TestUsingFile.java | 0
.../sis/test/mock/CoordinateSystemAxisMock.java | 0
.../apache/sis/test/mock/FeatureAttributeMock.java | 0
.../apache/sis/test/mock/IdentifiedObjectMock.java | 0
.../org/apache/sis/test/mock/MetadataMock.java | 0
.../org/apache/sis/test/mock/VerticalCRSMock.java | 0
.../org/apache/sis/test/mock/package-info.java | 0
.../test/org/apache/sis/test/sql/TestDatabase.java | 311 ++
.../org/apache/sis/test/sql/package-info.java | 0
.../sis/test/xml/AnnotationConsistencyCheck.java | 0
.../apache/sis/test/xml/DocumentComparator.java | 0
.../test}/org/apache/sis/test/xml/InfiniteSet.java | 0
.../org/apache/sis/test/xml/PackageVerifier.java | 0
.../org/apache/sis/test/xml/SchemaCompliance.java | 0
.../test}/org/apache/sis/test/xml/TestCase.java | 0
.../org/apache/sis/test/xml/package-info.java | 0
.../apache/sis/util/iso/DefaultLocalNameTest.java | 0
.../sis/util/iso/DefaultNameFactoryTest.java | 0
.../sis/util/iso/DefaultRecordSchemaTest.java | 0
.../org/apache/sis/util/iso/DefaultRecordTest.java | 0
.../apache/sis/util/iso/DefaultRecordTypeTest.java | 0
.../apache/sis/util/iso/DefaultScopedNameTest.java | 0
.../apache/sis/util/iso/NameMarshallingTest.java | 0
.../test}/org/apache/sis/util/iso/NamesTest.java | 0
.../sis/util/iso/SerializableRecordSchema.java | 0
.../org/apache/sis/util/iso/TypeNamesTest.java | 0
.../test}/org/apache/sis/util/iso/TypesTest.java | 0
.../sis/xml/CharSequenceSubstitutionTest.java | 0
.../test}/org/apache/sis/xml/LegacyCodesTest.java | 0
.../org/apache/sis/xml/MarshallerPoolTest.java | 0
.../test}/org/apache/sis/xml/NamespacesTest.java | 0
.../apache/sis/xml/NilReasonMarshallingTest.java | 0
.../test}/org/apache/sis/xml/NilReasonTest.java | 0
.../org/apache/sis/xml/ReferenceResolverMock.java | 0
.../org/apache/sis/xml/RenameListGenerator.java | 0
.../test}/org/apache/sis/xml/TransformerTest.java | 0
.../apache/sis/xml/TransformingNamespacesTest.java | 0
.../org/apache/sis/xml/UUIDMarshallingTest.java | 0
.../org/apache/sis/xml/ValueConverterTest.java | 0
.../org/apache/sis/xml/XLinkMarshallingTest.java | 0
.../test}/org/apache/sis/xml/XLinkTest.java | 0
.../test}/org/apache/sis/xml/XPointerTest.java | 0
.../bundle}/META-INF/manifest.xml | 0
.../bundle}/Referencing.xcu | 0
.../bundle/build-instruction.html | 119 +
.../bundle}/description.txt | 0
.../bundle}/description.xml | 0
.../org.apache.sis.openoffice/bundle}/license.txt | 0
.../org/apache/sis/openoffice/XReferencing.class | Bin
.../src/org.apache.sis.openoffice/bundle}/sis.png | Bin
.../src/org.apache.sis.openoffice/bundle}/sis.rdb | Bin
.../main/module-info.java | 31 +
.../org/apache/sis/openoffice/AnglePattern.java | 0
.../main}/org/apache/sis/openoffice/CacheKey.java | 0
.../org/apache/sis/openoffice/CalcAddins.java | 0
.../sis/openoffice/ReferencingFunctions.java | 0
.../org/apache/sis/openoffice/Registration.java | 115 +
.../org/apache/sis/openoffice/Transformer.java | 0
.../org/apache/sis/openoffice/XReferencing.idl | 0
.../org/apache/sis/openoffice/XReferencing.java | 145 +
.../org/apache/sis/openoffice/package-info.java | 31 +
.../sis/openoffice/ReferencingFunctionsTest.java | 0
.../org/apache/sis/openoffice/TransformerTest.java | 0
.../org.apache.sis.portrayal/main/module-info.java | 41 +
.../sis/internal/map/ExceptionPresentation.java | 0
.../apache/sis/internal/map/ListChangeEvent.java | 0
.../org/apache/sis/internal/map/NotifiedList.java | 0
.../org/apache/sis/internal/map/Presentation.java | 0
.../sis/internal/map/PropertyNameCollector.java | 0
.../sis/internal/map/ResourceSymbolizer.java | 0
.../org/apache/sis/internal/map/SEPortrayer.java | 0
.../apache/sis/internal/map/SEPresentation.java | 0
.../apache/sis/internal/map/SymbologyVisitor.java | 0
.../coverage/MultiResolutionCoverageLoader.java | 0
.../sis/internal/map/coverage/RenderingData.java | 0
.../internal/map/coverage/RenderingWorkaround.java | 0
.../sis/internal/map/coverage/package-info.java | 0
.../org/apache/sis/internal/map/package-info.java | 0
.../main}/org/apache/sis/portrayal/Canvas.java | 0
.../org/apache/sis/portrayal/CanvasContext.java | 0
.../org/apache/sis/portrayal/CanvasExtent.java | 0
.../org/apache/sis/portrayal/CanvasFollower.java | 0
.../main}/org/apache/sis/portrayal/MapItem.java | 0
.../main}/org/apache/sis/portrayal/MapLayer.java | 0
.../main}/org/apache/sis/portrayal/MapLayers.java | 0
.../main}/org/apache/sis/portrayal/Observable.java | 0
.../org/apache/sis/portrayal/PlanarCanvas.java | 0
.../org/apache/sis/portrayal/RenderException.java | 0
.../apache/sis/portrayal/TransformChangeEvent.java | 0
.../org/apache/sis/portrayal/package-info.java | 0
.../main}/org/apache/sis/style/Style.java | 0
.../main}/org/apache/sis/style/package-info.java | 0
.../org/apache/sis/style/se1/AbstractStyle.java | 0
.../org/apache/sis/style/se1/AnchorPoint.java | 0
.../org/apache/sis/style/se1/ChannelSelection.java | 0
.../main}/org/apache/sis/style/se1/ColorMap.java | 0
.../org/apache/sis/style/se1/ColorReplacement.java | 0
.../apache/sis/style/se1/ContrastEnhancement.java | 0
.../org/apache/sis/style/se1/ContrastMethod.java | 0
.../org/apache/sis/style/se1/CoverageStyle.java | 0
.../org/apache/sis/style/se1/Description.java | 0
.../org/apache/sis/style/se1/Displacement.java | 0
.../main}/org/apache/sis/style/se1/ElseFilter.java | 0
.../apache/sis/style/se1/ExpressionAdapter.java | 0
.../org/apache/sis/style/se1/ExternalGraphic.java | 0
.../org/apache/sis/style/se1/FeatureTypeStyle.java | 0
.../main}/org/apache/sis/style/se1/Fill.java | 0
.../main}/org/apache/sis/style/se1/Font.java | 0
.../main}/org/apache/sis/style/se1/Graphic.java | 0
.../org/apache/sis/style/se1/GraphicFill.java | 0
.../org/apache/sis/style/se1/GraphicStroke.java | 0
.../org/apache/sis/style/se1/GraphicalElement.java | 0
.../org/apache/sis/style/se1/GraphicalSymbol.java | 0
.../main}/org/apache/sis/style/se1/Halo.java | 0
.../org/apache/sis/style/se1/LabelPlacement.java | 0
.../org/apache/sis/style/se1/LegendGraphic.java | 0
.../org/apache/sis/style/se1/LinePlacement.java | 0
.../org/apache/sis/style/se1/LineSymbolizer.java | 0
.../main}/org/apache/sis/style/se1/Mark.java | 0
.../org/apache/sis/style/se1/OverlapBehavior.java | 0
.../org/apache/sis/style/se1/PointPlacement.java | 0
.../org/apache/sis/style/se1/PointSymbolizer.java | 0
.../apache/sis/style/se1/PolygonSymbolizer.java | 0
.../org/apache/sis/style/se1/RasterSymbolizer.java | 0
.../main}/org/apache/sis/style/se1/Rule.java | 0
.../org/apache/sis/style/se1/SelectedChannel.java | 0
.../org/apache/sis/style/se1/SemanticType.java | 0
.../org/apache/sis/style/se1/ShadedRelief.java | 0
.../main}/org/apache/sis/style/se1/Stroke.java | 0
.../org/apache/sis/style/se1/StyleElement.java | 0
.../org/apache/sis/style/se1/StyleFactory.java | 0
.../main}/org/apache/sis/style/se1/Symbolizer.java | 0
.../main}/org/apache/sis/style/se1/Symbology.java | 0
.../org/apache/sis/style/se1/TextSymbolizer.java | 0
.../org/apache/sis/style/se1/Translucent.java | 0
.../org/apache/sis/style/se1/package-info.java | 0
.../apache/sis/internal/map/SEPortrayerTest.java | 0
.../MultiResolutionCoverageLoaderTest.java | 0
.../org/apache/sis/portrayal/MapLayersTest.java | 0
.../org/apache/sis/style/se1/AnchorPointTest.java | 0
.../apache/sis/style/se1/ChannelSelectionTest.java | 0
.../sis/style/se1/ContrastEnhancementTest.java | 0
.../org/apache/sis/style/se1/DescriptionTest.java | 0
.../org/apache/sis/style/se1/DisplacementTest.java | 0
.../apache/sis/style/se1/ExternalGraphicTest.java | 0
.../apache/sis/style/se1/FeatureTypeStyleTest.java | 0
.../test}/org/apache/sis/style/se1/FillTest.java | 0
.../test}/org/apache/sis/style/se1/FontTest.java | 0
.../apache/sis/style/se1/GraphicStrokeTest.java | 0
.../org/apache/sis/style/se1/GraphicTest.java | 0
.../test}/org/apache/sis/style/se1/HaloTest.java | 0
.../apache/sis/style/se1/LinePlacementTest.java | 0
.../apache/sis/style/se1/LineSymbolizerTest.java | 0
.../test}/org/apache/sis/style/se1/MarkTest.java | 0
.../apache/sis/style/se1/PointPlacementTest.java | 0
.../apache/sis/style/se1/PointSymbolizerTest.java | 0
.../sis/style/se1/PolygonSymbolizerTest.java | 0
.../apache/sis/style/se1/RasterSymbolizerTest.java | 0
.../test}/org/apache/sis/style/se1/RuleTest.java | 0
.../apache/sis/style/se1/SelectedChannelTest.java | 0
.../org/apache/sis/style/se1/ShadedReliefTest.java | 0
.../test}/org/apache/sis/style/se1/StrokeTest.java | 0
.../org/apache/sis/style/se1/StyleTestCase.java | 0
.../org/apache/sis/style/se1/SymbolizerTest.java | 0
.../org/apache/sis/style/se1/SymbologyTest.java | 0
.../apache/sis/style/se1/TextSymbolizerTest.java | 0
.../test}/org/apache/sis/style/se1/XmlTest.java | 0
.../org.apache.sis.internal.jaxb.TypeRegistration | 4 +
.../main/module-info.java | 36 +
.../sis/internal/profile/fra/Constraints.java | 0
.../internal/profile/fra/DataIdentification.java | 0
.../profile/fra/DirectReferenceSystem.java | 0
.../profile/fra/IndirectReferenceSystem.java | 0
.../sis/internal/profile/fra/LegalConstraints.java | 0
.../sis/internal/profile/fra/ProfileTypes.java | 69 +
.../sis/internal/profile/fra/RenameOnImport.lst | 0
.../internal/profile/fra/SecurityConstraints.java | 0
.../sis/internal/profile/fra/package-info.java | 0
.../apache/sis/profile/france/FrenchProfile.java | 0
.../apache/sis/profile/france/package-info.java | 0
.../profile/fra/DataIdentificationTest.java | 0
.../internal/profile/fra/DirectReferenceSystem.xml | 0
.../profile/fra/DirectReferenceSystemTest.java | 0
.../sis/profile/france/FrenchProfileTest.java | 0
.../org.apache.sis.internal.netcdf.Convention | 5 +
.../ucar.nc2.dataset.spi.CoordSystemBuilderFactory | 4 +
.../main/module-info.java | 37 +
.../sis/internal/earth/netcdf/FactoryForUCAR.java | 0
.../apache/sis/internal/earth/netcdf/GCOM_C.java | 0
.../apache/sis/internal/earth/netcdf/GCOM_W.java | 0
.../sis/internal/earth/netcdf/package-info.java | 0
.../apache/sis/profile/japan/JapaneseProfile.java | 42 +
.../org/apache/sis/profile/japan/package-info.java | 0
.../apache/sis/profile/japan/JapanProfileTest.java | 0
.../main/module-info.java | 30 +
.../apache/sis/internal/gazetteer/Resources.java | 301 ++
.../sis/internal/gazetteer/Resources.properties | 43 +
.../sis/internal/gazetteer/Resources_en.java | 0
.../sis/internal/gazetteer/Resources_fr.java | 0
.../sis/internal/gazetteer/Resources_fr.properties | 48 +
.../referencing/gazetteer/AbstractLocation.java | 0
.../gazetteer/AbstractLocationType.java | 0
.../referencing/gazetteer/FinalLocationType.java | 0
.../referencing/gazetteer/GazetteerException.java | 0
.../referencing/gazetteer/GazetteerFactory.java | 105 +
.../gazetteer/GeohashReferenceSystem.java | 0
.../sis/referencing/gazetteer/LocationFormat.java | 0
.../gazetteer/MilitaryGridReferenceSystem.java | 0
.../gazetteer/ModifiableLocationType.java | 0
.../gazetteer/ReferenceVerifyException.java | 0
.../gazetteer/ReferencingByIdentifiers.java | 0
.../sis/referencing/gazetteer/SimpleLocation.java | 0
.../sis/referencing/gazetteer/package-info.java | 0
.../gazetteer/GazetteerFactoryTest.java | 0
.../gazetteer/GeohashReferenceSystemTest.java | 0
.../referencing/gazetteer/LocationFormatTest.java | 0
.../referencing/gazetteer/LocationTypeTest.java | 0
.../sis/referencing/gazetteer/LocationViewer.java | 0
.../gazetteer/MilitaryGridReferenceSystemTest.java | 0
.../gazetteer/ReferencingByIdentifiersTest.java | 0
.../main}/META-INF/GIGS.properties | 0
...org.apache.sis.internal.jaxb.AdapterReplacement | 4 +
.../org.apache.sis.internal.jaxb.TypeRegistration | 4 +
...pache.sis.internal.metadata.ReferencingServices | 4 +
...rg.apache.sis.internal.metadata.sql.Initializer | 4 +
...org.opengis.referencing.crs.CRSAuthorityFactory | 5 +
.../org.opengis.referencing.crs.CRSFactory | 4 +
.../org.opengis.referencing.cs.CSAuthorityFactory | 4 +
.../services/org.opengis.referencing.cs.CSFactory | 4 +
...opengis.referencing.datum.DatumAuthorityFactory | 4 +
.../org.opengis.referencing.datum.DatumFactory | 4 +
...g.operation.CoordinateOperationAuthorityFactory | 4 +
...eferencing.operation.CoordinateOperationFactory | 4 +
...ngis.referencing.operation.MathTransformFactory | 4 +
...g.opengis.referencing.operation.OperationMethod | 78 +
.../main/module-info.java | 218 ++
.../sis/geometry/AbstractDirectPosition.java | 0
.../org/apache/sis/geometry/AbstractEnvelope.java | 0
.../org/apache/sis/geometry/ArrayEnvelope.java | 0
.../org/apache/sis/geometry/CoordinateFormat.java | 1864 +++++++++++
.../org/apache/sis/geometry/CurveExtremum.java | 0
.../org/apache/sis/geometry/DirectPosition1D.java | 0
.../org/apache/sis/geometry/DirectPosition2D.java | 0
.../main}/org/apache/sis/geometry/Envelope2D.java | 0
.../org/apache/sis/geometry/EnvelopeReducer.java | 0
.../main}/org/apache/sis/geometry/Envelopes.java | 0
.../apache/sis/geometry/GeneralDirectPosition.java | 0
.../org/apache/sis/geometry/GeneralEnvelope.java | 0
.../org/apache/sis/geometry/ImmutableEnvelope.java | 0
.../main}/org/apache/sis/geometry/Shapes2D.java | 0
.../main}/org/apache/sis/geometry/SubEnvelope.java | 0
.../apache/sis/geometry/WraparoundAdjustment.java | 0
.../apache/sis/geometry/WraparoundInEnvelope.java | 0
.../org/apache/sis/geometry/WraparoundMethod.java | 0
.../apache/sis/geometry/doc-files/AntiMeridian.png | Bin
.../apache/sis/geometry/doc-files/ConicArea.png | Bin
.../org/apache/sis/geometry/doc-files/Contains.png | Bin
.../sis/geometry/doc-files/GeographicArea.png | Bin
.../org/apache/sis/geometry/package-info.java | 0
.../internal/jaxb/referencing/CC_Conversion.java | 0
.../jaxb/referencing/CC_CoordinateOperation.java | 0
.../referencing/CC_GeneralOperationParameter.java | 0
.../jaxb/referencing/CC_GeneralParameterValue.java | 0
.../jaxb/referencing/CC_OperationMethod.java | 0
.../jaxb/referencing/CC_OperationParameter.java | 0
.../referencing/CC_OperationParameterGroup.java | 0
.../internal/jaxb/referencing/CD_Ellipsoid.java | 0
.../jaxb/referencing/CD_EngineeringDatum.java | 0
.../jaxb/referencing/CD_GeodeticDatum.java | 0
.../internal/jaxb/referencing/CD_ImageDatum.java | 0
.../jaxb/referencing/CD_ParametricDatum.java | 0
.../internal/jaxb/referencing/CD_PixelInCell.java | 0
.../jaxb/referencing/CD_PrimeMeridian.java | 0
.../jaxb/referencing/CD_TemporalDatum.java | 0
.../jaxb/referencing/CD_VerticalDatum.java | 0
.../jaxb/referencing/CD_VerticalDatumType.java | 0
.../sis/internal/jaxb/referencing/CS_AffineCS.java | 0
.../jaxb/referencing/CS_AxisDirection.java | 0
.../internal/jaxb/referencing/CS_CartesianCS.java | 0
.../jaxb/referencing/CS_CoordinateSystem.java | 0
.../jaxb/referencing/CS_CoordinateSystemAxis.java | 0
.../jaxb/referencing/CS_CylindricalCS.java | 0
.../jaxb/referencing/CS_EllipsoidalCS.java | 0
.../sis/internal/jaxb/referencing/CS_LinearCS.java | 0
.../internal/jaxb/referencing/CS_ParametricCS.java | 0
.../sis/internal/jaxb/referencing/CS_PolarCS.java | 0
.../internal/jaxb/referencing/CS_RangeMeaning.java | 0
.../internal/jaxb/referencing/CS_SphericalCS.java | 0
.../sis/internal/jaxb/referencing/CS_TimeCS.java | 0
.../jaxb/referencing/CS_UserDefinedCS.java | 0
.../internal/jaxb/referencing/CS_VerticalCS.java | 0
.../apache/sis/internal/jaxb/referencing/Code.java | 0
.../internal/jaxb/referencing/RS_Identifier.java | 0
.../sis/internal/jaxb/referencing/SC_CRS.java | 0
.../jaxb/referencing/SC_DerivedCRSType.java | 0
.../internal/jaxb/referencing/SC_GeographicCRS.txt | 0
.../internal/jaxb/referencing/SC_SingleCRS.java | 0
.../internal/jaxb/referencing/SC_VerticalCRS.java | 89 +
.../jaxb/referencing/SecondDefiningParameter.java | 0
.../internal/jaxb/referencing/package-info.java | 0
.../sis/internal/referencing/AnnotatedMatrix.java | 0
.../sis/internal/referencing/Arithmetic.java | 0
.../sis/internal/referencing/AxesMapper.java | 0
.../sis/internal/referencing/AxisDirections.java | 0
.../internal/referencing/CoordinateOperations.java | 0
.../sis/internal/referencing/DatabaseListener.java | 71 +
.../referencing/DeferredCoordinateOperation.java | 0
.../internal/referencing/DefinitionVerifier.java | 0
.../sis/internal/referencing/DeprecatedCode.java | 0
.../sis/internal/referencing/DeprecatedName.java | 0
.../internal/referencing/DirectPositionView.java | 0
.../sis/internal/referencing/EPSGFactoryProxy.java | 0
.../internal/referencing/EPSGFactoryProxyCOP.java | 0
.../internal/referencing/EPSGFactoryProxyCRS.java | 0
.../internal/referencing/EPSGFactoryProxyCS.java | 0
.../referencing/EPSGFactoryProxyDatum.java | 0
.../internal/referencing/EPSGParameterDomain.java | 0
.../referencing/EllipsoidalHeightCombiner.java | 0
.../referencing/ExtendedPrecisionMatrix.java | 0
.../sis/internal/referencing/ExtentSelector.java | 0
.../apache/sis/internal/referencing/Formulas.java | 0
.../referencing/GeodeticObjectBuilder.java | 0
.../apache/sis/internal/referencing/LazySet.java | 0
.../apache/sis/internal/referencing/Legacy.java | 0
.../referencing/MathTransformsOrFactory.java | 0
.../sis/internal/referencing/MergedProperties.java | 0
.../internal/referencing/NilReferencingObject.java | 0
.../internal/referencing/PositionTransformer.java | 0
.../referencing/PositionalAccuracyConstant.java | 0
.../apache/sis/internal/referencing/RTreeNode.java | 0
.../referencing/ReferencingFactoryContainer.java | 0
.../sis/internal/referencing/ReferencingTypes.java | 76 +
.../internal/referencing/ReferencingUtilities.java | 0
.../apache/sis/internal/referencing/Resources.java | 795 +++++
.../sis/internal/referencing/Resources.properties | 132 +
.../sis/internal/referencing/Resources_en.java | 0
.../sis/internal/referencing/Resources_fr.java | 0
.../internal/referencing/Resources_fr.properties | 137 +
.../internal/referencing/ServicesForMetadata.java | 537 ++++
.../internal/referencing/SignReversalComment.java | 0
.../sis/internal/referencing/TemporalAccessor.java | 0
.../internal/referencing/VerticalDatumTypes.java | 0
.../sis/internal/referencing/WKTKeywords.java | 0
.../sis/internal/referencing/WKTUtilities.java | 0
.../internal/referencing/WraparoundApplicator.java | 0
.../internal/referencing/WraparoundAxesFinder.java | 0
.../internal/referencing/j2d/AbstractShape.java | 0
.../sis/internal/referencing/j2d/AffineMatrix.java | 0
.../referencing/j2d/AffineTransform2D.java | 0
.../sis/internal/referencing/j2d/Bezier.java | 0
.../referencing/j2d/ImmutableAffineTransform.java | 0
.../referencing/j2d/IntervalRectangle.java | 0
.../referencing/j2d/LinearTransform2D.java | 0
.../referencing/j2d/ParameterizedAffine.java | 0
.../internal/referencing/j2d/ShapeUtilities.java | 0
.../apache/sis/internal/referencing/j2d/Tile.java | 0
.../internal/referencing/j2d/TileOrganizer.java | 0
.../sis/internal/referencing/j2d/package-info.java | 0
.../sis/internal/referencing/package-info.java | 0
.../referencing/provider/AbridgedMolodensky.java | 0
.../referencing/provider/AbstractLambert.java | 0
.../referencing/provider/AbstractMercator.java | 0
.../referencing/provider/AbstractProvider.java | 0
.../provider/AbstractStereographic.java | 0
.../sis/internal/referencing/provider/Affine.java | 0
.../referencing/provider/AlbersEqualArea.java | 0
.../referencing/provider/AxisOrderReversal.java | 0
.../referencing/provider/AxisOrderReversal3D.java | 0
.../provider/AzimuthalEquidistantSpherical.java | 0
.../referencing/provider/CassiniSoldner.java | 0
.../provider/CoordinateFrameRotation.java | 0
.../provider/CoordinateFrameRotation2D.java | 0
.../provider/CoordinateFrameRotation3D.java | 0
.../provider/DatumShiftGridCompressed.java | 0
.../referencing/provider/DatumShiftGridFile.java | 0
.../referencing/provider/DatumShiftGridGroup.java | 0
.../referencing/provider/DatumShiftGridLoader.java | 0
.../referencing/provider/DatumShiftMethod.java | 0
.../internal/referencing/provider/Description.java | 0
.../referencing/provider/Descriptions.properties | 0
.../internal/referencing/provider/EPSGName.java | 0
.../sis/internal/referencing/provider/ESRI.java | 0
.../referencing/provider/Equirectangular.java | 0
.../provider/FranceGeocentricInterpolation.java | 0
.../referencing/provider/GeocentricAffine.java | 0
.../GeocentricAffineBetweenGeographic.java | 0
.../provider/GeocentricToGeographic.java | 0
.../provider/GeocentricToTopocentric.java | 0
.../provider/GeocentricTranslation.java | 0
.../provider/GeocentricTranslation2D.java | 0
.../provider/GeocentricTranslation3D.java | 0
.../referencing/provider/GeodeticOperation.java | 0
.../referencing/provider/Geographic2Dto3D.java | 0
.../referencing/provider/Geographic3Dto2D.java | 0
.../provider/Geographic3DtoVertical.txt | 0
.../provider/GeographicAndVerticalOffsets.java | 0
.../referencing/provider/GeographicOffsets.java | 0
.../referencing/provider/GeographicOffsets2D.java | 0
.../provider/GeographicRedimension.java | 0
.../provider/GeographicToGeocentric.java | 0
.../provider/GeographicToTopocentric.java | 0
.../provider/HyperbolicCassiniSoldner.java | 0
.../referencing/provider/Interpolation1D.java | 0
.../provider/LambertAzimuthalEqualArea.java | 0
.../LambertAzimuthalEqualAreaSpherical.java | 0
.../referencing/provider/LambertConformal1SP.java | 0
.../referencing/provider/LambertConformal2SP.java | 0
.../provider/LambertConformalBelgium.java | 0
.../provider/LambertConformalMichigan.java | 0
.../referencing/provider/LambertConformalWest.java | 0
.../provider/LambertCylindricalEqualArea.java | 0
.../LambertCylindricalEqualAreaSpherical.java | 0
.../referencing/provider/LongitudeRotation.java | 0
.../referencing/provider/MapProjection.java | 0
.../referencing/provider/MapProjection3D.java | 0
.../internal/referencing/provider/Mercator1SP.java | 0
.../internal/referencing/provider/Mercator2SP.java | 0
.../provider/MercatorAuxiliarySphere.java | 0
.../referencing/provider/MercatorSpherical.java | 0
.../referencing/provider/MillerCylindrical.java | 0
.../provider/ModifiedAzimuthalEquidistant.java | 0
.../internal/referencing/provider/Mollweide.java | 0
.../internal/referencing/provider/Molodensky.java | 0
.../provider/MolodenskyInterpolation.java | 0
.../sis/internal/referencing/provider/NADCON.java | 0
.../sis/internal/referencing/provider/NTv1.java | 0
.../sis/internal/referencing/provider/NTv2.java | 0
.../referencing/provider/NorthPoleRotation.java | 0
.../referencing/provider/ObliqueMercator.java | 0
.../provider/ObliqueMercatorCenter.java | 0
.../provider/ObliqueMercatorTwoPoints.java | 0
.../provider/ObliqueMercatorTwoPointsCenter.java | 0
.../referencing/provider/ObliqueStereographic.java | 0
.../referencing/provider/Orthographic.java | 0
.../referencing/provider/PolarStereographicA.java | 0
.../referencing/provider/PolarStereographicB.java | 0
.../referencing/provider/PolarStereographicC.java | 0
.../provider/PolarStereographicNorth.java | 0
.../provider/PolarStereographicSouth.java | 0
.../internal/referencing/provider/Polyconic.java | 0
.../referencing/provider/PositionVector7Param.java | 0
.../provider/PositionVector7Param2D.java | 0
.../provider/PositionVector7Param3D.java | 0
.../referencing/provider/PseudoMercator.java | 0
.../referencing/provider/PseudoPlateCarree.java | 0
.../referencing/provider/PseudoSinusoidal.java | 0
.../referencing/provider/RegionalMercator.java | 0
.../referencing/provider/SatelliteTracking.java | 0
.../internal/referencing/provider/Sinusoidal.java | 0
.../referencing/provider/SouthPoleRotation.java | 0
.../referencing/provider/TransverseMercator.java | 0
.../provider/TransverseMercatorSouth.java | 0
.../referencing/provider/VerticalOffset.java | 0
.../internal/referencing/provider/Wraparound.java | 0
.../provider/ZonedTransverseMercator.java | 0
.../referencing/provider/package-info.java | 0
.../org/apache/sis/io/wkt/AbstractParser.java | 0
.../main}/org/apache/sis/io/wkt/Colors.java | 0
.../main}/org/apache/sis/io/wkt/Convention.java | 0
.../main}/org/apache/sis/io/wkt/Element.java | 0
.../main}/org/apache/sis/io/wkt/ElementKind.java | 0
.../org/apache/sis/io/wkt/FormattableObject.java | 0
.../main}/org/apache/sis/io/wkt/Formatter.java | 0
.../apache/sis/io/wkt/GeodeticObjectParser.java | 0
.../main}/org/apache/sis/io/wkt/KeywordCase.java | 0
.../main}/org/apache/sis/io/wkt/KeywordStyle.java | 0
.../org/apache/sis/io/wkt/MathTransformParser.java | 0
.../main}/org/apache/sis/io/wkt/Parser.java | 0
.../org/apache/sis/io/wkt/SingletonElement.java | 0
.../main}/org/apache/sis/io/wkt/StoredTree.java | 0
.../main}/org/apache/sis/io/wkt/Symbols.java | 0
.../org/apache/sis/io/wkt/Transliterator.java | 0
.../sis/io/wkt/UnformattableObjectException.java | 0
.../sis/io/wkt/UnparsableObjectException.java | 0
.../main}/org/apache/sis/io/wkt/VerticalInfo.java | 0
.../main/org/apache/sis/io/wkt/WKTDictionary.java | 1124 +++++++
.../main}/org/apache/sis/io/wkt/WKTFormat.java | 0
.../main}/org/apache/sis/io/wkt/Warnings.java | 0
.../main}/org/apache/sis/io/wkt/doc-files/ESRI.txt | 0
.../main}/org/apache/sis/io/wkt/package-info.java | 0
.../sis/parameter/AbstractParameterDescriptor.java | 0
.../sis/parameter/AbstractParameterValue.txt | 0
.../sis/parameter/DefaultParameterDescriptor.java | 0
.../parameter/DefaultParameterDescriptorGroup.java | 0
.../sis/parameter/DefaultParameterValue.java | 0
.../sis/parameter/DefaultParameterValueGroup.java | 0
.../apache/sis/parameter/FilteredParameters.java | 0
.../org/apache/sis/parameter/IntegerList.java | 0
.../sis/parameter/MapProjectionDescriptor.java | 0
.../sis/parameter/MapProjectionParameters.java | 0
.../org/apache/sis/parameter/MatrixParameters.java | 0
.../sis/parameter/MatrixParametersAlphaNum.java | 0
.../org/apache/sis/parameter/ParameterBuilder.java | 0
.../org/apache/sis/parameter/ParameterFormat.java | 0
.../apache/sis/parameter/ParameterTableRow.java | 0
.../apache/sis/parameter/ParameterValueList.java | 0
.../org/apache/sis/parameter/Parameterized.java | 0
.../main}/org/apache/sis/parameter/Parameters.java | 0
.../org/apache/sis/parameter/TensorParameters.java | 840 +++++
.../org/apache/sis/parameter/TensorValues.java | 0
.../sis/parameter/UninitializedParameter.java | 0
.../sis/parameter/UnmodifiableParameterValue.java | 0
.../parameter/UnmodifiableParameterValueGroup.java | 0
.../main}/org/apache/sis/parameter/Verifier.java | 0
.../org/apache/sis/parameter/package-info.java | 0
.../sis/referencing/AbstractIdentifiedObject.java | 0
.../sis/referencing/AbstractReferenceSystem.java | 0
.../apache/sis/referencing/AuthorityFactories.java | 251 ++
.../main}/org/apache/sis/referencing/Builder.java | 0
.../main/org/apache/sis/referencing/CRS.java | 1488 +++++++++
.../main/org/apache/sis/referencing/CommonCRS.java | 2052 ++++++++++++
.../sis/referencing/EPSGFactoryFallback.java | 0
.../referencing/EllipsoidalHeightSeparator.java | 0
.../sis/referencing/GeodesicsOnEllipsoid.java | 0
.../apache/sis/referencing/GeodeticCalculator.java | 0
.../apache/sis/referencing/GeodeticException.java | 0
.../apache/sis/referencing/IdentifiedObjects.java | 0
.../sis/referencing/ImmutableIdentifier.java | 0
.../org/apache/sis/referencing/NameIterator.java | 0
.../apache/sis/referencing/NamedIdentifier.java | 572 ++++
.../org/apache/sis/referencing/Properties.java | 0
.../sis/referencing/PropertiesConverter.java | 0
.../sis/referencing/StandardDefinitions.java | 0
.../main}/org/apache/sis/referencing/SubTypes.java | 0
.../apache/sis/referencing/crs/AbstractCRS.java | 0
.../sis/referencing/crs/AbstractDerivedCRS.java | 0
.../apache/sis/referencing/crs/ConversionKeys.java | 0
.../sis/referencing/crs/DefaultCompoundCRS.java | 661 ++++
.../sis/referencing/crs/DefaultDerivedCRS.java | 0
.../sis/referencing/crs/DefaultEngineeringCRS.java | 0
.../sis/referencing/crs/DefaultGeocentricCRS.java | 0
.../sis/referencing/crs/DefaultGeodeticCRS.java | 0
.../sis/referencing/crs/DefaultGeographicCRS.java | 0
.../sis/referencing/crs/DefaultImageCRS.java | 0
.../sis/referencing/crs/DefaultParametricCRS.java | 0
.../sis/referencing/crs/DefaultProjectedCRS.java | 0
.../sis/referencing/crs/DefaultTemporalCRS.java | 525 ++++
.../sis/referencing/crs/DefaultVerticalCRS.java | 0
.../sis/referencing/crs/ExplicitParameters.java | 0
.../sis/referencing/crs/SC_GeographicCRS.java | 0
.../org/apache/sis/referencing/crs/SubTypes.java | 0
.../apache/sis/referencing/crs/package-info.java | 0
.../org/apache/sis/referencing/cs/AbstractCS.java | 0
.../apache/sis/referencing/cs/AxesConvention.java | 0
.../org/apache/sis/referencing/cs/AxisFilter.java | 0
.../org/apache/sis/referencing/cs/AxisName.java | 0
.../main}/org/apache/sis/referencing/cs/Codes.java | 0
.../sis/referencing/cs/CoordinateSystems.java | 0
.../apache/sis/referencing/cs/DefaultAffineCS.java | 0
.../sis/referencing/cs/DefaultCartesianCS.java | 0
.../sis/referencing/cs/DefaultCompoundCS.java | 0
.../cs/DefaultCoordinateSystemAxis.java | 0
.../sis/referencing/cs/DefaultCylindricalCS.java | 0
.../sis/referencing/cs/DefaultEllipsoidalCS.java | 0
.../apache/sis/referencing/cs/DefaultLinearCS.java | 0
.../sis/referencing/cs/DefaultParametricCS.java | 0
.../apache/sis/referencing/cs/DefaultPolarCS.java | 0
.../sis/referencing/cs/DefaultSphericalCS.java | 0
.../apache/sis/referencing/cs/DefaultTimeCS.java | 0
.../sis/referencing/cs/DefaultUserDefinedCS.java | 0
.../sis/referencing/cs/DefaultVerticalCS.java | 0
.../sis/referencing/cs/DirectionAlongMeridian.java | 0
.../org/apache/sis/referencing/cs/Normalizer.java | 0
.../org/apache/sis/referencing/cs/SubTypes.java | 0
.../apache/sis/referencing/cs/package-info.java | 0
.../sis/referencing/datum/AbstractDatum.java | 0
.../sis/referencing/datum/BursaWolfParameters.java | 0
.../sis/referencing/datum/DatumShiftGrid.java | 0
.../sis/referencing/datum/DefaultEllipsoid.java | 0
.../referencing/datum/DefaultEngineeringDatum.java | 0
.../referencing/datum/DefaultGeodeticDatum.java | 0
.../sis/referencing/datum/DefaultImageDatum.java | 0
.../referencing/datum/DefaultParametricDatum.java | 0
.../referencing/datum/DefaultPrimeMeridian.java | 0
.../referencing/datum/DefaultTemporalDatum.java | 0
.../referencing/datum/DefaultVerticalDatum.java | 0
.../org/apache/sis/referencing/datum/Sphere.java | 0
.../org/apache/sis/referencing/datum/SubTypes.java | 0
.../sis/referencing/datum/TimeDependentBWP.java | 0
.../org/apache/sis/referencing/datum/formulas.html | 0
.../apache/sis/referencing/datum/package-info.java | 0
.../factory/AuthorityFactoryIdentifier.java | 0
.../referencing/factory/AuthorityFactoryProxy.java | 0
.../sis/referencing/factory/CacheRecord.java | 0
.../referencing/factory/CommonAuthorityCode.java | 0
.../factory/CommonAuthorityFactory.java | 0
.../factory/ConcurrentAuthorityFactory.java | 0
.../referencing/factory/FactoryDataException.java | 0
.../sis/referencing/factory/FilteredCodes.java | 0
.../factory/GeodeticAuthorityFactory.java | 0
.../referencing/factory/GeodeticObjectFactory.java | 1727 ++++++++++
.../factory/IdentifiedObjectFinder.java | 0
.../referencing/factory/IdentifiedObjectSet.java | 0
.../factory/InvalidGeodeticParameterException.java | 0
.../factory/LazySynchronizedIterator.java | 0
.../factory/MissingFactoryResourceException.java | 0
.../factory/MultiAuthoritiesFactory.java | 0
.../factory/NoSuchAuthorityFactoryException.java | 0
.../sis/referencing/factory/ReferenceKeeper.java | 0
.../factory/UnavailableFactoryException.java | 0
.../sis/referencing/factory/package-info.java | 0
.../referencing/factory/sql/AuthorityCodes.java | 0
.../sis/referencing/factory/sql/AxisName.java | 0
.../sis/referencing/factory/sql/BursaWolfInfo.java | 0
.../factory/sql/CloseableReference.java | 0
.../factory/sql/CoordinateOperationSet.java | 0
.../referencing/factory/sql/EPSGCodeFinder.java | 0
.../referencing/factory/sql/EPSGDataAccess.java | 3320 ++++++++++++++++++++
.../sis/referencing/factory/sql/EPSGFactory.java | 544 ++++
.../sis/referencing/factory/sql/EPSGInstaller.java | 311 ++
.../sis/referencing/factory/sql/EPSG_Finish.sql | 0
.../sis/referencing/factory/sql/EPSG_Prepare.sql | 0
.../sis/referencing/factory/sql/EPSG_README.txt | 0
.../factory/sql/InstallationScriptProvider.java | 380 +++
.../sis/referencing/factory/sql/SQLTranslator.java | 0
.../sis/referencing/factory/sql/TableInfo.java | 0
.../sis/referencing/factory/sql/package-info.java | 92 +
.../operation/AbstractCoordinateOperation.java | 1204 +++++++
.../operation/AbstractSingleOperation.java | 0
.../apache/sis/referencing/operation/CRSPair.java | 0
.../operation/CoordinateOperationContext.java | 0
.../operation/CoordinateOperationFinder.java | 0
.../operation/CoordinateOperationRegistry.java | 0
.../operation/CoordinateOperationSorter.java | 0
.../operation/DefaultConcatenatedOperation.java | 0
.../operation/DefaultConicProjection.java | 0
.../referencing/operation/DefaultConversion.java | 0
.../DefaultCoordinateOperationFactory.java | 0
.../operation/DefaultCylindricalProjection.java | 0
.../sis/referencing/operation/DefaultFormula.java | 0
.../operation/DefaultOperationMethod.java | 0
.../operation/DefaultPassThroughOperation.java | 0
.../operation/DefaultPlanarProjection.java | 0
.../referencing/operation/DefaultProjection.java | 0
.../operation/DefaultTransformation.java | 0
.../operation/InverseOperationMethod.java | 0
.../operation/LooselyDefinedMethod.java | 0
.../operation/MathTransformContext.java | 0
.../operation/MismatchedDatumException.java | 0
.../referencing/operation/SubOperationInfo.java | 383 +++
.../apache/sis/referencing/operation/SubTypes.java | 0
.../operation/builder/LinearTransformBuilder.java | 0
.../referencing/operation/builder/Linearizer.java | 0
.../operation/builder/LocalizationGridBuilder.java | 0
.../builder/LocalizationGridException.java | 0
.../operation/builder/ProjectedTransformTry.java | 0
.../operation/builder/ResidualGrid.java | 0
.../operation/builder/TransformBuilder.java | 0
.../operation/builder/package-info.java | 0
.../sis/referencing/operation/builder/readme.html | 0
.../operation/matrix/AffineTransforms2D.java | 0
.../operation/matrix/GeneralMatrix.java | 0
.../sis/referencing/operation/matrix/Matrices.java | 0
.../sis/referencing/operation/matrix/Matrix1.java | 0
.../sis/referencing/operation/matrix/Matrix2.java | 0
.../sis/referencing/operation/matrix/Matrix3.java | 0
.../sis/referencing/operation/matrix/Matrix4.java | 0
.../referencing/operation/matrix/MatrixSIS.java | 815 +++++
.../matrix/MismatchedMatrixSizeException.java | 0
.../operation/matrix/NonSquareMatrix.java | 0
.../matrix/NoninvertibleMatrixException.java | 0
.../sis/referencing/operation/matrix/Solver.java | 0
.../operation/matrix/UnmodifiableMatrix.java | 0
.../operation/matrix/doc-files/AffineTransform.png | Bin
.../operation/matrix/doc-files/scaleX0.png | Bin
.../operation/matrix/doc-files/scaleY0.png | Bin
.../referencing/operation/matrix/package-info.java | 0
.../sis/referencing/operation/package-info.java | 0
.../operation/projection/AlbersEqualArea.java | 0
.../operation/projection/AuthalicConversion.java | 0
.../operation/projection/AuthalicMercator.java | 0
.../operation/projection/AzimuthalEquidistant.java | 0
.../operation/projection/CassiniSoldner.java | 0
.../operation/projection/ConformalProjection.java | 0
.../operation/projection/CylindricalEqualArea.java | 0
.../operation/projection/Initializer.java | 0
.../referencing/operation/projection/Inverter.java | 0
.../projection/LambertAzimuthalEqualArea.java | 0
.../projection/LambertConicConformal.java | 0
.../operation/projection/LongitudeWraparound.java | 0
.../referencing/operation/projection/Mercator.java | 0
.../operation/projection/MeridianArcBased.java | 0
.../projection/ModifiedAzimuthalEquidistant.java | 0
.../operation/projection/Mollweide.java | 0
.../operation/projection/NormalizedProjection.java | 0
.../operation/projection/ObliqueMercator.java | 0
.../operation/projection/ObliqueStereographic.java | 0
.../operation/projection/Orthographic.java | 0
.../operation/projection/PolarStereographic.java | 0
.../operation/projection/Polyconic.java | 0
.../operation/projection/ProjectionException.java | 0
.../operation/projection/ProjectionVariant.java | 0
.../operation/projection/SatelliteTracking.java | 0
.../operation/projection/Sinusoidal.java | 0
.../operation/projection/TransverseMercator.java | 0
.../operation/projection/ZonedGridSystem.java | 0
.../operation/projection/package-info.java | 0
.../transform/AbridgedMolodenskyTransform2D.java | 108 +
.../transform/AbstractLinearTransform.java | 0
.../operation/transform/AbstractMathTransform.java | 0
.../transform/AbstractMathTransform1D.java | 0
.../transform/AbstractMathTransform2D.java | 0
.../operation/transform/CartesianToPolar.java | 0
.../operation/transform/CartesianToSpherical.java | 0
.../operation/transform/ConcatenatedTransform.java | 0
.../transform/ConcatenatedTransform1D.java | 0
.../transform/ConcatenatedTransform2D.java | 0
.../transform/ConcatenatedTransformDirect.java | 0
.../transform/ConcatenatedTransformDirect1D.java | 0
.../transform/ConcatenatedTransformDirect2D.java | 0
.../operation/transform/ConstantTransform1D.java | 0
.../operation/transform/ContextualParameter.java | 0
.../operation/transform/ContextualParameters.java | 0
.../transform/CoordinateSystemTransform.java | 0
.../operation/transform/CopyTransform.java | 0
.../operation/transform/DatumShiftTransform.java | 338 ++
.../transform/DefaultMathTransformFactory.java | 1783 +++++++++++
.../operation/transform/DomainDefinition.java | 0
.../transform/EllipsoidToCentricTransform.java | 1045 ++++++
.../transform/ExponentialTransform1D.java | 0
.../operation/transform/IdentityTransform.java | 0
.../operation/transform/IdentityTransform1D.java | 0
.../transform/InterpolatedGeocentricTransform.java | 0
.../InterpolatedGeocentricTransform2D.java | 0
.../transform/InterpolatedMolodenskyTransform.java | 0
.../InterpolatedMolodenskyTransform2D.java | 0
.../operation/transform/InterpolatedTransform.java | 0
.../transform/InterpolatedTransform2D.java | 0
.../operation/transform/IterationStrategy.java | 0
.../operation/transform/LinearInterpolator1D.java | 0
.../operation/transform/LinearTransform.java | 0
.../operation/transform/LinearTransform1D.java | 0
.../transform/LogarithmicTransform1D.java | 0
.../operation/transform/MathTransformProvider.java | 120 +
.../operation/transform/MathTransforms.java | 0
.../operation/transform/MolodenskyFormula.java | 0
.../operation/transform/MolodenskyTransform.java | 0
.../operation/transform/MolodenskyTransform2D.java | 0
.../operation/transform/OperationMethodSet.java | 0
.../operation/transform/PassThroughTransform.java | 0
.../transform/PassThroughTransform2D.java | 0
.../operation/transform/PolarToCartesian.java | 0
.../operation/transform/PoleRotation.java | 0
.../operation/transform/PowerTransform1D.java | 0
.../operation/transform/ProjectiveTransform.java | 0
.../operation/transform/ProjectiveTransform2D.java | 0
.../operation/transform/ScaleTransform.java | 0
.../transform/SpecializableTransform.java | 0
.../transform/SpecializableTransform1D.txt | 0
.../transform/SpecializableTransform2D.java | 0
.../operation/transform/SphericalToCartesian.java | 0
.../operation/transform/TransferFunction.java | 0
.../operation/transform/TransformAdapter2D.java | 0
.../operation/transform/TransformSeparator.java | 0
.../operation/transform/TranslationTransform.java | 0
.../operation/transform/UnitConversion.java | 0
.../operation/transform/WraparoundTransform.java | 0
.../referencing/operation/transform/formulas.html | 0
.../operation/transform/package-info.java | 0
.../org/apache/sis/referencing/package-info.java | 0
.../sis/geometry/AbstractDirectPositionTest.java | 0
.../apache/sis/geometry/AbstractEnvelopeTest.java | 0
.../org/apache/sis/geometry/ArrayEnvelopeTest.java | 0
.../apache/sis/geometry/CoordinateFormatTest.java | 0
.../org/apache/sis/geometry/CurveExtremumTest.java | 0
.../apache/sis/geometry/DirectPosition1DTest.java | 0
.../apache/sis/geometry/DirectPosition2DTest.java | 0
.../org/apache/sis/geometry/Envelope2DTest.java | 0
.../apache/sis/geometry/EnvelopeReducerTest.java | 0
.../org/apache/sis/geometry/EnvelopesTest.java | 0
.../sis/geometry/GeneralDirectPositionTest.java | 0
.../apache/sis/geometry/GeneralEnvelopeTest.java | 0
.../apache/sis/geometry/ImmutableEnvelopeTest.java | 0
.../org/apache/sis/geometry/Shapes2DTest.java | 0
.../org/apache/sis/geometry/SubEnvelopeTest.java | 0
.../org/apache/sis/geometry/TransformTestCase.java | 0
.../sis/geometry/WraparoundAdjustmentTest.java | 0
.../CC_GeneralOperationParameterTest.java | 0
.../CC_OperationParameterGroupTest.java | 0
.../sis/internal/jaxb/referencing/CodeTest.java | 0
.../referencing/SecondDefiningParameterTest.java | 0
.../sis/internal/referencing/AxesMapperTest.java | 0
.../internal/referencing/AxisDirectionsTest.java | 0
.../referencing/CoordinateOperationsTest.java | 0
.../referencing/DefinitionVerifierTest.java | 0
.../referencing/EllipsoidalHeightCombinerTest.java | 0
.../internal/referencing/ExtentSelectorTest.java | 0
.../sis/internal/referencing/FormulasTest.java | 0
.../referencing/GeodeticObjectBuilderTest.java | 0
.../sis/internal/referencing/LazySetTest.java | 0
.../PositionalAccuracyConstantTest.java | 0
.../referencing/ReferencingUtilitiesTest.java | 0
.../referencing/ServicesForMetadataTest.java | 0
.../referencing/VerticalDatumTypesTest.java | 0
.../sis/internal/referencing/WKTKeywordsTest.java | 0
.../sis/internal/referencing/WKTUtilitiesTest.java | 0
.../referencing/WraparoundApplicatorTest.java | 0
.../referencing/j2d/AbstractShapeTest.java | 0
.../referencing/j2d/ShapeUtilitiesExt.java | 0
.../referencing/j2d/ShapeUtilitiesTest.java | 0
.../referencing/j2d/ShapeUtilitiesViewer.java | 0
.../internal/referencing/provider/AffineTest.java | 0
.../provider/CoordinateFrameRotationTest.java | 0
.../provider/DatumShiftGridCompressedTest.java | 0
.../provider/DatumShiftGridFileTest.java | 0
.../referencing/provider/DatumShiftTestCase.java | 0
.../FranceGeocentricInterpolationTest.java | 0
.../referencing/provider/GR3DF-extract.txt | 0
.../provider/GeocentricTranslationTest.java | 0
.../referencing/provider/Geographic3Dto2DTest.java | 0
.../provider/GeographicOffsetsTest.java | 0
.../provider/LongitudeRotationTest.java | 0
.../referencing/provider/MapProjectionTest.java | 0
.../referencing/provider/MolodenskyTest.java | 0
.../internal/referencing/provider/NADCONTest.java | 0
.../referencing/provider/NTF_R93-extract.gsb | Bin
.../internal/referencing/provider/NTv2Test.java | 0
.../provider/ParameterNameTableGenerator.java | 0
.../provider/PositionVector7ParamTest.java | 0
.../referencing/provider/ProviderMock.java | 0
.../referencing/provider/ProvidersTest.java | 0
.../referencing/provider/SeismicBinGridMock.java | 0
.../provider/TransverseMercatorTest.java | 0
.../referencing/provider/conus-extract.laa | 0
.../referencing/provider/conus-extract.loa | 0
.../test}/org/apache/sis/io/wkt/ColorsTest.java | 0
.../org/apache/sis/io/wkt/ComparisonWithEPSG.java | 0
.../org/apache/sis/io/wkt/ConventionTest.java | 0
.../test}/org/apache/sis/io/wkt/ElementTest.java | 0
.../test}/org/apache/sis/io/wkt/ExtraCRS.txt | 0
.../test}/org/apache/sis/io/wkt/FormatterTest.java | 0
.../sis/io/wkt/GeodeticObjectParserTest.java | 0
.../test}/org/apache/sis/io/wkt/Malformed.txt | 0
.../apache/sis/io/wkt/MathTransformParserTest.java | 0
.../test}/org/apache/sis/io/wkt/SymbolsTest.java | 0
.../org/apache/sis/io/wkt/TransliteratorTest.java | 0
.../org/apache/sis/io/wkt/WKTDictionaryTest.java | 0
.../test}/org/apache/sis/io/wkt/WKTFormatTest.java | 0
.../test/org/apache/sis/io/wkt/WKTParserTest.java | 700 +++++
.../DefaultParameterDescriptorGroupTest.java | 0
.../parameter/DefaultParameterDescriptorTest.java | 0
.../parameter/DefaultParameterValueGroupTest.java | 0
.../sis/parameter/DefaultParameterValueTest.java | 0
.../apache/sis/parameter/DuplicatedParameters.xml | 0
.../sis/parameter/MapProjectionParametersTest.java | 0
.../parameter/MatrixParametersAlphaNumTest.java | 0
.../apache/sis/parameter/MatrixParametersTest.java | 0
.../apache/sis/parameter/ParameterBuilderTest.java | 0
.../sis/parameter/ParameterDescriptorGroup.xml | 0
.../apache/sis/parameter/ParameterFormatTest.java | 0
.../sis/parameter/ParameterMarshallingTest.java | 0
.../apache/sis/parameter/ParameterValueGroup.xml | 0
.../sis/parameter/ParameterValueGroupWrapper.java | 0
.../org/apache/sis/parameter/ParametersTest.java | 0
.../apache/sis/parameter/TensorParametersTest.java | 0
.../org/apache/sis/parameter/TensorValuesTest.java | 0
.../UnmodifiableParameterValueGroupTest.java | 0
.../parameter/UnmodifiableParameterValueTest.java | 0
.../referencing/AbstractIdentifiedObjectTest.java | 0
.../referencing/AbstractReferenceSystemTest.java | 0
.../org/apache/sis/referencing/Assertions.java | 538 ++++
.../sis/referencing/AuthorityFactoriesTest.java | 0
.../org/apache/sis/referencing/BuilderMock.java | 0
.../org/apache/sis/referencing/BuilderTest.java | 0
.../test}/org/apache/sis/referencing/CRSTest.java | 0
.../apache/sis/referencing/ClenshawSummation.java | 0
.../org/apache/sis/referencing/CommonCRSTest.java | 0
.../sis/referencing/EPSGFactoryFallbackTest.java | 0
.../sis/referencing/GeodesicsOnEllipsoidTest.java | 0
.../sis/referencing/GeodeticCalculatorTest.java | 0
.../sis/referencing/GeodeticObjectVerifier.java | 0
.../sis/referencing/IdentifiedObjectsTest.java | 0
.../sis/referencing/ImmutableIdentifierTest.java | 0
.../sis/referencing/NamedIdentifierTest.java | 0
.../sis/referencing/StandardDefinitionsTest.java | 0
.../sis/referencing/crs/AbstractCRSTest.java | 0
.../org/apache/sis/referencing/crs/CompoundCRS.xml | 0
.../referencing/crs/DefaultCompoundCRSTest.java | 0
.../sis/referencing/crs/DefaultDerivedCRSTest.java | 0
.../referencing/crs/DefaultEngineeringCRSTest.java | 0
.../referencing/crs/DefaultGeocentricCRSTest.java | 0
.../referencing/crs/DefaultGeodeticCRSTest.java | 0
.../referencing/crs/DefaultGeographicCRSTest.java | 0
.../sis/referencing/crs/DefaultImageCRSTest.java | 0
.../referencing/crs/DefaultProjectedCRSTest.java | 0
.../referencing/crs/DefaultTemporalCRSTest.java | 0
.../referencing/crs/DefaultVerticalCRSTest.java | 0
.../org/apache/sis/referencing/crs/DerivedCRS.xml | 0
.../apache/sis/referencing/crs/GeographicCRS.xml | 0
.../apache/sis/referencing/crs/HardCodedCRS.java | 0
.../sis/referencing/crs/HardCodedCRSTest.java | 0
.../apache/sis/referencing/crs/ProjectedCRS.xml | 0
.../apache/sis/referencing/crs/SubTypesTest.java | 0
.../apache/sis/referencing/cs/AbstractCSTest.java | 0
.../org/apache/sis/referencing/cs/CartesianCS.xml | 0
.../org/apache/sis/referencing/cs/CodesTest.java | 0
.../sis/referencing/cs/CoordinateSystemsTest.java | 0
.../sis/referencing/cs/DefaultCartesianCSTest.java | 0
.../sis/referencing/cs/DefaultCompoundCSTest.java | 0
.../cs/DefaultCoordinateSystemAxisTest.java | 0
.../referencing/cs/DefaultCylindricalCSTest.java | 0
.../referencing/cs/DefaultEllipsoidalCSTest.java | 0
.../sis/referencing/cs/DefaultPolarCSTest.java | 0
.../sis/referencing/cs/DefaultSphericalCSTest.java | 0
.../referencing/cs/DirectionAlongMeridianTest.java | 0
.../apache/sis/referencing/cs/EllipsoidalCS.xml | 0
.../apache/sis/referencing/cs/HardCodedAxes.java | 0
.../org/apache/sis/referencing/cs/HardCodedCS.java | 0
.../apache/sis/referencing/cs/HardCodedCSTest.java | 0
.../apache/sis/referencing/cs/NormalizerTest.java | 0
.../referencing/datum/BursaWolfParametersTest.java | 0
.../referencing/datum/DefaultEllipsoidTest.java | 0
.../datum/DefaultGeodeticDatumTest.java | 0
.../datum/DefaultPrimeMeridianTest.java | 0
.../datum/DefaultTemporalDatumTest.java | 0
.../datum/DefaultVerticalDatumTest.java | 0
.../org/apache/sis/referencing/datum/Ellipsoid.xml | 0
.../apache/sis/referencing/datum/GeodeticDatum.xml | 0
.../sis/referencing/datum/GeodeticDatumMock.java | 0
.../org/apache/sis/referencing/datum/Greenwich.xml | 0
.../sis/referencing/datum/HardCodedDatum.java | 0
.../apache/sis/referencing/datum/PrimeMeridian.xml | 0
.../sis/referencing/datum/PrimeMeridianMock.java | 0
.../org/apache/sis/referencing/datum/Sphere.xml | 0
.../apache/sis/referencing/datum/TemporalDatum.xml | 0
.../referencing/datum/TimeDependentBWPTest.java | 0
.../referencing/datum/VerticalDatum (GML 3.1).xml | 0
.../apache/sis/referencing/datum/VerticalDatum.xml | 0
.../referencing/factory/AuthorityFactoryMock.java | 0
.../factory/AuthorityFactoryProxyTest.java | 0
.../factory/CommonAuthorityFactoryTest.java | 0
.../factory/ConcurrentAuthorityFactoryTest.java | 0
.../factory/GeodeticObjectFactoryTest.java | 0
.../factory/IdentifiedObjectFinderTest.java | 0
.../factory/MultiAuthoritiesFactoryTest.java | 0
.../sis/referencing/factory/TestFactorySource.java | 0
.../referencing/factory/sql/EPSGFactoryTest.java | 0
.../referencing/factory/sql/EPSGInstallerTest.java | 0
.../sis/referencing/factory/sql/TableInfoTest.java | 0
.../factory/sql/epsg/DataScriptFormatter.java | 0
.../factory/sql/epsg/DataScriptFormatterTest.java | 0
.../referencing/factory/sql/epsg/DebugTools.sql | 0
.../sis/referencing/factory/sql/epsg/package.html | 0
.../referencing/geoapi/AuthorityFactoryTest.java | 0
.../geoapi/ParameterizedTransformTest.java | 0
.../operation/ConcatenatedOperation.xml | 0
.../sis/referencing/operation/Conversion.xml | 0
.../operation/CoordinateOperationFinderTest.java | 0
.../operation/CoordinateOperationRegistryTest.java | 0
.../DefaultConcatenatedOperationTest.java | 0
.../operation/DefaultConversionTest.java | 0
.../DefaultCoordinateOperationFactoryTest.java | 0
.../referencing/operation/DefaultFormulaTest.java | 0
.../operation/DefaultOperationMethodTest.java | 0
.../operation/DefaultPassThroughOperationTest.java | 0
.../operation/DefaultTransformationTest.java | 0
.../operation/HardCodedConversions.java | 0
.../referencing/operation/PassThroughOperation.xml | 0
.../operation/SingleOperationMarshallingTest.java | 0
.../sis/referencing/operation/Transformation.xml | 0
.../builder/LinearTransformBuilderTest.java | 0
.../operation/builder/LinearizerTest.java | 0
.../builder/LocalizationGridBuilderTest.java | 0
.../operation/builder/NonLinearTransform.java | 0
.../operation/builder/ResidualGridTest.java | 0
.../operation/matrix/AffineTransforms2DTest.java | 0
.../operation/matrix/GeneralMatrixTest.java | 0
.../referencing/operation/matrix/MatricesTest.java | 0
.../referencing/operation/matrix/Matrix1Test.java | 0
.../referencing/operation/matrix/Matrix2Test.java | 0
.../referencing/operation/matrix/Matrix3Test.java | 0
.../referencing/operation/matrix/Matrix4Test.java | 0
.../operation/matrix/MatrixTestCase.java | 0
.../operation/matrix/NonSquareMatrixTest.java | 0
.../referencing/operation/matrix/SolverTest.java | 0
.../operation/projection/AlbersEqualAreaTest.java | 0
.../projection/AuthalicConversionTest.java | 0
.../projection/AzimuthalEquidistantTest.java | 0
.../operation/projection/Benchmark.java | 0
.../operation/projection/CassiniSoldnerTest.java | 0
.../projection/ConformalProjectionTest.java | 0
.../projection/CylindricalEqualAreaTest.java | 0
.../operation/projection/EquirectangularTest.java | 0
.../operation/projection/InitializerTest.java | 0
.../projection/LambertAzimuthalEqualAreaTest.java | 0
.../projection/LambertConicConformalTest.java | 0
.../projection/MapProjectionTestCase.java | 0
.../projection/MercatorMethodComparison.java | 0
.../operation/projection/MercatorTest.java | 0
.../operation/projection/MeridianArcTest.java | 0
.../ModifiedAzimuthalEquidistantTest.java | 0
.../operation/projection/MollweideTest.java | 0
.../sis/referencing/operation/projection/NoOp.java | 0
.../projection/NormalizedProjectionTest.java | 0
.../operation/projection/ObliqueMercatorTest.java | 0
.../projection/ObliqueStereographicTest.java | 0
.../operation/projection/OrthographicTest.java | 0
.../projection/PolarStereographicTest.java | 0
.../operation/projection/PolyconicTest.java | 0
.../projection/ProjectionResultComparator.java | 0
.../projection/SatelliteTrackingTest.java | 0
.../operation/projection/SinusoidalTest.java | 0
.../projection/TransverseMercatorTest.java | 0
.../operation/projection/ZonedGridSystemTest.java | 0
.../doc-files/TransverseMercatorErrors.png | Bin
.../transform/AbridgedMolodenskyTransformTest.java | 0
.../transform/AbstractMathTransformTest.java | 0
.../operation/transform/CartesianToPolarTest.java | 0
.../transform/CartesianToSphericalTest.java | 0
.../transform/ConcatenatedTransformTest.java | 0
.../transform/ContextualParametersTest.java | 0
.../operation/transform/CoordinateDomain.java | 0
.../operation/transform/CoordinateDomainTest.java | 0
.../transform/CoordinateSystemTransformTest.java | 0
.../operation/transform/CopyTransformTest.java | 0
.../transform/DefaultMathTransformFactoryTest.java | 401 +++
.../operation/transform/DomainDefinitionTest.java | 0
.../transform/EllipsoidToCentricTransformTest.java | 0
.../transform/ExponentialTransform1DTest.java | 0
.../InterpolatedGeocentricTransformTest.java | 0
.../InterpolatedMolodenskyTransformTest.java | 0
.../transform/InterpolatedTransformTest.java | 0
.../operation/transform/IterationStrategyTest.java | 0
.../transform/LinearInterpolator1DTest.java | 0
.../operation/transform/LinearTransformTest.java | 0
.../transform/LogarithmicTransform1DTest.java | 0
.../transform/MathTransformFactoryBase.java | 0
.../transform/MathTransformFactoryMock.java | 0
.../operation/transform/MathTransformTestCase.java | 0
.../operation/transform/MathTransformWrapper.java | 0
.../operation/transform/MathTransformsTest.java | 0
.../transform/MolodenskyTransformTest.java | 0
.../transform/OperationMethodSetTest.java | 0
.../transform/PassThroughTransformTest.java | 0
.../operation/transform/PolarToCartesianTest.java | 0
.../operation/transform/PoleRotationTest.java | 0
.../transform/ProjectiveTransformTest.java | 0
.../operation/transform/PseudoTransform.java | 0
.../transform/RandomFailureTransform.java | 0
.../operation/transform/ScaleTransformTest.java | 0
.../operation/transform/SinusoidalShiftGrid.java | 0
.../transform/SpecializableTransformTest.java | 0
.../transform/SphericalToCartesianTest.java | 0
.../operation/transform/TransferFunctionTest.java | 0
.../transform/TransformResultComparator.java | 0
.../transform/TransformSeparatorTest.java | 0
.../transform/TranslationTransformTest.java | 0
.../operation/transform/UnitConversionTest.java | 0
.../transform/WraparoundTransformTest.java | 0
.../report/CoordinateOperationMethods.java | 0
.../report/CoordinateReferenceSystems.java | 0
.../sis/referencing/report/HTMLGenerator.java | 0
.../sis/referencing/report/package-info.java | 0
.../sis/test/integration/ConsistencyTest.java | 0
.../test/integration/CoordinateOperationTest.java | 0
.../integration/CoordinateReferenceSystemTest.java | 0
.../sis/test/integration/DatumShiftTest.java | 0
.../integration/Metadata with vertical CRS.xml | 0
.../org/apache/sis/test/integration/Metadata.xml | 0
.../apache/sis/test/integration/MetadataTest.java | 0
.../sis/test/integration/MetadataVerticalTest.java | 0
.../apache/sis/test/integration/package-info.java | 0
.../org/apache/sis/test/widget/ShapeViewer.java | 0
.../apache/sis/test/widget/SwingAssertions.java | 0
.../org/apache/sis/test/widget/VisualCheck.java | 0
.../org/apache/sis/test/widget/package-info.java | 0
.../org.apache.sis.storage.DataStoreProvider | 4 +
.../main/module-info.java | 35 +
.../main}/org/apache/sis/storage/landsat/Band.java | 0
.../org/apache/sis/storage/landsat/BandGroup.java | 0
.../apache/sis/storage/landsat/BandGroupName.java | 0
.../org/apache/sis/storage/landsat/BandName.java | 0
.../apache/sis/storage/landsat/LandsatStore.java | 0
.../sis/storage/landsat/LandsatStoreProvider.java | 0
.../apache/sis/storage/landsat/MetadataReader.java | 0
.../storage/landsat/doc-files/MetadataMapping.html | 0
.../apache/sis/storage/landsat/package-info.java | 0
.../storage/landsat/LandsatStoreProviderTest.java | 0
.../org/apache/sis/storage/landsat/LandsatTest.txt | 0
.../sis/storage/landsat/MetadataReaderTest.java | 0
.../org.apache.sis.storage.DataStoreProvider | 4 +
.../main/module-info.java | 39 +
.../apache/sis/internal/geotiff/Compression.java | 0
.../org/apache/sis/internal/geotiff/Predictor.java | 0
.../org/apache/sis/internal/geotiff/Resources.java | 0
.../sis/internal/geotiff/Resources.properties | 0
.../apache/sis/internal/geotiff/Resources_en.java | 0
.../apache/sis/internal/geotiff/Resources_fr.java | 0
.../sis/internal/geotiff/Resources_fr.properties | 0
.../sis/internal/geotiff/SchemaModifier.java | 0
.../apache/sis/internal/geotiff/package-info.java | 0
.../sis/internal/storage/inflater/CCITTRLE.java | 0
.../storage/inflater/CompressionChannel.java | 0
.../internal/storage/inflater/CopyFromBytes.java | 0
.../storage/inflater/HorizontalPredictor.java | 0
.../sis/internal/storage/inflater/Inflater.java | 0
.../apache/sis/internal/storage/inflater/LZW.java | 0
.../sis/internal/storage/inflater/PackBits.java | 0
.../internal/storage/inflater/PixelChannel.java | 0
.../storage/inflater/PredictorChannel.java | 0
.../apache/sis/internal/storage/inflater/ZIP.java | 0
.../internal/storage/inflater/package-info.java | 0
.../org/apache/sis/storage/geotiff/CRSBuilder.java | 0
.../sis/storage/geotiff/CompressedSubset.java | 0
.../org/apache/sis/storage/geotiff/DataCube.java | 0
.../org/apache/sis/storage/geotiff/DataSubset.java | 0
.../apache/sis/storage/geotiff/DeferredEntry.java | 0
.../org/apache/sis/storage/geotiff/GeoCodes.java | 0
.../org/apache/sis/storage/geotiff/GeoKeys.java | 0
.../apache/sis/storage/geotiff/GeoKeysLoader.java | 0
.../org/apache/sis/storage/geotiff/GeoTIFF.java | 0
.../apache/sis/storage/geotiff/GeoTiffStore.java | 0
.../sis/storage/geotiff/GeoTiffStoreProvider.java | 0
.../sis/storage/geotiff/GridGeometryBuilder.java | 0
.../sis/storage/geotiff/ImageFileDirectory.java | 0
.../sis/storage/geotiff/ImageMetadataBuilder.java | 0
.../apache/sis/storage/geotiff/Localization.java | 0
.../sis/storage/geotiff/MultiResolutionImage.java | 0
.../apache/sis/storage/geotiff/NativeMetadata.java | 0
.../org/apache/sis/storage/geotiff/Reader.java | 0
.../sis/storage/geotiff/ReversedBitsChannel.java | 0
.../main}/org/apache/sis/storage/geotiff/Tags.java | 0
.../main}/org/apache/sis/storage/geotiff/Type.java | 0
.../apache/sis/storage/geotiff/XMLMetadata.java | 0
.../apache/sis/storage/geotiff/package-info.java | 0
.../sis/internal/geotiff/CompressionTest.java | 0
.../internal/storage/inflater/CCITTRLETest.java | 0
.../internal/storage/inflater/InflaterTest.java | 0
.../apache/sis/storage/geotiff/CRSBuilderTest.java | 0
.../apache/sis/storage/geotiff/GeoCodesTest.java | 0
.../apache/sis/storage/geotiff/GeoIdentifiers.java | 0
.../apache/sis/storage/geotiff/GeoKeysTest.java | 0
.../sis/storage/geotiff/SelfConsistencyTest.java | 0
.../org/apache/sis/storage/geotiff/TagsTest.java | 0
.../org/apache/sis/storage/geotiff/TypeTest.java | 0
.../sis/storage/geotiff/XMLMetadataTest.java | 0
.../org.apache.sis.storage.DataStoreProvider | 4 +
.../main/module-info.java | 40 +
.../main}/org/apache/sis/internal/netcdf/Axis.java | 0
.../org/apache/sis/internal/netcdf/AxisType.java | 0
.../org/apache/sis/internal/netcdf/CRSBuilder.java | 0
.../org/apache/sis/internal/netcdf/CRSMerger.java | 0
.../org/apache/sis/internal/netcdf/Convention.java | 796 +++++
.../org/apache/sis/internal/netcdf/DataType.java | 0
.../org/apache/sis/internal/netcdf/Decoder.java | 0
.../org/apache/sis/internal/netcdf/Dimension.java | 0
.../sis/internal/netcdf/DiscreteSampling.java | 0
.../org/apache/sis/internal/netcdf/FeatureSet.java | 0
.../main}/org/apache/sis/internal/netcdf/Grid.java | 0
.../apache/sis/internal/netcdf/GridAdjustment.java | 0
.../apache/sis/internal/netcdf/GridCacheKey.java | 0
.../apache/sis/internal/netcdf/GridCacheValue.java | 0
.../apache/sis/internal/netcdf/GridMapping.java | 0
.../org/apache/sis/internal/netcdf/HYCOM.java | 0
.../org/apache/sis/internal/netcdf/Linearizer.java | 0
.../apache/sis/internal/netcdf/NamedElement.java | 0
.../main}/org/apache/sis/internal/netcdf/Node.java | 0
.../org/apache/sis/internal/netcdf/Raster.java | 0
.../apache/sis/internal/netcdf/RasterResource.java | 0
.../org/apache/sis/internal/netcdf/Resources.java | 323 ++
.../sis/internal/netcdf/Resources.properties | 47 +
.../apache/sis/internal/netcdf/Resources_en.java | 0
.../apache/sis/internal/netcdf/Resources_fr.java | 0
.../sis/internal/netcdf/Resources_fr.properties | 52 +
.../org/apache/sis/internal/netcdf/Variable.java | 0
.../apache/sis/internal/netcdf/VariableRole.java | 0
.../sis/internal/netcdf/impl/ChannelDecoder.java | 0
.../sis/internal/netcdf/impl/DimensionInfo.java | 0
.../apache/sis/internal/netcdf/impl/GridInfo.java | 0
.../sis/internal/netcdf/impl/VariableInfo.java | 0
.../sis/internal/netcdf/impl/package-info.java | 0
.../apache/sis/internal/netcdf/package-info.java | 0
.../sis/internal/netcdf/ucar/DecoderWrapper.java | 0
.../sis/internal/netcdf/ucar/DimensionWrapper.java | 0
.../sis/internal/netcdf/ucar/FeaturesWrapper.java | 0
.../sis/internal/netcdf/ucar/GridWrapper.java | 0
.../sis/internal/netcdf/ucar/GroupWrapper.java | 0
.../sis/internal/netcdf/ucar/LogAdapter.java | 0
.../org/apache/sis/internal/netcdf/ucar/Utils.java | 0
.../sis/internal/netcdf/ucar/VariableWrapper.java | 0
.../sis/internal/netcdf/ucar/package-info.java | 0
.../apache/sis/storage/netcdf/AttributeNames.java | 0
.../apache/sis/storage/netcdf/MetadataReader.java | 1083 +++++++
.../org/apache/sis/storage/netcdf/NetcdfStore.java | 0
.../sis/storage/netcdf/NetcdfStoreProvider.java | 470 +++
.../apache/sis/storage/netcdf/package-info.java | 0
.../org/apache/sis/internal/netcdf/AxisTest.java | 0
.../apache/sis/internal/netcdf/DataTypeTest.java | 0
.../apache/sis/internal/netcdf/DecoderTest.java | 0
.../apache/sis/internal/netcdf/FeatureSetTest.java | 0
.../org/apache/sis/internal/netcdf/GridTest.java | 0
.../org/apache/sis/internal/netcdf/TestCase.java | 0
.../apache/sis/internal/netcdf/VariableTest.java | 0
.../internal/netcdf/impl/ChannelDecoderTest.java | 0
.../sis/internal/netcdf/impl/FeatureSetTest.java | 0
.../sis/internal/netcdf/impl/GridInfoTest.java | 0
.../sis/internal/netcdf/impl/VariableInfoTest.java | 0
.../sis/storage/netcdf/MetadataReaderTest.java | 0
.../storage/netcdf/NetcdfStoreProviderTest.java | 0
.../apache/sis/storage/netcdf/NetcdfStoreTest.java | 0
.../sis/storage/netcdf/SelfConsistencyTest.java | 0
.../main/module-info.java | 33 +
.../apache/sis/internal/sql/feature/Analyzer.java | 0
.../sis/internal/sql/feature/BinaryEncoding.java | 0
.../apache/sis/internal/sql/feature/Column.java | 0
.../apache/sis/internal/sql/feature/Database.java | 0
.../sis/internal/sql/feature/FeatureAdapter.java | 0
.../sis/internal/sql/feature/FeatureAnalyzer.java | 0
.../sis/internal/sql/feature/FeatureIterator.java | 0
.../sis/internal/sql/feature/FeatureStream.java | 0
.../sis/internal/sql/feature/GeometryGetter.java | 0
.../sis/internal/sql/feature/InfoStatements.java | 0
.../sis/internal/sql/feature/PrimaryKey.java | 0
.../sis/internal/sql/feature/QueryAnalyzer.java | 0
.../apache/sis/internal/sql/feature/Relation.java | 0
.../apache/sis/internal/sql/feature/Resources.java | 265 ++
.../sis/internal/sql/feature/Resources.properties | 37 +
.../sis/internal/sql/feature/Resources_en.java | 0
.../sis/internal/sql/feature/Resources_fr.java | 0
.../internal/sql/feature/Resources_fr.properties | 42 +
.../sis/internal/sql/feature/SchemaModifier.java | 0
.../sis/internal/sql/feature/SelectionClause.java | 0
.../sql/feature/SelectionClauseWriter.java | 0
.../org/apache/sis/internal/sql/feature/Table.java | 0
.../sis/internal/sql/feature/TableAnalyzer.java | 0
.../sis/internal/sql/feature/TableReference.java | 0
.../sis/internal/sql/feature/ValueGetter.java | 0
.../sis/internal/sql/feature/package-info.java | 0
.../org/apache/sis/internal/sql/postgis/Band.java | 0
.../internal/sql/postgis/ExtendedClauseWriter.java | 0
.../sis/internal/sql/postgis/ExtendedInfo.java | 0
.../sis/internal/sql/postgis/ExtentEstimator.java | 0
.../sis/internal/sql/postgis/ObjectGetter.java | 0
.../apache/sis/internal/sql/postgis/Postgres.java | 0
.../sis/internal/sql/postgis/RasterFormat.java | 0
.../sis/internal/sql/postgis/RasterGetter.java | 0
.../sis/internal/sql/postgis/RasterReader.java | 0
.../sis/internal/sql/postgis/RasterWriter.java | 0
.../sis/internal/sql/postgis/package-info.java | 0
.../sis/internal/stream/BaseStreamWrapper.java | 0
.../apache/sis/internal/stream/DeferredStream.java | 0
.../sis/internal/stream/DoubleStreamWrapper.java | 0
.../sis/internal/stream/PaginedDoubleStream.java | 0
.../apache/sis/internal/stream/PaginedStream.java | 0
.../apache/sis/internal/stream/StreamWrapper.java | 0
.../apache/sis/internal/stream/package-info.java | 0
.../apache/sis/storage/sql/ResourceDefinition.java | 0
.../main}/org/apache/sis/storage/sql/SQLStore.java | 0
.../apache/sis/storage/sql/SQLStoreProvider.java | 0
.../org/apache/sis/storage/sql/package-info.java | 0
.../internal/sql/feature/GeometryGetterTest.java | 0
.../sis/internal/sql/feature/ResultSetMock.java | 0
.../sql/feature/SelectionClauseWriterTest.java | 0
.../sql/feature/TemporalValueGetterTest.java | 0
.../apache/sis/internal/sql/postgis/BandTest.java | 0
.../sis/internal/sql/postgis/PostgresTest.java | 0
.../sis/internal/sql/postgis/RasterReaderTest.java | 0
.../sis/internal/sql/postgis/RasterWriterTest.java | 0
.../sis/internal/sql/postgis/SpatialFeatures.sql | 0
.../sis/internal/sql/postgis/TestRaster.java | 0
.../sis/internal/sql/postgis/raster-ushort.wkb | Bin
.../test}/org/apache/sis/storage/sql/Features.sql | 0
.../org/apache/sis/storage/sql/SQLStoreTest.java | 0
.../apache/sis/storage/sql/TestOnAllDatabases.java | 0
.../org.apache.sis.storage.DataStoreProvider | 4 +
.../main/module-info.java | 44 +
.../sis/internal/storage/gpx/Attributes.java | 0
.../apache/sis/internal/storage/gpx/Bounds.java | 0
.../apache/sis/internal/storage/gpx/Copyright.java | 0
.../internal/storage/gpx/Definitions.properties | 0
.../internal/storage/gpx/Definitions_fr.properties | 0
.../sis/internal/storage/gpx/Description.java | 0
.../internal/storage/gpx/Designations.properties | 0
.../storage/gpx/Designations_fr.properties | 0
.../org/apache/sis/internal/storage/gpx/Email.java | 0
.../org/apache/sis/internal/storage/gpx/Link.java | 0
.../apache/sis/internal/storage/gpx/Metadata.java | 0
.../apache/sis/internal/storage/gpx/Person.java | 0
.../apache/sis/internal/storage/gpx/Reader.java | 0
.../org/apache/sis/internal/storage/gpx/Store.java | 0
.../sis/internal/storage/gpx/StoreProvider.java | 0
.../org/apache/sis/internal/storage/gpx/Tags.java | 0
.../org/apache/sis/internal/storage/gpx/Types.java | 0
.../apache/sis/internal/storage/gpx/Updater.java | 0
.../sis/internal/storage/gpx/WritableStore.java | 0
.../apache/sis/internal/storage/gpx/Writer.java | 0
.../sis/internal/storage/gpx/package-info.java | 0
.../storage/xml/stream/FormattedWriter.java | 0
.../sis/internal/storage/xml/stream/InputType.java | 0
.../storage/xml/stream/NamespaceEraser.java | 0
.../internal/storage/xml/stream/OutputType.java | 0
.../storage/xml/stream/RewriteOnUpdate.java | 0
.../internal/storage/xml/stream/StaxDataStore.java | 0
.../storage/xml/stream/StaxDataStoreProvider.java | 0
.../internal/storage/xml/stream/StaxStreamIO.java | 0
.../storage/xml/stream/StaxStreamReader.java | 0
.../storage/xml/stream/StaxStreamWriter.java | 0
.../internal/storage/xml/stream/package-info.java | 0
.../main}/org/apache/sis/storage/gps/Fix.java | 0
.../org/apache/sis/storage/gps/package-info.java | 0
.../sis/internal/storage/gpx/1.0/metadata.xml | 0
.../apache/sis/internal/storage/gpx/1.0/route.xml | 0
.../apache/sis/internal/storage/gpx/1.0/track.xml | 0
.../sis/internal/storage/gpx/1.0/waypoint.xml | 0
.../sis/internal/storage/gpx/1.1/metadata.xml | 0
.../apache/sis/internal/storage/gpx/1.1/route.xml | 0
.../apache/sis/internal/storage/gpx/1.1/track.xml | 0
.../sis/internal/storage/gpx/1.1/waypoint.xml | 0
.../sis/internal/storage/gpx/MetadataTest.java | 0
.../sis/internal/storage/gpx/ReaderTest.java | 0
.../apache/sis/internal/storage/gpx/TestData.java | 0
.../apache/sis/internal/storage/gpx/TypesTest.java | 0
.../sis/internal/storage/gpx/UpdaterTest.java | 0
.../sis/internal/storage/gpx/WriterTest.java | 0
.../services/java.nio.file.spi.FileTypeDetector | 4 +
.../org.apache.sis.storage.DataStoreProvider | 10 +
.../org.apache.sis.storage/main/module-info.java | 80 +
.../apache/sis/internal/storage/Capability.java | 0
.../org/apache/sis/internal/storage/CodeType.java | 0
.../internal/storage/DocumentedStoreProvider.java | 0
.../internal/storage/FeatureCatalogBuilder.java | 0
.../sis/internal/storage/GridResourceWrapper.java | 0
.../sis/internal/storage/MemoryFeatureSet.java | 0
.../sis/internal/storage/MemoryGridResource.java | 0
.../sis/internal/storage/MetadataBuilder.java | 0
.../apache/sis/internal/storage/PRJDataStore.java | 0
.../sis/internal/storage/ResourceLineage.java | 0
.../sis/internal/storage/ResourceOnFileSystem.java | 0
.../sis/internal/storage/ResourceTransaction.java | 0
.../org/apache/sis/internal/storage/Resources.java | 603 ++++
.../sis/internal/storage/Resources.properties | 100 +
.../apache/sis/internal/storage/Resources_en.java | 0
.../apache/sis/internal/storage/Resources_fr.java | 0
.../sis/internal/storage/Resources_fr.properties | 105 +
.../apache/sis/internal/storage/StoreMetadata.java | 0
.../apache/sis/internal/storage/StoreResource.java | 0
.../sis/internal/storage/StoreTypeDetector.java | 0
.../sis/internal/storage/StoreUtilities.java | 0
.../sis/internal/storage/TiledDeferredImage.java | 0
.../sis/internal/storage/TiledGridCoverage.java | 0
.../sis/internal/storage/TiledGridResource.java | 0
.../internal/storage/TransactionalResource.java | 0
.../apache/sis/internal/storage/URIDataStore.java | 0
.../internal/storage/WritableResourceSupport.java | 0
.../sis/internal/storage/csv/FeatureIterator.java | 0
.../sis/internal/storage/csv/FixedSizeList.java | 0
.../apache/sis/internal/storage/csv/Foliation.java | 0
.../sis/internal/storage/csv/GeometryParser.java | 0
.../internal/storage/csv/MovingFeatureBuilder.java | 0
.../storage/csv/MovingFeatureIterator.java | 0
.../org/apache/sis/internal/storage/csv/Store.java | 0
.../sis/internal/storage/csv/StoreProvider.java | 0
.../sis/internal/storage/csv/TimeEncoding.java | 0
.../sis/internal/storage/csv/package-info.java | 0
.../sis/internal/storage/esri/AsciiGridStore.java | 0
.../storage/esri/AsciiGridStoreProvider.java | 0
.../sis/internal/storage/esri/CharactersView.java | 0
.../sis/internal/storage/esri/RasterStore.java | 0
.../sis/internal/storage/esri/RawRasterLayout.java | 0
.../sis/internal/storage/esri/RawRasterReader.java | 0
.../sis/internal/storage/esri/RawRasterStore.java | 0
.../storage/esri/RawRasterStoreProvider.java | 0
.../sis/internal/storage/esri/WritableStore.java | 0
.../sis/internal/storage/esri/package-info.java | 0
.../internal/storage/folder/ConcurrentCloser.java | 0
.../apache/sis/internal/storage/folder/Store.java | 0
.../sis/internal/storage/folder/StoreProvider.java | 0
.../storage/folder/UnstructuredAggregate.java | 0
.../sis/internal/storage/folder/WritableStore.java | 0
.../sis/internal/storage/folder/package-info.java | 0
.../sis/internal/storage/image/FormatFilter.java | 0
.../sis/internal/storage/image/FormatFinder.java | 0
.../internal/storage/image/MultiImageStore.java | 0
.../internal/storage/image/SingleImageStore.java | 0
.../internal/storage/image/WarningListener.java | 0
.../internal/storage/image/WorldFileResource.java | 0
.../sis/internal/storage/image/WorldFileStore.java | 0
.../storage/image/WorldFileStoreProvider.java | 0
.../internal/storage/image/WritableResource.java | 0
.../storage/image/WritableSingleImageStore.java | 0
.../sis/internal/storage/image/WritableStore.java | 0
.../sis/internal/storage/image/package-info.java | 0
.../sis/internal/storage/io/ByteRangeChannel.java | 0
.../apache/sis/internal/storage/io/ByteWriter.java | 0
.../sis/internal/storage/io/ChannelData.java | 0
.../sis/internal/storage/io/ChannelDataInput.java | 0
.../sis/internal/storage/io/ChannelDataOutput.java | 0
.../sis/internal/storage/io/ChannelFactory.java | 0
.../storage/io/ChannelImageInputStream.java | 0
.../storage/io/ChannelImageOutputStream.java | 0
.../sis/internal/storage/io/DataTransfer.java | 0
.../internal/storage/io/FileCacheByteChannel.java | 0
.../sis/internal/storage/io/HttpByteChannel.java | 0
.../internal/storage/io/HyperRectangleReader.java | 0
.../sis/internal/storage/io/IOUtilities.java | 0
.../internal/storage/io/InputStreamAdapter.java | 0
.../storage/io/InputStreamArrayGetter.java | 0
.../sis/internal/storage/io/InternalOptionKey.java | 0
.../apache/sis/internal/storage/io/Markable.java | 0
.../internal/storage/io/MemoryDataTransfer.java | 0
.../sis/internal/storage/io/NullChannel.java | 0
.../internal/storage/io/OutputStreamAdapter.java | 0
.../org/apache/sis/internal/storage/io/Region.java | 0
.../internal/storage/io/RewindableLineReader.java | 0
.../sis/internal/storage/io/package-info.java | 0
.../apache/sis/internal/storage/package-info.java | 0
.../sis/internal/storage/wkt/FirstKeywordPeek.java | 0
.../org/apache/sis/internal/storage/wkt/Store.java | 0
.../sis/internal/storage/wkt/StoreFormat.java | 0
.../sis/internal/storage/wkt/StoreProvider.java | 0
.../sis/internal/storage/wkt/package-info.java | 0
.../sis/internal/storage/xml/AbstractProvider.java | 0
.../internal/storage/xml/GeographicEnvelope.java | 0
.../sis/internal/storage/xml/MimeTypeDetector.java | 0
.../org/apache/sis/internal/storage/xml/Store.java | 0
.../sis/internal/storage/xml/StoreProvider.java | 0
.../sis/internal/storage/xml/package-info.java | 32 +
.../org/apache/sis/storage/AbstractFeatureSet.java | 0
.../sis/storage/AbstractGridCoverageResource.java | 0
.../org/apache/sis/storage/AbstractResource.java | 0
.../main}/org/apache/sis/storage/Aggregate.java | 0
.../apache/sis/storage/CanNotProbeException.java | 0
.../sis/storage/ConcurrentReadException.java | 0
.../sis/storage/ConcurrentWriteException.java | 0
.../org/apache/sis/storage/CoverageQuery.java | 0
.../org/apache/sis/storage/CoverageSubset.java | 0
.../org/apache/sis/storage/DataOptionKey.java | 0
.../main}/org/apache/sis/storage/DataSet.java | 0
.../main}/org/apache/sis/storage/DataStore.java | 0
.../sis/storage/DataStoreClosedException.java | 0
.../sis/storage/DataStoreContentException.java | 0
.../org/apache/sis/storage/DataStoreException.java | 0
.../org/apache/sis/storage/DataStoreProvider.java | 628 ++++
.../sis/storage/DataStoreReferencingException.java | 0
.../org/apache/sis/storage/DataStoreRegistry.java | 324 ++
.../main/org/apache/sis/storage/DataStores.java | 86 +
.../org/apache/sis/storage/FeatureNaming.java | 0
.../main}/org/apache/sis/storage/FeatureQuery.java | 0
.../main}/org/apache/sis/storage/FeatureSet.java | 0
.../org/apache/sis/storage/FeatureSubset.java | 0
.../sis/storage/ForwardOnlyStorageException.java | 0
.../apache/sis/storage/GridCoverageResource.java | 0
.../sis/storage/IllegalFeatureTypeException.java | 0
.../apache/sis/storage/IllegalNameException.java | 0
.../sis/storage/IllegalOpenParameterException.java | 0
.../sis/storage/IncompatibleResourceException.java | 0
.../sis/storage/InternalDataStoreException.java | 0
.../apache/sis/storage/NoSuchDataException.java | 0
.../org/apache/sis/storage/ProbeInputStream.java | 0
.../org/apache/sis/storage/ProbeProviderPair.java | 0
.../main}/org/apache/sis/storage/ProbeReader.java | 0
.../main}/org/apache/sis/storage/ProbeResult.java | 0
.../main}/org/apache/sis/storage/Query.java | 0
.../apache/sis/storage/RasterLoadingStrategy.java | 0
.../sis/storage/ReadOnlyStorageException.java | 0
.../main}/org/apache/sis/storage/Resource.java | 0
.../storage/ResourceAlreadyExistsException.java | 0
.../org/apache/sis/storage/StorageConnector.java | 0
.../sis/storage/UnsupportedEncodingException.java | 0
.../sis/storage/UnsupportedQueryException.java | 0
.../sis/storage/UnsupportedStorageException.java | 0
.../org/apache/sis/storage/WritableAggregate.java | 0
.../org/apache/sis/storage/WritableFeatureSet.java | 0
.../sis/storage/WritableGridCoverageResource.java | 0
.../storage/aggregate/AggregatedFeatureSet.java | 0
.../sis/storage/aggregate/AggregatedResource.java | 0
.../aggregate/BandAggregateGridResource.java | 0
.../storage/aggregate/ConcatenatedFeatureSet.java | 0
.../aggregate/ConcatenatedGridCoverage.java | 0
.../aggregate/ConcatenatedGridResource.java | 0
.../sis/storage/aggregate/CoverageAggregator.java | 0
.../sis/storage/aggregate/DimensionSelector.java | 0
.../apache/sis/storage/aggregate/GridSlice.java | 0
.../sis/storage/aggregate/GridSliceLocator.java | 0
.../org/apache/sis/storage/aggregate/Group.java | 0
.../sis/storage/aggregate/GroupAggregate.java | 0
.../apache/sis/storage/aggregate/GroupByCRS.java | 0
.../sis/storage/aggregate/GroupBySample.java | 0
.../sis/storage/aggregate/GroupByTransform.java | 0
.../sis/storage/aggregate/JoinFeatureSet.java | 0
.../sis/storage/aggregate/MergeStrategy.java | 0
.../apache/sis/storage/aggregate/package-info.java | 0
.../sis/storage/event/CascadedStoreEvent.java | 0
.../org/apache/sis/storage/event/CloseEvent.java | 0
.../org/apache/sis/storage/event/StoreEvent.java | 0
.../apache/sis/storage/event/StoreListener.java | 0
.../apache/sis/storage/event/StoreListeners.java | 0
.../org/apache/sis/storage/event/WarningEvent.java | 0
.../org/apache/sis/storage/event/package-info.java | 0
.../main}/org/apache/sis/storage/package-info.java | 0
.../main}/org/apache/sis/storage/tiling/Tile.java | 0
.../org/apache/sis/storage/tiling/TileMatrix.java | 0
.../apache/sis/storage/tiling/TileMatrixSet.java | 0
.../org/apache/sis/storage/tiling/TileStatus.java | 0
.../apache/sis/storage/tiling/TiledResource.java | 0
.../sis/storage/tiling/WritableTileMatrix.java | 0
.../sis/storage/tiling/WritableTileMatrixSet.java | 0
.../sis/storage/tiling/WritableTiledResource.java | 0
.../apache/sis/storage/tiling/package-info.java | 0
.../apache/sis/internal/storage/CodeTypeTest.java | 0
.../internal/storage/MemoryGridResourceTest.java | 0
.../sis/internal/storage/MetadataBuilderTest.java | 0
.../sis/internal/storage/StoreUtilitiesTest.java | 0
.../internal/storage/csv/StoreProviderTest.java | 0
.../apache/sis/internal/storage/csv/StoreTest.java | 0
.../internal/storage/esri/AsciiGridStoreTest.java | 0
.../org/apache/sis/internal/storage/esri/BIL.hdr | 0
.../org/apache/sis/internal/storage/esri/BIL.raw | Bin
.../internal/storage/esri/BILConsistencyTest.java | 0
.../org/apache/sis/internal/storage/esri/BIP.hdr | 0
.../org/apache/sis/internal/storage/esri/BIP.raw | Bin
.../org/apache/sis/internal/storage/esri/BIP.stx | 0
.../internal/storage/esri/BIPConsistencyTest.java | 0
.../org/apache/sis/internal/storage/esri/BSQ.hdr | 0
.../org/apache/sis/internal/storage/esri/BSQ.raw | Bin
.../internal/storage/esri/BSQConsistencyTest.java | 0
.../internal/storage/esri/WritableStoreTest.java | 0
.../org/apache/sis/internal/storage/esri/grid.asc | 0
.../org/apache/sis/internal/storage/esri/grid.clr | 0
.../org/apache/sis/internal/storage/esri/grid.prj | 0
.../sis/internal/storage/folder/StoreTest.java | 126 +
.../internal/storage/folder/test-data/README.txt | 0
.../sis/internal/storage/folder/test-data/crs.prj | 0
.../internal/storage/folder/test-data/data1.xml | 0
.../internal/storage/folder/test-data/data2.xml | 0
.../internal/storage/folder/test-data/data3.xml | 0
.../storage/folder/test-data/data4/data5.xml | 0
.../apache/sis/internal/storage/image/README.md | 0
.../storage/image/SelfConsistencyTest.java | 0
.../internal/storage/image/WorldFileStoreTest.java | 0
.../apache/sis/internal/storage/image/gradient.pgw | 0
.../apache/sis/internal/storage/image/gradient.png | Bin
.../apache/sis/internal/storage/image/gradient.prj | 0
.../sis/internal/storage/io/ByteArrayChannel.java | 0
.../internal/storage/io/ChannelDataInputTest.java | 0
.../internal/storage/io/ChannelDataOutputTest.java | 0
.../internal/storage/io/ChannelDataTestCase.java | 0
.../storage/io/ChannelImageInputStreamTest.java | 0
.../storage/io/ChannelImageOutputStreamTest.java | 0
.../internal/storage/io/ComputedInputStream.java | 0
.../sis/internal/storage/io/DripByteChannel.java | 0
.../storage/io/FileCacheByteChannelTest.java | 0
.../storage/io/HyperRectangleReaderTest.java | 0
.../sis/internal/storage/io/IOUtilitiesTest.java | 0
.../storage/io/ImageInputStreamComparator.java | 0
.../storage/io/InputStreamArrayGetterTest.java | 0
.../storage/io/MemoryCacheImageOutputStream.java | 0
.../storage/io/RewindableLineReaderTest.java | 0
.../internal/storage/wkt/StoreProviderTest.java | 0
.../apache/sis/internal/storage/wkt/StoreTest.java | 0
.../internal/storage/xml/MimeTypeDetectorTest.java | 0
.../internal/storage/xml/StoreProviderTest.java | 0
.../apache/sis/internal/storage/xml/StoreTest.java | 0
.../test}/org/apache/sis/storage/Any.txt | 0
.../org/apache/sis/storage/CoverageQueryTest.java | 0
.../org/apache/sis/storage/CoverageSubsetTest.java | 0
.../org/apache/sis/storage/DataStoreMock.java | 0
.../apache/sis/storage/DataStoreProviderTest.java | 0
.../org/apache/sis/storage/DataStoresTest.java | 0
.../org/apache/sis/storage/FeatureNamingTest.java | 0
.../org/apache/sis/storage/FeatureQueryTest.java | 0
.../org/apache/sis/storage/GridResourceMock.java | 0
.../org/apache/sis/storage/ProbeResultTest.java | 0
.../apache/sis/storage/StorageConnectorTest.java | 0
.../aggregate/BandAggregateGridResourceTest.java | 0
.../aggregate/ConcatenatedFeatureSetTest.java | 0
.../storage/aggregate/CoverageAggregatorTest.java | 0
.../sis/storage/aggregate/JoinFeatureSetTest.java | 0
.../sis/storage/aggregate/OpaqueGridResource.java | 0
.../sis/storage/event/StoreListenersTest.java | 0
.../sis/test/storage/CoverageReadConsistency.java | 0
.../apache/sis/test/storage/SubsampledImage.java | 0
.../org/apache/sis/test/storage/package-info.java | 0
.../test/module-info.java | 29 +
.../services/javax.measure.spi.ServiceProvider | 4 +
.../services/org.apache.sis.util.ObjectConverter | 43 +
.../src/org.apache.sis.util/main/module-info.java | 165 +
.../sis/internal/converter/AngleConverter.java | 0
.../sis/internal/converter/ArrayConverter.java | 0
.../internal/converter/CharSequenceConverter.java | 0
.../apache/sis/internal/converter/ClassPair.java | 0
.../internal/converter/CollectionConverter.java | 0
.../org/apache/sis/internal/converter/Column.java | 0
.../sis/internal/converter/ConverterRegistry.java | 607 ++++
.../sis/internal/converter/DateConverter.java | 0
.../sis/internal/converter/FallbackConverter.java | 0
.../sis/internal/converter/FractionConverter.java | 0
.../sis/internal/converter/IdentityConverter.java | 0
.../sis/internal/converter/NumberConverter.java | 186 ++
.../sis/internal/converter/ObjectToString.java | 0
.../sis/internal/converter/PathConverter.java | 0
.../sis/internal/converter/StringConverter.java | 0
.../internal/converter/SurjectiveConverter.java | 0
.../sis/internal/converter/SystemConverter.java | 0
.../sis/internal/converter/SystemRegistry.java | 231 ++
.../sis/internal/converter/package-info.java | 43 +
.../org/apache/sis/internal/jdk17/HexFormat.java | 0
.../main}/org/apache/sis/internal/jdk17/JDK17.java | 0
.../org/apache/sis/internal/jdk17/Record.java | 0
.../apache/sis/internal/jdk17/package-info.java | 0
.../apache/sis/internal/system/CommonExecutor.java | 0
.../apache/sis/internal/system/Configuration.java | 0
.../apache/sis/internal/system/DaemonThread.java | 0
.../apache/sis/internal/system/DataDirectory.java | 0
.../sis/internal/system/DelayedExecutor.java | 0
.../sis/internal/system/DelayedRunnable.java | 0
.../sis/internal/system/Descriptions.properties | 0
.../sis/internal/system/Descriptions_fr.properties | 0
.../org/apache/sis/internal/system/Fallback.java | 0
.../sis/internal/system/LocalizedStaticObject.java | 0
.../org/apache/sis/internal/system/Loggers.java | 224 ++
.../org/apache/sis/internal/system/Modules.java | 0
.../sis/internal/system/OptionalDependency.java | 88 +
.../internal/system/ReferenceQueueConsumer.java | 0
.../org/apache/sis/internal/system/Reflect.java | 106 +
.../org/apache/sis/internal/system/Semaphores.java | 0
.../org/apache/sis/internal/system/Shutdown.java | 208 ++
.../org/apache/sis/internal/system/Supervisor.java | 0
.../sis/internal/system/SupervisorMBean.java | 55 +
.../apache/sis/internal/system/SystemListener.java | 154 +
.../org/apache/sis/internal/system/Threads.java | 103 +
.../apache/sis/internal/system/package-info.java | 0
.../sis/internal/temporal/DefaultInstant.java | 0
.../sis/internal/temporal/DefaultPeriod.java | 0
.../internal/temporal/DefaultPeriodDuration.java | 0
.../internal/temporal/DefaultTemporalFactory.java | 0
.../apache/sis/internal/temporal/Primitive.java | 0
.../apache/sis/internal/temporal/package-info.java | 0
.../apache/sis/internal/util/AbstractIterator.java | 0
.../org/apache/sis/internal/util/AbstractMap.java | 0
.../apache/sis/internal/util/AbstractMapEntry.java | 0
.../org/apache/sis/internal/util/Acyclic.java | 0
.../internal/util/ArgumentCheckByAssertion.java | 0
.../sis/internal/util/AutoMessageFormat.java | 0
.../main}/org/apache/sis/internal/util/Bag.java | 0
.../apache/sis/internal/util/CheckedArrayList.java | 0
.../apache/sis/internal/util/CheckedHashSet.java | 0
.../org/apache/sis/internal/util/CloneAccess.java | 0
.../main}/org/apache/sis/internal/util/Cloner.java | 0
.../org/apache/sis/internal/util/CodeLists.java | 162 +
.../apache/sis/internal/util/CollectionsExt.java | 0
.../org/apache/sis/internal/util/Constants.java | 0
.../apache/sis/internal/util/DefinitionURI.java | 0
.../org/apache/sis/internal/util/DoubleDouble.java | 0
.../org/apache/sis/internal/util/EmptyQueue.java | 0
.../sis/internal/util/ListOfUnknownSize.java | 0
.../sis/internal/util/LocalizedParseException.java | 0
.../apache/sis/internal/util/MetadataServices.java | 209 ++
.../org/apache/sis/internal/util/Numerics.java | 0
.../apache/sis/internal/util/PropertyFormat.java | 0
.../apache/sis/internal/util/SetOfUnknownSize.java | 0
.../sis/internal/util/SimpleCharacterIterator.java | 0
.../sis/internal/util/StandardDateFormat.java | 0
.../org/apache/sis/internal/util/Strings.java | 0
.../sis/internal/util/TreeFormatCustomization.java | 0
.../main}/org/apache/sis/internal/util/URLs.java | 0
.../sis/internal/util/UnmodifiableArrayList.java | 0
.../main}/org/apache/sis/internal/util/X364.java | 0
.../org/apache/sis/internal/util/package-info.java | 0
.../main}/org/apache/sis/io/AppendableWriter.java | 0
.../main}/org/apache/sis/io/Appender.java | 0
.../main}/org/apache/sis/io/ClassFormat.java | 0
.../main/org/apache/sis/io/CompoundFormat.java | 544 ++++
.../main}/org/apache/sis/io/DefaultFormat.java | 0
.../main}/org/apache/sis/io/IO.java | 0
.../org/apache/sis/io/IdentifiedObjectFormat.java | 0
.../org/apache/sis/io/InvalidSeekException.java | 0
.../main}/org/apache/sis/io/LineAppender.java | 0
.../main}/org/apache/sis/io/TableAppender.java | 0
.../main}/org/apache/sis/io/TabularFormat.java | 0
.../main}/org/apache/sis/io/package-info.java | 0
.../main}/org/apache/sis/math/ArrayVector.java | 0
.../apache/sis/math/CompoundDirectPositions.java | 0
.../org/apache/sis/math/ConcatenatedVector.java | 0
.../org/apache/sis/math/DecimalFunctions.java | 0
.../main}/org/apache/sis/math/Fraction.java | 0
.../org/apache/sis/math/FunctionProperty.java | 0
.../main}/org/apache/sis/math/Line.java | 0
.../org/apache/sis/math/LinearlyDerivedVector.java | 0
.../main}/org/apache/sis/math/MathFunctions.java | 0
.../main}/org/apache/sis/math/PackedVector.java | 0
.../main}/org/apache/sis/math/Plane.java | 0
.../main}/org/apache/sis/math/RepeatedVector.java | 0
.../main}/org/apache/sis/math/SequenceVector.java | 0
.../main}/org/apache/sis/math/Statistics.java | 0
.../org/apache/sis/math/StatisticsFormat.java | 0
.../main}/org/apache/sis/math/Vector.java | 0
.../main}/org/apache/sis/math/package-info.java | 0
.../org/apache/sis/measure/AbstractConverter.java | 0
.../main}/org/apache/sis/measure/AbstractUnit.java | 0
.../main}/org/apache/sis/measure/Angle.java | 0
.../main}/org/apache/sis/measure/AngleFormat.java | 0
.../org/apache/sis/measure/AngularVelocity.java | 0
.../apache/sis/measure/ConcatenatedConverter.java | 0
.../org/apache/sis/measure/ConventionalUnit.java | 0
.../apache/sis/measure/DefaultQuantityFactory.java | 0
.../org/apache/sis/measure/DerivedScalar.java | 0
.../org/apache/sis/measure/ElevationAngle.java | 0
.../main}/org/apache/sis/measure/FormatField.java | 0
.../sis/measure/FormattedCharacterIterator.java | 0
.../org/apache/sis/measure/IdentityConverter.java | 0
.../main}/org/apache/sis/measure/Latitude.java | 0
.../org/apache/sis/measure/LinearConverter.java | 470 +++
.../main}/org/apache/sis/measure/Longitude.java | 0
.../org/apache/sis/measure/MeasurementRange.java | 0
.../main}/org/apache/sis/measure/NumberRange.java | 0
.../main}/org/apache/sis/measure/PowerOf10.java | 0
.../main}/org/apache/sis/measure/Prefixes.java | 0
.../main}/org/apache/sis/measure/Quantities.java | 0
.../org/apache/sis/measure/QuantityFormat.java | 0
.../main}/org/apache/sis/measure/Range.java | 0
.../main}/org/apache/sis/measure/RangeFormat.java | 0
.../main}/org/apache/sis/measure/Salinity.java | 0
.../main}/org/apache/sis/measure/Scalar.java | 0
.../org/apache/sis/measure/ScalarFactory.java | 0
.../org/apache/sis/measure/ScalarFallback.java | 0
.../org/apache/sis/measure/ScaleRateOfChange.java | 0
.../apache/sis/measure/SexagesimalConverter.java | 0
.../main}/org/apache/sis/measure/SystemUnit.java | 0
.../org/apache/sis/measure/UnitAliases.properties | 0
.../org/apache/sis/measure/UnitDimension.java | 0
.../main}/org/apache/sis/measure/UnitFormat.java | 0
.../org/apache/sis/measure/UnitNames.properties | 0
.../org/apache/sis/measure/UnitNames_en.properties | 0
.../apache/sis/measure/UnitNames_en_US.properties | 0
.../org/apache/sis/measure/UnitNames_fr.properties | 0
.../main}/org/apache/sis/measure/UnitRegistry.java | 0
.../main}/org/apache/sis/measure/UnitServices.java | 0
.../main}/org/apache/sis/measure/Units.java | 0
.../main}/org/apache/sis/measure/ValueRange.java | 0
.../main}/org/apache/sis/measure/package-info.java | 0
.../main/org/apache/sis/setup/About.java | 811 +++++
.../main/org/apache/sis/setup/Configuration.java | 150 +
.../org/apache/sis/setup/GeometryLibrary.java | 0
.../apache/sis/setup/InstallationResources.java | 220 ++
.../main}/org/apache/sis/setup/OptionKey.java | 0
.../apache/sis/setup/OptionalInstallations.java | 0
.../main}/org/apache/sis/setup/package-info.java | 0
.../sis/util/AbstractInternationalString.java | 0
.../main}/org/apache/sis/util/ArgumentChecks.java | 0
.../main}/org/apache/sis/util/ArraysExt.java | 0
.../main}/org/apache/sis/util/CharSequences.java | 0
.../main}/org/apache/sis/util/Characters.java | 0
.../main}/org/apache/sis/util/Classes.java | 0
.../main}/org/apache/sis/util/ComparisonMode.java | 0
.../apache/sis/util/CorruptedObjectException.java | 0
.../main}/org/apache/sis/util/Debug.java | 0
.../sis/util/DefaultInternationalString.java | 405 +++
.../main}/org/apache/sis/util/Deprecable.java | 0
.../main}/org/apache/sis/util/Disposable.java | 0
.../main}/org/apache/sis/util/Emptiable.java | 0
.../main}/org/apache/sis/util/Exceptions.java | 0
.../org/apache/sis/util/LenientComparable.java | 0
.../main}/org/apache/sis/util/Locales.java | 0
.../main}/org/apache/sis/util/Localized.java | 0
.../org/apache/sis/util/LocalizedException.java | 0
.../org/apache/sis/util/NullArgumentException.java | 0
.../main}/org/apache/sis/util/Numbers.java | 0
.../main}/org/apache/sis/util/ObjectConverter.java | 0
.../org/apache/sis/util/ObjectConverters.java | 0
.../org/apache/sis/util/OptionalCandidate.java | 0
.../sis/util/ResourceInternationalString.java | 0
.../apache/sis/util/SimpleInternationalString.java | 129 +
.../main}/org/apache/sis/util/Static.java | 0
.../main}/org/apache/sis/util/StringBuilders.java | 0
.../sis/util/UnconvertibleObjectException.java | 0
.../org/apache/sis/util/UnknownNameException.java | 0
.../util/UnsupportedImplementationException.java | 0
.../main}/org/apache/sis/util/Utilities.java | 0
.../main}/org/apache/sis/util/Version.java | 0
.../main}/org/apache/sis/util/Workaround.java | 0
.../sis/util/collection/BackingStoreException.java | 0
.../org/apache/sis/util/collection/Cache.java | 0
.../apache/sis/util/collection/CacheEntries.java | 0
.../sis/util/collection/CheckedContainer.java | 0
.../apache/sis/util/collection/CodeListSet.java | 0
.../org/apache/sis/util/collection/Containers.java | 0
.../sis/util/collection/DefaultTreeTable.java | 0
.../sis/util/collection/DerivedIterator.java | 0
.../org/apache/sis/util/collection/DerivedMap.java | 0
.../org/apache/sis/util/collection/DerivedSet.java | 0
.../sis/util/collection/FrequencySortedSet.java | 0
.../apache/sis/util/collection/IntegerList.java | 0
.../org/apache/sis/util/collection/RangeSet.java | 1653 ++++++++++
.../apache/sis/util/collection/TableColumn.java | 0
.../apache/sis/util/collection/TreeNodeList.java | 0
.../org/apache/sis/util/collection/TreeTable.java | 0
.../sis/util/collection/TreeTableFormat.java | 0
.../org/apache/sis/util/collection/TreeTables.java | 0
.../org/apache/sis/util/collection/WeakEntry.java | 0
.../apache/sis/util/collection/WeakHashSet.java | 0
.../sis/util/collection/WeakValueHashMap.java | 0
.../apache/sis/util/collection/package-info.java | 0
.../org/apache/sis/util/logging/Initializer.java | 0
.../main}/org/apache/sis/util/logging/Logging.java | 0
.../apache/sis/util/logging/MonolineFormatter.java | 0
.../apache/sis/util/logging/PerformanceLevel.java | 0
.../org/apache/sis/util/logging/package-info.java | 0
.../main}/org/apache/sis/util/package-info.java | 0
.../org/apache/sis/util/resources/Errors.java | 0
.../apache/sis/util/resources/Errors.properties | 0
.../org/apache/sis/util/resources/Errors_en.java | 0
.../org/apache/sis/util/resources/Errors_fr.java | 0
.../apache/sis/util/resources/Errors_fr.properties | 0
.../sis/util/resources/IndexedResourceBundle.java | 0
.../apache/sis/util/resources/KeyConstants.java | 0
.../org/apache/sis/util/resources/Messages.java | 0
.../apache/sis/util/resources/Messages.properties | 0
.../org/apache/sis/util/resources/Messages_en.java | 0
.../org/apache/sis/util/resources/Messages_fr.java | 0
.../sis/util/resources/Messages_fr.properties | 0
.../resources/ResourceInternationalString.java | 196 ++
.../org/apache/sis/util/resources/Vocabulary.java | 0
.../sis/util/resources/Vocabulary.properties | 0
.../apache/sis/util/resources/Vocabulary_en.java | 0
.../apache/sis/util/resources/Vocabulary_fr.java | 0
.../sis/util/resources/Vocabulary_fr.properties | 0
.../apache/sis/util/resources/package-info.java | 0
.../sis/internal/converter/AngleConverterTest.java | 0
.../sis/internal/converter/ArrayConverterTest.java | 0
.../internal/converter/ConverterRegistryTest.java | 0
.../internal/converter/FallbackConverterTest.java | 0
.../internal/converter/NumberConverterTest.java | 0
.../sis/internal/converter/PathConverterTest.java | 0
.../internal/converter/StringConverterTest.java | 0
.../sis/internal/converter/SystemRegistryTest.java | 0
.../apache/sis/internal/system/LoggersTest.java | 0
.../system/ReferenceQueueConsumerTest.java | 0
.../org/apache/sis/internal/test/AssertTest.java | 0
.../sis/internal/test/TestUtilitiesTest.java | 0
.../org/apache/sis/internal/test/package-info.java | 0
.../apache/sis/internal/util/AbstractMapTest.java | 0
.../org/apache/sis/internal/util/BagTest.java | 0
.../sis/internal/util/CheckedArrayListTest.java | 0
.../sis/internal/util/CollectionsExtTest.java | 0
.../sis/internal/util/DefinitionURITest.java | 0
.../apache/sis/internal/util/DoubleDoubleTest.java | 0
.../sis/internal/util/ListOfUnknownSizeTest.java | 0
.../internal/util/LocalizedParseExceptionTest.java | 0
.../org/apache/sis/internal/util/NumericsTest.java | 0
.../sis/internal/util/StandardDateFormatTest.java | 0
.../org/apache/sis/internal/util/StringsTest.java | 0
.../org/apache/sis/internal/util/X364Test.java | 0
.../test}/org/apache/sis/io/AppenderTestCase.java | 0
.../test}/org/apache/sis/io/EchoAppendable.java | 0
.../test}/org/apache/sis/io/LeftMarginTest.java | 0
.../test}/org/apache/sis/io/LineAppenderTest.java | 0
.../org/apache/sis/io/SingleCharAppendable.java | 0
.../test}/org/apache/sis/io/TableAppenderTest.java | 0
.../org/apache/sis/io/TabulationExpansionTest.java | 0
.../test}/org/apache/sis/io/WordWrapTest.java | 0
.../sis/io/WordWrapWithLineSeparatorTest.java | 0
.../org/apache/sis/math/DecimalFunctionsTest.java | 0
.../test}/org/apache/sis/math/FractionTest.java | 0
.../org/apache/sis/math/FunctionPropertyTest.java | 0
.../test}/org/apache/sis/math/LineTest.java | 0
.../apache/sis/math/LinearlyDerivedVectorTest.java | 0
.../org/apache/sis/math/MathFunctionsTest.java | 0
.../test}/org/apache/sis/math/PlaneTest.java | 0
.../org/apache/sis/math/RepeatedVectorTest.java | 0
.../org/apache/sis/math/StatisticsFormatTest.java | 0
.../test}/org/apache/sis/math/StatisticsTest.java | 0
.../test}/org/apache/sis/math/VectorTest.java | 0
.../org/apache/sis/measure/AngleFormatTest.java | 0
.../test}/org/apache/sis/measure/AngleTest.java | 0
.../apache/sis/measure/ConventionalUnitTest.java | 0
.../org/apache/sis/measure/DateRangeTest.java | 0
.../measure/FormattedCharacterIteratorTest.java | 0
.../apache/sis/measure/LinearConverterTest.java | 0
.../apache/sis/measure/MeasurementRangeTest.java | 0
.../org/apache/sis/measure/NumberRangeTest.java | 0
.../test}/org/apache/sis/measure/PrefixesTest.java | 0
.../org/apache/sis/measure/QuantitiesTest.java | 0
.../org/apache/sis/measure/RangeFormatTest.java | 0
.../test}/org/apache/sis/measure/RangeTest.java | 0
.../test}/org/apache/sis/measure/ScalarTest.java | 0
.../sis/measure/SexagesimalConverterTest.java | 0
.../org/apache/sis/measure/SystemUnitTest.java | 0
.../org/apache/sis/measure/UnitDimensionTest.java | 0
.../org/apache/sis/measure/UnitFormatTest.java | 0
.../org/apache/sis/measure/UnitServicesTest.java | 0
.../test}/org/apache/sis/measure/UnitsTest.java | 0
.../test}/org/apache/sis/setup/OptionKeyTest.java | 0
.../test}/org/apache/sis/test/Assertions.java | 0
.../test}/org/apache/sis/test/Assume.java | 0
.../test}/org/apache/sis/test/DependsOn.java | 0
.../test}/org/apache/sis/test/DependsOnMethod.java | 0
.../org/apache/sis/test/LogRecordCollector.java | 0
.../test}/org/apache/sis/test/LoggingWatcher.java | 0
.../org/apache/sis/test/OptionalTestData.java | 0
.../test}/org/apache/sis/test/Performance.java | 0
.../org/apache/sis/test/PlatformDependent.java | 0
.../org/apache/sis/test/ProjectDirectories.java | 0
.../test}/org/apache/sis/test/TestCase.java | 0
.../org/apache/sis/test/TestConfiguration.java | 0
.../test}/org/apache/sis/test/TestRunner.java | 0
.../test}/org/apache/sis/test/TestStep.java | 0
.../test}/org/apache/sis/test/TestUtilities.java | 0
.../test/foreigner/SerializableTableColumn.java | 0
.../apache/sis/test/foreigner/package-info.java | 0
.../test}/org/apache/sis/test/package-info.java | 0
.../org/apache/sis/util/ArgumentChecksTest.java | 0
.../test}/org/apache/sis/util/ArraysExtTest.java | 0
.../org/apache/sis/util/CharSequencesTest.java | 0
.../test}/org/apache/sis/util/CharactersTest.java | 0
.../test}/org/apache/sis/util/ClassesTest.java | 0
.../sis/util/DefaultInternationalStringTest.java | 0
.../test}/org/apache/sis/util/ExceptionsTest.java | 0
.../test}/org/apache/sis/util/LocalesTest.java | 0
.../test}/org/apache/sis/util/NumbersTest.java | 0
.../sis/util/SimpleInternationalStringTest.java | 0
.../org/apache/sis/util/StringBuildersTest.java | 0
.../test}/org/apache/sis/util/UtilitiesTest.java | 0
.../test}/org/apache/sis/util/VersionTest.java | 0
.../org/apache/sis/util/collection/CacheTest.java | 0
.../sis/util/collection/CodeListSetTest.java | 0
.../sis/util/collection/DefaultTreeTableTest.java | 0
.../apache/sis/util/collection/DerivedMapTest.java | 0
.../apache/sis/util/collection/DerivedSetTest.java | 0
.../util/collection/FrequencySortedSetTest.java | 0
.../org/apache/sis/util/collection/IntObject.java | 0
.../sis/util/collection/IntegerListTest.java | 0
.../apache/sis/util/collection/LargeCodeList.java | 0
.../apache/sis/util/collection/RangeSetTest.java | 0
.../sis/util/collection/TableColumnTest.java | 0
.../sis/util/collection/TreeTableFormatTest.java | 0
.../apache/sis/util/collection/TreeTablesTest.java | 0
.../sis/util/collection/WeakHashSetTest.java | 0
.../sis/util/collection/WeakValueHashMapTest.java | 0
.../sis/util/logging/MonolineFormatterTest.java | 0
.../sis/util/logging/PerformanceLevelTest.java | 0
.../util/resources/IndexedResourceBundleTest.java | 0
ide-project/NetBeans/README.txt | 33 -
ide-project/NetBeans/build.xml | 359 ---
ide-project/NetBeans/manifest.mf | 3 -
ide-project/NetBeans/nbproject/build-impl.xml | 2084 ------------
ide-project/NetBeans/nbproject/cfg_hints.xml | 213 --
ide-project/NetBeans/nbproject/genfiles.properties | 8 -
ide-project/NetBeans/nbproject/project.properties | 266 --
ide-project/NetBeans/nbproject/project.xml | 137 -
ide-project/README.txt | 14 -
incubator/build.gradle.kts | 144 +
.../main/antlr/org/apache/sis/internal/cql/CQL.g4 | 301 ++
.../src/org.apache.sis.cql/main/module-info.java | 29 +
.../main}/org/apache/sis/cql/CQL.java | 0
.../main}/org/apache/sis/cql/CQLException.java | 0
.../org/apache/sis/cql/FilterToCQLVisitor.java | 0
.../main}/org/apache/sis/cql/Query.java | 0
.../main/org/apache/sis/internal/cql/.gitignore | 7 +
.../org/apache/sis/internal/cql/AntlrCQL.java | 0
.../test}/org/apache/sis/cql/CQLTestCase.java | 0
.../org/apache/sis/cql/ExpressionReadingTest.java | 0
.../org/apache/sis/cql/ExpressionWritingTest.java | 0
.../org/apache/sis/cql/FilterReadingTest.java | 0
.../org/apache/sis/cql/FilterWritingTest.java | 0
.../test}/org/apache/sis/cql/QueryReadingTest.java | 0
.../test}/org/apache/sis/cql/QueryWritingTest.java | 0
.../main/module-info.java | 33 +
.../apache/sis/internal/shapefile/AutoChecker.java | 0
...nvalidRecordNumberForDirectAccessException.java | 0
.../SQLNoDirectAccessAvailableException.java | 0
.../shapefile/SQLShapefileNotFoundException.java | 0
.../internal/shapefile/ShapefileByteReader.java | 0
.../shapefile/ShapefileByteReader.properties | 0
.../shapefile/ShapefileByteReader_fr.properties | 0
.../internal/shapefile/ShapefileDescriptor.java | 0
.../shapefile/jdbc/AbstractDbase3ByteReader.java | 0
.../jdbc/AbstractDbase3ByteReader.properties | 0
.../jdbc/AbstractDbase3ByteReader_fr.properties | 0
.../sis/internal/shapefile/jdbc/AbstractJDBC.java | 0
.../shapefile/jdbc/AbstractJDBC.properties | 0
.../shapefile/jdbc/AbstractJDBC_fr.properties | 0
.../internal/shapefile/jdbc/CommonByteReader.java | 0
.../shapefile/jdbc/CommonByteReader.properties | 0
.../sis/internal/shapefile/jdbc/DBFDriver.java | 0
.../shapefile/jdbc/DBase3FieldDescriptor.java | 0
.../jdbc/DBase3FieldDescriptor.properties | 0
.../jdbc/DBase3FieldDescriptor_fr.properties | 0
.../sis/internal/shapefile/jdbc/DBaseDataType.java | 0
.../internal/shapefile/jdbc/Dbase3ByteReader.java | 0
.../internal/shapefile/jdbc/MappedByteReader.java | 0
.../shapefile/jdbc/MappedByteReader.properties | 0
.../shapefile/jdbc/MappedByteReader_fr.properties | 0
.../jdbc/SQLConnectionClosedException.java | 0
.../jdbc/SQLDbaseFileNotFoundException.java | 0
.../jdbc/SQLInvalidDbaseFileFormatException.java | 0
.../jdbc/connection/AbstractConnection.java | 0
.../jdbc/connection/AbstractConnection.properties | 0
.../connection/AbstractConnection_fr.properties | 0
.../shapefile/jdbc/connection/DBFConnection.java | 0
.../jdbc/connection/DBFConnection.properties | 0
.../jdbc/connection/DBFConnection_fr.properties | 0
.../connection/SQLClosingIOFailureException.java | 0
.../shapefile/jdbc/connection/package-info.java | 0
.../jdbc/metadata/AbstractDatabaseMetaData.java | 0
.../jdbc/metadata/DBFDatabaseMetaData.java | 0
.../jdbc/metadata/DBFResultSetMataData.java | 0
.../jdbc/metadata/DBFResultSetMataData.properties | 0
.../metadata/DBFResultSetMataData_fr.properties | 0
.../shapefile/jdbc/metadata/package-info.java | 0
.../sis/internal/shapefile/jdbc/package-info.java | 0
.../jdbc/resultset/AbstractResultSet.java | 0
.../jdbc/resultset/AbstractResultSet.properties | 0
.../jdbc/resultset/AbstractResultSet_fr.properties | 0
.../jdbc/resultset/BuiltInMemoryResultSet.java | 0
...iltInMemoryResultSetForCatalogNamesListing.java | 0
...DBFBuiltInMemoryResultSetForColumnsListing.java | 0
...ltInMemoryResultSetForColumnsListing.properties | 0
...nMemoryResultSetForColumnsListing_fr.properties | 0
.../DBFBuiltInMemoryResultSetForSchemaListing.java | 0
.../DBFBuiltInMemoryResultSetForTablesListing.java | 0
...iltInMemoryResultSetForTablesListing.properties | 0
...uiltInMemoryResultSetForTablesTypesListing.java | 0
...MemoryResultSetForTablesTypesListing.properties | 0
.../jdbc/resultset/DBFRecordBasedResultSet.java | 0
.../resultset/DBFRecordBasedResultSet.properties | 0
.../DBFRecordBasedResultSet_fr.properties | 0
.../shapefile/jdbc/resultset/DBFResultSet.java | 0
.../jdbc/resultset/DBFResultSet.properties | 0
.../jdbc/resultset/DBFResultSet_fr.properties | 0
.../resultset/SQLIllegalColumnIndexException.java | 0
.../jdbc/resultset/SQLNoResultException.java | 0
.../jdbc/resultset/SQLNoSuchFieldException.java | 0
.../jdbc/resultset/SQLNotDateException.java | 0
.../jdbc/resultset/SQLNotNumericException.java | 0
.../shapefile/jdbc/resultset/package-info.java | 0
.../shapefile/jdbc/sql/ClauseResolver.java | 0
.../shapefile/jdbc/sql/ClauseResolver.properties | 0
.../jdbc/sql/ClauseResolver_fr.properties | 0
.../jdbc/sql/ConditionalClauseResolver.java | 0
.../shapefile/jdbc/sql/CrudeSQLParser.java | 0
.../shapefile/jdbc/sql/CrudeSQLParser.properties | 0
.../jdbc/sql/SQLIllegalParameterException.java | 0
.../jdbc/sql/SQLInvalidStatementException.java | 0
.../sql/SQLUnsupportedParsingFeatureException.java | 0
.../internal/shapefile/jdbc/sql/package-info.java | 0
.../jdbc/statement/AbstractStatement.java | 0
.../shapefile/jdbc/statement/DBFStatement.java | 0
.../jdbc/statement/DBFStatement.properties | 0
.../jdbc/statement/DBFStatement_fr.properties | 0
.../shapefile/jdbc/statement/package-info.java | 0
.../sis/internal/shapefile/package-info.java | 0
.../storage/shapefile/DataStoreQueryException.java | 0
.../shapefile/DataStoreQueryResultException.java | 0
.../shapefile/DbaseFileNotFoundException.java | 0
.../sis/storage/shapefile/InputFeatureStream.java | 0
.../shapefile/InputFeatureStream.properties | 0
.../shapefile/InputFeatureStream_fr.properties | 0
.../shapefile/InvalidDbaseFileFormatException.java | 0
.../shapefile/InvalidShapefileFormatException.java | 0
.../apache/sis/storage/shapefile/ShapeFile.java | 0
.../sis/storage/shapefile/ShapeTypeEnum.java | 0
.../shapefile/ShapefileNotFoundException.java | 0
.../apache/sis/storage/shapefile/cpg/CpgFiles.java | 0
.../apache/sis/storage/shapefile/package-info.java | 0
.../jdbc/AbstractTestBaseForInternalJDBC.java | 0
.../internal/shapefile/jdbc/DBFConnectionTest.java | 0
.../internal/shapefile/jdbc/DBFResultSetTest.java | 0
.../internal/shapefile/jdbc/DBFStatementTest.java | 0
.../apache/sis/internal/shapefile/jdbc/readme.txt | 0
.../shapefile/jdbc/sql/WhereClauseTest.java | 0
.../shapefile/ABRALicenseePt_4326_clipped.dbf | Bin
.../shapefile/ABRALicenseePt_4326_clipped.prj | 0
.../shapefile/ABRALicenseePt_4326_clipped.shp | Bin
.../shapefile/ABRALicenseePt_4326_clipped.shx | Bin
.../org/apache/sis/storage/shapefile/NOTES.md | 0
.../sis/storage/shapefile/ShapeFileTest.java | 0
.../shapefile/SignedBikeRoute_4326_clipped.dbf | Bin
.../shapefile/SignedBikeRoute_4326_clipped.prj | 0
.../shapefile/SignedBikeRoute_4326_clipped.shp | Bin
.../shapefile/SignedBikeRoute_4326_clipped.shx | Bin
.../test/module-info.java | 27 +
.../org.apache.sis.webapp/main/module-info.java | 27 +
.../org/apache/sis/services/OSGiActivator.java | 85 +
.../main}/org/apache/sis/services/Servlet.java | 0
.../org/apache/sis/services/ServletListener.java | 0
.../org/apache/sis/services/package-info.java | 0
.../webapp/META-INF/context.xml | 26 +
.../org.apache.sis.webapp}/webapp/WEB-INF/web.xml | 0
non-free/README | 14 -
optional/build.gradle.kts | 168 +
optional/src/org.apache.sis.gui/bundle/LICENSE | 1 +
optional/src/org.apache.sis.gui/bundle/NOTICE | 1 +
.../src/org.apache.sis.gui/bundle}/README | 0
optional/src/org.apache.sis.gui/bundle/bin/sis | 32 +
optional/src/org.apache.sis.gui/bundle/bin/sis.bat | 29 +
optional/src/org.apache.sis.gui/bundle/bin/sisfx | 44 +
.../src/org.apache.sis.gui/bundle/bin/sisfx.bat | 35 +
.../bundle}/conf/logging.properties | 0
.../src/org.apache.sis.gui/bundle}/conf/setenv.bat | 0
.../src/org.apache.sis.gui/bundle}/conf/setenv.sh | 0
.../src/org.apache.sis.gui/bundle}/data/README | 0
.../src/org.apache.sis.gui/bundle}/lib/README | 0
.../src/org.apache.sis.gui/bundle}/lib/logo.jpg | Bin
.../src/org.apache.sis.gui/bundle}/log/README | 0
.../org.apache.sis.setup.InstallationResources | 4 +
.../src/org.apache.sis.gui/main/module-info.java | 52 +
.../main}/org/apache/sis/gui/AboutDialog.java | 0
.../main}/org/apache/sis/gui/DataViewer.java | 0
.../main}/org/apache/sis/gui/RecentFiles.java | 0
.../main}/org/apache/sis/gui/SIS_128px.png | Bin
.../main}/org/apache/sis/gui/SIS_64px.png | Bin
.../main}/org/apache/sis/gui/SystemMonitor.java | 0
.../main}/org/apache/sis/gui/Widget.java | 0
.../apache/sis/gui/coverage/BandRangeTable.java | 0
.../sis/gui/coverage/BandSelectionListener.java | 0
.../org/apache/sis/gui/coverage/CellFormat.java | 0
.../apache/sis/gui/coverage/CoverageCanvas.java | 0
.../apache/sis/gui/coverage/CoverageControls.java | 0
.../apache/sis/gui/coverage/CoverageExplorer.java | 0
.../apache/sis/gui/coverage/CoverageStyling.java | 0
.../org/apache/sis/gui/coverage/GridCell.java | 0
.../org/apache/sis/gui/coverage/GridControls.java | 0
.../org/apache/sis/gui/coverage/GridError.java | 0
.../main}/org/apache/sis/gui/coverage/GridRow.java | 0
.../org/apache/sis/gui/coverage/GridRowSkin.java | 0
.../apache/sis/gui/coverage/GridSliceSelector.java | 0
.../org/apache/sis/gui/coverage/GridTile.java | 0
.../org/apache/sis/gui/coverage/GridTileCache.java | 0
.../org/apache/sis/gui/coverage/GridView.java | 0
.../org/apache/sis/gui/coverage/GridViewSkin.java | 0
.../sis/gui/coverage/ImagePropertyExplorer.java | 0
.../org/apache/sis/gui/coverage/ImageRequest.java | 0
.../sis/gui/coverage/InterpolationConverter.java | 0
.../apache/sis/gui/coverage/IsolineRenderer.java | 0
.../gui/coverage/MultiResolutionImageLoader.java | 0
.../sis/gui/coverage/PropertyPaneCreator.java | 0
.../org/apache/sis/gui/coverage/Stretching.java | 0
.../sis/gui/coverage/StyledRenderingData.java | 0
.../apache/sis/gui/coverage/ViewAndControls.java | 0
.../org/apache/sis/gui/coverage/package-info.java | 0
.../org/apache/sis/gui/dataset/ExpandableList.java | 0
.../apache/sis/gui/dataset/ExpandedFeature.java | 0
.../org/apache/sis/gui/dataset/FeatureList.java | 0
.../org/apache/sis/gui/dataset/FeatureLoader.java | 0
.../org/apache/sis/gui/dataset/FeatureTable.java | 0
.../org/apache/sis/gui/dataset/LogViewer.java | 0
.../org/apache/sis/gui/dataset/PathAction.java | 0
.../org/apache/sis/gui/dataset/ResourceCell.java | 0
.../org/apache/sis/gui/dataset/ResourceEvent.java | 0
.../apache/sis/gui/dataset/ResourceExplorer.java | 0
.../org/apache/sis/gui/dataset/ResourceItem.java | 0
.../org/apache/sis/gui/dataset/ResourceTree.java | 0
.../org/apache/sis/gui/dataset/RootResource.java | 0
.../org/apache/sis/gui/dataset/TreeViewType.java | 0
.../org/apache/sis/gui/dataset/WindowHandler.java | 0
.../org/apache/sis/gui/dataset/WindowManager.java | 0
.../org/apache/sis/gui/dataset/package-info.java | 0
.../org/apache/sis/gui/map/GestureFollower.java | 0
.../main}/org/apache/sis/gui/map/MapCanvas.java | 0
.../main}/org/apache/sis/gui/map/MapCanvasAWT.java | 0
.../main}/org/apache/sis/gui/map/MapMenu.java | 0
.../org/apache/sis/gui/map/OperationFinder.java | 0
.../org/apache/sis/gui/map/RenderingTask.java | 0
.../main}/org/apache/sis/gui/map/StatusBar.java | 0
.../org/apache/sis/gui/map/ValuesFormatter.java | 0
.../org/apache/sis/gui/map/ValuesFromCoverage.java | 0
.../org/apache/sis/gui/map/ValuesUnderCursor.java | 0
.../main}/org/apache/sis/gui/map/package-info.java | 0
.../sis/gui/metadata/IdentificationInfo.java | 0
.../apache/sis/gui/metadata/MetadataSummary.java | 0
.../org/apache/sis/gui/metadata/MetadataTree.java | 0
.../sis/gui/metadata/RepresentationInfo.java | 0
.../main}/org/apache/sis/gui/metadata/Section.java | 0
.../sis/gui/metadata/StandardMetadataTree.java | 0
.../apache/sis/gui/metadata/VerboseFormats.java | 0
.../apache/sis/gui/metadata/WorldMap360x180.png | Bin
.../org/apache/sis/gui/metadata/package-info.java | 0
.../main}/org/apache/sis/gui/package-info.java | 0
.../main}/org/apache/sis/gui/pseudo-classes.css | 0
.../apache/sis/gui/referencing/AuthorityCodes.java | 0
.../org/apache/sis/gui/referencing/CRSChooser.java | 0
.../main}/org/apache/sis/gui/referencing/Code.java | 0
.../org/apache/sis/gui/referencing/CodeFilter.java | 0
.../org/apache/sis/gui/referencing/MenuSync.java | 0
.../sis/gui/referencing/ObjectStringConverter.java | 0
.../gui/referencing/PositionableProjection.java | 0
.../gui/referencing/RecentReferenceSystems.java | 0
.../org/apache/sis/gui/referencing/Utils.java | 0
.../org/apache/sis/gui/referencing/WKTPane.java | 0
.../apache/sis/gui/referencing/package-info.java | 0
.../apache/sis/internal/gui/BackgroundThreads.java | 0
.../org/apache/sis/internal/gui/ColorName.java | 0
.../org/apache/sis/internal/gui/DataFormats.java | 0
.../apache/sis/internal/gui/DataStoreOpener.java | 0
.../apache/sis/internal/gui/ExceptionReporter.java | 0
.../sis/internal/gui/FixedHeaderColumnSize.java | 0
.../org/apache/sis/internal/gui/GUIUtilities.java | 0
.../sis/internal/gui/IdentityValueFactory.java | 0
.../apache/sis/internal/gui/ImageConverter.java | 0
.../sis/internal/gui/ImmutableObjectProperty.java | 0
.../org/apache/sis/internal/gui/LogHandler.java | 0
.../org/apache/sis/internal/gui/MouseDrags.java | 0
.../sis/internal/gui/NonNullObjectProperty.java | 0
.../sis/internal/gui/OptionalDataDownloader.java | 0
.../org/apache/sis/internal/gui/PrivateAccess.java | 0
.../sis/internal/gui/PropertyValueFormats.java | 0
.../sis/internal/gui/PropertyValueFormatter.java | 0
.../org/apache/sis/internal/gui/PropertyView.java | 0
.../org/apache/sis/internal/gui/RecentChoices.java | 0
.../org/apache/sis/internal/gui/Resources.java | 585 ++++
.../apache/sis/internal/gui/Resources.properties | 98 +
.../org/apache/sis/internal/gui/Resources_en.java | 0
.../org/apache/sis/internal/gui/Resources_fr.java | 0
.../sis/internal/gui/Resources_fr.properties | 103 +
.../main}/org/apache/sis/internal/gui/Styles.java | 0
.../org/apache/sis/internal/gui/ToolbarButton.java | 0
.../apache/sis/internal/gui/control/ColorCell.java | 0
.../internal/gui/control/ColorColumnHandler.java | 0
.../apache/sis/internal/gui/control/ColorRamp.java | 0
.../sis/internal/gui/control/FormatApplicator.java | 0
.../sis/internal/gui/control/FormatTableCell.java | 0
.../sis/internal/gui/control/SyncWindowList.java | 0
.../sis/internal/gui/control/TabularWidget.java | 0
.../sis/internal/gui/control/ValueColorMapper.java | 0
.../sis/internal/gui/control/package-info.java | 0
.../apache/sis/internal/gui/io/FileAccessItem.java | 0
.../apache/sis/internal/gui/io/FileAccessView.java | 0
.../apache/sis/internal/gui/io/package-info.java | 0
.../org/apache/sis/internal/gui/package-info.java | 0
.../org/apache/sis/internal/setup/FXFinder.java | 439 +++
.../org/apache/sis/internal/setup/Inflater.java | 0
.../org/apache/sis/internal/setup/Wizard.java | 0
.../org/apache/sis/internal/setup/WizardPage.java | 0
.../apache/sis/internal/setup/package-info.java | 0
.../apache/sis/gui/coverage/CoverageCanvasApp.java | 0
.../sis/gui/coverage/CoverageStylingApp.java | 0
.../sis/gui/coverage/GridSliceSelectorApp.java | 0
.../org/apache/sis/gui/coverage/GridViewApp.java | 0
.../apache/sis/gui/referencing/CRSChooserApp.java | 0
.../apache/sis/internal/gui/GUIUtilitiesTest.java | 0
.../internal/gui/control/ValueColorMapperApp.java | 0
.../test/module-info.java | 27 +
{ide-project => parent}/LicenseHeader.txt | 0
parent/checkstyle.xml | 95 +
parent/logging.properties | 40 +
{src/main/javadoc => parent}/overview.html | 0
parent/pom.xml | 433 +++
{src/main/javadoc => parent}/sis.css | 0
{src/main/javadoc => parent}/warning.png | Bin
pom.xml | 1030 ------
profiles/pom.xml | 130 -
profiles/sis-french-profile/pom.xml | 133 -
.../sis/internal/profile/fra/ProfileTypes.java | 68 -
.../org.apache.sis.internal.jaxb.TypeRegistration | 1 -
profiles/sis-japan-profile/pom.xml | 123 -
.../apache/sis/profile/japan/JapaneseProfile.java | 42 -
.../org.apache.sis.internal.netcdf.Convention | 2 -
.../ucar.nc2.dataset.spi.CoordSystemBuilderFactory | 1 -
settings.gradle.kts | 92 +
src/README.txt | 3 -
src/main/config/logging.properties | 40 -
storage/pom.xml | 180 --
storage/sis-earth-observation/pom.xml | 135 -
.../org.apache.sis.storage.DataStoreProvider | 1 -
storage/sis-geotiff/pom.xml | 142 -
.../org.apache.sis.storage.DataStoreProvider | 1 -
storage/sis-netcdf/pom.xml | 165 -
.../org/apache/sis/internal/netcdf/Convention.java | 798 -----
.../org/apache/sis/internal/netcdf/Resources.java | 323 --
.../sis/internal/netcdf/Resources.properties | 47 -
.../sis/internal/netcdf/Resources_fr.properties | 52 -
.../apache/sis/storage/netcdf/MetadataReader.java | 1083 -------
.../sis/storage/netcdf/NetcdfStoreProvider.java | 470 ---
.../org.apache.sis.storage.DataStoreProvider | 1 -
storage/sis-shapefile/pom.xml | 132 -
storage/sis-sqlstore/pom.xml | 164 -
.../apache/sis/internal/sql/feature/Resources.java | 265 --
.../sis/internal/sql/feature/Resources.properties | 37 -
.../internal/sql/feature/Resources_fr.properties | 42 -
storage/sis-storage/pom.xml | 157 -
.../org/apache/sis/internal/storage/Resources.java | 603 ----
.../sis/internal/storage/Resources.properties | 100 -
.../sis/internal/storage/Resources_fr.properties | 105 -
.../sis/internal/storage/xml/package-info.java | 32 -
.../org/apache/sis/storage/DataStoreProvider.java | 632 ----
.../org/apache/sis/storage/DataStoreRegistry.java | 324 --
.../java/org/apache/sis/storage/DataStores.java | 86 -
.../services/java.nio.file.spi.FileTypeDetector | 1 -
.../org.apache.sis.storage.DataStoreProvider | 7 -
.../sis/internal/storage/folder/StoreTest.java | 126 -
storage/sis-xmlstore/pom.xml | 137 -
.../org.apache.sis.storage.DataStoreProvider | 1 -
3616 files changed, 67141 insertions(+), 71100 deletions(-)
diff --cc buildSrc/src/org.apache.sis.buildtools/main/org/apache/sis/buildtools/gradle/ModularJAR.java
index 0000000000,99802d3caa..113084ce7c
mode 000000,100644..100644
--- a/buildSrc/src/org.apache.sis.buildtools/main/org/apache/sis/buildtools/gradle/ModularJAR.java
+++ b/buildSrc/src/org.apache.sis.buildtools/main/org/apache/sis/buildtools/gradle/ModularJAR.java
@@@ -1,0 -1,176 +1,176 @@@
+ /*
+ * 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.buildtools.gradle;
+
+ import java.util.Map;
+ import java.util.HashMap;
+ import java.util.Iterator;
+ import java.util.jar.Manifest;
+ import java.util.jar.Attributes;
+ import java.util.jar.JarOutputStream;
+ import java.nio.file.Files;
+ import java.nio.file.Path;
+ import java.io.File;
+ import java.io.FileOutputStream;
+ import java.io.BufferedOutputStream;
+ import java.io.IOException;
+ import java.io.UncheckedIOException;
+ import org.gradle.api.Project;
+ import org.gradle.api.tasks.bundling.Jar;
+
+
+ /**
+ * Extension to Gradle {@link Jar} task. This extension generates one JAR file per module.
+ * If the {@code build.gradle} file specifies a {@code Main-Class} attribute, the latter
+ * can apply to only one module, which is identified in this class as the "main module".
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.4
+ * @since 1.4
+ */
+ final class ModularJAR extends ZipWriter.JDK {
+ /**
+ * Version of the GeoAPI dependency.
+ * This value depends on the Apache SIS branch being compiled.
+ *
+ * @todo should be specified in a property.
+ */
- private static final String GEOAPI_VERSION = "4.0-SNAPSHOT";
++ private static final String GEOAPI_VERSION = "3.1-SNAPSHOT";
+
+ /**
+ * Attributes where values are class names. Those attributes can be assigned
+ * to only one module, because the same class cannot appear in two modules.
+ */
+ private static final String[] CLASSNAME_ATTRIBUTES = {
+ Attributes.Name.MAIN_CLASS.toString(),
+ "RegistrationClassName"
+ };
+
+ /**
+ * Creates a helper instance.
+ *
+ * @param project the sub-project being compiled.
+ * @param out output stream of the JAR file to create.
+ */
+ private ModularJAR(final Project project, final JarOutputStream out) {
+ super(project, out);
+ }
+
+ /**
+ * Lists all compiled modules in the current Gradle sub-project.
+ *
+ * @return all modules in current Gradle sub-project.
+ */
+ private static File[] listModules(final Project project) {
+ return new File(project.getBuildDir(), MAIN_CLASSES_DIRECTORY).listFiles(File::isDirectory);
+ }
+
+ /**
+ * Invoked when the {@code jar} task is executed.
+ *
+ * @param context the extension which is invoking this task.
+ * @param task the {@link Javadoc} task to configure.
+ */
+ static void execute(final BuildHelper context, final Jar task) {
+ final Project project = task.getProject();
+ final Map<String,?> attributes = task.getManifest().getAttributes();
+ final var filteredAttributes = new HashMap<String,String>();
+ final var classnameAttributes = new HashMap<String,String>();
+ for (final String classname : CLASSNAME_ATTRIBUTES) {
+ final Object value = attributes.get(classname);
+ if (value instanceof String) {
+ final String path = ((String) value).replace('.', File.separatorChar) + ".class";
+ classnameAttributes.put(classname, path);
+ }
+ }
+ final File target = new File(project.getBuildDir(), LIBS_DIRECTORY);
+ for (final File module : listModules(project)) {
+ for (final Iterator<Map.Entry<String,String>> it = classnameAttributes.entrySet().iterator(); it.hasNext();) {
+ final Map.Entry<String,String> entry = it.next();
+ if (new File(module, entry.getValue()).isFile()) {
+ final String key = entry.getKey();
+ filteredAttributes.put(key, (String) attributes.get(key));
+ it.remove();
+ }
+ }
+ try {
+ write(project, module, new File(target, module.getName() + ".jar"), filteredAttributes);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ filteredAttributes.clear();
+ }
+ for (final Map.Entry<String,String> entry : classnameAttributes.entrySet()) {
+ task.getLogger().warn(entry.getKey() + " not found: " + entry.getValue());
+ }
+ try {
+ linkDependencies(project, target);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ } catch (UnsupportedOperationException e) {
+ project.getLogger().warn("Links to dependencies not provided because hard-links are not supported on this platform.", e);
+ }
+ }
+
+ /**
+ * Writes a JAR file for a single module.
+ *
+ * @param project the project for which to write a JAR file.
+ * @param source root directory of compiled class files for the module to package.
+ * @param target the file to write.
+ * @param specific attributes specific to this module.
+ * @throws IOException if an error occurred while reading the source or writing the JAR file.
+ */
+ private static void write(final Project project, final File source, final File target,
+ final Map<String,String> specific) throws IOException
+ {
+ final var mf = new Manifest();
+ final Attributes attributes = mf.getMainAttributes();
+ attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
+ attributes.put(Attributes.Name.SPECIFICATION_TITLE, "GeoAPI");
+ attributes.put(Attributes.Name.SPECIFICATION_VENDOR, "Open Geospatial Consortium");
+ attributes.put(Attributes.Name.SPECIFICATION_VERSION, GEOAPI_VERSION);
+ attributes.put(Attributes.Name.IMPLEMENTATION_TITLE, "Apache Spatial Information System (SIS)");
+ attributes.put(Attributes.Name.IMPLEMENTATION_VENDOR, "The Apache Software Foundation");
+ attributes.put(Attributes.Name.IMPLEMENTATION_VERSION, project.getVersion().toString());
+ for (final Map.Entry<String,String> entry : specific.entrySet()) {
+ attributes.put(new Attributes.Name(entry.getKey()), entry.getValue());
+ }
+ try (JarOutputStream out = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(target)), mf)) {
+ new ModularJAR(project, out).writeDirectory(source, null, "");
+ }
+ }
+
+ /**
+ * Adds hard-links to all dependencies.
+ *
+ * @param project the project for which to add dependencies.
+ * @param target where to write dependencies.
+ * @throws IOException if an I/O error occurred while reading the module description.
+ * @throws UnsupportedOperationException if links are not supported on this platform.
+ */
+ private static void linkDependencies(final Project project, final File target) throws IOException {
+ for (final Dependency dep : Dependency.find(project)) {
+ if (dep.module != null) {
+ final Path f = new File(target, dep.module + ".jar").toPath();
+ if (Files.notExists(f)) {
+ Files.createLink(f, dep.file.toPath());
+ }
+ }
+ }
+ }
+ }
diff --cc endorsed/build.gradle.kts
index 0000000000,6c9ad7a0f6..b72ee933be
mode 000000,100644..100644
--- a/endorsed/build.gradle.kts
+++ b/endorsed/build.gradle.kts
@@@ -1,0 -1,392 +1,392 @@@
+ /*
+ * 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.
+ */
+ group = "org.apache.sis"
-version = "2.0-SNAPSHOT"
++version = "1.x-SNAPSHOT"
+
+ /*
+ * "org.apache.sis.buildtools" is a custom Gradle plugin for building a project with Module Source Hierarchy
+ * as specified in https://docs.oracle.com/en/java/javase/20/docs/specs/man/javac.html#directory-hierarchies
+ * The expected hierarchy is:
+ *
+ * endorsed
+ * ├─ build
+ * └─ src
+ * ├─ org.apache.sis.metadata
+ * │ ├─ main
+ * │ │ ├─ module-info.java
+ * │ │ └─ org/apache/sis/metadata/…
+ * │ └─ test
+ * │ └─ org/apache/sis/metadata/…
+ * ├─ org.apache.sis.referencing
+ * │ ├─ main
+ * │ │ ├─ module-info.java
+ * │ │ └─ org/apache/sis/referencing/…
+ * │ └─ test
+ * │ └─ org/apache/sis/referencing/…
+ * └─ etc.
+ */
+ plugins {
+ `java-library`
+ `maven-publish`
+ id("org.apache.sis.buildtools")
+ }
+
+ /*
+ * All JAR files that may potentially be used by a module.
+ * For each Apache SIS module, the dependencies actually
+ * used are declared in the `module-info.java` file.
+ */
+ dependencies {
+ // Mandatory dependencies
+ api(libs.units)
+ api(libs.geoapi)
+ api(libs.jaxb.api)
+
+ // Optional dependencies
+ runtimeOnly(libs.jaxb.impl)
+ compileOnly(libs.jts.core)
+ compileOnly(libs.esri.geometry)
+ compileOnly(libs.libreoffice)
+ compileOnly(libs.ucar)
+ compileOnly(libs.aws.s3)
+ compileOnly(drivers.postgres)
+
+ // Test dependencies
+ testImplementation(tests.junit4)
+ testImplementation(tests.geoapi)
+ testImplementation(tests.jama)
+ testImplementation(tests.geographiclib)
+ testImplementation(libs.jts.core) // We need to repeat optional dependencies.
+ testImplementation(libs.esri.geometry) // Idem.
+ testImplementation(libs.libreoffice)
+ testImplementation(libs.ucar)
+ testImplementation(libs.aws.s3)
+ testImplementation(drivers.derby.tools)
+ testImplementation(drivers.derby.core)
+ testImplementation(drivers.postgres)
+ testImplementation(drivers.hsql)
+ testImplementation(drivers.h2)
+
+ // For test execution
+ testRuntimeOnly(tests.junit)
+ testRuntimeOnly(tests.junitLauncher)
+ testRuntimeOnly(tests.slf4j)
+ }
+
+ /*
+ * Compile main and tests classes from Module Source Hierarchy.
+ * The test classes require some additional dependencies declared in the `org.apache.sis.test.endorsed` module.
+ */
+ var srcDir = file("src") // Must be the same as the hard-coded value in `BuildHelper.java`.
+ tasks.compileJava {
+ options.release.set(11) // The version of both Java source code and compiled byte code.
+ }
+ tasks.compileTestJava {
+ srcDir.list().forEach {
+ addRead(options.compilerArgs, it, "org.apache.sis.test.endorsed,junit")
+ }
+ addExportForTests(options.compilerArgs)
+ }
+
+ /*
+ * Adds a JVM argument for adding dependencies to a module.
+ * This is for dependencies not declared in `module-info`
+ * but needed for test compilation or test execution.
+ */
+ fun addRead(args : MutableList<String>, module : String, dependencies : String) {
+ args.add("--add-reads")
+ args.add(module + '=' + dependencies)
+ }
+
+ /*
+ * Adds a JVM argument for making an internal package accessible to another module.
+ * This is for making internal packages accessible to JUnit or to some test classes
+ * defined in other modules.
+ */
+ fun addExport(args : MutableList<String>, module : String, pkg : String, consumers : String) {
+ args.add("--add-exports")
+ args.add(module + '/' + pkg + '=' + consumers)
+ }
+
+ /*
+ * Add compiler and runtime options for patching the Apache SIS main modules with the test classes.
+ * The same options are required for both compiling and executing the tests.
+ */
+ fun addExportForTests(args : MutableList<String>) {
+ var allModules = srcDir.list().joinToString(separator=",")
+
+ // ――――――――――――― Module name ――――――――――――――――――――――― Package to export ―――――――――――――――
+ addExport(args, "org.apache.sis.util", "org.apache.sis.test",
+ allModules)
+
+ addExport(args, "org.apache.sis.metadata", "org.apache.sis.test.mock",
+ "org.apache.sis.referencing")
+
+ addExport(args, "org.apache.sis.metadata", "org.apache.sis.test.sql",
+ "org.apache.sis.referencing," +
+ "org.apache.sis.storage.sql")
+
+ addExport(args, "org.apache.sis.metadata", "org.apache.sis.test.xml",
+ "org.apache.sis.referencing," +
+ "org.apache.sis.profile.france")
+
+ addExport(args, "org.apache.sis.storage", "org.apache.sis.test.storage",
+ "org.apache.sis.storage.geotiff," +
+ "org.apache.sis.storage.netcdf")
+ /*
+ * Some test classes need access to more internal packages than requested by the main classes.
+ * The following lines may need to be edited when export statements are added or removed in a
+ * module-info.java file of main source code, or when a test class starts using or stop using
+ * an internal API.
+ */
+ // ――――――――――――― Module name ――――――――――――――――――――――― Package to export ―――――――――――――――
+ addExport(args, "org.apache.sis.metadata", "org.apache.sis.internal.metadata",
+ "org.apache.sis.referencing.gazetteer")
+
+ addExport(args, "org.apache.sis.metadata", "org.apache.sis.metadata.xml",
+ "org.apache.sis.storage," +
+ "org.apache.sis.console")
+
+ addExport(args, "org.apache.sis.metadata", "org.apache.sis.internal.xml",
+ "org.apache.sis.storage.geotiff")
+
+ addExport(args, "org.apache.sis.metadata", "org.apache.sis.internal.jaxb.gcx",
+ "org.apache.sis.referencing")
+
+ addExport(args, "org.apache.sis.feature", "org.apache.sis.internal.feature.jts",
+ "org.apache.sis.storage.sql," +
+ "org.apache.sis.portrayal")
+
+ addExport(args, "org.apache.sis.storage", "org.apache.sis.internal.storage",
+ "org.apache.sis.portrayal")
+ }
+
+ /*
+ * Discover and execute JUnit-based tests.
+ */
+ tasks.test {
+ val args = mutableListOf("-enableassertions")
+ addExportForTests(args)
+ /*
+ * Dependencies needed only for executing the tests (not for compilation).
+ */
+ addRead(args, "org.apache.sis.metadata", "org.apache.derby.tools,com.h2database,org.hsqldb")
+ addRead(args, "org.apache.sis.referencing", "jama,GeographicLib.Java")
+ addRead(args, "org.apache.sis.storage", "esri.geometry.api")
+ addRead(args, "org.apache.sis.storage.xml", "esri.geometry.api")
+ /*
+ * JAXB implementation needs permissions to do reflection.
+ */
+ args.add("--add-opens")
+ args.add("org.apache.sis.metadata/org.apache.sis.test.mock=jakarta.xml.bind")
+ setAllJvmArgs(args)
+ /*
+ * Request full stack trace in case of failure. The short stack trace is not enough
+ * for identifying the failure cause.
+ */
+ testLogging {
+ events("FAILED", "STANDARD_OUT", "STANDARD_ERROR")
+ setExceptionFormat("FULL")
+ }
+ }
+
+ /*
+ * Javadoc generation. Most of the configuration is specified in the `../buildSrc` plugin.
+ * This file contains only the subproject-dependent parts.
+ */
+ tasks.javadoc {
+ setTitle("Apache SIS ${version} API")
+ }
+
+ /*
+ * Configuration of some META-INF/MANIFEST.MF attributes.
+ * Other attributes are hard-coded in `../buildSrc`.
+ */
+ tasks.jar {
+ manifest {
+ attributes["Main-Class"] = "org.apache.sis.console.Command"
+ attributes["RegistrationClassName"] = "org.apache.sis.openoffice.Registration"
+ }
+ }
+
+ /*
+ * Configuration of the modules to deploy as Maven artifacts.
+ */
+ publishing {
+ publications {
+ create<MavenPublication>("util") {
+ groupId = "org.apache.sis.core"
+ artifactId = "sis-utility"
+ artifact(file("${buildDir}/libs/org.apache.sis.util.jar"))
+ pom {
+ name = "Apache SIS utilities"
+ description = "Units of measurement and miscellaneous utility methods required by Apache SIS."
+ }
+ }
+ create<MavenPublication>("metadata") {
+ groupId = "org.apache.sis.core"
+ artifactId = "sis-metadata"
+ artifact(file("${buildDir}/libs/org.apache.sis.metadata.jar"))
+ pom {
+ name = "Apache SIS metadata"
+ description = "Implementations of metadata derived from ISO 19115. " +
+ "This module provides both an implementation of the metadata interfaces defined in GeoAPI, " +
+ "and a framework for handling those metadata through Java reflection."
+ }
+ }
+ create<MavenPublication>("referencing") {
+ groupId = "org.apache.sis.core"
+ artifactId = "sis-referencing"
+ artifact(file("${buildDir}/libs/org.apache.sis.referencing.jar"))
+ pom {
+ name = "Apache SIS referencing"
+ description = "Implementations of Coordinate Reference Systems (CRS), " +
+ "conversion and transformation services derived from ISO 19111."
+ }
+ }
+ create<MavenPublication>("referencing.gazetteer") {
+ groupId = "org.apache.sis.core"
+ artifactId = "sis-referencing-by-identifiers"
+ artifact(file("${buildDir}/libs/org.apache.sis.referencing.gazetteer.jar"))
+ pom {
+ name = "Apache SIS referencing by geographic identifiers"
+ description = "Implementations of Spatial Reference Systems using Geographic Identifiers " +
+ "gazetteer services derived from ISO 19112."
+ }
+ }
+ create<MavenPublication>("feature") {
+ groupId = "org.apache.sis.core"
+ artifactId = "sis-feature"
+ artifact(file("${buildDir}/libs/org.apache.sis.feature.jar"))
+ pom {
+ name = "Apache SIS features"
+ description = "Representations of geographic features. " +
+ "Includes access to both vector and raster data."
+ }
+ }
+ create<MavenPublication>("portrayal") {
+ groupId = "org.apache.sis.core"
+ artifactId = "sis-portrayal"
+ artifact(file("${buildDir}/libs/org.apache.sis.portrayal.jar"))
+ pom {
+ name = "Apache SIS portrayal"
+ description = "Symbology and map representations, together with a rendering engine for display."
+ }
+ }
+ create<MavenPublication>("storage") {
+ groupId = "org.apache.sis.storage"
+ artifactId = "sis-storage"
+ artifact(file("${buildDir}/libs/org.apache.sis.storage.jar"))
+ pom {
+ name = "Apache SIS common storage"
+ description = "Provides the interfaces and base classes to be implemented by various storage formats."
+ }
+ }
+ create<MavenPublication>("storage.xml") {
+ groupId = "org.apache.sis.storage"
+ artifactId = "sis-xmlstore"
+ artifact(file("${buildDir}/libs/org.apache.sis.storage.xml.jar"))
+ pom {
+ name = "Apache SIS XML storage"
+ description = "Read and write files in the GPX format."
+ }
+ }
+ create<MavenPublication>("storage.netcdf") {
+ groupId = "org.apache.sis.storage"
+ artifactId = "sis-netcdf"
+ artifact(file("${buildDir}/libs/org.apache.sis.storage.netcdf.jar"))
+ pom {
+ name = "Apache SIS netCDF storage"
+ description = "Bridge between netCDF Climate and Forecast (CF) convention and ISO 19115 metadata."
+ }
+ }
+ create<MavenPublication>("storage.geotiff") {
+ groupId = "org.apache.sis.storage"
+ artifactId = "sis-geotiff"
+ artifact(file("${buildDir}/libs/org.apache.sis.storage.geotiff.jar"))
+ pom {
+ name = "Apache SIS GeoTIFF storage"
+ description = "Cloud Optimized GeoTIFF reader and bridge to ISO 19115 metadata."
+ }
+ }
+ create<MavenPublication>("storage.earthobservation") {
+ groupId = "org.apache.sis.storage"
+ artifactId = "sis-earth-observation"
+ artifact(file("${buildDir}/libs/org.apache.sis.storage.earthobservation.jar"))
+ pom {
+ name = "Apache SIS Earth Observation storage"
+ description = "Read a directory of Landsat files as a single resource."
+ }
+ }
+ create<MavenPublication>("storage.sql") {
+ groupId = "org.apache.sis.storage"
+ artifactId = "sis-sqlstore"
+ artifact(file("${buildDir}/libs/org.apache.sis.storage.sql.jar"))
+ pom {
+ name = "Apache SIS SQL storage"
+ description = "Read and write features from SQL databases."
+ }
+ }
+ create<MavenPublication>("cloud.aws") {
+ groupId = "org.apache.sis.cloud"
+ artifactId = "sis-cloud-aws"
+ artifact(file("${buildDir}/libs/org.apache.sis.cloud.aws.jar"))
+ pom {
+ name = "Apache SIS storage from Amazon AWS S3"
+ description = "Provides access to Amazon AWS S3 storage from Apache SIS data stores."
+ }
+ }
+ create<MavenPublication>("profile.france") {
+ groupId = "org.apache.sis.profiles"
+ artifactId = "sis-french-profile"
+ artifact(file("${buildDir}/libs/org.apache.sis.profile.france.jar"))
+ pom {
+ name = "Apache SIS French profiles"
+ description = "Extensions to ISO-19115 metadata mandated by the French government."
+ }
+ }
+ create<MavenPublication>("profile.japan") {
+ groupId = "org.apache.sis.profiles"
+ artifactId = "sis-japan-profile"
+ artifact(file("${buildDir}/libs/org.apache.sis.profile.japan.jar"))
+ pom {
+ name = "Apache SIS Japanese profiles"
+ description = "Extensions to netCDF reader for file formats published by Japanese Aerospace Exploration Agency (JAXA)."
+ }
+ }
+ create<MavenPublication>("console") {
+ groupId = "org.apache.sis.application"
+ artifactId = "sis-console"
+ artifact(file("${buildDir}/libs/org.apache.sis.console.jar"))
+ pom {
+ name = "Apache SIS console"
+ description = "Console application."
+ }
+ }
+ create<MavenPublication>("openoffice") {
+ groupId = "org.apache.sis.application"
+ artifactId = "sis-openoffice"
+ artifact(file("${buildDir}/libs/org.apache.sis.openoffice.jar"))
+ pom {
+ name = "Bridges to Apache OpenOffice or LibreOffice"
+ description = "Provides some Apache SIS functionalities as Apache OpenOffice addins. " +
+ "For example, addins provide coordinate operation services as formulas " +
+ "inside the Calc spreadsheet."
+ }
+ }
+ }
+ }
diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/internal/simple/CitationConstant.java
index 0000000000,a583f12530..2d3adbcda4
mode 000000,100644..100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/internal/simple/CitationConstant.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/internal/simple/CitationConstant.java
@@@ -1,0 -1,242 +1,242 @@@
+ /*
+ * 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.internal.simple;
+
+ import java.util.Date;
+ import java.util.Collection;
+ import java.util.logging.Logger;
+ import java.io.ObjectStreamException;
+ import org.opengis.metadata.Identifier;
+ import org.opengis.metadata.citation.Citation;
+ import org.opengis.metadata.citation.CitationDate;
+ import org.opengis.metadata.citation.OnlineResource;
+ import org.opengis.metadata.citation.PresentationForm;
-import org.opengis.metadata.citation.Responsibility;
++import org.opengis.metadata.citation.ResponsibleParty;
+ import org.opengis.metadata.citation.Series;
+ import org.opengis.metadata.identification.BrowseGraphic;
+ import org.opengis.util.InternationalString;
+ import org.apache.sis.xml.IdentifierSpace;
+ import org.apache.sis.metadata.sql.MetadataSource;
+ import org.apache.sis.metadata.sql.MetadataStoreException;
+ import org.apache.sis.metadata.iso.citation.Citations;
+ import org.apache.sis.internal.system.Loggers;
+ import org.apache.sis.internal.util.Strings;
+ import org.apache.sis.util.logging.Logging;
+
+
+ /**
+ * Base class for the {@code public static final Citation} constants defined in some SIS classes.
+ * This base class contains only an abbreviation (e.g. {@code "OGC"} or {@code "EPSG"}) which can
+ * be used as the primary key where to search for more information in a database. If no database
+ * is available, then that simple primary key will be used as the citation title.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.4
+ *
+ * @see IdentifierSpace
+ * @see Citations
+ *
+ * @since 0.6
+ */
+ public class CitationConstant extends SimpleCitation {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = -8429121584437634107L;
+
+ /**
+ * Where to log warnings when searching for an entry in the database.
+ */
+ private static final Logger LOGGER = Logger.getLogger(Loggers.SQL);
+
+ /**
+ * Class of {@code public static final Citation} constants which are also used as namespace for identifiers.
+ * The most typical example is the "EPSG" authority which manage the codes identifying Coordinate Reference
+ * System (CRS) objects in the EPSG namespace.
+ *
+ * @param <T> the type of object used as identifier values.
+ */
+ public static class Authority<T> extends CitationConstant implements IdentifierSpace<T> {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = 2067932813561130294L;
+
+ /**
+ * Creates a new citation for an authority managing codes in the given namespace.
+ * This constructor assumes that the namespace is the same as the abbreviation given as citation title.
+ *
+ * @param namespace the namespace of codes managed by this authority (e.g. "EPSG").
+ */
+ public Authority(final String namespace) {
+ super(namespace);
+ }
+
+ /**
+ * Creates a new citation for an authority managing codes in the given namespace.
+ *
+ * @param name a human-understandable primary key for fetching more information.
+ * @param namespace the namespace of codes managed by this authority (e.g. "EPSG").
+ */
+ public Authority(final String name, final String namespace) {
+ super(name, namespace);
+ }
+
+ /**
+ * Returns the name space given at construction time. Can be one of the following:
+ * <ul>
+ * <li>Abbreviation of the authority managing the codes (e.g. {@code "EPSG"} or {@code "ISBN"}).</li>
+ * <li>XML attribute name with its prefix (e.g. {@code "gml:id"}, {@code "gco:uuid"} or {@code "xlink:href"}).</li>
+ * </ul>
+ */
+ @Override
+ public final String getName() {
+ return namespace;
+ }
+
+ /**
+ * Returns a string representation of this identifier space.
+ */
+ @Override
+ public final String toString() {
+ return Strings.bracket(IdentifierSpace.class, title);
+ }
+ }
+
+ /**
+ * The name by which this citation is known to {@link Citations#fromName(String)}.
+ * Often the same than the abbreviation that {@link CitationConstant} uses as the title.
+ * If this {@code CitationConstant} is a {@link Authority} subtype, then this is also
+ * the authority namespace.
+ */
+ public final String namespace;
+
+ /**
+ * The citation which contain the "real" data, or {@code null} if not yet created.
+ * This is usually an instance created by {@link MetadataSource}. Those instances
+ * manage their own caching, so accesses to the database should not occur often.
+ */
+ private transient volatile Citation delegate;
+
+ /**
+ * Creates a new proxy for the given primary key.
+ * The key should be readable enough for being usable as a fallback if the database is not available.
+ *
+ * @param name a human-understandable primary key for fetching more information.
+ */
+ public CitationConstant(final String name) {
+ super(name);
+ this.namespace = name;
+ }
+
+ /**
+ * Creates a new proxy for the given primary key but a different programmatic name.
+ * The key should be readable enough for being usable as a fallback if the database is not available.
+ *
+ * @param name a human-understandable primary key for fetching more information.
+ * @param namespace the name by which this citation is known to {@link Citations#fromName(String)}.
+ */
+ public CitationConstant(final String name, final String namespace) {
+ super(name);
+ this.namespace = namespace;
+ }
+
+ /**
+ * Notify this instance that the database content may have changed, or that the module path has changed.
+ */
+ public final void refresh() {
+ delegate = null;
+ }
+
+ /**
+ * Returns the citation instance which contain the actual data. That instance is provided by the
+ * {@code org.apache.sis.metadata} module, which is optional. If that module is not on the module path,
+ * then this {@code delegate()} method will use the few information provided by the current instance.
+ *
+ * <p>Note that it should be very rare to not have {@code org.apache.sis.metadata} on the module path,
+ * since that module is required by {@code org.apache.sis.referencing} which is itself required by
+ * almost all other SIS modules.</p>
+ */
+ @SuppressWarnings("DoubleCheckedLocking")
+ private Citation delegate() {
+ Citation c = delegate;
+ if (c == null) {
+ synchronized (this) {
+ c = delegate;
+ if (c == null) {
+ try {
+ c = MetadataSource.getProvided().lookup(Citation.class, title);
+ } catch (MetadataStoreException e) {
+ /*
+ * If no database was available, MetadataSource.getProvided() was supposed to fallback on
+ * the MetadataFallback class. So if we get this exception, a more serious error occurred.
+ * It is still not fatal however, since most of Citation content is informative.
+ */
+ Logging.unexpectedException(LOGGER, CitationConstant.class, "delegate", e);
+ c = new SimpleCitation(title);
+ }
+ delegate = c;
+ }
+ }
+ }
+ return c;
+ }
+
+ /**
+ * Returns the title, which is mandatory.
+ */
+ @Override
+ public InternationalString getTitle() {
+ InternationalString title = delegate().getTitle();
+ return (title != null) ? title : super.getTitle();
+ }
+
+ /**
+ * Redirects the call to the delegate citation (the instance which actually contain the data).
+ *
+ * @return the value returned by the delegate.
+ */
+ @Override public Collection<? extends InternationalString> getAlternateTitles() {return delegate().getAlternateTitles();}
+ @Override public Collection<? extends CitationDate> getDates() {return delegate().getDates();}
+ @Override public InternationalString getEdition() {return delegate().getEdition();}
+ @Override public Date getEditionDate() {return delegate().getEditionDate();}
+ @Override public Collection<? extends Identifier> getIdentifiers() {return delegate().getIdentifiers();}
- @Override public Collection<? extends Responsibility> getCitedResponsibleParties() {return delegate().getCitedResponsibleParties();}
++ @Override public Collection<? extends ResponsibleParty> getCitedResponsibleParties() {return delegate().getCitedResponsibleParties();}
+ @Override public Collection<PresentationForm> getPresentationForms() {return delegate().getPresentationForms();}
+ @Override public Series getSeries() {return delegate().getSeries();}
- @Override public Collection<? extends InternationalString> getOtherCitationDetails() {return delegate().getOtherCitationDetails();}
++ @Override public InternationalString getOtherCitationDetails() {return delegate().getOtherCitationDetails();}
+ @Override public Collection<? extends OnlineResource> getOnlineResources() {return delegate().getOnlineResources();}
+ @Override public Collection<? extends BrowseGraphic> getGraphics() {return delegate().getGraphics();}
+ @Override public String getISBN() {return delegate().getISBN();}
+ @Override public String getISSN() {return delegate().getISSN();}
+
+ /**
+ * Invoked at deserialization time in order to replace the deserialized instance by the existing
+ * instance defined in the {@link org.apache.sis.metadata.iso.citation.Citations} class.
+ *
+ * @return the instance to use, as an unique instance if possible.
+ * @throws ObjectStreamException never thrown.
+ */
+ protected Object readResolve() throws ObjectStreamException {
+ final Citation c = Citations.fromName(title);
+ return (c instanceof CitationConstant) ? c : this;
+ /*
+ * Returns 'this' should happen only if the Citation has been serialized
+ * on a more recent version of Apache SIS than the current version.
+ */
+ }
+ }
diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/OnlineResourceAdapter.java
index d531a6fd5d,0000000000..d531a6fd5d
mode 100644,000000..100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/OnlineResourceAdapter.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/OnlineResourceAdapter.java
diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/URIStringAdapter.java
index b35da1dfd3,0000000000..b35da1dfd3
mode 100644,000000..100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/URIStringAdapter.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/URIStringAdapter.java
diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/AttributeTypeAdapter.java
index 7619b889e5,0000000000..7619b889e5
mode 100644,000000..100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/AttributeTypeAdapter.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/AttributeTypeAdapter.java
diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/FeatureTypeAdapter.java
index c3ef65d804,0000000000..c3ef65d804
mode 100644,000000..100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/FeatureTypeAdapter.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/FeatureTypeAdapter.java
diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/LegacyFeatureType.java
index c9cef03754,0000000000..c9cef03754
mode 100644,000000..100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/LegacyFeatureType.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/LegacyFeatureType.java
diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
index 0000000000,a27ad7c8cd..c838241200
mode 000000,100644..100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
@@@ -1,0 -1,1488 +1,1488 @@@
+ /*
+ * 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.referencing;
+
+ import java.util.Map;
+ import java.util.List;
+ import java.util.ArrayList;
+ import java.util.logging.Filter;
+ import java.util.logging.Logger;
+ import java.util.logging.LogRecord;
+ import org.opengis.util.FactoryException;
+ import org.opengis.geometry.Envelope;
+ import org.opengis.referencing.NoSuchAuthorityCodeException;
+ import org.opengis.referencing.IdentifiedObject;
+ import org.opengis.referencing.cs.CartesianCS;
+ import org.opengis.referencing.cs.EllipsoidalCS;
+ import org.opengis.referencing.cs.AxisDirection;
+ import org.opengis.referencing.cs.CoordinateSystem;
+ import org.opengis.referencing.cs.CoordinateSystemAxis;
+ import org.opengis.referencing.crs.SingleCRS;
+ import org.opengis.referencing.crs.CompoundCRS;
+ import org.opengis.referencing.crs.CoordinateReferenceSystem;
+ import org.opengis.referencing.crs.CRSAuthorityFactory;
+ import org.opengis.referencing.crs.GeodeticCRS;
+ import org.opengis.referencing.crs.GeographicCRS;
+ import org.opengis.referencing.crs.GeneralDerivedCRS;
+ import org.opengis.referencing.crs.ProjectedCRS;
+ import org.opengis.referencing.crs.TemporalCRS;
+ import org.opengis.referencing.crs.VerticalCRS;
+ import org.opengis.referencing.crs.EngineeringCRS;
+ import org.opengis.referencing.datum.Datum;
+ import org.opengis.referencing.datum.GeodeticDatum;
+ import org.opengis.referencing.operation.Conversion;
+ import org.opengis.referencing.operation.OperationNotFoundException;
+ import org.opengis.metadata.citation.Citation;
+ import org.opengis.metadata.extent.Extent;
+ import org.opengis.metadata.extent.BoundingPolygon;
+ import org.opengis.metadata.extent.GeographicBoundingBox;
+ import org.opengis.metadata.extent.GeographicExtent;
+ import org.opengis.referencing.operation.CoordinateOperation;
+ import org.opengis.referencing.operation.TransformException;
+ import org.apache.sis.measure.Units;
+ import org.apache.sis.geometry.Envelopes;
+ import org.apache.sis.geometry.GeneralEnvelope;
+ import org.apache.sis.internal.referencing.AxisDirections;
+ import org.apache.sis.internal.referencing.EllipsoidalHeightCombiner;
+ import org.apache.sis.internal.referencing.PositionalAccuracyConstant;
+ import org.apache.sis.internal.referencing.ReferencingUtilities;
+ import org.apache.sis.internal.referencing.DefinitionVerifier;
+ import org.apache.sis.internal.referencing.Resources;
+ import org.apache.sis.internal.system.Modules;
+ import org.apache.sis.internal.system.Loggers;
+ import org.apache.sis.internal.util.Numerics;
+ import org.apache.sis.referencing.cs.AxisFilter;
+ import org.apache.sis.referencing.cs.CoordinateSystems;
+ import org.apache.sis.referencing.cs.DefaultVerticalCS;
+ import org.apache.sis.referencing.crs.DefaultGeographicCRS;
+ import org.apache.sis.referencing.crs.DefaultProjectedCRS;
+ import org.apache.sis.referencing.crs.DefaultVerticalCRS;
+ import org.apache.sis.referencing.crs.DefaultCompoundCRS;
+ import org.apache.sis.referencing.crs.DefaultEngineeringCRS;
+ import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
+ import org.apache.sis.referencing.operation.CoordinateOperationContext;
+ import org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
+ import org.apache.sis.referencing.operation.DefaultConversion;
+ import org.apache.sis.referencing.factory.GeodeticObjectFactory;
+ import org.apache.sis.referencing.factory.UnavailableFactoryException;
+ import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
+ import org.apache.sis.metadata.iso.extent.Extents;
+ import org.apache.sis.util.resources.Errors;
+ import org.apache.sis.util.logging.Logging;
+ import org.apache.sis.util.OptionalCandidate;
+ import org.apache.sis.util.ArgumentChecks;
+ import org.apache.sis.util.Utilities;
+ import org.apache.sis.util.Static;
+
+ // Branch-dependent imports
+ import org.opengis.geometry.Geometry;
+
+
+ /**
+ * Static methods working on {@linkplain CoordinateReferenceSystem Coordinate Reference Systems}.
+ * The methods defined in this class can be grouped in three categories:
+ *
+ * <ul>
+ * <li>Factory methods, the most notable one being {@link #forCode(String)}.</li>
+ * <li>Methods providing information, like {@link #isHorizontalCRS(CoordinateReferenceSystem)}.</li>
+ * <li>Finding coordinate operations between a source and a target CRS.</li>
+ * </ul>
+ *
+ * <h2>Usage example</h2>
+ * The most frequently used methods in this class are {@link #forCode forCode(…)}, {@link #fromWKT fromWKT(…)}
+ * and {@link #findOperation findOperation(…)}. An usage example is like below
+ * (see the <a href="https://sis.apache.org/tables/CoordinateReferenceSystems.html">Apache SIS™ Coordinate
+ * Reference System (CRS) codes</a> page for the complete list of EPSG codes):
+ *
+ * {@snippet lang="java" :
+ * CoordinateReferenceSystem source = CRS.forCode("EPSG:4326"); // WGS 84
+ * CoordinateReferenceSystem target = CRS.forCode("EPSG:3395"); // WGS 84 / World Mercator
+ * CoordinateOperation operation = CRS.findOperation(source, target, null);
+ * if (CRS.getLinearAccuracy(operation) > 100) {
+ * // If the accuracy is coarser than 100 metres (or any other threshold at application choice)
+ * // maybe the operation is not suitable. Decide here what to do (throw an exception, etc).
+ * }
+ * MathTransform mt = operation.getMathTransform();
+ * DirectPosition position = new DirectPosition2D(20, 30); // 20°N 30°E (watch out axis order!)
+ * position = mt.transform(position, position);
+ * System.out.println(position);
+ * }
+ *
+ * <h2>Note on kinds of CRS</h2>
+ * The {@link #getSingleComponents(CoordinateReferenceSystem)} method decomposes an arbitrary CRS into a flat
+ * list of single components. In such flat list, vertical and temporal components can easily be identified by
+ * {@code instanceof} checks. But identifying the horizontal component is not as easy. The list below suggests
+ * ways to classify the components:
+ *
+ * <ul>
+ * <li><code>if (crs instanceof TemporalCRS)</code> determines if the CRS is for the temporal component.</li>
+ * <li><code>if (crs instanceof VerticalCRS)</code> determines if the CRS is for the vertical component.</li>
+ * <li><code>if (CRS.{@linkplain #isHorizontalCRS(CoordinateReferenceSystem) isHorizontalCRS}(crs))</code>
+ * determines if the CRS is for the horizontal component.</li>
+ * </ul>
+ *
+ * @author Martin Desruisseaux (IRD, Geomatys)
+ * @author Alexis Manin (Geomatys)
+ * @version 1.4
+ * @since 0.3
+ */
+ public final class CRS extends Static {
+ /**
+ * The logger for referencing operations.
+ */
+ static final Logger LOGGER = Logger.getLogger(Modules.REFERENCING);
+
+ /**
+ * Do not allow instantiation of this class.
+ */
+ private CRS() {
+ }
+
+ /**
+ * Returns the Coordinate Reference System for the given authority code.
+ * There is <a href="https://sis.apache.org/tables/CoordinateReferenceSystems.html">many thousands
+ * of reference systems</a> defined by the EPSG authority or by other authorities.
+ * Whether those codes are recognized or not depends on whether the
+ * <a href="https://sis.apache.org/epsg.html">EPSG dataset is installed</a>.
+ * The following table lists a small subset of codes which are guaranteed to be available
+ * on any installation of Apache SIS:
+ *
+ * <blockquote><table class="sis">
+ * <caption>Minimal set of supported authority codes</caption>
+ * <tr><th>Code</th> <th>Enum</th> <th>CRS Type</th> <th>Description</th></tr>
+ * <tr><td>CRS:27</td> <td>{@link CommonCRS#NAD27 NAD27}</td> <td>Geographic</td> <td>Like EPSG:4267 except for (<var>longitude</var>, <var>latitude</var>) axis order</td></tr>
+ * <tr><td>CRS:83</td> <td>{@link CommonCRS#NAD83 NAD83}</td> <td>Geographic</td> <td>Like EPSG:4269 except for (<var>longitude</var>, <var>latitude</var>) axis order</td></tr>
+ * <tr><td>CRS:84</td> <td>{@link CommonCRS#WGS84 WGS84}</td> <td>Geographic</td> <td>Like EPSG:4326 except for (<var>longitude</var>, <var>latitude</var>) axis order</td></tr>
+ * <tr><td>CRS:88</td> <td>{@link CommonCRS.Vertical#NAVD88 NAVD88}</td><td>Vertical</td><td>North American Vertical Datum 1988 height</td></tr>
+ * <tr><td>EPSG:4230</td> <td>{@link CommonCRS#ED50 ED50}</td> <td>Geographic</td> <td>European Datum 1950</td></tr>
+ * <tr><td>EPSG:4258</td> <td>{@link CommonCRS#ETRS89 ETRS89}</td> <td>Geographic</td> <td>European Terrestrial Reference System 1989</td></tr>
+ * <tr><td>EPSG:4267</td> <td>{@link CommonCRS#NAD27 NAD27}</td> <td>Geographic</td> <td>North American Datum 1927</td></tr>
+ * <tr><td>EPSG:4269</td> <td>{@link CommonCRS#NAD83 NAD83}</td> <td>Geographic</td> <td>North American Datum 1983</td></tr>
+ * <tr><td>EPSG:4322</td> <td>{@link CommonCRS#WGS72 WGS72}</td> <td>Geographic</td> <td>World Geodetic System 1972</td></tr>
+ * <tr><td>EPSG:4326</td> <td>{@link CommonCRS#WGS84 WGS84}</td> <td>Geographic</td> <td>World Geodetic System 1984</td></tr>
+ * <tr><td>EPSG:4936</td> <td>{@link CommonCRS#ETRS89 ETRS89}</td> <td>Geocentric</td> <td>European Terrestrial Reference System 1989</td></tr>
+ * <tr><td>EPSG:4937</td> <td>{@link CommonCRS#ETRS89 ETRS89}</td> <td>Geographic 3D</td> <td>European Terrestrial Reference System 1989</td></tr>
+ * <tr><td>EPSG:4978</td> <td>{@link CommonCRS#WGS84 WGS84}</td> <td>Geocentric</td> <td>World Geodetic System 1984</td></tr>
+ * <tr><td>EPSG:4979</td> <td>{@link CommonCRS#WGS84 WGS84}</td> <td>Geographic 3D</td> <td>World Geodetic System 1984</td></tr>
+ * <tr><td>EPSG:4984</td> <td>{@link CommonCRS#WGS72 WGS72}</td> <td>Geocentric</td> <td>World Geodetic System 1972</td></tr>
+ * <tr><td>EPSG:4985</td> <td>{@link CommonCRS#WGS72 WGS72}</td> <td>Geographic 3D</td> <td>World Geodetic System 1972</td></tr>
+ * <tr><td>EPSG:5041</td> <td>{@link CommonCRS#WGS84 WGS84}</td> <td>Projected</td> <td>WGS 84 / UPS North (E,N)</td></tr>
+ * <tr><td>EPSG:5042</td> <td>{@link CommonCRS#WGS84 WGS84}</td> <td>Projected</td> <td>WGS 84 / UPS South (E,N)</td></tr>
+ * <tr><td>EPSG:322##</td> <td>{@link CommonCRS#WGS72 WGS72}</td> <td>Projected</td> <td>WGS 72 / UTM zone ##N</td></tr>
+ * <tr><td>EPSG:323##</td> <td>{@link CommonCRS#WGS72 WGS72}</td> <td>Projected</td> <td>WGS 72 / UTM zone ##S</td></tr>
+ * <tr><td>EPSG:326##</td> <td>{@link CommonCRS#WGS84 WGS84}</td> <td>Projected</td> <td>WGS 84 / UTM zone ##N</td></tr>
+ * <tr><td>EPSG:327##</td> <td>{@link CommonCRS#WGS84 WGS84}</td> <td>Projected</td> <td>WGS 84 / UTM zone ##S</td></tr>
+ * <tr><td>EPSG:5714</td> <td>{@link CommonCRS.Vertical#MEAN_SEA_LEVEL MEAN_SEA_LEVEL}</td> <td>Vertical</td> <td>Mean Sea Level height</td></tr>
+ * <tr><td>EPSG:5715</td> <td>{@link CommonCRS.Vertical#DEPTH DEPTH}</td> <td>Vertical</td> <td>Mean Sea Level depth</td></tr>
+ * <tr><td>OGC:JulianDate</td><td>{@link CommonCRS.Temporal#JULIAN JULIAN}</td> <td>Temporal</td> <td>Julian date (days)</td></tr>
+ * <tr><td>OGC:TruncatedJulianDate</td><td>{@link CommonCRS.Temporal#TRUNCATED_JULIAN TRUNCATED_JULIAN}</td> <td>Temporal</td> <td>Truncated Julian date (days)</td></tr>
+ * <tr><td>OGC:UnixTime</td> <td>{@link CommonCRS.Temporal#UNIX UNIX}</td> <td>Unix</td> <td>Unix time (seconds)</td></tr>
+ * </table></blockquote>
+ *
+ * For codes in above table, the EPSG geodetic database is used when available,
+ * otherwise Apache SIS fallbacks on definitions from public sources with no EPSG metadata except the identifiers.
+ * If the EPSG geodetic dataset has been used, the {@linkplain NamedIdentifier#getAuthority() authority} title
+ * will be something like <cite>"EPSG geodetic dataset"</cite>, otherwise it will be <cite>"Subset of EPSG"</cite>.
+ *
+ * <h4>URI forms</h4>
+ * This method accepts also the URN and URL syntaxes.
+ * For example, the following codes are considered equivalent to {@code "EPSG:4326"}:
+ * <ul>
+ * <li>{@code "EPSG::4326"}</li>
+ * <li>{@code "urn:ogc:def:crs:EPSG::4326"}</li>
+ * <li>{@code "http://www.opengis.net/def/crs/epsg/0/4326"}</li>
+ * <li>{@code "http://www.opengis.net/gml/srs/epsg.xml#4326"}</li>
+ * </ul>
+ *
+ * URIs can be combined for creating larger objects. For example, the following URIs combine a
+ * two-dimensional WGS84 reference system (EPSG:4326) with a Mean Sea Level height (EPSG:5714).
+ * The result is a three-dimensional {@linkplain org.apache.sis.referencing.crs.DefaultCompoundCRS
+ * compound coordinate reference system}:
+ *
+ * <ul>
+ * <li>{@code "urn:ogc:def:crs,crs:EPSG::4326,crs:EPSG::5714"}</li>
+ * <li><code>"http://www.opengis.net/def/crs-compound?<br>
+ * 1=http://www.opengis.net/def/crs/epsg/0/4326&<br>
+ * 2=http://www.opengis.net/def/crs/epsg/0/5714"</code></li>
+ * </ul>
+ *
+ * <p>URNs (but not URLs) can also combine a
+ * {@linkplain org.apache.sis.referencing.datum.DefaultGeodeticDatum geodetic datum} with an
+ * {@linkplain org.apache.sis.referencing.cs.DefaultEllipsoidalCS ellipsoidal coordinate system} for creating a new
+ * {@linkplain org.apache.sis.referencing.crs.DefaultGeographicCRS geographic CRS}, or a base geographic CRS with a
+ * {@linkplain org.apache.sis.referencing.operation.DefaultConversion conversion} and a
+ * {@linkplain org.apache.sis.referencing.cs.DefaultCartesianCS Cartesian coordinate system} for creating a new
+ * {@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS projected coordinate reference system}.</p>
+ *
+ * <h4>Reverse operation</h4>
+ * The {@link IdentifiedObjects#lookupURN(IdentifiedObject, Citation)} method can be seen
+ * as a converse of this method: from a CRS object, it tries to find a URN that describes it.
+ * More codes may also be supported depending on which extension modules are available.
+ *
+ * @param code the authority code.
+ * @return the Coordinate Reference System for the given authority code.
+ * @throws NoSuchAuthorityCodeException if there is no known CRS associated to the given code.
+ * @throws FactoryException if the CRS creation failed for another reason.
+ *
+ * @see #getAuthorityFactory(String)
+ * @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory
+ * @see <a href="https://epsg.org/">EPSG Geodetic Registry</a>
+ *
+ * @category factory
+ */
+ public static CoordinateReferenceSystem forCode(final String code)
+ throws NoSuchAuthorityCodeException, FactoryException
+ {
+ ArgumentChecks.ensureNonNull("code", code);
+ try {
+ return AuthorityFactories.ALL.createCoordinateReferenceSystem(code);
+ } catch (UnavailableFactoryException e) {
+ return AuthorityFactories.fallback(e).createCoordinateReferenceSystem(code);
+ }
+ }
+
+ /**
+ * Creates a Coordinate Reference System object from a <cite>Well Known Text</cite> (WKT).
+ * The default {@linkplain org.apache.sis.io.wkt Apache SIS parser} understands both
+ * version 1 (a.k.a. OGC 01-009) and version 2 (a.k.a. ISO 19162) of the WKT format.
+ *
+ * <h4>Example</h4>
+ * Below is a slightly simplified WKT 2 string for a Mercator projection.
+ * For making this example smaller, some optional {@code UNIT[…]} and {@code ORDER[…]} elements have been omitted.
+ *
+ * {@snippet lang="wkt" :
+ * ProjectedCRS["SIRGAS 2000 / Brazil Mercator",
+ * BaseGeodCRS["SIRGAS 2000",
+ * Datum["Sistema de Referencia Geocentrico para las Americas 2000",
+ * Ellipsoid["GRS 1980", 6378137, 298.257222101]]],
+ * Conversion["Petrobras Mercator",
+ * Method["Mercator (variant B)", Id["EPSG",9805]],
+ * Parameter["Latitude of 1st standard parallel", -2],
+ * Parameter["Longitude of natural origin", -43],
+ * Parameter["False easting", 5000000],
+ * Parameter["False northing", 10000000]],
+ * CS[cartesian,2],
+ * Axis["easting (E)", east],
+ * Axis["northing (N)", north],
+ * LengthUnit["metre", 1],
+ * Id["EPSG",5641]]
+ * }
+ *
+ * <h4>Logging</h4>
+ * If the parsing produced warnings, they will be reported in a logger named {@code "org.apache.sis.io.wkt"}.
+ * In particular, this method verifies if the description provided by the WKT matches the description provided
+ * by the authority ({@code "EPSG:5641"} in above example) and reports discrepancies.
+ * Note that this comparison between parsed CRS and authoritative CRS is specific to this convenience method;
+ * other APIs documented in <cite>see also</cite> section do not perform this comparison automatically.
+ * Should the WKT description and the authoritative description be in conflict, the WKT description prevails
+ * as mandated by ISO 19162 standard (see {@link #fromAuthority fromAuthority(…)} if a different behavior is needed).
+ *
+ * <h4>Usage and performance considerations</h4>
+ * This convenience method delegates to {@link GeodeticObjectFactory#createFromWKT(String)}
+ * using a default factory instance. This is okay for occasional use, but has the following limitations:
+ *
+ * <ul>
+ * <li>Performance may be sub-optimal in a multi-thread environment.</li>
+ * <li>No control on the WKT {@linkplain org.apache.sis.io.wkt.Convention conventions} in use.</li>
+ * <li>No control on the handling of {@linkplain org.apache.sis.io.wkt.Warnings warnings}.</li>
+ * </ul>
+ *
+ * Applications which need to parse a large amount of WKT strings should consider to use
+ * the {@link org.apache.sis.io.wkt.WKTFormat} class instead of this method.
+ *
+ * @param text coordinate system encoded in Well-Known Text format (version 1 or 2).
+ * @return the parsed Coordinate Reference System.
+ * @throws FactoryException if the given WKT cannot be parsed.
+ *
+ * @see org.apache.sis.io.wkt.WKTFormat
+ * @see GeodeticObjectFactory#createFromWKT(String)
+ * @see org.apache.sis.geometry.Envelopes#fromWKT(CharSequence)
+ * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">WKT 2 specification</a>
+ *
+ * @since 0.6
+ */
+ public static CoordinateReferenceSystem fromWKT(final String text) throws FactoryException {
+ ArgumentChecks.ensureNonNull("text", text);
+ final CoordinateReferenceSystem crs = GeodeticObjectFactory.provider().createFromWKT(text);
+ DefinitionVerifier.withAuthority(crs, Loggers.WKT, CRS.class, "fromWKT");
+ return crs;
+ }
+
+ /**
+ * Creates a coordinate reference system object from a XML string.
+ * Note that the given argument is the XML document itself, <strong>not</strong> a URL to a XML document.
+ * For reading XML documents from readers or input streams,
+ * see static methods in the {@link org.apache.sis.xml.XML} class.
+ *
+ * <p>If the unmarshalling produced warnings, they will be reported in a logger named {@code "org.apache.sis.xml"}.
+ * In particular, this method verifies if the description provided by the XML matches the description provided by
+ * the authority code given in {@code <gml:identifier>} element, and reports discrepancies.
+ * Note that this comparison between unmarshalled CRS and authoritative CRS is specific to this convenience method;
+ * other APIs documented in <cite>see also</cite> section do not perform this comparison automatically.
+ * Should the XML description and the authoritative description be in conflict, the XML description prevails
+ * (see {@link #fromAuthority fromAuthority(…)} if a different behavior is needed).</p>
+ *
+ * @param xml coordinate reference system encoded in XML format.
+ * @return the unmarshalled Coordinate Reference System.
+ * @throws FactoryException if the object creation failed.
+ *
+ * @see GeodeticObjectFactory#createFromXML(String)
+ * @see org.apache.sis.xml.XML#unmarshal(String)
+ *
+ * @since 0.7
+ */
+ public static CoordinateReferenceSystem fromXML(final String xml) throws FactoryException {
+ ArgumentChecks.ensureNonNull("text", xml);
+ final CoordinateReferenceSystem crs = GeodeticObjectFactory.provider().createFromXML(xml);
+ DefinitionVerifier.withAuthority(crs, Loggers.XML, CRS.class, "fromXML");
+ return crs;
+ }
+
+ /**
+ * Replaces the given coordinate reference system by an authoritative description, if one can be found.
+ * This method can be invoked after constructing a CRS in a context where the EPSG (or other authority)
+ * code is suspected more reliable than the rest of the description. A common case is a <cite>Well Known
+ * Text</cite> (WKT) string declaring wrong projection method or parameter values for the EPSG code that
+ * it pretends to describe. For example:
+ *
+ * <blockquote>
+ * {@code PROJCS["WGS 84 / Pseudo-Mercator",}<br>
+ * {@code }(…base CRS omitted for brevity…)<br>
+ * {@code PROJECTION["Mercator (variant A)"],} — <em><b>wrong:</b> shall be "Popular Visualisation Pseudo Mercator"</em><br>
+ * {@code }(…parameters and axes omitted for brevity…)<br>
+ * {@code AUTHORITY["EPSG", "3857"]]}
+ * </blockquote>
+ *
+ * In such cases, Apache SIS behavior in {@link #fromWKT(String)}, {@link #fromXML(String)} and other methods is
+ * conform to the <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">ISO 19162 specification</a>:
+ *
+ * <blockquote><cite>"Should any attributes or values given in the cited identifier be in conflict with attributes
+ * or values given explicitly in the WKT description, the WKT values shall prevail."</cite></blockquote>
+ *
+ * In situations where the opposite behavior is desired (i.e. to make the authority identifier prevails),
+ * this method can be invoked. This method performs the following actions:
+ *
+ * <ul>
+ * <li>If the given CRS has an {@linkplain AbstractIdentifiedObject#getIdentifiers() identifier} and if the authority factory can
+ * {@linkplain org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createCoordinateReferenceSystem(String) create a CRS}
+ * for that identifier, then:
+ * <ul>
+ * <li>If the CRS defined by the authority is {@linkplain Utilities#equalsIgnoreMetadata equal, ignoring metadata},
+ * to the given CRS, then this method returns silently the <em>authoritative</em> CRS.</li>
+ * <li>Otherwise if the CRS defined by the authority is equal, ignoring axis order and units, to the given CRS,
+ * then this method returns a <em>new</em> CRS derived from the authoritative one but with same
+ * {@linkplain org.apache.sis.referencing.cs.AxesConvention axes convention} than the given CRS.
+ * A warning is emitted.</li>
+ * <li>Otherwise this method discards the given CRS and returns the <em>authoritative</em> CRS.
+ * A warning is emitted with a message indicating where a difference has been found.</li>
+ * </ul>
+ * </li>
+ * <li>Otherwise if the given CRS does not have identifier, then this method
+ * {@linkplain org.apache.sis.referencing.factory.IdentifiedObjectFinder searches for an equivalent CRS}
+ * defined by the authority factory. If such CRS is found, then:
+ * <ul>
+ * <li>If the CRS defined by the authority is {@linkplain Utilities#equalsIgnoreMetadata equal, ignoring metadata},
+ * to the given CRS, then this method returns silently the <em>authoritative</em> CRS.</li>
+ * <li>Otherwise if the CRS defined by the authority is equal, ignoring axis order and units, to the given CRS,
+ * then this method returns silently a <em>new</em> CRS derived from the authoritative one but with same
+ * {@linkplain org.apache.sis.referencing.cs.AxesConvention axes convention} than the given CRS.</li>
+ * </ul>
+ * </li>
+ * <li>Otherwise this method silently returns the given CRS as-is.</li>
+ * </ul>
+ *
+ * <h4>Avoiding warning redundancies</h4>
+ * The warnings logged by this method are redundant with warnings logged by other methods in this class,
+ * in particular {@link #fromWKT(String)} and {@link #fromXML(String)} methods. For avoiding this annoyance,
+ * a {@code null} value for the {@code warningFilter} argument means to shut off those redundant loggings.
+ * A non-null {@code warningFilter} argument is more useful for CRS parsed by methods outside this class,
+ * for example {@link org.apache.sis.io.wkt.WKTFormat} or {@link org.apache.sis.xml.XML#unmarshal(String)}.
+ *
+ * @param crs the CRS to replace by an authoritative CRS, or {@code null}.
+ * @param factory the factory where to search for authoritative definitions, or {@code null} for the default.
+ * @param warningFilter whether to log warnings, or {@code null} for the default behavior (which is to filter out
+ * the warnings that are redundant with warnings emitted by other methods in this class).
+ * @return the suggested CRS to use (may be the {@code crs} argument itself), or {@code null} if the given CRS was null.
+ * @throws FactoryException if an error occurred while querying the authority factory.
+ *
+ * @since 1.0
+ */
+ public static CoordinateReferenceSystem fromAuthority(CoordinateReferenceSystem crs,
+ final CRSAuthorityFactory factory, final Filter warningFilter) throws FactoryException
+ {
+ if (crs != null) {
+ final DefinitionVerifier verification = DefinitionVerifier.withAuthority(crs, factory, true, null);
+ if (verification != null) {
+ crs = verification.recommendation;
+ if (warningFilter != null) {
+ final LogRecord record = verification.warning(false);
+ if (record != null) {
+ record.setLoggerName(Modules.REFERENCING);
+ record.setSourceClassName(CRS.class.getName());
+ record.setSourceMethodName("fromAuthority");
+ if (warningFilter.isLoggable(record)) {
+ LOGGER.log(record);
+ }
+ }
+ }
+ }
+ }
+ return crs;
+ }
+
+ /**
+ * Suggests a coordinate reference system which could be a common target for coordinate operations having the
+ * given sources. This method compares the {@linkplain #getGeographicBoundingBox(CoordinateReferenceSystem)
+ * domain of validity} of all given CRSs. If a CRS has a domain of validity that contains the domain of all other
+ * CRS, then that CRS is returned. Otherwise this method verifies if a {@linkplain GeneralDerivedCRS#getBaseCRS()
+ * base CRS} (usually a {@linkplain org.apache.sis.referencing.crs.DefaultGeographicCRS geographic CRS} instance)
+ * would be suitable. If no suitable CRS is found, then this method returns {@code null}.
+ *
+ * <h4>Use case</h4>
+ * Before to test if two arbitrary envelopes {@linkplain GeneralEnvelope#intersects(Envelope) intersect} each other,
+ * they need to be {@linkplain Envelopes#transform(Envelope, CoordinateReferenceSystem) transformed} in the same CRS.
+ * However if one CRS is a Transverse Mercator projection while the other CRS is a world-wide geographic CRS, then
+ * attempts to use the Transverse Mercator projection as the common CRS is likely to fail since the geographic envelope
+ * may span an area far outside the projection domain of validity. This {@code suggestCommonTarget(…)} method can used
+ * for choosing a common CRS which is less likely to fail.
+ *
+ * @param regionOfInterest the geographic area for which the coordinate operations will be applied,
+ * or {@code null} if unknown. Will be intersected with CRS domains of validity.
+ * @param sourceCRS the coordinate reference systems for which a common target CRS is desired.
+ * May contain {@code null} elements, which are ignored.
+ * @return a CRS that may be used as a common target for all the given source CRS in the given region of interest,
+ * or {@code null} if this method did not find a common target CRS. The returned CRS may be different than
+ * all given CRS.
+ *
+ * @since 0.8
+ */
+ @OptionalCandidate
+ public static CoordinateReferenceSystem suggestCommonTarget(GeographicBoundingBox regionOfInterest,
+ CoordinateReferenceSystem... sourceCRS)
+ {
+ CoordinateReferenceSystem bestCRS = null;
+ /*
+ * Compute the union of the domain of validity of all CRS. If a CRS does not specify a domain of validity,
+ * then assume that the CRS is valid for the whole world if the CRS is geodetic (otherwise ignore that CRS).
+ * Opportunistically remember the domain of validity of each CRS in this loop since we will need them later.
+ */
+ boolean worldwide = false;
+ DefaultGeographicBoundingBox domain = null;
+ final GeographicBoundingBox[] domains = new GeographicBoundingBox[sourceCRS.length];
+ for (int i=0; i < sourceCRS.length; i++) {
+ final CoordinateReferenceSystem crs = sourceCRS[i];
+ final GeographicBoundingBox bbox = getGeographicBoundingBox(crs);
+ if (bbox != null) {
+ domains[i] = bbox;
+ if (!worldwide) {
+ if (domain == null) {
+ domain = new DefaultGeographicBoundingBox(bbox);
+ } else {
+ domain.add(bbox);
+ }
+ }
+ } else if (crs instanceof GeodeticCRS) {
+ /*
+ * Geodetic CRS (geographic or geocentric) can generally be presumed valid in a worldwide area.
+ * The 'worldwide' flag is a little optimization for remembering that we do not need to compute
+ * the union anymore, but we still need to continue the loop for fetching all bounding boxes.
+ */
+ bestCRS = crs; // Fallback to be used if we don't find anything better.
+ worldwide = true;
+ }
+ }
+ /*
+ * At this point we got the union of the domain of validity of all CRS. We are interested only in the
+ * part that intersect the region of interest. If the union is whole world, we do not need to compute
+ * the intersection; we can just leave the region of interest unchanged.
+ */
+ if (domain != null && !worldwide) {
+ if (regionOfInterest != null) {
+ domain.intersect(regionOfInterest);
+ }
+ regionOfInterest = domain;
+ domain = null;
+ }
+ /*
+ * Iterate again over the domain of validity of all CRS. For each domain of validity, compute the area
+ * which is inside the domain or interest and the area which is outside. The "best CRS" will be the one
+ * which comply with the following rules, in preference order:
+ *
+ * 1) The CRS which is valid over the largest area of the region of interest.
+ * 2) If two CRS are equally good according rule 1, then the CRS with the smallest "outside area".
+ *
+ * Example: given two source CRS, a geographic one and a projected one:
+ *
+ * - If the projected CRS contains fully the region of interest, then it will be returned.
+ * The preference is given to the projected CRS because geometric operations are likely
+ * to be more accurate in that space. Furthermore, forward conversions from geographic to
+ * projected CRS are usually faster than inverse conversions.
+ *
+ * - Otherwise (i.e. if the region of interest is likely to be wider than the projected CRS
+ * domain of validity), then the geographic CRS will be returned.
+ */
+ final double roiArea = Extents.area(regionOfInterest); // NaN if `regionOfInterest` is null.
+ double maxInsideArea = 0;
+ double minOutsideArea = Double.POSITIVE_INFINITY;
+ boolean tryDerivedCRS = false;
+ do {
+ for (int i=0; i < domains.length; i++) {
+ final GeographicBoundingBox bbox = domains[i];
+ if (bbox != null) {
+ double insideArea = Extents.area(bbox);
+ double outsideArea = 0;
+ if (regionOfInterest != null) {
+ if (domain == null) {
+ domain = new DefaultGeographicBoundingBox(bbox);
+ } else {
+ domain.setBounds(bbox);
+ }
+ domain.intersect(regionOfInterest);
+ final double area = insideArea;
+ insideArea = Extents.area(domain);
+ outsideArea = area - insideArea;
+ }
+ if (insideArea > maxInsideArea || (insideArea == maxInsideArea && outsideArea < minOutsideArea)) {
+ maxInsideArea = insideArea;
+ minOutsideArea = outsideArea;
+ bestCRS = sourceCRS[i];
+ }
+ }
+ }
+ /*
+ * If the best CRS does not cover fully the region of interest, then we will redo the check again
+ * but using base CRS instead. For example if the list of source CRS had some projected CRS, we
+ * will try with the geographic CRS on which those projected CRS are based.
+ */
+ if (Double.isNaN(roiArea) || maxInsideArea < roiArea) {
+ if (tryDerivedCRS) break; // Do not try twice.
- final SingleCRS[] derivedCRS = new SingleCRS[sourceCRS.length];
++ final CoordinateReferenceSystem[] derivedCRS = new CoordinateReferenceSystem[sourceCRS.length];
+ for (int i=0; i < derivedCRS.length; i++) {
+ GeographicBoundingBox bbox = null;
+ final CoordinateReferenceSystem crs = sourceCRS[i];
+ if (crs instanceof GeneralDerivedCRS) {
- final SingleCRS baseCRS = ((GeneralDerivedCRS) crs).getBaseCRS();
++ final CoordinateReferenceSystem baseCRS = ((GeneralDerivedCRS) crs).getBaseCRS();
+ bbox = getGeographicBoundingBox(baseCRS);
+ if (bbox == null && bestCRS == null && baseCRS instanceof GeodeticCRS) {
+ bestCRS = baseCRS; // Fallback to be used if we don't find anything better.
+ }
+ tryDerivedCRS = true;
+ derivedCRS[i] = baseCRS;
+ }
+ domains[i] = bbox;
+ }
+ sourceCRS = derivedCRS;
+ } else {
+ break;
+ }
+ } while (tryDerivedCRS);
+ return bestCRS;
+ }
+
+ /**
+ * Finds a mathematical operation that transforms or converts coordinates from the given source to the
+ * given target coordinate reference system. If an estimation of the geographic area containing the points
+ * to transform is known, it can be specified for helping this method to find a better suited operation.
+ * If no area of interest is specified, then the current default is the widest
+ * {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of validity}.
+ * A future Apache SIS version may also take the country of current locale in account.
+ *
+ * <div class="note"><b>Note:</b>
+ * the area of interest is just one aspect that may affect the coordinate operation.
+ * Other aspects are the time of interest (because some coordinate operations take in account the
+ * plate tectonics movement) or the desired accuracy. For more control on the coordinate operation
+ * to create, see {@link CoordinateOperationContext}.</div>
+ *
+ * After the caller received a {@code CoordinateOperation} instance, the following methods can be invoked
+ * for checking if the operation suits the caller's needs:
+ *
+ * <ul>
+ * <li>{@link #getGeographicBoundingBox(CoordinateOperation)}
+ * for checking if the operation is valid in the caller's area of interest.</li>
+ * <li>{@link #getLinearAccuracy(CoordinateOperation)}
+ * for checking if the operation has sufficient accuracy for caller's purpose.</li>
+ * </ul>
+ *
+ * If the source and target CRS are equivalent, then this method returns an operation backed by an
+ * {@linkplain org.opengis.referencing.operation.MathTransform#isIdentity() identity} transform.
+ * If there is no known operation between the given pair of CRS, then this method throws an
+ * {@link OperationNotFoundException}.
+ *
+ * <p>Note that <code>CRS.findOperation(<var>B</var>, <var>A</var>, <var>aoi</var>)</code> is not necessarily
+ * the exact converse of <code>CRS.findOperation(<var>A</var>, <var>B</var>, <var>aoi</var>)</code>.
+ * Some deviations may exist for example because of different paths explored in the geodetic database.
+ * For the inverse of an existing {@link CoordinateOperation}, using
+ * {@link org.opengis.referencing.operation.MathTransform#inverse()} is preferable.</p>
+ *
+ * @param sourceCRS the CRS of source coordinates.
+ * @param targetCRS the CRS of target coordinates.
+ * @param areaOfInterest the area of interest, or {@code null} if none.
+ * @return the mathematical operation from {@code sourceCRS} to {@code targetCRS}.
+ * @throws OperationNotFoundException if no operation was found between the given pair of CRS.
+ * @throws FactoryException if the operation cannot be created for another reason.
+ *
+ * @see Envelopes#findOperation(Envelope, Envelope)
+ * @see DefaultCoordinateOperationFactory#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, CoordinateOperationContext)
+ *
+ * @since 0.7
+ */
+ public static CoordinateOperation findOperation(final CoordinateReferenceSystem sourceCRS,
+ final CoordinateReferenceSystem targetCRS,
+ final GeographicBoundingBox areaOfInterest)
+ throws FactoryException
+ {
+ ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
+ ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
+ final CoordinateOperationContext context = CoordinateOperationContext.fromBoundingBox(areaOfInterest);
+ /*
+ * In principle following code should just delegate to factory.createOperation(…). However, that operation
+ * may fail if a connection to the EPSG database has been found, but the EPSG tables do not yet exist in
+ * that database and we do not have the SQL scripts for creating them.
+ */
+ final DefaultCoordinateOperationFactory factory = DefaultCoordinateOperationFactory.provider();
+ try {
+ return factory.createOperation(sourceCRS, targetCRS, context);
+ } catch (UnavailableFactoryException e) {
+ if (AuthorityFactories.failure(e)) {
+ throw e;
+ } else try {
+ // Above method call replaced the EPSG factory by a fallback. Try again.
+ return factory.createOperation(sourceCRS, targetCRS, context);
+ } catch (FactoryException ex) {
+ ex.addSuppressed(e);
+ throw ex;
+ }
+ }
+ }
+
+ /**
+ * Finds mathematical operations that transform or convert coordinates from the given source to the
+ * given target coordinate reference system. If at least one operation exists, they are returned in
+ * preference order: the operation having the widest intersection between its
+ * {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of validity}
+ * and the given area of interest are returned first.
+ *
+ * @param sourceCRS the CRS of source coordinates.
+ * @param targetCRS the CRS of target coordinates.
+ * @param areaOfInterest the area of interest, or {@code null} if none.
+ * @return mathematical operations from {@code sourceCRS} to {@code targetCRS}.
+ * @throws OperationNotFoundException if no operation was found between the given pair of CRS.
+ * @throws FactoryException if the operation cannot be created for another reason.
+ *
+ * @see DefaultCoordinateOperationFactory#createOperations(CoordinateReferenceSystem, CoordinateReferenceSystem, CoordinateOperationContext)
+ *
+ * @since 1.0
+ */
+ public static List<CoordinateOperation> findOperations(final CoordinateReferenceSystem sourceCRS,
+ final CoordinateReferenceSystem targetCRS,
+ final GeographicBoundingBox areaOfInterest)
+ throws FactoryException
+ {
+ ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
+ ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
+ final CoordinateOperationContext context = CoordinateOperationContext.fromBoundingBox(areaOfInterest);
+ final DefaultCoordinateOperationFactory factory = DefaultCoordinateOperationFactory.provider();
+ try {
+ return factory.createOperations(sourceCRS, targetCRS, context);
+ } catch (UnavailableFactoryException e) {
+ if (AuthorityFactories.failure(e)) {
+ throw e;
+ } else try {
+ return List.of(factory.createOperation(sourceCRS, targetCRS, context));
+ } catch (FactoryException ex) {
+ ex.addSuppressed(e);
+ throw ex;
+ }
+ }
+ }
+
+ /**
+ * Returns a positional accuracy estimation in metres for the given operation, or {@code NaN} if unknown.
+ * This method applies the following heuristics:
+ *
+ * <ul>
+ * <li>If the given operation is an instance of {@link AbstractCoordinateOperation}, then delegate to the
+ * operation {@link AbstractCoordinateOperation#getLinearAccuracy() getLinearAccuracy()} method.</li>
+ *
+ * <li>Otherwise if at least one {@linkplain org.apache.sis.metadata.iso.quality.DefaultQuantitativeResult
+ * quantitative result} is found with a linear unit, then return the largest value converted to metres.</li>
+ *
+ * <li>Otherwise if the operation is a {@linkplain org.apache.sis.referencing.operation.DefaultConversion
+ * conversion}, then returns 0 since a conversion is by definition accurate up to rounding errors.</li>
+ *
+ * <li>Otherwise if the operation is a {@linkplain org.apache.sis.referencing.operation.DefaultTransformation
+ * transformation}, then the returned value depends on whether the datum shift were applied with the help
+ * of Bursa-Wolf parameters of not.</li>
+ * </ul>
+ *
+ * See {@link AbstractCoordinateOperation#getLinearAccuracy()} for more details on the above heuristic rules.
+ *
+ * @param operation the coordinate operation for which to get the accuracy estimation, or {@code null}.
+ * @return the accuracy estimation (always in meters), or NaN if unknown.
+ *
+ * @see #findOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, GeographicBoundingBox)
+ *
+ * @since 0.7
+ */
+ @OptionalCandidate
+ public static double getLinearAccuracy(final CoordinateOperation operation) {
+ if (operation == null) {
+ return Double.NaN;
+ } else if (operation instanceof AbstractCoordinateOperation) {
+ return ((AbstractCoordinateOperation) operation).getLinearAccuracy();
+ } else {
+ return PositionalAccuracyConstant.getLinearAccuracy(operation);
+ }
+ }
+
+ /**
+ * Returns the valid geographic area for the given coordinate operation, or {@code null} if unknown.
+ * This method explores the {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of validity}
+ * associated with the given operation. If more than one geographic bounding box is found, then this method
+ * computes their {@linkplain DefaultGeographicBoundingBox#add(GeographicBoundingBox) union}.
+ *
+ * <p><b>Fallback:</b> if the given operation does not declare explicitly a domain of validity, then this
+ * method computes the intersection of the domain of validity declared by source and target CRS. If no CRS
+ * declare a domain of validity, then this method returns {@code null}.</p>
+ *
+ * @param operation the coordinate operation for which to get the domain of validity, or {@code null}.
+ * @return the geographic area where the operation is valid, or {@code null} if unspecified.
+ *
+ * @see #findOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, GeographicBoundingBox)
+ * @see Extents#getGeographicBoundingBox(Extent)
+ *
+ * @category information
+ *
+ * @since 0.7
+ */
+ @OptionalCandidate
+ public static GeographicBoundingBox getGeographicBoundingBox(final CoordinateOperation operation) {
+ if (operation == null) {
+ return null;
+ }
+ GeographicBoundingBox bbox = Extents.getGeographicBoundingBox(operation.getDomainOfValidity());
+ if (bbox == null) {
+ bbox = Extents.intersection(getGeographicBoundingBox(operation.getSourceCRS()),
+ getGeographicBoundingBox(operation.getTargetCRS()));
+ }
+ return bbox;
+ }
+
+ /**
+ * Returns the valid geographic area for the given coordinate reference system, or {@code null} if unknown.
+ * This method explores the {@linkplain org.apache.sis.referencing.crs.AbstractCRS#getDomainOfValidity() domain of
+ * validity} associated with the given CRS. If more than one geographic bounding box is found, then this method
+ * computes their {@linkplain DefaultGeographicBoundingBox#add(GeographicBoundingBox) union}.
+ * together.
+ *
+ * @param crs the coordinate reference system for which to get the domain of validity, or {@code null}.
+ * @return the geographic area where the coordinate reference system is valid, or {@code null} if unspecified.
+ *
+ * @see #getDomainOfValidity(CoordinateReferenceSystem)
+ * @see Extents#getGeographicBoundingBox(Extent)
+ *
+ * @category information
+ */
+ @OptionalCandidate
+ public static GeographicBoundingBox getGeographicBoundingBox(final CoordinateReferenceSystem crs) {
+ return (crs != null) ? Extents.getGeographicBoundingBox(crs.getDomainOfValidity()) : null;
+ }
+
+ /**
+ * Returns the domain of validity of the specified coordinate reference system, or {@code null} if unknown.
+ * If non-null, then the returned envelope will use the same coordinate reference system than the given CRS
+ * argument.
+ *
+ * <p>This method looks in two places:</p>
+ * <ol>
+ * <li>First, it checks the {@linkplain org.apache.sis.referencing.crs.AbstractCRS#getDomainOfValidity()
+ * domain of validity} associated with the given CRS. Only geographic extents that are instances of
+ * {@link BoundingPolygon} associated to the given CRS are taken in account for this first step.</li>
+ * <li>If the above step did not found found any bounding polygon, then the
+ * {@linkplain #getGeographicBoundingBox(CoordinateReferenceSystem) geographic bounding boxes}
+ * are used as a fallback and transformed to the given CRS.</li>
+ * </ol>
+ *
+ * @param crs the coordinate reference system, or {@code null}.
+ * @return the envelope with coordinates in the given CRS, or {@code null} if none.
+ *
+ * @see #getGeographicBoundingBox(CoordinateReferenceSystem)
+ *
+ * @category information
+ * @since 0.8
+ */
+ @OptionalCandidate
+ public static Envelope getDomainOfValidity(final CoordinateReferenceSystem crs) {
+ Envelope envelope = null;
+ GeneralEnvelope merged = null;
+ if (crs != null) {
+ final Extent domainOfValidity = crs.getDomainOfValidity();
+ if (domainOfValidity != null) {
+ for (final GeographicExtent extent : domainOfValidity.getGeographicElements()) {
+ if (extent instanceof BoundingPolygon && !Boolean.FALSE.equals(extent.getInclusion())) {
+ for (final Geometry geometry : ((BoundingPolygon) extent).getPolygons()) {
+ final Envelope candidate = geometry.getEnvelope();
+ if (candidate != null) {
+ final CoordinateReferenceSystem sourceCRS = candidate.getCoordinateReferenceSystem();
+ if (sourceCRS == null || Utilities.equalsIgnoreMetadata(sourceCRS, crs)) {
+ if (envelope == null) {
+ envelope = candidate;
+ } else {
+ if (merged == null) {
+ envelope = merged = new GeneralEnvelope(envelope);
+ }
+ merged.add(envelope);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ /*
+ * If no envelope was found, uses the geographic bounding box as a fallback. We will
+ * need to transform it from WGS84 to the supplied CRS. This step was not required in
+ * the previous block because the latter selected only envelopes in the right CRS.
+ */
+ if (envelope == null) {
+ final GeographicBoundingBox bounds = getGeographicBoundingBox(crs);
+ if (bounds != null && !Boolean.FALSE.equals(bounds.getInclusion())) {
+ /*
+ * We do not assign WGS84 unconditionally to the geographic bounding box, because
+ * it is not defined to be on a particular datum; it is only approximated bounds.
+ * We try to get the GeographicCRS from the user supplied CRS in order to reduce
+ * the amount of transformation needed.
+ */
+ final SingleCRS targetCRS = getHorizontalComponent(crs);
+ final GeographicCRS sourceCRS = ReferencingUtilities.toNormalizedGeographicCRS(targetCRS, false, false);
+ if (sourceCRS != null) {
+ envelope = merged = new GeneralEnvelope(bounds);
+ merged.translate(-getGreenwichLongitude(sourceCRS), 0);
+ merged.setCoordinateReferenceSystem(sourceCRS);
+ try {
+ envelope = Envelopes.transform(envelope, targetCRS);
+ } catch (TransformException exception) {
+ /*
+ * The envelope is probably outside the range of validity for this CRS.
+ * It should not occurs, since the envelope is supposed to describe the
+ * CRS area of validity. Logs a warning and returns null, since it is a
+ * legal return value according this method contract.
+ */
+ unexpectedException("getEnvelope", exception);
+ envelope = null;
+ }
+ }
+ }
+ }
+ return envelope;
+ }
+
+ /**
+ * Creates a compound coordinate reference system from an ordered list of CRS components.
+ * A CRS is inferred from the given components and the domain of validity is set to the
+ * {@linkplain org.apache.sis.metadata.iso.extent.DefaultExtent#intersect intersection}
+ * of the domain of validity of all components.
+ *
+ * <h4>Ellipsoidal height</h4>
+ * If a two-dimensional geographic or projected CRS if followed or preceded by a vertical CRS with ellipsoidal
+ * {@linkplain org.apache.sis.referencing.datum.DefaultVerticalDatum#getVerticalDatumType() datum type}, then
+ * this method combines them in a single three-dimensional geographic or projected CRS. Note that standalone
+ * ellipsoidal heights are not allowed according ISO 19111. But if such situation is nevertheless found, then
+ * the action described here fixes the issue. This is the reverse of <code>{@linkplain #getVerticalComponent
+ * getVerticalComponent}(crs, true)</code>.
+ *
+ * <h4>Components order</h4>
+ * Apache SIS is permissive on the order of components that can be used in a compound CRS.
+ * However for better inter-operability, users are encouraged to follow the order mandated by ISO 19162:
+ *
+ * <ol>
+ * <li>A mandatory horizontal CRS (only one of two-dimensional {@code GeographicCRS} or {@code ProjectedCRS} or {@code EngineeringCRS}).</li>
+ * <li>Optionally followed by a {@code VerticalCRS} or a {@code ParametricCRS} (but not both).</li>
+ * <li>Optionally followed by a {@code TemporalCRS}.</li>
+ * </ol>
+ *
+ * @param components the sequence of coordinate reference systems making the compound CRS.
+ * @return the compound CRS, or {@code components[0]} if the given array contains only one component.
+ * @throws IllegalArgumentException if the given array is empty or if the array contains incompatible components.
+ * @throws FactoryException if the geodetic factory failed to create the compound CRS.
+ *
+ * @since 0.8
+ *
+ * @see org.apache.sis.referencing.crs.DefaultCompoundCRS
+ * @see GeodeticObjectFactory#createCompoundCRS(Map, CoordinateReferenceSystem...)
+ * @see org.apache.sis.geometry.Envelopes#compound(Envelope...)
+ * @see org.apache.sis.referencing.operation.transform.MathTransforms#compound(MathTransform...)
+ */
+ public static CoordinateReferenceSystem compound(final CoordinateReferenceSystem... components) throws FactoryException {
+ ArgumentChecks.ensureNonEmpty("components", components);
+ if (components.length == 1) {
+ final CoordinateReferenceSystem crs = components[0];
+ if (crs != null) return crs;
+ }
+ return new EllipsoidalHeightCombiner().createCompoundCRS(components);
+ }
+
+ /**
+ * Gets or creates a coordinate reference system with a subset of the dimensions of the given CRS.
+ * This method can be used for dimensionality reduction, but not for changing axis order.
+ * The specified dimensions are used as if they were in strictly increasing order without duplicated values.
+ *
+ * <h4>Ellipsoidal height</h4>
+ * This method can transform a three-dimensional geographic CRS into a two-dimensional geographic CRS.
+ * In this aspect, this method is the converse of {@link #compound(CoordinateReferenceSystem...)}.
+ * This method can also extract the {@linkplain CommonCRS.Vertical#ELLIPSOIDAL ellipsoidal height}
+ * from a three-dimensional geographic CRS, but this is generally not recommended since ellipsoidal
+ * heights make little sense without their (<var>latitude</var>, <var>longitude</var>) locations.
+ *
+ * @param crs the CRS to reduce the dimensionality, or {@code null} if none.
+ * @param dimensions the dimensions to retain. The dimensions will be taken in increasing order, ignoring duplicated values.
+ * @return a coordinate reference system for the given dimensions. May be the given {@code crs}, which may be {@code null}.
+ * @throws IllegalArgumentException if the given array is empty or if the array contains invalid indices.
+ * @throws FactoryException if this method needed to create a new CRS and that operation failed.
+ *
+ * @see #getComponentAt(CoordinateReferenceSystem, int, int)
+ * @see #compound(CoordinateReferenceSystem...)
+ *
+ * @since 1.3
+ */
+ public static CoordinateReferenceSystem selectDimensions(final CoordinateReferenceSystem crs,
+ final int... dimensions) throws FactoryException
+ {
+ final var components = selectComponents(crs, dimensions);
+ if (components.isEmpty()) {
+ return null;
+ }
+ return compound(components.toArray(CoordinateReferenceSystem[]::new));
+ }
+
+ /**
+ * Gets or creates CRS components for a subset of the dimensions of the given CRS.
+ * The method performs the same work as {@link #selectDimensions(CoordinateReferenceSystem, int...)}
+ * except that it does not build new {@link CompoundCRS} instances when the specified dimensions span
+ * more than one {@linkplain DefaultCompoundCRS#getComponents() component}.
+ * Instead, the components are returned directly.
+ *
+ * <p>While this method does not create new {@code CompoundCRS} instances, it still may create other
+ * kinds of CRS for handling ellipsoidal height as documented in the {@code selectDimensions(…)} method.</p>
+ *
+ * @param crs the CRS from which to get a subset of the components, or {@code null} if none.
+ * @param dimensions the dimensions to retain. The dimensions will be taken in increasing order, ignoring duplicated values.
+ * @return components in the specified dimensions, or an empty list if the specified {@code crs} is {@code null}.
+ * @throws IllegalArgumentException if the given array is empty or if the array contains invalid indices.
+ * @throws FactoryException if this method needed to create a new CRS and that operation failed.
+ *
+ * @see #selectDimensions(CoordinateReferenceSystem, int...)
+ *
+ * @since 1.4
+ */
+ public static List<CoordinateReferenceSystem> selectComponents(final CoordinateReferenceSystem crs,
+ final int... dimensions) throws FactoryException
+ {
+ ArgumentChecks.ensureNonNull("dimensions", dimensions);
+ if (crs == null) {
+ return List.of();
+ }
+ final int dimension = ReferencingUtilities.getDimension(crs);
+ long selected = 0;
+ for (final int d : dimensions) {
+ if (d < 0 || d >= dimension) {
+ throw new IndexOutOfBoundsException(Errors.format(Errors.Keys.IndexOutOfBounds_1, d));
+ }
+ if (d >= Long.SIZE) {
+ throw new ArithmeticException(Errors.format(Errors.Keys.ExcessiveNumberOfDimensions_1, d+1));
+ }
+ selected |= (1L << d);
+ }
+ if (selected == 0) {
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyArgument_1, "dimensions"));
+ }
+ final List<CoordinateReferenceSystem> components = new ArrayList<>(Long.bitCount(selected));
+ reduce(0, crs, dimension, selected, components);
+ return components;
+ }
+
+ /**
+ * Adds the components of reduced CRS into the given list.
+ * This method may invoke itself recursively for walking through compound CRS.
+ *
+ * @param previous number of dimensions of previous CRS.
+ * @param crs the CRS for which to select components.
+ * @param dimension number of dimensions of {@code crs}.
+ * @param selected bitmask of dimensions to select.
+ * @param addTo where to add CRS components.
+ * @return new bitmask after removal of dimensions of the components added to {@code addTo}.
+ */
+ private static long reduce(int previous, final CoordinateReferenceSystem crs, int dimension, long selected,
+ final List<CoordinateReferenceSystem> addTo) throws FactoryException
+ {
+ final long current = (Numerics.bitmask(dimension) - 1) << previous;
+ final long intersect = selected & current;
+ if (intersect != 0) {
+ if (intersect == current) {
+ addTo.add(crs);
+ selected &= ~current;
+ } else if (crs instanceof CompoundCRS) {
+ for (final CoordinateReferenceSystem component : ((CompoundCRS) crs).getComponents()) {
+ dimension = ReferencingUtilities.getDimension(component);
+ selected = reduce(previous, component, dimension, selected, addTo);
+ if ((selected & current) == 0) break; // Stop if it would be useless to continue.
+ previous += dimension;
+ }
+ } else if (dimension == 3 && crs instanceof SingleCRS) {
+ final Datum datum = ((SingleCRS) crs).getDatum();
+ if (datum instanceof GeodeticDatum) {
+ final boolean isVertical = Long.bitCount(intersect) == 1; // Presumed for now, verified later.
+ final int verticalDimension = Long.numberOfTrailingZeros((isVertical ? intersect : ~intersect) >>> previous);
+ final CoordinateSystemAxis verticalAxis = crs.getCoordinateSystem().getAxis(verticalDimension);
+ if (AxisDirections.isVertical(verticalAxis.getDirection())) try {
+ addTo.add(new EllipsoidalHeightSeparator((GeodeticDatum) datum, isVertical).separate((SingleCRS) crs));
+ selected &= ~current;
+ } catch (IllegalArgumentException | ClassCastException e) {
+ throw new FactoryException(Resources.format(Resources.Keys.CanNotSeparateCRS_1, crs.getName()));
+ }
+ }
+ }
+ }
+ if ((selected & current) != 0) {
+ throw new FactoryException(Resources.format(Resources.Keys.CanNotSeparateCRS_1, crs.getName()));
+ }
+ return selected;
+ }
+
+ /**
+ * Returns {@code true} if the given CRS is horizontal. The current implementation considers a
+ * CRS as horizontal if it is two-dimensional and comply with one of the following conditions:
+ *
+ * <ul>
+ * <li>is an instance of {@link GeographicCRS} (or an equivalent {@link GeodeticCRS}), or</li>
+ * <li>is an instance of {@link ProjectedCRS}, or</li>
+ * <li>is an instance of {@link EngineeringCRS} (following
+ * <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#111">ISO 19162 §16.1</a>
+ * definition of {@literal <horizontal crs>}).</li>
+ * </ul>
+ *
+ * In case of doubt, this method conservatively returns {@code false}.
+ *
+ * @todo Future SIS implementation may extend the above conditions list. For example, a radar station could
+ * use a polar coordinate system in a <code>DerivedCRS</code> instance based on a projected CRS.
+ * Conversely, a future SIS versions may impose more conditions on <code>EngineeringCRS</code>.
+ * See <a href="http://issues.apache.org/jira/browse/SIS-161">SIS-161</a>.
+ *
+ * @param crs the coordinate reference system, or {@code null}.
+ * @return {@code true} if the given CRS is non-null and likely horizontal, or {@code false} otherwise.
+ *
+ * @see #getHorizontalComponent(CoordinateReferenceSystem)
+ *
+ * @category information
+ */
+ public static boolean isHorizontalCRS(final CoordinateReferenceSystem crs) {
+ return horizontalCode(crs) == 2;
+ }
+
+ /**
+ * If the given CRS would qualify as horizontal except for its number of dimensions, returns that number.
+ * Otherwise returns 0. The number of dimensions can only be 2 or 3.
+ */
+ private static int horizontalCode(final CoordinateReferenceSystem crs) {
+ /*
+ * In order to determine if the CRS is geographic, checking the CoordinateSystem type is more reliable
+ * then checking if the CRS implements the GeographicCRS interface. This is because the GeographicCRS
+ * type did not existed in ISO 19111:2007, so a CRS could be standard-compliant without implementing
+ * the GeographicCRS interface.
+ */
+ boolean isEngineering = false;
+ final boolean isGeodetic = (crs instanceof GeodeticCRS);
+ if (isGeodetic || crs instanceof ProjectedCRS || (isEngineering = (crs instanceof EngineeringCRS))) {
+ final CoordinateSystem cs = crs.getCoordinateSystem();
+ final int dim = cs.getDimension();
+ if ((dim & ~1) == 2 && (!isGeodetic || (cs instanceof EllipsoidalCS))) {
+ if (isEngineering) {
+ int n = 0;
+ for (int i=0; i<dim; i++) {
+ if (AxisDirections.isCompass(cs.getAxis(i).getDirection())) n++;
+ }
+ // If we don't have exactly 2 east, north, etc. directions, consider as non-horizontal.
+ if (n != 2) return 0;
+ }
+ return dim;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Returns the first horizontal coordinate reference system found in the given CRS, or {@code null} if there is
+ * none. If the given CRS is already horizontal according {@link #isHorizontalCRS(CoordinateReferenceSystem)},
+ * then this method returns it as-is. Otherwise if the given CRS is compound, then this method searches for the
+ * first horizontal component in the order of the {@linkplain #getSingleComponents(CoordinateReferenceSystem)
+ * single components list}.
+ *
+ * <p>In the special case where a three-dimensional geographic or projected CRS is found, this method
+ * will create a two-dimensional geographic or projected CRS without the vertical axis.</p>
+ *
+ * @param crs the coordinate reference system, or {@code null}.
+ * @return the first horizontal CRS, or {@code null} if none.
+ *
+ * @category information
+ *
+ * @see org.apache.sis.geometry.GeneralEnvelope#horizontal()
+ */
+ @OptionalCandidate
+ public static SingleCRS getHorizontalComponent(final CoordinateReferenceSystem crs) {
+ switch (horizontalCode(crs)) {
+ /*
+ * If the CRS is already two-dimensional and horizontal, return as-is.
+ * We don't need to check if crs is an instance of SingleCRS since all
+ * CRS accepted by horizontalCode(…) are SingleCRS.
+ */
+ case 2: {
+ return (SingleCRS) crs;
+ }
+ case 3: {
+ /*
+ * The CRS would be horizontal if we can remove the vertical axis. CoordinateSystems.replaceAxes(…)
+ * will do this task for us. We can verify if the operation has been successful by checking that
+ * the number of dimensions has been reduced by 1 (from 3 to 2).
+ */
+ final CoordinateSystem cs = CoordinateSystems.replaceAxes(crs.getCoordinateSystem(), new AxisFilter() {
+ @Override public boolean accept(final CoordinateSystemAxis axis) {
+ return !AxisDirections.isVertical(axis.getDirection());
+ }
+ });
+ if (cs.getDimension() != 2) break;
+ /*
+ * Most of the time, the CRS to rebuild will be geodetic. In such case we known that the
+ * coordinate system is ellipsoidal because (i.e. the CRS is geographic) because it was
+ * a condition verified by horizontalCode(…). A ClassCastException would be a bug.
+ */
+ final Map<String, ?> properties = ReferencingUtilities.getPropertiesForModifiedCRS(crs);
+ if (crs instanceof GeodeticCRS) {
+ return new DefaultGeographicCRS(properties, ((GeodeticCRS) crs).getDatum(), (EllipsoidalCS) cs);
+ }
+ /*
+ * In Apache SIS implementation, the Conversion contains the source and target CRS together with
+ * a MathTransform. We need to recreate the same conversion, but without CRS and MathTransform
+ * for letting SIS create or associate new ones, which will be two-dimensional now.
+ */
+ if (crs instanceof ProjectedCRS) {
+ final ProjectedCRS proj = (ProjectedCRS) crs;
+ final GeographicCRS base = (GeographicCRS) getHorizontalComponent(proj.getBaseCRS());
+ Conversion fromBase = proj.getConversionFromBase();
+ fromBase = new DefaultConversion(IdentifiedObjects.getProperties(fromBase),
+ fromBase.getMethod(), null, fromBase.getParameterValues());
+ return new DefaultProjectedCRS(properties, base, fromBase, (CartesianCS) cs);
+ }
+ /*
+ * If the CRS is neither geographic or projected, then it is engineering.
+ */
+ return new DefaultEngineeringCRS(properties, ((EngineeringCRS) crs).getDatum(), cs);
+ }
+ }
+ if (crs instanceof CompoundCRS) {
+ final CompoundCRS cp = (CompoundCRS) crs;
+ for (final CoordinateReferenceSystem c : cp.getComponents()) {
+ final SingleCRS candidate = getHorizontalComponent(c);
+ if (candidate != null) {
+ return candidate;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the first vertical coordinate reference system found in the given CRS, or {@code null} if there is none.
+ * If the given CRS is already an instance of {@code VerticalCRS}, then this method returns it as-is.
+ * Otherwise if the given CRS is compound, then this method searches for the first vertical component
+ * in the order of the {@linkplain #getSingleComponents(CoordinateReferenceSystem) single components list}.
+ *
+ * <h4>Height in a three-dimensional geographic CRS</h4>
+ * In ISO 19111 model, ellipsoidal heights are indissociable from geographic CRS because such heights
+ * without their (<var>latitude</var>, <var>longitude</var>) locations make little sense. Consequently
+ * a standard-conformant library should return {@code null} when asked for the {@code VerticalCRS}
+ * component of a geographic CRS. This is what {@code getVerticalComponent(…)} does when the
+ * {@code allowCreateEllipsoidal} argument is {@code false}.
+ *
+ * <p>However, in some exceptional cases, handling ellipsoidal heights like any other kind of heights
+ * may simplify the task. For example, when computing <em>difference</em> between heights above the
+ * same datum, the impact of ignoring locations may be smaller (but not necessarily canceled).
+ * Orphan {@code VerticalCRS} may also be useful for information purpose like labeling a plot axis.
+ * If the caller feels confident that ellipsoidal heights are safe for his task, he can set the
+ * {@code allowCreateEllipsoidal} argument to {@code true}. In such case, this {@code getVerticalComponent(…)}
+ * method will create a temporary {@code VerticalCRS} from the first three-dimensional {@code GeographicCRS}
+ * <em>in last resort</em>, only if it cannot find an existing {@code VerticalCRS} instance.
+ * <strong>Note that this is not a valid CRS according ISO 19111</strong> — use with care.</p>
+ *
+ * @param crs the coordinate reference system, or {@code null}.
+ * @param allowCreateEllipsoidal {@code true} for allowing the creation of orphan CRS for ellipsoidal heights.
+ * The recommended value is {@code false}.
+ * @return the first vertical CRS, or {@code null} if none.
+ *
+ * @see #compound(CoordinateReferenceSystem...)
+ *
+ * @category information
+ */
+ @OptionalCandidate
+ public static VerticalCRS getVerticalComponent(final CoordinateReferenceSystem crs, final boolean allowCreateEllipsoidal) {
+ if (crs instanceof VerticalCRS) {
+ return (VerticalCRS) crs;
+ }
+ if (crs instanceof CompoundCRS) {
+ final CompoundCRS cp = (CompoundCRS) crs;
+ boolean a = false;
+ do { // Executed at most twice.
+ for (final CoordinateReferenceSystem c : cp.getComponents()) {
+ final VerticalCRS candidate = getVerticalComponent(c, a);
+ if (candidate != null) {
+ return candidate;
+ }
+ }
+ } while ((a = !a) == allowCreateEllipsoidal);
+ }
+ if (allowCreateEllipsoidal && horizontalCode(crs) == 3) {
+ final CoordinateSystem cs = crs.getCoordinateSystem();
+ final int i = AxisDirections.indexOfColinear(cs, AxisDirection.UP);
+ if (i >= 0) {
+ final CoordinateSystemAxis axis = cs.getAxis(i);
+ VerticalCRS c = CommonCRS.Vertical.ELLIPSOIDAL.crs();
+ if (!c.getCoordinateSystem().getAxis(0).equals(axis)) {
+ final Map<String,?> properties = IdentifiedObjects.getProperties(c);
+ c = new DefaultVerticalCRS(properties, c.getDatum(), new DefaultVerticalCS(properties, axis));
+ }
+ return c;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the first temporal coordinate reference system found in the given CRS, or {@code null} if there is none.
+ * If the given CRS is already an instance of {@code TemporalCRS}, then this method returns it as-is.
+ * Otherwise if the given CRS is compound, then this method searches for the first temporal component
+ * in the order of the {@linkplain #getSingleComponents(CoordinateReferenceSystem) single components list}.
+ *
+ * @param crs the coordinate reference system, or {@code null}.
+ * @return the first temporal CRS, or {@code null} if none.
+ *
+ * @category information
+ */
+ @OptionalCandidate
+ public static TemporalCRS getTemporalComponent(final CoordinateReferenceSystem crs) {
+ if (crs instanceof TemporalCRS) {
+ return (TemporalCRS) crs;
+ }
+ if (crs instanceof CompoundCRS) {
+ final CompoundCRS cp = (CompoundCRS) crs;
+ for (final CoordinateReferenceSystem c : cp.getComponents()) {
+ final TemporalCRS candidate = getTemporalComponent(c);
+ if (candidate != null) {
+ return candidate;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the ordered list of single coordinate reference systems for the specified CRS.
+ * This method performs the following choices:
+ *
+ * <ul>
+ * <li>If the given CRS is null, returns an empty list.</li>
+ * <li>If the given CRS is an instance of {@link SingleCRS}, returns that instance in a singleton list.</li>
+ * <li>If the given CRS is an instance of {@link CompoundCRS}, returns a flattened list of its
+ * {@linkplain DefaultCompoundCRS#getComponents() components}. Some components may themselves be
+ * other {@code CompoundCRS} instances, in which case those compound CRS are also flattened in their
+ * list of {@code SingleCRS} components.</li>
+ * <li>Otherwise throws a {@code ClassCastException}.</li>
+ * </ul>
+ *
+ * <h4>Example</h4>
+ * Apache SIS allows 4-dimensional (<var>x</var>,<var>y</var>,<var>z</var>,<var>t</var>)
+ * coordinate reference system to be built in two different ways as shown below:
+ *
+ * <div class="horizontal-flow">
+ * <div><p><b>Hierarchical structure</b></p>
+ * <blockquote>
+ * <code>CompoundCRS</code> — (<var>x</var>, <var>y</var>, <var>z</var>, <var>t</var>)<br>
+ * <code> ├─CompoundCRS</code> — (<var>x</var>, <var>y</var>, <var>z</var>)<br>
+ * <code> │ ├─ProjectedCRS</code> — (<var>x</var>, <var>y</var>)<br>
+ * <code> │ └─VerticalCRS</code> — (<var>z</var>)<br>
+ * <code> └─TemporalCRS</code> — (<var>t</var>)
+ * </blockquote></div>
+ * <div><p><b>Flat list</b></p>
+ * <blockquote>
+ * <code>CompoundCRS</code> — (<var>x</var>, <var>y</var>, <var>z</var>, <var>t</var>)<br>
+ * <code> ├─ProjectedCRS</code> — (<var>x</var>, <var>y</var>)<br>
+ * <code> ├─VerticalCRS</code> — (<var>z</var>)<br>
+ * <code> └─TemporalCRS</code> — (<var>t</var>)
+ * </blockquote>
+ * </div></div>
+ *
+ * This method guaranteed that the returned list is a flat one as shown on the right side.
+ * Note that such flat lists are the only one allowed by ISO/OGC standards for compound CRS.
+ * The hierarchical structure is an Apache SIS flexibility.
+ *
+ * @param crs the coordinate reference system, or {@code null}.
+ * @return the single coordinate reference systems, or an empty list if the given CRS is {@code null}.
+ * @throws ClassCastException if a CRS is neither a {@link SingleCRS} or a {@link CompoundCRS}.
+ *
+ * @see DefaultCompoundCRS#getSingleComponents()
+ */
+ public static List<SingleCRS> getSingleComponents(final CoordinateReferenceSystem crs) {
+ final List<SingleCRS> singles;
+ if (crs == null) {
+ singles = List.of();
+ } else if (crs instanceof CompoundCRS) {
+ if (crs instanceof DefaultCompoundCRS) {
+ singles = ((DefaultCompoundCRS) crs).getSingleComponents();
+ } else {
+ final List<CoordinateReferenceSystem> elements = ((CompoundCRS) crs).getComponents();
+ singles = new ArrayList<>(elements.size());
+ ReferencingUtilities.getSingleComponents(elements, singles);
+ }
+ } else {
+ // Intentional CassCastException here if the crs is not a SingleCRS.
+ singles = List.of((SingleCRS) crs);
+ }
+ return singles;
+ }
+
+ /**
+ * Returns the coordinate reference system in the given range of dimension indices.
+ * This method processes as below:
+ *
+ * <ul>
+ * <li>If the given {@code crs} is {@code null}, then this method returns {@code null}.</li>
+ * <li>Otherwise if {@code lower} is 0 and {@code upper} is the number of CRS dimensions,
+ * then this method returns the given CRS unchanged.</li>
+ * <li>Otherwise if the given CRS is an instance of {@link CompoundCRS}, then this method
+ * searches for a {@linkplain CompoundCRS#getComponents() component} where:
+ * <ul>
+ * <li>The {@linkplain org.apache.sis.referencing.cs.AbstractCS#getDimension() number of dimensions}
+ * is equal to {@code upper - lower};</li>
+ * <li>The sum of the number of dimensions of all previous CRS is equal to {@code lower}.</li>
+ * </ul>
+ * If such component is found, then it is returned.</li>
+ * <li>Otherwise (i.e. no component match), this method returns {@code null}.</li>
+ * </ul>
+ *
+ * This method does <strong>not</strong> build new CRS from the components. For example, this method does not
+ * create a {@link CompoundCRS} or a three-dimensional CRS if the given range spans more than one component.
+ *
+ * @param crs the coordinate reference system to decompose, or {@code null}.
+ * @param lower the first dimension to keep, inclusive.
+ * @param upper the last dimension to keep, exclusive.
+ * @return the sub-coordinate system, or {@code null} if the given {@code crs} was {@code null}
+ * or cannot be decomposed for dimensions in the [{@code lower} … {@code upper}] range.
+ * @throws IndexOutOfBoundsException if the given index are out of bounds.
+ *
+ * @see #selectDimensions(CoordinateReferenceSystem, int...)
+ * @see org.apache.sis.geometry.GeneralEnvelope#subEnvelope(int, int)
+ *
+ * @since 0.5
+ */
+ @OptionalCandidate
+ public static CoordinateReferenceSystem getComponentAt(CoordinateReferenceSystem crs, int lower, int upper) {
+ if (crs == null) return null; // Skip bounds check.
+ int dimension = ReferencingUtilities.getDimension(crs);
+ ArgumentChecks.ensureValidIndexRange(dimension, lower, upper);
+ check: while (lower != 0 || upper != dimension) {
+ if (crs instanceof CompoundCRS) {
+ // We need nested CompoundCRS (if any) below, not a flattened list of SingleCRS.
+ final List<CoordinateReferenceSystem> components = ((CompoundCRS) crs).getComponents();
+ final int size = components.size();
+ for (int i=0; i<size; i++) {
+ crs = components.get(i);
+ dimension = crs.getCoordinateSystem().getDimension();
+ if (lower < dimension) {
+ /*
+ * The requested dimensions may intersect the dimension of this CRS.
+ * The outer loop will perform the verification, and eventually go
+ * down again in the tree of sub-components.
+ */
+ continue check;
+ }
+ lower -= dimension;
+ upper -= dimension;
+ }
+ }
+ return null;
+ }
+ return crs;
+ }
+
+ /**
+ * Returns the Greenwich longitude of the prime meridian of the given CRS in degrees.
+ * If the prime meridian uses another unit than degrees, then the value will be converted.
+ *
+ * @param crs the coordinate reference system from which to get the prime meridian.
+ * @return the Greenwich longitude (in degrees) of the prime meridian of the given CRS.
+ *
+ * @see org.apache.sis.referencing.datum.DefaultPrimeMeridian#getGreenwichLongitude(Unit)
+ *
+ * @since 0.5
+ */
+ public static double getGreenwichLongitude(final GeodeticCRS crs) {
+ ArgumentChecks.ensureNonNull("crs", crs);
+ return ReferencingUtilities.getGreenwichLongitude(crs.getDatum().getPrimeMeridian(), Units.DEGREE);
+ }
+
+ /**
+ * Returns the system-wide authority factory used by {@link #forCode(String)} and other SIS methods.
+ * If the given authority is non-null, then this method returns a factory specifically for that authority.
+ * Otherwise, this method returns the {@link org.apache.sis.referencing.factory.MultiAuthoritiesFactory}
+ * instance that manages all other factories.
+ *
+ * <p>The {@code authority} argument can be {@code "EPSG"}, {@code "OGC"} or any other authority found
+ * on the module path. In the {@code "EPSG"} case, whether the full set of EPSG codes is supported or not
+ * depends on whether a {@linkplain org.apache.sis.referencing.factory.sql connection to the database}
+ * can be established. If no connection can be established, then this method returns a small embedded
+ * EPSG factory containing at least the CRS defined in the {@link #forCode(String)} method javadoc.</p>
+ *
+ * <p>User-defined authorities can be added to the SIS environment by creating a {@code CRSAuthorityFactory}
+ * implementation with a public no-argument constructor or a public static {@code provider()} method,
+ * and declaring the name of that class in the {@code module-info.java} file as a provider of the
+ * {@code org.opengis.referencing.crs.CRSAuthorityFactory} service.</p>
+ *
+ * @param authority the authority of the desired factory (typically {@code "EPSG"} or {@code "OGC"}),
+ * or {@code null} for the {@link org.apache.sis.referencing.factory.MultiAuthoritiesFactory}
+ * instance that manage all factories.
+ * @return the system-wide authority factory used by SIS for the given authority.
+ * @throws FactoryException if no factory can be returned for the given authority.
+ *
+ * @see #forCode(String)
+ * @see org.apache.sis.referencing.factory.MultiAuthoritiesFactory
+ *
+ * @since 0.7
+ */
+ public static CRSAuthorityFactory getAuthorityFactory(final String authority) throws FactoryException {
+ if (authority == null) {
+ return AuthorityFactories.ALL;
+ }
+ return AuthorityFactories.ALL.getAuthorityFactory(CRSAuthorityFactory.class, authority, null);
+ }
+
+ /**
+ * Invoked when an unexpected exception occurred. Those exceptions must be non-fatal, i.e. the caller
+ * <strong>must</strong> have a reasonable fallback (otherwise it should propagate the exception).
+ */
+ private static void unexpectedException(final String methodName, final Exception exception) {
+ Logging.unexpectedException(LOGGER, CRS.class, methodName, exception);
+ }
+ }
diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/NamedIdentifier.java
index 0000000000,f19273483b..cf1d9cb42a
mode 000000,100644..100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/NamedIdentifier.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/NamedIdentifier.java
@@@ -1,0 -1,571 +1,572 @@@
+ /*
+ * 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.referencing;
+
+ import java.util.Map;
+ import java.util.List;
+ import java.util.Locale;
+ import java.util.Objects;
+ import java.io.IOException;
+ import java.io.ObjectInputStream;
+ import java.io.ObjectOutputStream;
+ import org.opengis.util.NameSpace;
+ import org.opengis.util.LocalName;
+ import org.opengis.util.ScopedName;
+ import org.opengis.util.GenericName;
+ import org.opengis.util.NameFactory;
+ import org.opengis.util.InternationalString;
+ import org.apache.sis.util.resources.Errors;
+ import org.opengis.metadata.citation.Citation;
+ import org.opengis.metadata.Identifier;
++import org.opengis.referencing.ReferenceIdentifier;
+ import org.opengis.parameter.InvalidParameterValueException;
+ import org.apache.sis.internal.metadata.NameToIdentifier;
+ import org.apache.sis.metadata.iso.citation.Citations;
+ import org.apache.sis.util.iso.DefaultNameFactory;
+ import org.apache.sis.util.ArgumentChecks;
+
+
+ /**
+ * An identification of a CRS object which is both a {@link Identifier} and a {@link GenericName}.
+ * This class implements both interfaces in order to allow usage of the same instance either as an object
+ * {@linkplain AbstractIdentifiedObject#getName() name} or {@linkplain AbstractIdentifiedObject#getAlias() alias}.
+ * This flexibility make easier to uses object's names in two different models:
+ *
+ * <ul>
+ * <li>In the ISO 19111 model, objects have a single name of type {@code RS_Identifier} and an arbitrary amount
+ * of aliases of type {@code GenericName}.</li>
+ * <li>In the GML model, objects have an arbitrary number of names of type {@code gml:CodeType},
+ * but do not have any alias.</li>
+ * </ul>
+ *
+ * By using this {@code NamedIdentifier} class, users can declare supplemental object's names as
+ * {@linkplain AbstractIdentifiedObject#getAlias() aliases} and have those names used in contexts
+ * where {@code Identifier} instances are required, like GML marshalling time.
+ *
+ * <h2>Name ↔ Identifier mapping</h2>
+ * The {@code GenericName} attributes will be inferred from {@code Identifier} attributes as below:
+ *
+ * <ul>
+ * <li><b>{@linkplain #tip() Tip}:</b> derived from the identifier {@linkplain #getCode() code}.</li>
+ * <li><b>{@linkplain #head() Head}:</b> derived from the identifier {@linkplain #getCodeSpace() code space} if non-null.
+ * If there is no code space, then the scope is derived from the shortest {@linkplain #getAuthority() authority}'s
+ * {@linkplain Citation#getAlternateTitles() alternate titles}, or the {@linkplain Citation#getTitle() main title}
+ * if there are no alternate titles. This policy exploits the ISO 19115 comment saying that citation alternate titles
+ * often contain abbreviation (for example "DCW" as an alternative title for <cite>"Digital Chart of the World"</cite>).</li>
+ * </ul>
+ *
+ * <h3>Example</h3>
+ * If the identifier attributes are {@code authority} = {@code new DefaultCitation("IOGP")},
+ * {@code codeSpace} = {@code "EPSG"} and {@code code} = {@code "4326"}, then the name attributes will be
+ * {@code head} = {@code "EPSG"}, {@code tip} = {@code "4326"} and {@link #toString()} = {@code "EPSG:4326"}.
+ * Note that the scope does not appear in the string representation of names.
+ *
+ *
+ * <h2>Immutability and thread safety</h2>
+ * This class is immutable and thus inherently thread-safe if the {@link Citation} and {@link InternationalString}
+ * arguments given to the constructor are also immutable. It is caller's responsibility to ensure that those
+ * conditions hold, for example by invoking {@link org.apache.sis.metadata.iso.citation.DefaultCitation#transitionTo
+ * DefaultCitation.transitionTo(DefaultCitation.State.FINAL)} before passing the arguments to the constructor.
+ * Subclasses shall make sure that any overridden methods remain safe to call from multiple threads and do not change
+ * any public {@code NamedIdentifier} state.
+ *
+ * @author Martin Desruisseaux (IRD, Geomatys)
+ * @version 1.4
+ *
+ * @see org.apache.sis.metadata.iso.DefaultIdentifier
+ * @see org.apache.sis.util.iso.AbstractName
+ * @see AbstractIdentifiedObject#getName()
+ *
+ * @since 0.4
+ */
-public class NamedIdentifier extends ImmutableIdentifier implements GenericName {
++public class NamedIdentifier extends ImmutableIdentifier implements GenericName, ReferenceIdentifier {
+ /**
+ * Serial number for inter-operability with different versions.
+ */
+ private static final long serialVersionUID = -3982456534858346939L;
+
+ /**
+ * The name of this identifier as a generic name.
+ * If {@code null}, will be constructed only when first needed.
+ */
+ private transient GenericName name;
+
+ /**
+ * {@code true} if {@link #name} has been given explicitly by the user.
+ * Consider this field as final - it is not only for constructors convenience.
+ */
+ private transient boolean isNameSupplied;
+
+ /**
+ * Creates a new identifier from the specified one. This is a copy constructor which get the code,
+ * codespace, authority, version and the description (if available) from the given identifier.
+ *
+ * <p>If the given identifier implements the {@link GenericName} interface, then calls to
+ * {@link #tip()}, {@link #head()}, {@link #scope()} and similar methods will delegate
+ * to that name.</p>
+ *
+ * @param identifier the identifier to copy.
+ *
+ * @see #castOrCopy(Identifier)
+ */
+ public NamedIdentifier(final Identifier identifier) {
+ super(identifier);
+ if (identifier instanceof GenericName) {
+ name = (GenericName) identifier;
+ isNameSupplied = true;
+ }
+ }
+
+ /**
+ * Creates a new identifier from the specified name. This constructor infers the identifier attributes
+ * (code, codespace and authority) from the given name. Calls to name-related methods like {@link #tip()},
+ * {@link #head()} and {@link #scope()} will delegate to the given name.
+ *
+ * @param name the name to wrap.
+ *
+ * @see #castOrCopy(GenericName)
+ */
+ public NamedIdentifier(final GenericName name) {
+ super(name instanceof Identifier ? (Identifier) name : new NameToIdentifier(name));
+ this.name = name;
+ isNameSupplied = true;
+ }
+
+ /**
+ * Constructs an identifier from the given properties. The content of the properties map is used as
+ * described in the {@linkplain ImmutableIdentifier#ImmutableIdentifier(Map) super-class constructor},
+ * with the addition of an optional {@code "name"} property.
+ *
+ * <table class="sis">
+ * <caption>Recognized properties</caption>
+ * <tr>
+ * <th>Property name</th>
+ * <th>Value type</th>
+ * <th>Returned by</th>
+ * </tr>
+ * <tr>
+ * <td>{@code "name"}</td>
+ * <td>{@link GenericName}</td>
+ * <td>(none)</td>
+ * </tr>
+ * <tr>
+ * <th colspan="3" class="hsep">Defined in parent class (reminder)</th>
+ * </tr>
+ * <tr>
+ * <td>{@value org.opengis.metadata.Identifier#CODE_KEY}</td>
+ * <td>{@link String}</td>
+ * <td>{@link #getCode()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@value org.opengis.metadata.Identifier#CODESPACE_KEY}</td>
+ * <td>{@link String}</td>
+ * <td>{@link #getCodeSpace()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@value org.opengis.metadata.Identifier#AUTHORITY_KEY}</td>
+ * <td>{@link String} or {@link Citation}</td>
+ * <td>{@link #getAuthority()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@value org.opengis.metadata.Identifier#VERSION_KEY}</td>
+ * <td>{@link String}</td>
+ * <td>{@link #getVersion()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@value org.opengis.metadata.Identifier#DESCRIPTION_KEY}</td>
+ * <td>{@link String} or {@link InternationalString}</td>
+ * <td>{@link #getDescription()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@value org.apache.sis.referencing.AbstractIdentifiedObject#LOCALE_KEY}</td>
+ * <td>{@link Locale}</td>
+ * <td>(none)</td>
+ * </tr>
+ * </table>
+ *
+ * The {@value org.opengis.metadata.Identifier#CODE_KEY} property is mandatory and all other properties
+ * are optional. If a {@code "name"} property is provided, then calls to name-related methods like
+ * {@link #tip()}, {@link #head()} and {@link #scope()} will delegate to the given name.
+ *
+ * @param properties the properties to be given to this identifier.
+ * @throws InvalidParameterValueException if a property has an invalid value.
+ * @throws IllegalArgumentException if a property is invalid for some other reason.
+ */
+ public NamedIdentifier(final Map<String,?> properties) throws IllegalArgumentException {
+ super(properties);
+ name = (GenericName) properties.get("name");
+ isNameSupplied = (name != null);
+ }
+
+ /**
+ * Constructs an identifier from an authority and code.
+ * This is a convenience constructor for commonly-used parameters.
+ *
+ * <p>If the given code is an {@link InternationalString}, then the {@code code.toString(Locale.ROOT)}
+ * return value will be used for the {@link #getCode() code} property, and the complete international
+ * string will be used for the {@link #getName() name} property.</p>
+ *
+ * @param authority
+ * organization or party responsible for definition and maintenance of the code space or code,
+ * or {@code null} if not available.
+ * @param code
+ * identifier code or name, optionally from a controlled list or pattern defined by the authority.
+ * The code cannot be null.
+ */
+ public NamedIdentifier(final Citation authority, final CharSequence code) {
+ super(authority, Citations.toCodeSpace(authority), toString(code));
+ if (code instanceof InternationalString) {
+ name = createName(authority, super.getCodeSpace(), code);
+ isNameSupplied = true; // Because 'code' is an international string.
+ }
+ }
+
+ /**
+ * Constructs an identifier from an authority and localizable code,
+ * with an optional version number and description.
+ *
+ * <p>If the given code is an {@link InternationalString}, then the {@code code.toString(Locale.ROOT)}
+ * return value will be used for the {@link #getCode() code} property, and the complete international
+ * string will be used for the {@link #getName() name} property.</p>
+ *
+ * @param authority
+ * organization or party responsible for definition and maintenance of the code space or code,
+ * or {@code null} if not available.
+ * @param codeSpace
+ * name or identifier of the person or organization responsible for namespace, or {@code null}
+ * if not available. This is often an abbreviation of the authority name.
+ * @param code
+ * identifier code or name, optionally from a controlled list or pattern defined by a code space.
+ * The code cannot be null.
+ * @param version
+ * the version of the associated code space or code as specified by the code authority,
+ * or {@code null} if none.
+ * @param description
+ * natural language description of the meaning of the code value, or {@code null} if none.
+ */
+ public NamedIdentifier(final Citation authority, final String codeSpace, final CharSequence code,
+ final String version, final InternationalString description)
+ {
+ super(authority, codeSpace, toString(code), version, description);
+ if (code instanceof InternationalString) {
+ name = createName(authority, codeSpace, code);
+ isNameSupplied = true; // Because 'code' is an international string.
+ }
+ }
+
+ /**
+ * Returns the unlocalized string representation of the given code.
+ */
+ private static String toString(final CharSequence code) {
+ ArgumentChecks.ensureNonNull("code", code);
+ final String c;
+ if (code instanceof InternationalString) {
+ c = ((InternationalString) code).toString(Locale.ROOT);
+ } else {
+ c = code.toString();
+ }
+ if (c != null) {
+ return c;
+ }
+ /*
+ * May happen if the user gave us an instance of 'org.apache.sis.internal.jaxb.gcx.Anchor' class
+ * (maybe he got the instance indirectly) and the construction of that instance is not completed.
+ */
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentClass_2, "code", code.getClass()));
+ }
+
+ /**
+ * Returns the generic name of this identifier.
+ * The name will be constructed automatically the first time it will be needed.
+ * The name's head is inferred from the shortest alternative title (if any).
+ * This heuristic rule is compatible to the ISO 19115 remark saying that the
+ * {@linkplain Citation#getAlternateTitles() alternate titles} often contains abbreviation
+ * (for example "DCW" as an alternative title for "Digital Chart of the World").
+ * If no alternative title is found or if the main title is yet shorter, then it is used.
+ *
+ * @category Generic name
+ */
+ private synchronized GenericName getName() {
+ if (name == null) {
+ name = createName(super.getAuthority(), super.getCodeSpace(), super.getCode());
+ }
+ return name;
+ }
+
+ /**
+ * Constructs a generic name from the specified authority and code.
+ *
+ * @param authority the authority, or {@code null} if none.
+ * @param codeSpace the code space, or {@code null} if none.
+ * @param code the code.
+ * @return a new generic name for the given authority and code.
+ * @category Generic name
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/SIS-197">SIS-197</a>
+ */
+ private static GenericName createName(final Citation authority, String codeSpace, final CharSequence code) {
+ if (codeSpace == null) {
+ codeSpace = Citations.toCodeSpace(authority); // Whitespaces trimed by Citations.
+ }
+ final NameFactory factory = DefaultNameFactory.provider();
+ if (codeSpace != null) {
+ return factory.createGenericName(null, codeSpace, code);
+ } else {
+ return factory.createLocalName(null, code);
+ }
+ }
+
+ /**
+ * Returns a SIS identifier implementation with the values of the given arbitrary implementation.
+ * This method performs the first applicable action in the following choices:
+ *
+ * <ul>
+ * <li>If the given object is {@code null}, then this method returns {@code null}.</li>
+ * <li>Otherwise if the given object is already an instance of
+ * {@code NamedIdentifier}, then it is returned unchanged.</li>
+ * <li>Otherwise a new {@code NamedIdentifier} instance is created using the
+ * {@linkplain #NamedIdentifier(Identifier) copy constructor} and returned.
+ * Note that this is a <em>shallow</em> copy operation, because the other
+ * metadata contained in the given object are not recursively copied.</li>
+ * </ul>
+ *
+ * @param object the object to get as a SIS implementation, or {@code null} if none.
+ * @return a SIS implementation containing the values of the given object (may be the
+ * given object itself), or {@code null} if the argument was null.
+ *
+ * @since 1.0
+ */
+ public static NamedIdentifier castOrCopy(final Identifier object) {
+ if (object == null || object instanceof NamedIdentifier) {
+ return (NamedIdentifier) object;
+ }
+ return new NamedIdentifier(object);
+ }
+
+ /**
+ * Returns a SIS name implementation with the values of the given arbitrary implementation.
+ * This method performs the first applicable action in the following choices:
+ *
+ * <ul>
+ * <li>If the given object is {@code null}, then this method returns {@code null}.</li>
+ * <li>Otherwise if the given object is already an instance of
+ * {@code NamedIdentifier}, then it is returned unchanged.</li>
+ * <li>Otherwise a new {@code NamedIdentifier} instance is created using the
+ * {@linkplain #NamedIdentifier(GenericName) copy constructor} and returned.
+ * Note that this is a <em>shallow</em> copy operation, because the other
+ * metadata contained in the given object are not recursively copied.</li>
+ * </ul>
+ *
+ * @param object the object to get as a SIS implementation, or {@code null} if none.
+ * @return a SIS implementation containing the values of the given object (may be the
+ * given object itself), or {@code null} if the argument was null.
+ *
+ * @since 1.0
+ */
+ public static NamedIdentifier castOrCopy(final GenericName object) {
+ if (object == null || object instanceof NamedIdentifier) {
+ return (NamedIdentifier) object;
+ }
+ return new NamedIdentifier(object);
+ }
+
+ /**
+ * The last element in the sequence of {@linkplain #getParsedNames() parsed names}.
+ * By default, this is the same value than the {@linkplain #getCode() code} provided as a local name.
+ *
+ * @return the last element in the list of {@linkplain #getParsedNames() parsed names}.
+ *
+ * @see #getCode()
+ */
+ @Override
+ public LocalName tip() {
+ return getName().tip();
+ }
+
+ /**
+ * Returns the first element in the sequence of {@linkplain #getParsedNames() parsed names}.
+ * By default, this is the same value than the {@linkplain #getCodeSpace() code space} provided as a local name.
+ *
+ * @return the first element in the list of {@linkplain #getParsedNames() parsed names}.
+ *
+ * @see #scope()
+ * @see #getCodeSpace()
+ */
+ @Override
+ public LocalName head() {
+ return getName().head();
+ }
+
+ /**
+ * Returns the scope (name space) in which this name is local.
+ * By default, this is the same value than the {@link #getAuthority() authority} provided as a name space.
+ *
+ * @see #head()
+ * @see #getAuthority()
+ *
+ * @return the scope of this name.
+ */
+ @Override
+ public NameSpace scope() {
+ return getName().scope();
+ }
+
+ /**
+ * Returns the depth of this name within the namespace hierarchy.
+ *
+ * @return the depth of this name.
+ */
+ @Override
+ public int depth() {
+ return getName().depth();
+ }
+
+ /**
+ * Returns the sequence of {@linkplain LocalName local names} making this generic name.
+ * The length of this sequence is the {@linkplain #depth() depth}.
+ * It does not include the {@linkplain #scope() scope}.
+ *
+ * @return the local names making this generic name, without the {@linkplain #scope() scope}.
+ * Shall never be {@code null} neither empty.
+ */
+ @Override
+ public List<? extends LocalName> getParsedNames() {
+ return getName().getParsedNames();
+ }
+
+ /**
+ * Returns this name expanded with the specified scope. One may represent this operation
+ * as a concatenation of the specified {@code name} with {@code this}.
+ *
+ * @param scope The name to use as prefix.
+ * @return a concatenation of the given scope with this name.
+ */
+ @Override
+ public ScopedName push(final GenericName scope) {
+ return getName().push(scope);
+ }
+
+ /**
+ * Returns a view of this name as a fully-qualified name.
+ *
+ * @return the fully-qualified name (never {@code null}).
+ */
+ @Override
+ public GenericName toFullyQualifiedName() {
+ return getName().toFullyQualifiedName();
+ }
+
+ /**
+ * Returns a local-dependent string representation of this generic name.
+ * This string is similar to the one returned by {@link #toString()} except that each element has
+ * been localized in the {@linkplain InternationalString#toString(Locale) specified locale}.
+ * If no international string is available, then this method returns an implementation mapping
+ * to {@code toString()} for all locales.
+ *
+ * @return a localizable string representation of this name.
+ */
+ @Override
+ public InternationalString toInternationalString() {
+ return getName().toInternationalString();
+ }
+
+ /**
+ * Returns a string representation of this generic name. This string representation
+ * is local-independent. It contains all elements listed by {@link #getParsedNames()}
+ * separated by a namespace-dependent character (usually {@code :} or {@code /}).
+ *
+ * @return a local-independent string representation of this generic name.
+ *
+ * @see IdentifiedObjects#toString(Identifier)
+ */
+ @Override
+ public String toString() {
+ return getName().toString();
+ }
+
+ /**
+ * Compares this name with the specified object for order. Returns a negative integer,
+ * zero, or a positive integer as this name lexicographically precedes, is equal to,
+ * or follows the specified object.
+ *
+ * @param object the object to compare with.
+ * @return -1 if this identifier precedes the given object, +1 if it follows it.
+ */
+ @Override
+ public int compareTo(final GenericName object) {
+ return getName().compareTo(object);
+ }
+
+ /**
+ * Compares this identifier with the specified object for equality.
+ *
+ * @param object the object to compare with this name.
+ * @return {@code true} if the given object is equal to this name.
+ */
+ @Override
+ public boolean equals(final Object object) {
+ if (object == this) {
+ return true;
+ }
+ if (super.equals(object)) {
+ if (!isNameSupplied) {
+ return true; // No need to compare names if they are computed from the same values.
+ }
+ final NamedIdentifier that = (NamedIdentifier) object;
+ return Objects.equals(this.getName(), that.getName());
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for this object.
+ */
+ @Override
+ public int hashCode() {
+ /*
+ * We do not use the name because it is usually inferred from existing properties.
+ * We only revert the bits for differentiating this NamedIdentifier class from its parent class.
+ */
+ return ~super.hashCode();
+ }
+
+ /**
+ * Invoked on serialization for writing the {@linkplain #name} if it was supplied by the user.
+ * Otherwise, we will let {@link #getName()} recompute the name only when needed.
+ *
+ * @param out the output stream where to serialize this named identifier.
+ * @throws IOException if an I/O error occurred while writing.
+ */
+ private void writeObject(final ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+ out.writeObject(isNameSupplied ? name : null);
+ }
+
+ /**
+ * Invoked on deserialization for reading the name written by {@link #writeObject(ObjectOutputStream)},
+ * if any.
+ *
+ * @param in the input stream from which to deserialize a named identifier.
+ * @throws IOException if an I/O error occurred while reading or if the stream contains invalid data.
+ * @throws ClassNotFoundException if the class serialized on the stream is not on the module path.
+ */
+ private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ name = (GenericName) in.readObject();
+ isNameSupplied = (name != null);
+ }
+ }
diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
index 0000000000,d3132feb94..56caeaed0e
mode 000000,100644..100644
--- 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
@@@ -1,0 -1,383 +1,383 @@@
+ /*
+ * 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.referencing.operation;
+
+ import java.util.List;
+ import org.opengis.referencing.crs.*;
+ import org.opengis.referencing.operation.CoordinateOperation;
+ import org.opengis.referencing.operation.OperationNotFoundException;
+ import org.opengis.referencing.operation.TransformException;
+ import org.opengis.util.FactoryException;
+ import org.apache.sis.referencing.operation.matrix.Matrices;
+ import org.apache.sis.referencing.operation.matrix.MatrixSIS;
+
+
+ /**
+ * Information about the operation from a source component to a target component in {@code CompoundCRS} instances.
+ * An instance of {@code SubOperationInfo} is created for each target CRS component. This class allows to collect
+ * information about all operation steps before to start the creation of pass-through operations. This separation
+ * is useful for applying reordering.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.1
+ *
+ * @see CoordinateOperationFinder#createOperationStep(CoordinateReferenceSystem, List, CoordinateReferenceSystem, List)
+ *
+ * @since 0.7
+ */
+ final class SubOperationInfo {
+ /**
+ * Types of target CRS, together with the type of CRS that may be used as the source for that target.
+ * For each array {@code COMPATIBLE_TYPES[i]}, the first element (i.e. {@code COMPATIBLE_TYPES[i][0]})
+ * is the target CRS and the whole array (including the first element) gives the valid source CRS type,
+ * if preference order.
+ *
+ * <h4>Example</h4>
+ * If a target CRS is of type {@link VerticalCRS}, then the source CRS may be another {@code VerticalCRS}
+ * or a {@link GeodeticCRS}. The geodetic CRS is possible because it may be three-dimensional.
+ *
+ * <h4>Exclusions</h4>
+ * {@link ProjectedCRS} and {@link DerivedCRS} are not in this list because we rather use their base CRS
+ * as the criterion for determining their type.
+ */
+ private static final Class<?>[][] COMPATIBLE_TYPES = {
+ {GeodeticCRS.class},
+ {VerticalCRS.class, GeodeticCRS.class},
+ {TemporalCRS.class},
+ {ParametricCRS.class},
+ {EngineeringCRS.class},
+ {ImageCRS.class}
+ };
+
+ /**
+ * Returns the class of the given CRS after unwrapping derived and projected CRS.
+ * The returned type is for use with {@link #COMPATIBLE_TYPES}.
+ */
+ private static Class<?> type(SingleCRS crs) {
+ while (crs instanceof GeneralDerivedCRS) {
- crs = ((GeneralDerivedCRS) crs).getBaseCRS();
++ crs = (SingleCRS) ((GeneralDerivedCRS) crs).getBaseCRS();
+ }
+ return crs.getClass();
+ }
+
+ /**
+ * The coordinate operation between a source CRS component and a target CRS component.
+ * Exactly one of {@link #operation} or {@link #constants} shall be non-null.
+ */
+ final CoordinateOperation operation;
+
+ /**
+ * The constant values to store in target coordinates, or {@code null} if none. This array is usually null.
+ * It may be non-null if no source CRS component has been found for a target CRS component. For example, if
+ * the source CRS has (<var>x</var>, <var>y</var>) axes and the target CRS has (<var>x</var>, <var>y</var>,
+ * <var>t</var>) axes, then this array may be set to a non-null value for specifying the <var>t</var> value.
+ * The array length is the number of dimensions in the full (usually compound) target CRS, but only the
+ * coordinate values for sourceless dimensions are used. Other coordinates are ignored and can be NaN.
+ * Exactly one of {@link #operation} or {@link #constants} shall be non-null.
+ *
+ * @see CoordinateOperationContext#getConstantCoordinates()
+ */
+ private final double[] constants;
+
+ /**
+ * The first dimension (inclusive) and the last dimension (exclusive) where the {@link SingleCRS} starts/ends
+ * in the full (usually compound) CRS. It may be an index in source dimensions or in target dimensions,
+ * depending on the following rules:
+ *
+ * <ul>
+ * <li>If {@link #operation} is non-null, then this is an index in the <em>source</em> dimensions.
+ * This is the normal case.</li>
+ * <li>Otherwise the operation is sourceless with coordinate results described by the {@link #constants} array.
+ * Since there is no source, the index become an index in target dimensions instead of source dimensions.</li>
+ * </ul>
+ *
+ * @see #sourceToSelected(int, SubOperationInfo[])
+ */
+ private final int startAtDimension, endAtDimension;
+
+ /**
+ * Index of this instance in the array of {@code SubOperationInfo} instances,
+ * before the reordering applied by {@link #getSourceCRS(SubOperationInfo[])}.
+ */
+ final int targetComponentIndex;
+
+ /**
+ * Creates a new instance wrapping the given coordinate operation or coordinate constants.
+ * Exactly one of {@code operation} or {@code constants} shall be non-null.
+ */
+ private SubOperationInfo(final int targetComponentIndex, final CoordinateOperation operation,
+ final double[] constants, final int startAtDimension, final int endAtDimension)
+ {
+ this.operation = operation;
+ this.constants = constants;
+ this.startAtDimension = startAtDimension;
+ this.endAtDimension = endAtDimension;
+ this.targetComponentIndex = targetComponentIndex;
+ assert (operation == null) != (constants == null);
+ }
+
+ /**
+ * Searches in given list of source components for operations capable to transform coordinates to each target CRS.
+ * There is one {@code SubOperationInfo} per target CRS because we need to satisfy all target dimensions, while it
+ * is okay to ignore some source dimensions. If an operation cannot be found, then this method returns {@code null}.
+ *
+ * @param caller the object which is inferring a coordinate operation.
+ * @param sources all components of the source CRS.
+ * @param targets all components of the target CRS.
+ * @return information about each coordinate operation from a source CRS to a target CRS, or {@code null}.
+ * @throws FactoryException if an error occurred while grabbing a coordinate operation.
+ * @throws TransformException if an error occurred while computing the sourceless coordinate constants.
+ */
+ static SubOperationInfo[] createSteps(final CoordinateOperationFinder caller,
+ final List<? extends SingleCRS> sources,
+ final List<? extends SingleCRS> targets)
+ throws FactoryException, TransformException
+ {
+ final SubOperationInfo[] infos = new SubOperationInfo[targets.size()];
+ final boolean[] sourceComponentIsUsed = new boolean[sources.size()];
+ /*
+ * Iterate over target CRS because all of them must have an operation.
+ * One the other hand, source CRS can be used zero or one (not two) time.
+ *
+ * Note: the loops on source CRS and on target CRS follow the same pattern.
+ * The first 6 lines of code are the same with only `target` replaced
+ * by `source`.
+ */
+ int targetStartAtDimension;
+ int targetEndAtDimension = 0;
+ next: for (int targetComponentIndex = 0; targetComponentIndex < infos.length; targetComponentIndex++) {
+ final SingleCRS target = targets.get(targetComponentIndex);
+ targetStartAtDimension = targetEndAtDimension;
+ targetEndAtDimension += target.getCoordinateSystem().getDimension();
+
+ final Class<?> targetType = type(target);
+ OperationNotFoundException failure = null;
+ /*
+ * For each target CRS, search for a source CRS which has not yet been used.
+ * Some sources may be left unused after this method completion. Check only
+ * sources that may be compatible according the `COMPATIBLE_TYPES` array.
+ */
+ int sourceStartAtDimension;
+ int sourceEndAtDimension = 0;
+ for (int sourceComponentIndex = 0; sourceComponentIndex < sourceComponentIsUsed.length; sourceComponentIndex++) {
+ final SingleCRS source = sources.get(sourceComponentIndex);
+ sourceStartAtDimension = sourceEndAtDimension;
+ sourceEndAtDimension += source.getCoordinateSystem().getDimension();
+ if (!sourceComponentIsUsed[sourceComponentIndex]) {
+ for (final Class<?>[] sourceTypes : COMPATIBLE_TYPES) {
+ if (sourceTypes[0].isAssignableFrom(targetType)) {
+ for (final Class<?> sourceType : sourceTypes) {
+ if (sourceType.isAssignableFrom(type(source))) {
+ final CoordinateOperation operation;
+ try {
+ operation = caller.createOperation(source, target);
+ } catch (OperationNotFoundException exception) {
+ if (failure == null) {
+ failure = exception;
+ } else {
+ failure.addSuppressed(exception);
+ }
+ continue;
+ }
+ /*
+ * Found an operation. Exclude the source component from the list because each source
+ * should be used at most once by SourceComponent. Note that the same source may still
+ * be used again in another context if that source is also an interpolation CRS.
+ *
+ * EXAMPLE: consider a coordinate operation from (GeodeticCRS₁, VerticalCRS₁) source
+ * to (GeodeticCRS₂, VerticalCRS₂) target. The source GeodeticCRS₁ should be mapped
+ * to exactly one target component (which is GeodeticCRS₂) and VerticalCRS₁ mapped
+ * to VerticalCRS₂. But the operation on vertical coordinates may need GeodeticCRS₁
+ * for doing its work, so GeodeticCRS₁ is needed twice. However, when needed for the
+ * vertical coordinate operation, the GeodeticCRS₁ is used as an "interpolation CRS".
+ * Interpolation CRS are handled in other code paths; it is not the business of this
+ * SourceComponent class to care about them. From the point of view of this class,
+ * GeodeticCRS₁ is used only once.
+ */
+ sourceComponentIsUsed[sourceComponentIndex] = true;
+ infos[targetComponentIndex] = new SubOperationInfo(targetComponentIndex,
+ operation, null, sourceStartAtDimension, sourceEndAtDimension);
+
+ if (failure != null) {
+ CoordinateOperationRegistry.recoverableException("decompose", failure);
+ }
+ continue next;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (failure != null) {
+ throw failure;
+ }
+ /*
+ * If we reach this point, we have not been able to find a source CRS that we can map to the target CRS.
+ * Usually this is fatal; returning null will instruct the caller to throw `OperationNotFoundException`.
+ * However, in some contexts (e.g. when searching for an operation between two `GridGeometry` instances)
+ * it is possible to assign a constant value to the target coordinates. Those values cannot be guessed
+ * by `org.apache.sis.referencing`; they must be provided by caller. If such constants are specified,
+ * then we will try to apply them.
+ */
+ final double[] constants = CoordinateOperationContext.getConstantCoordinates();
+ if (constants == null || constants.length < targetEndAtDimension) {
+ return null;
+ }
+ for (int i = targetStartAtDimension; i < targetEndAtDimension; i++) {
+ if (Double.isNaN(constants[i])) return null;
+ }
+ infos[targetComponentIndex] = new SubOperationInfo(targetComponentIndex,
+ null, constants, targetStartAtDimension, targetEndAtDimension);
+ }
+ return infos;
+ }
+
+ /**
+ * Returns the source CRS of given operations. This method modifies the given array in-place by moving all
+ * sourceless operations last. Then an array is returned with the source CRS of only ordinary operations.
+ * Each CRS at index <var>i</var> in the returned array is the component from {@link #startAtDimension}
+ * inclusive to {@link #endAtDimension} exclusive in the complete (usually compound) source CRS analyzed
+ * by {@link CoordinateOperationFinder}.
+ *
+ * @param selected all operations from source to target {@link CompoundCRS}.
+ * @return source CRS of all ordinary operations (excluding operations producing constant values).
+ */
+ static CoordinateReferenceSystem[] getSourceCRS(final SubOperationInfo[] selected) {
+ int n = selected.length;
+ final int last = n - 1;
+ for (int i=0; i<n; i++) {
+ final SubOperationInfo component = selected[i];
+ if (component.operation == null) {
+ System.arraycopy(selected, i+1, selected, i, last - i);
+ selected[last] = component;
+ n--;
+ }
+ }
+ final CoordinateReferenceSystem[] stepComponents = new CoordinateReferenceSystem[n];
+ for (int i=0; i<n; i++) {
+ stepComponents[i] = selected[i].operation.getSourceCRS();
+ }
+ return stepComponents;
+ }
+
+ /**
+ * Returns the index of the last non-identity operation. This is used as a slight optimization for deciding when
+ * {@link CoordinateOperationFinder} can stop to create intermediate target {@link CompoundCRS} instances because
+ * all remaining operations leave target coordinates unchanged. It may help to skip a few operations for example
+ * when converting (<var>x</var>, <var>y</var>, <var>t</var>) coordinates where <var>t</var> value is unchanged.
+ *
+ * @param selected all operations from source to target {@link CompoundCRS}.
+ * @return index of the last non-identity operation, inclusive.
+ */
+ static int indexOfFinal(final SubOperationInfo[] selected) {
+ int n = selected.length;
+ while (n != 0) {
+ if (!selected[--n].isIdentity()) {
+ break;
+ }
+ }
+ return n;
+ }
+
+ /**
+ * Returns a matrix for an affine transform moving coordinate values from their position in the source CRS to a
+ * position in the order {@link #operation}s are applied. This matrix is needed because {@link #operation} may
+ * select any source CRS in the list of {@link SingleCRS} given to the {@link #createSteps createSteps(…)} method;
+ * the source CRS are not necessarily picked in the same order as they appear in the list.
+ *
+ * <h4>Example</h4>
+ * if the source CRS has (<var>x</var>, <var>y</var>, <var>t</var>) coordinates and the target CRS has
+ * (<var>t</var>, <var>x</var>, <var>y</var>) coordinates with some operation applied on <var>x</var>
+ * and <var>y</var>, then the operations will be applied in that order:
+ *
+ * <ol>
+ * <li>An operation for <var>t</var>, because it is the first coordinate to appear in target CRS.</li>
+ * <li>An operation for (<var>x</var>, <var>y</var>), because those coordinates are next in target CRS.</li>
+ * </ol>
+ *
+ * Since {@link DefaultPassThroughOperation} cannot take coordinates before the "first affected coordinate"
+ * dimension and move them into the "trailing coordinates" dimension, we have to reorder coordinates before
+ * to create the pass-through operations. This is done by the following matrix:
+ *
+ * <pre class="math">
+ * ┌ ┐ ┌ ┐┌ ┐
+ * │ t │ │ 0 0 1 0 ││ x │
+ * │ x │ = │ 1 0 0 0 ││ y │
+ * │ y │ │ 0 1 0 0 ││ t │
+ * │ 1 │ │ 0 0 0 1 ││ 1 │
+ * └ ┘ └ ┘└ ┘</pre>
+ *
+ * Furthermore, some dimensions may be dropped,
+ * e.g. from (<var>x</var>, <var>y</var>, <var>t</var>) to (<var>x</var>, <var>y</var>).
+ *
+ * @param sourceDimensions number of dimensions in the source {@link CompoundCRS}.
+ * @param selected all operations from source to target {@link CompoundCRS}.
+ * @return mapping from source {@link CompoundCRS} to each {@link CoordinateOperation#getSourceCRS()}.
+ */
+ static MatrixSIS sourceToSelected(final int sourceDimensions, final SubOperationInfo[] selected) {
+ int selectedDimensions = 0;
+ for (final SubOperationInfo component : selected) {
+ if (component.operation == null) break;
+ selectedDimensions += component.endAtDimension - component.startAtDimension;
+ }
+ final MatrixSIS select = Matrices.createZero(selectedDimensions + 1, sourceDimensions + 1);
+ select.setElement(selectedDimensions, sourceDimensions, 1);
+ int j = 0;
+ for (final SubOperationInfo component : selected) {
+ for (int i=component.startAtDimension; i<component.endAtDimension; i++) {
+ select.setElement(j++, i, 1);
+ }
+ }
+ return select;
+ }
+
+ /**
+ * Returns {@code true} if the coordinate operation wrapped by this object is an identity transform.
+ */
+ final boolean isIdentity() {
+ return (operation != null) && operation.getMathTransform().isIdentity();
+ }
+
+ /**
+ * Returns the matrix of an operation setting some coordinates to a constant values.
+ *
+ * @param selected all operations from source to target {@link CompoundCRS}.
+ * @param n index of the first selected operation which describe a constant value.
+ * @param srcDim number of dimensions in the target CRS of previous operation step.
+ * @param tgtDim number of dimensions in the full (usually compound) target CRS.
+ */
+ static MatrixSIS createConstantOperation(final SubOperationInfo[] selected, int n,
+ final int srcDim, final int tgtDim)
+ {
+ final boolean[] targetDimensionIsUsed = new boolean[tgtDim];
+ final MatrixSIS m = Matrices.createZero(tgtDim + 1, srcDim + 1);
+ m.setElement(tgtDim, srcDim, 1);
+ do {
+ final SubOperationInfo component = selected[n];
+ for (int j = component.startAtDimension; j < component.endAtDimension; j++) {
+ m.setElement(j, srcDim, component.constants[j]);
+ targetDimensionIsUsed[j] = true;
+ }
+ } while (++n < selected.length);
+ for (int i=0,j=0; j<tgtDim; j++) {
+ if (!targetDimensionIsUsed[j]) {
+ m.setElement(j, i++, 1);
+ }
+ }
+ return m;
+ }
+ }
diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
index 0000000000,99bf1aa7a5..a01b45b649
mode 000000,100644..100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
@@@ -1,0 -1,1770 +1,1783 @@@
+ /*
+ * 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.referencing.operation.transform;
+
+ import java.util.Set;
+ import java.util.Map;
+ import java.util.HashMap;
+ import java.util.IdentityHashMap;
+ import java.util.ServiceLoader;
+ import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.ConcurrentMap;
+ import java.util.concurrent.atomic.AtomicReference;
+ import java.util.logging.Level;
+ import java.util.logging.LogRecord;
+ import java.lang.reflect.Constructor;
+ import java.io.Serializable;
+ import javax.measure.Unit;
+ import javax.measure.quantity.Length;
+ import javax.measure.IncommensurableException;
+
+ import org.opengis.parameter.ParameterValue;
+ import org.opengis.parameter.ParameterValueGroup;
+ import org.opengis.parameter.ParameterDescriptorGroup;
+ import org.opengis.parameter.ParameterNotFoundException;
+ import org.opengis.parameter.InvalidParameterNameException;
+ import org.opengis.parameter.InvalidParameterValueException;
+ import org.opengis.referencing.IdentifiedObject;
+ import org.opengis.referencing.crs.CoordinateReferenceSystem;
+ import org.opengis.referencing.crs.GeodeticCRS;
+ import org.opengis.referencing.cs.CoordinateSystem;
+ import org.opengis.referencing.cs.EllipsoidalCS;
+ import org.opengis.referencing.cs.CartesianCS;
+ import org.opengis.referencing.datum.Ellipsoid;
+ import org.opengis.referencing.operation.Matrix;
+ import org.opengis.referencing.operation.MathTransform;
+ import org.opengis.referencing.operation.MathTransformFactory;
+ import org.opengis.referencing.operation.OperationMethod;
+ import org.opengis.referencing.operation.SingleOperation;
+ import org.opengis.util.FactoryException;
+ import org.opengis.util.NoSuchIdentifierException;
+
+ import org.apache.sis.io.wkt.Parser;
+ import org.apache.sis.internal.util.URLs;
+ import org.apache.sis.internal.util.Strings;
+ import org.apache.sis.internal.util.Constants;
+ import org.apache.sis.internal.referencing.Formulas;
+ import org.apache.sis.internal.referencing.CoordinateOperations;
+ import org.apache.sis.internal.referencing.ReferencingUtilities;
+ import org.apache.sis.internal.referencing.j2d.ParameterizedAffine;
+ import org.apache.sis.internal.referencing.provider.AbstractProvider;
+ import org.apache.sis.internal.referencing.provider.VerticalOffset;
+ import org.apache.sis.internal.referencing.provider.GeographicToGeocentric;
+ import org.apache.sis.internal.referencing.provider.GeocentricToGeographic;
+ import org.apache.sis.internal.referencing.Resources;
+ import org.apache.sis.internal.system.Reflect;
+ import org.apache.sis.metadata.iso.citation.Citations;
+ import org.apache.sis.parameter.DefaultParameterValueGroup;
+ import org.apache.sis.parameter.Parameterized;
+ import org.apache.sis.parameter.Parameters;
+ import org.apache.sis.referencing.IdentifiedObjects;
+ import org.apache.sis.referencing.cs.AxesConvention;
+ import org.apache.sis.referencing.cs.CoordinateSystems;
+ import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
+ import org.apache.sis.referencing.operation.DefaultOperationMethod;
+ import org.apache.sis.referencing.operation.matrix.Matrices;
+ import org.apache.sis.measure.Units;
+ import org.apache.sis.util.ArgumentChecks;
+ import org.apache.sis.util.ArraysExt;
+ import org.apache.sis.util.Classes;
+ import org.apache.sis.util.collection.WeakHashSet;
+ import org.apache.sis.util.iso.AbstractFactory;
+ import org.apache.sis.util.logging.Logging;
+ import org.apache.sis.util.resources.Errors;
+
+
+ /**
+ * Low level factory for creating {@linkplain AbstractMathTransform math transforms}.
+ * The objects created by this factory do not know what the source and target coordinate systems mean.
+ * Because of this low semantic value, high level GIS applications usually do not need to use this factory directly.
+ * They can use the static convenience methods in the {@link org.apache.sis.referencing.CRS}
+ * or {@link MathTransforms} classes instead.
+ *
+ *
+ * <h2>Standard parameters</h2>
+ * {@code MathTransform} instances are created from {@linkplain DefaultParameterValueGroup parameter values}.
+ * The parameters expected by each operation available in a default Apache SIS installation is
+ * <a href="https://sis.apache.org/tables/CoordinateOperationMethods.html">listed here</a>.
+ * The set of parameters varies for each operation or projection, but the following can be considered typical:
+ *
+ * <ul>
+ * <li>A <cite>semi-major</cite> and <cite>semi-minor</cite> axis length in metres.</li>
+ * <li>A <cite>central meridian</cite> and <cite>latitude of origin</cite> in decimal degrees.</li>
+ * <li>A <cite>scale factor</cite>, which default to 1.</li>
+ * <li>A <cite>false easting</cite> and <cite>false northing</cite> in metres, which default to 0.</li>
+ * </ul>
+ *
+ * <p>Each descriptor has many aliases, and those aliases may vary between different projections.
+ * For example, the <cite>false easting</cite> parameter is usually called {@code "false_easting"}
+ * by OGC, while EPSG uses various names like <cite>"False easting"</cite> or <cite>"Easting at
+ * false origin"</cite>.</p>
+ *
+ * <h2>Dynamic parameters</h2>
+ * A few non-standard parameters are defined for compatibility reasons,
+ * but delegates their work to standard parameters. Those dynamic parameters are not listed in the
+ * {@linkplain DefaultParameterValueGroup#values() parameter values}.
+ * Dynamic parameters are:
+ *
+ * <ul>
+ * <li>{@code "earth_radius"}, which copy its value to the {@code "semi_major"} and
+ * {@code "semi_minor"} parameter values.</li>
+ * <li>{@code "inverse_flattening"}, which compute the {@code "semi_minor"} value from
+ * the {@code "semi_major"} parameter value.</li>
+ * <li>{@code "standard_parallel"} expecting an array of type {@code double[]}, which copy
+ * its elements to the {@code "standard_parallel_1"} and {@code "standard_parallel_2"}
+ * parameter scalar values.</li>
+ * </ul>
+ *
+ * <p>The main purpose of those dynamic parameters is to support some less commonly used conventions
+ * without duplicating the most commonly used conventions. The alternative ways are used in netCDF
+ * files for example, which often use spherical models instead of ellipsoidal ones.</p>
+ *
+ *
+ * <h2><a id="Obligation">Mandatory and optional parameters</a></h2>
+ * Parameters are flagged as either <cite>mandatory</cite> or <cite>optional</cite>.
+ * A parameter may be mandatory and still have a default value. In the context of this package, "mandatory"
+ * means that the parameter is an essential part of the projection defined by standards.
+ * Such mandatory parameters will always appears in any <cite>Well Known Text</cite> (WKT) formatting,
+ * even if not explicitly set by the user. For example, the central meridian is typically a mandatory
+ * parameter with a default value of 0° (the Greenwich meridian).
+ *
+ * <p>Optional parameters, on the other hand, are often non-standard extensions.
+ * They will appear in WKT formatting only if the user defined explicitly a value which is different than the
+ * default value.</p>
+ *
+ *
+ * <h2>Operation methods discovery</h2>
+ * {@link OperationMethod} describes all the parameters expected for instantiating a particular kind of
+ * math transform. The set of operation methods known to this factory can be obtained in two ways:
+ *
+ * <ul>
+ * <li>{@linkplain #DefaultMathTransformFactory(Iterable) specified explicitly at construction time}, or</li>
+ * <li>{@linkplain #DefaultMathTransformFactory() discovered by scanning the module path}.</li>
+ * </ul>
+ *
+ * The default way is to scan the module path. See {@link MathTransformProvider} for indications about how to add
+ * custom coordinate operation methods in a default Apache SIS installation.
+ *
+ *
+ * <h2>Thread safety</h2>
+ * This class is safe for multi-thread usage if all referenced {@code OperationMethod} instances are thread-safe.
+ * There is typically only one {@code MathTransformFactory} instance for the whole application.
+ *
+ * @author Martin Desruisseaux (Geomatys, IRD)
+ * @version 1.4
+ *
+ * @see MathTransformProvider
+ * @see AbstractMathTransform
+ *
+ * @since 0.6
+ */
+ public class DefaultMathTransformFactory extends AbstractFactory implements MathTransformFactory, Parser {
+ /*
+ * NOTE FOR JAVADOC WRITER:
+ * The "method" word is ambiguous here, because it can be "Java method" or "coordinate operation method".
+ * In this class, we reserve the "method" word for "coordinate operation method" as much as possible.
+ * For Java methods, we rather use "constructor" or "function".
+ */
+
+ /**
+ * Minimal precision of ellipsoid semi-major and semi-minor axis lengths, in metres.
+ * If the length difference between the axis of two ellipsoids is greater than this threshold,
+ * we will report a mismatch. This is used for logging purpose only and do not have any impact
+ * on the {@code MathTransform} objects to be created by this factory.
+ */
+ private static final double ELLIPSOID_PRECISION = Formulas.LINEAR_TOLERANCE;
+
+ /**
+ * The constructor for WKT parsers, fetched when first needed. The WKT parser is defined in the
+ * same module than this class, so we will hopefully not have security issues. But we have to
+ * use reflection because the parser class is not yet public (because we do not want to commit
+ * its API yet).
+ */
+ private static volatile Constructor<? extends Parser> parserConstructor;
+
+ /**
+ * All methods specified at construction time or found on the module path.
+ * If the iterable is an instance of {@link ServiceLoader}, then it will
+ * be reloaded when {@link #reload()} is invoked.
+ *
+ * <p>All uses of this field shall be synchronized on {@code methods}.</p>
+ */
+ private final Iterable<? extends OperationMethod> methods;
+
+ /**
+ * The methods by name, cached for faster lookup and for avoiding some
+ * synchronizations on {@link #methods} and {@link #pool}.
+ */
+ private final ConcurrentMap<String, OperationMethod> methodsByName;
+
+ /**
+ * The methods by type. All uses of this map shall be synchronized on {@code methodsByType}.
+ *
+ * <h4>Implementation note</h4>
+ * We do not use a concurrent map here because the number of entries is expected to be very small
+ * (about 2 entries), which make concurrent algorithms hardly efficient. Furthermore, this map is
+ * not used often.
+ */
+ private final Map<Class<?>, OperationMethodSet> methodsByType;
+
+ /**
+ * The last coordinate operation method used by a {@code create(…)} constructor.
+ */
+ private final ThreadLocal<OperationMethod> lastMethod;
+
+ /**
+ * The math transforms created so far. This pool is used in order to return instances of existing
+ * math transforms when possible. If {@code null}, then no pool should be used. A null value is
+ * preferable when the transforms are known to be short-lived, for avoiding the cost of caching them.
+ */
+ private final WeakHashSet<MathTransform> pool;
+
+ /**
+ * The <cite>Well Known Text</cite> parser for {@code MathTransform} instances.
+ * This parser is not thread-safe, so we need to prevent two threads from using
+ * the same instance at the same time.
+ */
+ private final AtomicReference<Parser> parser;
+
+ /**
+ * The factory with opposite caching factory, or {@code null} if not yet created.
+ *
+ * @see #caching(boolean)
+ */
+ private DefaultMathTransformFactory oppositeCachingPolicy;
+
+ /**
+ * The default factory instance.
+ */
+ private static final DefaultMathTransformFactory INSTANCE = new DefaultMathTransformFactory();
+
+ /**
+ * Returns the default provider of {@code MathTransform} instances.
+ * This is the factory used by the Apache SIS library when no non-null
+ * {@link MathTransformFactory} has been explicitly specified.
+ * This method can be invoked directly, or indirectly through
+ * {@code ServiceLoader.load(MathTransformFactory.class)}.
+ *
+ * @return the default provider of math transforms.
+ *
+ * @see java.util.ServiceLoader
+ * @since 1.4
+ */
+ public static DefaultMathTransformFactory provider() {
+ return INSTANCE;
+ }
+
+ /**
+ * Creates a new factory which will discover operation methods with a {@link ServiceLoader}.
+ * The {@link OperationMethod} implementations shall be listed in {@code module-info.java}
+ * as provider of the {@code org.opengis.referencing.operation.OperationMethod} service.
+ * {@code DefaultMathTransformFactory} scans the providers of all modules in order to list
+ * all available operation methods.
+ * Currently, only operation methods implementing the {@link MathTransformProvider} interface
+ * can be used by the {@code create(…)} methods in this class.
+ *
+ * @see #provider()
+ * @see #reload()
+ */
+ public DefaultMathTransformFactory() {
+ this(ServiceLoader.load(OperationMethod.class, Reflect.getContextClassLoader()));
+ }
+
+ /**
+ * Creates a new factory which will use the given operation methods. The given iterable is stored by reference —
+ * its content is <strong>not</strong> copied — in order to allow deferred {@code OperationMethod} constructions.
+ * Note that by default, only operation methods that implement the {@link MathTransformProvider} interface can be
+ * used by the {@code create(…)} methods in this class.
+ *
+ * <h4>Requirements</h4>
+ * <ul>
+ * <li>The given iterable should not contain duplicated elements.</li>
+ * <li>The given iterable shall be stable: all elements returned by the first iteration must also be
+ * returned by any subsequent iterations, unless {@link #reload()} has been invoked.</li>
+ * <li>{@code OperationMethod} instances should also implement {@link MathTransformProvider}.</li>
+ * <li>All {@code OperationMethod} instances shall be thread-safe.</li>
+ * <li>The {@code Iterable} itself does not need to be thread-safe since all usages will be synchronized as below:
+ *
+ * {@snippet lang="java" :
+ * synchronized (methods) {
+ * for (OperationMethod method : methods) {
+ * // Use the method here.
+ * }
+ * }
+ * }
+ * </li>
+ * </ul>
+ *
+ * @param methods the operation methods to use, stored by reference (not copied).
+ */
+ public DefaultMathTransformFactory(final Iterable<? extends OperationMethod> methods) {
+ ArgumentChecks.ensureNonNull("methods", methods);
+ this.methods = methods;
+ methodsByName = new ConcurrentHashMap<>();
+ methodsByType = new IdentityHashMap<>();
+ lastMethod = new ThreadLocal<>();
+ pool = new WeakHashSet<>(MathTransform.class);
+ parser = new AtomicReference<>();
+ }
+
+ /**
+ * Creates a new factory with the same configuration than given factory but without caching.
+ */
+ private DefaultMathTransformFactory(final DefaultMathTransformFactory parent) {
+ methods = parent.methods;
+ methodsByName = parent.methodsByName;
+ methodsByType = parent.methodsByType;
+ lastMethod = new ThreadLocal<>();
+ pool = null;
+ parser = parent.parser;
+ oppositeCachingPolicy = parent;
+ }
+
+ /**
+ * Returns a factory for the same transforms than this factory, but with caching potentially disabled.
+ * By default, {@code DefaultMathTransformFactory} caches the {@link MathTransform} instances for sharing
+ * existing instances when transforms are created many times with the same set of parameters.
+ * However, this caching may be unnecessarily costly when the transforms to create are known to be short lived.
+ * This method allows to get a factory better suited for short-lived objects.
+ *
+ * <p>This method does not modify the state of this factory. Instead, different factory instances for the
+ * different caching policy are returned.</p>
+ *
+ * @param enabled whether caching should be enabled.
+ * @return a factory for the given caching policy.
+ *
+ * @since 1.1
+ */
+ public DefaultMathTransformFactory caching(final boolean enabled) {
+ if (enabled) {
+ return this;
+ }
+ synchronized (this) {
+ if (oppositeCachingPolicy == null) {
+ oppositeCachingPolicy = new NoCache(this);
+ }
+ return oppositeCachingPolicy;
+ }
+ }
+
+ /**
+ * Accessor for {@link NoCache} implementation.
+ */
+ final DefaultMathTransformFactory oppositeCachingPolicy() {
+ return oppositeCachingPolicy;
+ }
+
+ /**
+ * A factory performing no caching.
+ * This factory shares the same operation methods than the parent factory.
+ */
+ private static final class NoCache extends DefaultMathTransformFactory {
+ /** Creates a new factory with the same configuration than given factory. */
+ NoCache(final DefaultMathTransformFactory parent) {
+ super(parent);
+ }
+
+ /** Returns a factory for the same transforms but given caching policy. */
+ @Override public DefaultMathTransformFactory caching(final boolean enabled) {
+ return enabled ? oppositeCachingPolicy() : this;
+ }
+
+ /** Notifies parent factory that the set of operation methods may have changed. */
+ @Override public void reload() {
+ oppositeCachingPolicy().reload();
+ }
+ }
+
+ /**
+ * Returns a set of available methods for coordinate operations of the given type.
+ * The {@code type} argument can be used for filtering the kind of operations described by the returned
+ * {@code OperationMethod}s. The argument is usually (but not restricted to) one of the following types:
+ *
+ * <ul>
+ * <li>{@link org.opengis.referencing.operation.Transformation}
+ * for coordinate operations described by empirically derived parameters.</li>
+ * <li>{@link org.opengis.referencing.operation.Conversion}
+ * for coordinate operations described by definitions.</li>
+ * <li>{@link org.opengis.referencing.operation.Projection}
+ * for conversions from geodetic latitudes and longitudes to plane (map) coordinates.</li>
+ * <li>{@link SingleOperation} for all coordinate operations.</li>
+ * </ul>
+ *
+ * The returned set may conservatively contain more {@code OperationMethod} elements than requested
+ * if this {@code MathTransformFactory} does not support filtering by the given type.
+ *
+ * @param type <code>{@linkplain SingleOperation}.class</code> for fetching all operation methods,
+ * <code>{@linkplain org.opengis.referencing.operation.Projection}.class</code> for
+ * fetching only map projection methods, <i>etc</i>.
+ * @return methods available in this factory for coordinate operations of the given type.
+ *
+ * @see #getDefaultParameters(String)
+ * @see #createParameterizedTransform(ParameterValueGroup, Context)
+ * @see DefaultOperationMethod#getOperationType()
+ */
+ @Override
+ public Set<OperationMethod> getAvailableMethods(final Class<? extends SingleOperation> type) {
+ ArgumentChecks.ensureNonNull("type", type);
+ OperationMethodSet set;
+ synchronized (methodsByType) {
+ set = methodsByType.get(type);
+ }
+ if (set == null) {
+ /*
+ * Implementation note: we are better to avoid holding a lock on `methods` and `methodsByType`
+ * at the same time because the `methods` iterator could be a user's implementation which callback
+ * this factory.
+ */
+ synchronized (methods) {
+ set = new OperationMethodSet(type, methods);
+ }
+ final OperationMethodSet previous;
+ synchronized (methodsByType) {
+ previous = methodsByType.putIfAbsent(type, set);
+ }
+ if (previous != null) {
+ set = previous;
+ }
+ }
+ return set;
+ }
+
+ /**
+ * Returns the operation method for the specified name or identifier. The given argument shall be either
+ * a method {@linkplain DefaultOperationMethod#getName() name} (e.g. <cite>"Transverse Mercator"</cite>)
+ * or one of its {@linkplain DefaultOperationMethod#getIdentifiers() identifiers} (e.g. {@code "EPSG:9807"}).
+ *
+ * <p>The search is case-insensitive. Comparisons against method names can be
+ * {@linkplain DefaultOperationMethod#isHeuristicMatchForName(String) heuristic}.</p>
+ *
+ * <p>If more than one method match the given identifier, then the first (according iteration order)
+ * non-{@linkplain org.apache.sis.util.Deprecable#isDeprecated() deprecated} matching method is returned.
+ * If all matching methods are deprecated, the first one is returned.</p>
+ *
+ * @param identifier the name or identifier of the operation method to search.
+ * @return the coordinate operation method for the given name or identifier.
+ * @throws NoSuchIdentifierException if there is no operation method registered for the specified identifier.
+ *
+ * @see org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory#getOperationMethod(String)
+ */
+ public OperationMethod getOperationMethod(String identifier) throws NoSuchIdentifierException {
+ ArgumentChecks.ensureNonEmpty("identifier", identifier = identifier.strip());
+ OperationMethod method = methodsByName.get(identifier);
+ if (method == null) {
+ synchronized (methods) {
+ method = CoordinateOperations.getOperationMethod(methods, identifier);
+ }
+ if (method == null) {
+ throw new NoSuchIdentifierException(Resources.format(
+ Resources.Keys.NoSuchOperationMethod_2, identifier, URLs.OPERATION_METHODS), identifier);
+ }
+ /*
+ * Remember the method we just found, for faster check next time.
+ */
+ final OperationMethod previous = methodsByName.putIfAbsent(identifier.intern(), method);
+ if (previous != null) {
+ method = previous;
+ }
+ }
+ return method;
+ }
+
+ /**
+ * Returns the default parameter values for a math transform using the given operation method.
+ * The {@code method} argument is the name of any {@code OperationMethod} instance returned by
+ * <code>{@link #getAvailableMethods(Class) getAvailableMethods}({@linkplain SingleOperation}.class)</code>.
+ * Valid names are <a href="https://sis.apache.org/tables/CoordinateOperationMethods.html">listed here</a>.
+ *
+ * <p>This function creates new parameter instances at every call.
+ * Parameters are intended to be modified by the user before to be given to the
+ * {@link #createParameterizedTransform createParameterizedTransform(…)} method.</p>
+ *
+ * @param method the case insensitive name of the coordinate operation method to search for.
+ * @return a new group of parameter values for the {@code OperationMethod} identified by the given name.
+ * @throws NoSuchIdentifierException if there is no method registered for the given name or identifier.
+ *
+ * @see #getAvailableMethods(Class)
+ * @see #createParameterizedTransform(ParameterValueGroup, Context)
+ * @see AbstractMathTransform#getParameterValues()
+ */
+ @Override
+ public ParameterValueGroup getDefaultParameters(final String method) throws NoSuchIdentifierException {
+ return getOperationMethod(method).getParameters().createValue();
+ }
+
+ /**
+ * Creates a transform from a group of parameters.
+ * The set of expected parameters varies for each operation.
+ *
+ * @param parameters the parameter values. The {@linkplain ParameterDescriptorGroup#getName() parameter group name}
+ * shall be the name of the desired {@linkplain DefaultOperationMethod operation method}.
+ * @return the transform created from the given parameters.
+ * @throws NoSuchIdentifierException if there is no method for the given parameter group name.
+ * @throws FactoryException if the object creation failed. This exception is thrown
+ * if some required parameter has not been supplied, or has illegal value.
+ *
+ * @deprecated Replaced by {@link #createParameterizedTransform(ParameterValueGroup, Context)}
+ * where the {@code Context} argument can be null.
+ */
+ @Override
+ @Deprecated(since="0.7")
+ public MathTransform createParameterizedTransform(final ParameterValueGroup parameters)
+ throws NoSuchIdentifierException, FactoryException
+ {
+ return createParameterizedTransform(parameters, null);
+ }
+
+ /**
+ * Source and target coordinate systems for which a new parameterized transform is going to be used.
+ * {@link DefaultMathTransformFactory} uses this information for:
+ *
+ * <ul>
+ * <li>Completing some parameters if they were not provided. In particular, the {@linkplain #getSourceEllipsoid()
+ * source ellipsoid} can be used for providing values for the {@code "semi_major"} and {@code "semi_minor"}
+ * parameters in map projections.</li>
+ * <li>{@linkplain CoordinateSystems#swapAndScaleAxes Swapping and scaling axes} if the source or the target
+ * coordinate systems are not {@linkplain AxesConvention#NORMALIZED normalized}.</li>
+ * </ul>
+ *
+ * This class does <strong>not</strong> handle change of
+ * {@linkplain org.apache.sis.referencing.datum.DefaultGeodeticDatum#getPrimeMeridian() prime meridian}
+ * or anything else related to datum. Datum changes have dedicated {@link OperationMethod},
+ * for example <cite>"Longitude rotation"</cite> (EPSG:9601) for changing the prime meridian.
+ *
+ * <h2>Scope</h2>
+ * Instances of this class should be short-lived
+ * (they exist only the time needed for creating a {@link MathTransform})
+ * and should not be shared (because they provide no immutability guarantees).
+ * This class is not thread-safe.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.3
+ * @since 0.7
+ */
+ @SuppressWarnings("serial") // All field values are usually serializable instances.
+ public static class Context implements Serializable {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = -239563539875674709L;
+
+ /**
+ * Coordinate system of the source or target points.
+ */
+ private CoordinateSystem sourceCS, targetCS;
+
+ /**
+ * The ellipsoid of the source or target ellipsoidal coordinate system, or {@code null} if it does not apply.
+ * Valid only if {@link #sourceCS} or {@link #targetCS} is an instance of {@link EllipsoidalCS}.
+ */
+ private Ellipsoid sourceEllipsoid, targetEllipsoid;
+
+ /**
+ * The provider that created the parameterized {@link MathTransform} instance, or {@code null}
+ * if this information does not apply. This field is used for transferring information between
+ * {@code createParameterizedTransform(…)} and {@code swapAndScaleAxes(…)}.
+ */
+ private OperationMethod provider;
+
+ /**
+ * The parameters actually used.
+ *
+ * @see #getCompletedParameters()
+ */
+ private ParameterValueGroup parameters;
+
+ /**
+ * Names of parameters which have been inferred from context.
+ *
+ * @see #getContextualParameters()
+ */
+ private final Map<String,Boolean> contextualParameters;
+
+ /**
+ * Creates a new context with all properties initialized to {@code null}.
+ */
+ public Context() {
+ contextualParameters = new HashMap<>();
+ }
+
+ /**
+ * Sets the source coordinate system to the given value.
+ * The source ellipsoid is unconditionally set to {@code null}.
+ *
+ * @param cs the coordinate system to set as the source (can be {@code null}).
+ */
+ public void setSource(final CoordinateSystem cs) {
+ sourceCS = cs;
+ sourceEllipsoid = null;
+ }
+
+ /**
+ * Sets the source coordinate system and related ellipsoid to the components of given CRS.
+ * The {@link Ellipsoid}, fetched from the geodetic datum, is often used together with an {@link EllipsoidalCS},
+ * but not necessarily. The geodetic CRS may also be associated with a spherical or Cartesian coordinate system,
+ * and the ellipsoid information may still be needed even with those non-ellipsoidal coordinate systems.
+ *
+ * <p><strong>This method is not for datum shifts.</strong>
+ * All datum information other than the ellipsoid are ignored.</p>
+ *
+ * @param crs the coordinate system and ellipsoid to set as the source, or {@code null}.
+ *
+ * @since 1.3
+ */
+ public void setSource(final GeodeticCRS crs) {
+ if (crs != null) {
+ sourceCS = crs.getCoordinateSystem();
+ sourceEllipsoid = crs.getDatum().getEllipsoid();
+ } else {
+ sourceCS = null;
+ sourceEllipsoid = null;
+ }
+ }
+
+ /**
+ * Sets the target coordinate system to the given value.
+ * The target ellipsoid is unconditionally set to {@code null}.
+ *
+ * @param cs the coordinate system to set as the target (can be {@code null}).
+ */
+ public void setTarget(final CoordinateSystem cs) {
+ targetCS = cs;
+ targetEllipsoid = null;
+ }
+
+ /**
+ * Sets the target coordinate system and related ellipsoid to the components of given CRS.
+ * The {@link Ellipsoid}, fetched from the geodetic datum, is often used together with an {@link EllipsoidalCS},
+ * but not necessarily. The geodetic CRS may also be associated with a spherical or Cartesian coordinate system,
+ * and the ellipsoid information may still be needed even with those non-ellipsoidal coordinate systems.
+ *
+ * <p><strong>This method is not for datum shifts.</strong>
+ * All datum information other than the ellipsoid are ignored.</p>
+ *
+ * @param crs the coordinate system and ellipsoid to set as the target, or {@code null}.
+ *
+ * @since 1.3
+ */
+ public void setTarget(final GeodeticCRS crs) {
+ if (crs != null) {
+ targetCS = crs.getCoordinateSystem();
+ targetEllipsoid = crs.getDatum().getEllipsoid();
+ } else {
+ targetCS = null;
+ targetEllipsoid = null;
+ }
+ }
+
+ /**
+ * Returns the source coordinate system, or {@code null} if unspecified.
+ *
+ * @return the source coordinate system, or {@code null}.
+ */
+ public CoordinateSystem getSourceCS() {
+ return sourceCS;
+ }
+
+ /**
+ * Returns the ellipsoid of the source ellipsoidal coordinate system, or {@code null} if it does not apply.
+ * This information is valid only if {@link #getSourceCS()} returns an instance of {@link EllipsoidalCS}.
+ *
+ * @return the ellipsoid of the source ellipsoidal coordinate system, or {@code null} if it does not apply.
+ */
+ public Ellipsoid getSourceEllipsoid() {
+ return sourceEllipsoid;
+ }
+
+ /**
+ * Returns the target coordinate system, or {@code null} if unspecified.
+ *
+ * @return the target coordinate system, or {@code null}.
+ */
+ public CoordinateSystem getTargetCS() {
+ return targetCS;
+ }
+
+ /**
+ * Returns the ellipsoid of the target ellipsoidal coordinate system, or {@code null} if it does not apply.
+ * This information is valid only if {@link #getTargetCS()} returns an instance of {@link EllipsoidalCS}.
+ *
+ * @return the ellipsoid of the target ellipsoidal coordinate system, or {@code null} if it does not apply.
+ */
+ public Ellipsoid getTargetEllipsoid() {
+ return targetEllipsoid;
+ }
+
+ /**
+ * Returns the matrix that represent the affine transform to concatenate before or after
+ * the parameterized transform. The {@code role} argument specifies which matrix is desired:
+ *
+ * <ul class="verbose">
+ * <li>{@link org.apache.sis.referencing.operation.transform.ContextualParameters.MatrixRole#NORMALIZATION
+ * NORMALIZATION} for the conversion from the {@linkplain #getSourceCS() source coordinate system} to
+ * a {@linkplain AxesConvention#NORMALIZED normalized} coordinate system, usually with
+ * (<var>longitude</var>, <var>latitude</var>) axis order in degrees or
+ * (<var>easting</var>, <var>northing</var>) in metres.
+ * This normalization needs to be applied <em>before</em> the parameterized transform.</li>
+ *
+ * <li>{@link org.apache.sis.referencing.operation.transform.ContextualParameters.MatrixRole#DENORMALIZATION
+ * DENORMALIZATION} for the conversion from a normalized coordinate system to the
+ * {@linkplain #getTargetCS() target coordinate system}, for example with
+ * (<var>latitude</var>, <var>longitude</var>) axis order.
+ * This denormalization needs to be applied <em>after</em> the parameterized transform.</li>
+ *
+ * <li>{@link org.apache.sis.referencing.operation.transform.ContextualParameters.MatrixRole#INVERSE_NORMALIZATION INVERSE_NORMALIZATION} and
+ * {@link org.apache.sis.referencing.operation.transform.ContextualParameters.MatrixRole#INVERSE_DENORMALIZATION INVERSE_DENORMALIZATION}
+ * are also supported but rarely used.</li>
+ * </ul>
+ *
+ * This method is invoked by {@link DefaultMathTransformFactory#swapAndScaleAxes(MathTransform, Context)}.
+ * Users an override this method if they need to customize the normalization process.
+ *
+ * @param role whether the normalization or denormalization matrix is desired.
+ * @return the requested matrix, or {@code null} if this {@code Context} has no information about the coordinate system.
+ * @throws FactoryException if an error occurred while computing the matrix.
+ *
+ * @see DefaultMathTransformFactory#createAffineTransform(Matrix)
+ * @see DefaultMathTransformFactory#createParameterizedTransform(ParameterValueGroup, Context)
+ */
+ @SuppressWarnings("fallthrough")
+ public Matrix getMatrix(final ContextualParameters.MatrixRole role) throws FactoryException {
+ final CoordinateSystem specified;
+ boolean inverse = false;
+ switch (role) {
+ default: throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "role", role));
+ case INVERSE_NORMALIZATION: inverse = true; // Fall through
+ case NORMALIZATION: specified = getSourceCS(); break;
+ case INVERSE_DENORMALIZATION: inverse = true; // Fall through
+ case DENORMALIZATION: inverse = !inverse;
+ specified = getTargetCS(); break;
+ }
+ if (specified == null) {
+ return null;
+ }
+ final CoordinateSystem normalized = CoordinateSystems.replaceAxes(specified, AxesConvention.NORMALIZED);
+ try {
+ if (inverse) {
+ return CoordinateSystems.swapAndScaleAxes(normalized, specified);
+ } else {
+ return CoordinateSystems.swapAndScaleAxes(specified, normalized);
+ }
+ } catch (IllegalArgumentException | IncommensurableException cause) {
+ throw new InvalidGeodeticParameterException(cause.getLocalizedMessage(), cause);
+ }
+ }
+
+ /**
+ * Returns the operation method used for the math transform creation.
+ * This is the same information than {@link #getLastMethodUsed()} but more stable
+ * (not affected by transforms created with other contexts).
+ *
+ * @return the operation method used by the factory.
+ * @throws IllegalStateException if {@link #createParameterizedTransform(ParameterValueGroup, Context)}
+ * has not yet been invoked.
+ *
+ * @see #getLastMethodUsed()
+ *
+ * @since 1.3
+ */
+ public OperationMethod getMethodUsed() {
+ if (provider != null) {
+ return provider;
+ }
+ throw new IllegalStateException(Resources.format(Resources.Keys.UnspecifiedParameterValues));
+ }
+
+ /**
+ * Returns the names of parameters that have been inferred from the context.
+ * The set of keys can contain any of {@code "dim"},
+ * {@code "semi_major"}, {@code "semi_minor"},
+ * {@code "src_semi_major"}, {@code "src_semi_minor"},
+ * {@code "tgt_semi_major"}, {@code "tgt_semi_minor"} and/or
+ * {@code "inverse_flattening"}, depending on the operation method used.
+ * The parameters named in that set are included in the parameters
+ * returned by {@link #getCompletedParameters()}.
+ *
+ * <h4>Associated boolean values</h4>
+ * The associated boolean in the map tells whether the named parameter value is really contextual.
+ * The boolean is {@code FALSE} if the user explicitly specified a value in the parameters given to
+ * the {@link #createParameterizedTransform(ParameterValueGroup, Context)} method,
+ * and that value is different than the value inferred from the context.
+ * Such inconsistencies are also logged at {@link Level#WARNING}.
+ * In all other cases
+ * (no value specified by the user, or a value was specified but is consistent with the context),
+ * the associated boolean in the map is {@code TRUE}.
+ *
+ * <h4>Mutability</h4>
+ * The returned map is modifiable for making easier for callers to amend the contextual information.
+ * This map is not used by {@code Context} except for information purposes (e.g. in {@link #toString()}).
+ * In particular, modifications of this map have no incidence on the created {@link MathTransform}.
+ *
+ * @return names of parameters inferred from context.
+ *
+ * @since 1.3
+ */
+ @SuppressWarnings("ReturnOfCollectionOrArrayField") // Modifiable by method contract.
+ public Map<String,Boolean> getContextualParameters() {
+ return contextualParameters;
+ }
+
+ /**
+ * Returns the parameter values used for the math transform creation,
+ * including the parameters completed by the factory.
+ * The parameters inferred from the context are listed by {@link #getContextualParameters()}.
+ *
+ * @return the parameter values used by the factory.
+ * @throws IllegalStateException if {@link #createParameterizedTransform(ParameterValueGroup, Context)}
+ * has not yet been invoked.
+ */
+ public ParameterValueGroup getCompletedParameters() {
+ if (parameters != null) {
+ return parameters;
+ }
+ throw new IllegalStateException(Resources.format(Resources.Keys.UnspecifiedParameterValues));
+ }
+
+ /**
+ * If the parameters given by the user were not created by {@code getDefaultParameters(String)}
+ * or something equivalent, copies those parameters into the structure expected by the provider.
+ * The intent is to make sure that we have room for the parameters that {@code setEllipsoids(…)}
+ * may write.
+ *
+ * <p>A side effect of this method is that the copy operation may perform a check of
+ * parameter value validity. This may result in an {@link InvalidParameterNameException}
+ * or {@link InvalidParameterValueException} to be thrown.</p>
+ *
+ * @param writable {@code true} if this method should also check that the parameters group is editable.
+ * @throws IllegalArgumentException if the copy cannot be performed because a parameter has
+ * a unrecognized name or an illegal value.
+ */
+ private void ensureCompatibleParameters(final boolean writable) throws IllegalArgumentException {
+ final ParameterDescriptorGroup expected = provider.getParameters();
+ if (parameters.getDescriptor() != expected || (writable && Parameters.isUnmodifiable(parameters))) {
+ final ParameterValueGroup copy = expected.createValue();
+ Parameters.copy(parameters, copy);
+ parameters = copy;
+ }
+ }
+
+ /**
+ * Gets a parameter for which to infer a value from the context.
+ * The consistency flag is initially set to {@link Boolean#TRUE}.
+ *
+ * @param name name of the contextual parameter.
+ * @return the parameter.
+ * @throws ParameterNotFoundException if the parameter was not found.
+ */
+ private ParameterValue<?> getContextualParameter(final String name) throws ParameterNotFoundException {
+ ParameterValue<?> parameter = parameters.parameter(name);
+ contextualParameters.put(name, Boolean.TRUE); // Add only if above line succeeded.
+ return parameter;
+ }
+
+ /**
+ * Returns the value of the given parameter in the given unit, or {@code NaN} if the parameter is not set.
+ *
+ * <p><b>NOTE:</b> Do not merge this function with {@code ensureSet(…)}. We keep those two methods
+ * separated in order to give to {@code createParameterizedTransform(…)} a "all or nothing" behavior.</p>
+ */
+ private static double getValue(final ParameterValue<?> parameter, final Unit<?> unit) {
+ return (parameter.getValue() != null) ? parameter.doubleValue(unit) : Double.NaN;
+ }
+
+ /**
+ * Ensures that a value is set in the given parameter.
+ *
+ * <ul>
+ * <li>If the parameter has no value, then it is set to the given value.<li>
+ * <li>If the parameter already has a value, then the parameter is left unchanged
+ * but its value is compared to the given one for consistency.</li>
+ * </ul>
+ *
+ * @param parameter the parameter which must have a value.
+ * @param actual the current parameter value, or {@code NaN} if none.
+ * @param expected the expected parameter value, derived from the ellipsoid.
+ * @param unit the unit of {@code value}.
+ * @param tolerance maximal difference (in unit of {@code unit}) for considering the two values as equivalent.
+ * @return {@code true} if there is a mismatch between the actual value and the expected one.
+ */
+ private static boolean ensureSet(final ParameterValue<?> parameter, final double actual,
+ final double expected, final Unit<?> unit, final double tolerance)
+ {
+ if (Math.abs(actual - expected) <= tolerance) {
+ return false;
+ }
+ if (Double.isNaN(actual)) {
+ parameter.setValue(expected, unit);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Completes the parameter group with information about source or target ellipsoid axis lengths,
+ * if available. This method writes semi-major and semi-minor parameter values only if they do not
+ * already exists in the given parameters.
+ *
+ * @param ellipsoid the ellipsoid from which to get axis lengths of flattening factor, or {@code null}.
+ * @param semiMajor {@code "semi_major}, {@code "src_semi_major} or {@code "tgt_semi_major} parameter name.
+ * @param semiMinor {@code "semi_minor}, {@code "src_semi_minor} or {@code "tgt_semi_minor} parameter name.
+ * @param inverseFlattening {@code true} if this method can try to set the {@code "inverse_flattening"} parameter.
+ * @return the exception if the operation failed, or {@code null} if none. This exception is not thrown now
+ * because the caller may succeed in creating the transform anyway, or otherwise may produce a more
+ * informative exception.
+ */
+ private RuntimeException setEllipsoid(final Ellipsoid ellipsoid, final String semiMajor, final String semiMinor,
+ final boolean inverseFlattening, RuntimeException failure)
+ {
+ /*
+ * Note: we could also consider to set the "dim" parameter here based on the number of dimensions
+ * of the coordinate system. But except for the Molodensky operation, this would be SIS-specific.
+ * A more portable way is to concatenate a "Geographic 3D to 2D" operation after the transform if
+ * we see that the dimensions do not match. It also avoid attempt to set a "dim" parameter on map
+ * projections, which is not allowed.
+ */
+ if (ellipsoid != null) {
+ ensureCompatibleParameters(true);
+ ParameterValue<?> mismatchedParam = null;
+ double mismatchedValue = 0;
+ try {
+ final ParameterValue<?> ap = getContextualParameter(semiMajor);
+ final ParameterValue<?> bp = getContextualParameter(semiMinor);
+ final Unit<Length> unit = ellipsoid.getAxisUnit();
+ /*
+ * The two calls to getValue(…) shall succeed before we write anything, in order to have a
+ * "all or nothing" behavior as much as possible. Note that Ellipsoid.getSemi**Axis() have
+ * no reason to fail, so we do not take precaution for them.
+ */
+ final double a = getValue(ap, unit);
+ final double b = getValue(bp, unit);
+ final double tol = Units.METRE.getConverterTo(unit).convert(ELLIPSOID_PRECISION);
+ if (ensureSet(ap, a, ellipsoid.getSemiMajorAxis(), unit, tol)) {
+ contextualParameters.put(semiMajor, Boolean.FALSE);
+ mismatchedParam = ap;
+ mismatchedValue = a;
+ }
+ if (ensureSet(bp, b, ellipsoid.getSemiMinorAxis(), unit, tol)) {
+ contextualParameters.put(semiMinor, Boolean.FALSE);
+ mismatchedParam = bp;
+ mismatchedValue = b;
+ }
+ } catch (IllegalArgumentException | IllegalStateException e) {
+ /*
+ * Parameter not found, or is not numeric, or unit of measurement is not linear.
+ * Do not touch to the parameters. We will see if createParameterizedTransform(…)
+ * can do something about that. If it cannot, createParameterizedTransform(…) is
+ * the right place to throw the exception.
+ */
+ if (failure == null) {
+ failure = e;
+ } else {
+ failure.addSuppressed(e);
+ }
+ }
+ /*
+ * Following is specific to Apache SIS. We use this non-standard API for allowing the
+ * NormalizedProjection class (our base class for all map projection implementations)
+ * to known that the ellipsoid definitive parameter is the inverse flattening factor
+ * instead of the semi-major axis length. It makes a small difference in the accuracy
+ * of the eccentricity parameter.
+ */
+ if (mismatchedParam == null && inverseFlattening && ellipsoid.isIvfDefinitive()) try {
+ final ParameterValue<?> ep = getContextualParameter(Constants.INVERSE_FLATTENING);
+ final double e = getValue(ep, Units.UNITY);
+ if (ensureSet(ep, e, ellipsoid.getInverseFlattening(), Units.UNITY, 1E-10)) {
+ contextualParameters.put(Constants.INVERSE_FLATTENING, Boolean.FALSE);
+ mismatchedParam = ep;
+ mismatchedValue = e;
+ }
+ } catch (ParameterNotFoundException e) {
+ /*
+ * Should never happen with Apache SIS implementation, but may happen if the given parameters come
+ * from another implementation. We can safely abandon our attempt to set the inverse flattening value,
+ * since it was redundant with semi-minor axis length.
+ */
+ Logging.recoverableException(AbstractMathTransform.LOGGER,
+ DefaultMathTransformFactory.class, "createParameterizedTransform", e);
+ }
+ /*
+ * If a parameter was explicitly specified by user but has a value inconsistent with the context,
+ * log a warning. In addition, the associated boolean value in `contextualParameters` map should
+ * have been set to `Boolean.FALSE`.
+ */
+ if (mismatchedParam != null) {
+ final LogRecord record = Resources.forLocale(null).getLogRecord(Level.WARNING,
+ Resources.Keys.MismatchedEllipsoidAxisLength_3, ellipsoid.getName().getCode(),
+ mismatchedParam.getDescriptor().getName().getCode(), mismatchedValue);
+ Logging.completeAndLog(AbstractMathTransform.LOGGER,
+ DefaultMathTransformFactory.class, "createParameterizedTransform", record);
+ }
+ }
+ return failure;
+ }
+
+ /**
+ * Completes the parameter group with information about source and target ellipsoid axis lengths,
+ * if available. This method writes semi-major and semi-minor parameter values only if they do not
+ * already exists in the given parameters.
+ *
+ * <p>The given method and parameters are stored in the {@link #provider} and {@link #parameters}
+ * fields respectively. The actual stored values may differ from the values given to this method.</p>
+ *
+ * @param factory the enclosing factory.
+ * @param method description of the transform to be created, or {@code null} if unknown.
+ * @return the exception if the operation failed, or {@code null} if none. This exception is not thrown now
+ * because the caller may succeed in creating the transform anyway, or otherwise may produce a more
+ * informative exception.
+ * @throws IllegalArgumentException if the operation fails because a parameter has a unrecognized name or an
+ * illegal value.
+ *
+ * @see #getCompletedParameters()
+ */
+ final RuntimeException completeParameters(final DefaultMathTransformFactory factory, OperationMethod method,
+ final ParameterValueGroup userParams) throws FactoryException, IllegalArgumentException
+ {
+ /*
+ * The "Geographic/geocentric conversions" conversion (EPSG:9602) can be either:
+ *
+ * - "Ellipsoid_To_Geocentric"
+ * - "Geocentric_To_Ellipsoid"
+ *
+ * EPSG defines both by a single operation, but Apache SIS needs to distinguish them.
+ */
+ if (method instanceof AbstractProvider) {
+ final String alt = ((AbstractProvider) method).resolveAmbiguity(this);
+ if (alt != null) {
+ method = factory.getOperationMethod(alt);
+ }
+ }
+ provider = method;
+ parameters = userParams;
+ /*
+ * Get the operation method for the appropriate number of dimensions. For example, the default Molodensky
+ * operation expects two-dimensional source and target CRS. If a given CRS is three-dimensional, we need
+ * a provider variant which will not concatenate a "geographic 3D to 2D" operation before the Molodensky
+ * one.
+ */
+ if (method instanceof AbstractProvider) {
+ @SuppressWarnings("deprecation")
+ final Integer sourceDim = (sourceCS != null) ? sourceCS.getDimension() : method.getSourceDimensions();
+ @SuppressWarnings("deprecation")
+ final Integer targetDim = (targetCS != null) ? targetCS.getDimension() : method.getTargetDimensions();
+ if (sourceDim != null && targetDim != null) {
+ method = ((AbstractProvider) method).redimension(sourceDim, targetDim);
+ if (method instanceof MathTransformProvider) {
+ provider = method;
+ }
+ }
+ }
+ ensureCompatibleParameters(false); // Invoke only after we set `provider` to its final instance.
+ /*
+ * Get a mask telling us if we need to set parameters for the source and/or target ellipsoid.
+ * This information should preferably be given by the provider. But if the given provider is
+ * not a SIS implementation, use as a fallback whether ellipsoids are provided. This fallback
+ * may be less reliable.
+ */
+ final boolean sourceOnEllipsoid, targetOnEllipsoid;
+ if (provider instanceof AbstractProvider) {
+ final AbstractProvider p = (AbstractProvider) provider;
+ sourceOnEllipsoid = p.sourceOnEllipsoid;
+ targetOnEllipsoid = p.targetOnEllipsoid;
+ } else {
+ sourceOnEllipsoid = getSourceEllipsoid() != null;
+ targetOnEllipsoid = getTargetEllipsoid() != null;
+ }
+ /*
+ * Set the ellipsoid axis-length parameter values. Those parameters may appear in the source ellipsoid,
+ * in the target ellipsoid or in both ellipsoids.
+ */
+ if (!(sourceOnEllipsoid | targetOnEllipsoid)) return null;
+ if (!targetOnEllipsoid) return setEllipsoid(getSourceEllipsoid(), Constants.SEMI_MAJOR, Constants.SEMI_MINOR, true, null);
+ if (!sourceOnEllipsoid) return setEllipsoid(getTargetEllipsoid(), Constants.SEMI_MAJOR, Constants.SEMI_MINOR, true, null);
+ RuntimeException failure = null;
+ if (sourceCS != null) try {
+ ensureCompatibleParameters(true);
+ final ParameterValue<?> p = getContextualParameter(Constants.DIM);
+ if (p.getValue() == null) {
+ p.setValue(sourceCS.getDimension());
+ }
+ } catch (IllegalArgumentException | IllegalStateException e) {
+ failure = e;
+ }
+ failure = setEllipsoid(getSourceEllipsoid(), "src_semi_major", "src_semi_minor", false, failure);
+ failure = setEllipsoid(getTargetEllipsoid(), "tgt_semi_major", "tgt_semi_minor", false, failure);
+ return failure;
+ }
+
+ /**
+ * Returns a string representation of this context for debugging purposes.
+ * Current implementation write the name of source/target coordinate systems and ellipsoids.
+ * If {@linkplain #getContextualParameters() contextual parameters} have already been inferred,
+ * then their names are appended with inconsistent parameters (if any) written on a separated line.
+ *
+ * @return a string representation of this context.
+ */
+ @Override
+ public String toString() {
+ final Object[] properties = {
+ "sourceCS", sourceCS, "sourceEllipsoid", sourceEllipsoid,
+ "targetCS", targetCS, "targetEllipsoid", targetEllipsoid
+ };
+ for (int i=1; i<properties.length; i += 2) {
+ final IdentifiedObject value = (IdentifiedObject) properties[i];
+ if (value != null) properties[i] = value.getName();
+ }
+ String text = Strings.toString(getClass(), properties);
+ if (!contextualParameters.isEmpty()) {
+ final StringBuilder b = new StringBuilder(text);
+ boolean isContextual = true;
+ do {
+ boolean first = true;
+ for (final Map.Entry<String,Boolean> entry : contextualParameters.entrySet()) {
+ if (entry.getValue() == isContextual) {
+ if (first) {
+ first = false;
+ b.append(System.lineSeparator())
+ .append(isContextual ? "Contextual parameters" : "Inconsistencies").append(": ");
+ } else {
+ b.append(", ");
+ }
+ b.append(entry.getKey());
+ }
+ }
+ } while ((isContextual = !isContextual) == false);
+ text = b.toString();
+ }
+ return text;
+ }
+ }
+
+ /**
+ * Creates a transform from a group of parameters.
+ * The set of expected parameters varies for each operation.
+ * The easiest way to provide parameter values is to get an initially empty group for the desired
+ * operation by calling {@link #getDefaultParameters(String)}, then to fill the parameter values.
+ * Example:
+ *
+ * {@snippet lang="java" :
+ * ParameterValueGroup group = factory.getDefaultParameters("Transverse_Mercator");
+ * group.parameter("semi_major").setValue(6378137.000);
+ * group.parameter("semi_minor").setValue(6356752.314);
+ * MathTransform mt = factory.createParameterizedTransform(group, null);
+ * }
+ *
+ * Sometimes the {@code "semi_major"} and {@code "semi_minor"} parameter values are not explicitly provided,
+ * but rather inferred from the {@linkplain org.apache.sis.referencing.datum.DefaultGeodeticDatum geodetic
+ * datum} of the source Coordinate Reference System. If the given {@code context} argument is non-null,
+ * then this method will use those contextual information for:
+ *
+ * <ol>
+ * <li>Inferring the {@code "semi_major"}, {@code "semi_minor"}, {@code "src_semi_major"},
+ * {@code "src_semi_minor"}, {@code "tgt_semi_major"} or {@code "tgt_semi_minor"} parameter values
+ * from the {@linkplain org.apache.sis.referencing.datum.DefaultEllipsoid ellipsoids} associated to
+ * the source or target CRS, if those parameters are not explicitly given and if they are relevant
+ * for the coordinate operation method.</li>
+ * <li>{@linkplain #createConcatenatedTransform Concatenating} the parameterized transform
+ * with any other transforms required for performing units changes and coordinates swapping.</li>
+ * </ol>
+ *
+ * The complete group of parameters, including {@code "semi_major"}, {@code "semi_minor"} or other calculated values,
+ * can be obtained by a call to {@link Context#getCompletedParameters()} after {@code createParameterizedTransform(…)}
+ * returned. Note that the completed parameters may only have additional parameters compared to the given parameter
+ * group; existing parameter values should not be modified.
+ *
+ * <p>The {@code OperationMethod} instance used by this constructor can be obtained by a call to
+ * {@link #getLastMethodUsed()}.</p>
+ *
+ * @param parameters the parameter values. The {@linkplain ParameterDescriptorGroup#getName() parameter group name}
+ * shall be the name of the desired {@linkplain DefaultOperationMethod operation method}.
+ * @param context information about the context (for example source and target coordinate systems)
+ * in which the new transform is going to be used, or {@code null} if none.
+ * @return the transform created from the given parameters.
+ * @throws NoSuchIdentifierException if there is no method for the given parameter group name.
+ * @throws FactoryException if the object creation failed. This exception is thrown
+ * if some required parameter has not been supplied, or has illegal value.
+ *
+ * @see #getDefaultParameters(String)
+ * @see #getAvailableMethods(Class)
+ * @see #getLastMethodUsed()
+ * @see org.apache.sis.parameter.ParameterBuilder#createGroupForMapProjection(ParameterDescriptor...)
+ */
+ public MathTransform createParameterizedTransform(ParameterValueGroup parameters,
+ final Context context) throws NoSuchIdentifierException, FactoryException
+ {
+ OperationMethod method = null;
+ RuntimeException failure = null;
+ MathTransform transform;
+ try {
+ ArgumentChecks.ensureNonNull("parameters", parameters);
+ final ParameterDescriptorGroup descriptor = parameters.getDescriptor();
+ final String methodName = descriptor.getName().getCode();
+ String methodIdentifier = IdentifiedObjects.toString(IdentifiedObjects.getIdentifier(descriptor, Citations.EPSG));
+ if (methodIdentifier == null) {
+ methodIdentifier = methodName;
+ }
+ /*
+ * Get the MathTransformProvider of the same name or identifier than the given parameter group.
+ * We give precedence to EPSG identifier because operation method names are sometimes ambiguous
+ * (e.g. "Lambert Azimuthal Equal Area (Spherical)"). If we fail to find the method by its EPSG code,
+ * we will try searching by method name. As a side effect, this second attempt will produce a better
+ * error message if the method is really not found.
+ */
+ try {
+ method = getOperationMethod(methodIdentifier);
+ } catch (NoSuchIdentifierException exception) {
+ if (methodIdentifier.equals(methodName)) {
+ throw exception;
+ }
+ method = getOperationMethod(methodName);
+ Logging.recoverableException(AbstractMathTransform.LOGGER,
+ DefaultMathTransformFactory.class, "createParameterizedTransform", exception);
+ }
+ if (!(method instanceof MathTransformProvider)) {
+ throw new NoSuchIdentifierException(Errors.format( // For now, handle like an unknown operation.
+ Errors.Keys.UnsupportedImplementation_1, Classes.getClass(method)), methodName);
+ }
+ /*
+ * Will catch only exceptions that may be the result of improper parameter usage (e.g. a value out
+ * of range). Do not catch exceptions caused by programming errors (e.g. null pointer exception).
+ */
+ try {
+ /*
+ * If the user's parameters do not contain semi-major and semi-minor axis lengths, infer
+ * them from the ellipsoid. We have to do that because those parameters are often omitted,
+ * since the standard place where to provide this information is in the ellipsoid object.
+ */
+ if (context != null) {
+ failure = context.completeParameters(this, method, parameters);
+ parameters = context.parameters;
+ method = context.provider;
+ }
+ transform = ((MathTransformProvider) method).createMathTransform(this, parameters);
+ } catch (IllegalArgumentException | IllegalStateException exception) {
+ throw new InvalidGeodeticParameterException(exception.getLocalizedMessage(), exception);
+ }
+ /*
+ * Cache the transform that we just created and make sure that the number of dimensions
+ * is compatible with the OperationMethod instance. Then make final adjustment for axis
+ * directions and units of measurement.
+ */
+ transform = unique(transform);
+ if (method instanceof AbstractProvider) {
+ method = ((AbstractProvider) method).variantFor(transform);
+ }
+ if (context != null) {
+ transform = swapAndScaleAxes(transform, context);
+ }
+ } catch (FactoryException e) {
+ if (failure != null) {
+ e.addSuppressed(failure);
+ }
+ throw e;
+ } finally {
+ lastMethod.set(method); // May be null in case of failure, which is intended.
+ }
+ return transform;
+ }
+
+ /**
+ * Given a transform between normalized spaces,
+ * creates a transform taking in account axis directions, units of measurement and longitude rotation.
+ * This method {@linkplain #createConcatenatedTransform concatenates} the given parameterized transform
+ * with any other transform required for performing units changes and coordinates swapping.
+ *
+ * <p>The given {@code parameterized} transform shall expect
+ * {@linkplain org.apache.sis.referencing.cs.AxesConvention#NORMALIZED normalized} input coordinates and
+ * produce normalized output coordinates. See {@link org.apache.sis.referencing.cs.AxesConvention} for more
+ * information about what Apache SIS means by "normalized".</p>
+ *
+ * <h4>Example</h4>
+ * The most typical examples of transforms with normalized inputs/outputs are normalized
+ * map projections expecting (<cite>longitude</cite>, <cite>latitude</cite>) inputs in degrees
+ * and calculating (<cite>x</cite>, <cite>y</cite>) coordinates in metres,
+ * both of them with ({@linkplain org.opengis.referencing.cs.AxisDirection#EAST East},
+ * {@linkplain org.opengis.referencing.cs.AxisDirection#NORTH North}) axis orientations.
+ *
+ * <h4>Controlling the normalization process</h4>
+ * Users who need a different normalized space than the default one way find more convenient to
+ * override the {@link Context#getMatrix Context.getMatrix(ContextualParameters.MatrixRole)} method.
+ *
+ * @param parameterized a transform for normalized input and output coordinates.
+ * @param context source and target coordinate systems in which the transform is going to be used.
+ * @return a transform taking in account unit conversions and axis swapping.
+ * @throws FactoryException if the object creation failed.
+ *
+ * @see org.apache.sis.referencing.cs.AxesConvention#NORMALIZED
+ * @see org.apache.sis.referencing.operation.DefaultConversion#DefaultConversion(Map, OperationMethod, MathTransform, ParameterValueGroup)
+ *
+ * @since 0.7
+ */
+ public MathTransform swapAndScaleAxes(final MathTransform parameterized, final Context context) throws FactoryException {
+ ArgumentChecks.ensureNonNull("parameterized", parameterized);
+ ArgumentChecks.ensureNonNull("context", context);
+ /*
+ * Compute matrices for swapping axis and performing units conversion.
+ * There is one matrix to apply before projection from (λ,φ) coordinates,
+ * and one matrix to apply after projection on (easting,northing) coordinates.
+ */
+ final Matrix swap1 = context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION);
+ final Matrix swap3 = context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION);
+ /*
+ * Prepare the concatenation of the matrices computed above and the projection.
+ * Note that at this stage, the dimensions between each step may not be compatible.
+ * For example, the projection (step2) is usually two-dimensional while the source
+ * coordinate system (step1) may be three-dimensional if it has a height.
+ */
+ MathTransform step1 = (swap1 != null) ? createAffineTransform(swap1) : MathTransforms.identity(parameterized.getSourceDimensions());
+ MathTransform step3 = (swap3 != null) ? createAffineTransform(swap3) : MathTransforms.identity(parameterized.getTargetDimensions());
+ MathTransform step2 = parameterized;
+ /*
+ * Special case for the way EPSG handles reversal of axis direction. For now the "Vertical Offset" (EPSG:9616)
+ * method is the only one for which we found a need for special case. But if more special cases are added in a
+ * future SIS version, then we should replace the static method by a non-static one defined in AbstractProvider.
+ */
+ if (context.provider instanceof VerticalOffset) {
+ step2 = VerticalOffset.postCreate(step2, swap3);
+ }
+ /*
+ * If the target coordinate system has a height, instruct the projection to pass the height unchanged from
+ * the base CRS to the target CRS. After this block, the dimensions of `step2` and `step3` should match.
+ *
+ * The height is always the last dimension in a normalized EllipdoidalCS. We accept only a hard-coded list
+ * of dimensions because it is not `MathTransformFactory` job to build a transform chain in a generic way.
+ * We handle only the cases that are necessary because of the way some operation methods are provided.
+ * In particular Apache SIS provides only 2D map projections, so 3D projections have to be "generated"
+ * on the fly. That use case is:
+ *
+ * - Source CRS: a GeographicCRS (regardless its number of dimension – it will be addressed in next block)
+ * - Target CRS: a 3D ProjectedCRS
+ * - Parameterized transform: a 2D map projection. We need the ellipsoidal height to passthrough.
+ *
+ * The reverse order (projected source CRS and geographic target CRS) is also accepted but should be uncommon.
+ */
+ final int resultDim = step3.getSourceDimensions(); // Final result (minus trivial changes).
+ final int kernelDim = step2.getTargetDimensions(); // Result of the core part of transform.
+ final int numTrailingCoordinates = resultDim - kernelDim;
+ if (numTrailingCoordinates != 0) {
+ ensureDimensionChangeAllowed(parameterized, context, numTrailingCoordinates, resultDim);
+ if (numTrailingCoordinates > 0) {
+ step2 = createPassThroughTransform(0, step2, numTrailingCoordinates);
+ } else {
+ step2 = createConcatenatedTransform(step2, createAffineTransform(
+ Matrices.createDimensionSelect(kernelDim, ArraysExt.range(0, resultDim))));
+ }
+ }
+ /*
+ * If the source CS has a height but the target CS doesn't, drops the extra coordinates.
+ * Conversely if the source CS is missing a height, add a height with NaN values.
+ * After this block, the dimensions of `step1` and `step2` should match.
+ *
+ * When adding an ellipsoidal height, there is two scenarios: the ellipsoidal height may be used by the
+ * parameterized operation, or it may be passed through (in which case the operation ignores the height).
+ * If the height is expected as operation input, set the height to 0. Otherwise (the pass through case),
+ * set the height to NaN. We do that way because the given `parameterized` transform may be a Molodensky
+ * transform or anything else that could use the height in its calculation. If we have to add a height as
+ * a pass through dimension, maybe the parameterized transform is a 2D Molodensky instead of a 3D Molodensky.
+ * The result of passing through the height is not the same as if a 3D Molodensky was used in the first place.
+ * A NaN value avoid to give a false sense of accuracy.
+ */
+ final int sourceDim = step1.getTargetDimensions();
+ final int targetDim = step2.getSourceDimensions();
+ int insertCount = targetDim - sourceDim;
+ if (insertCount != 0) {
+ ensureDimensionChangeAllowed(parameterized, context, insertCount, targetDim);
+ final Matrix resize = Matrices.createZero(targetDim+1, sourceDim+1);
+ for (int j=0; j<targetDim; j++) {
+ resize.setElement(j, Math.min(j, sourceDim), (j < sourceDim) ? 1 :
+ ((--insertCount >= numTrailingCoordinates) ? 0 : Double.NaN)); // See above note.
+ }
+ resize.setElement(targetDim, sourceDim, 1); // Element in the lower-right corner.
+ step1 = createConcatenatedTransform(step1, createAffineTransform(resize));
+ }
+ MathTransform mt = createConcatenatedTransform(createConcatenatedTransform(step1, step2), step3);
+ /*
+ * At this point we finished to create the transform. But before to return it, verify if the
+ * parameterized transform given in argument had some custom parameters. This happen with the
+ * Equirectangular projection, which can be simplified as an AffineTransform while we want to
+ * continue to describe it with the "semi_major", "semi_minor", etc. parameters instead of
+ * "elt_0_0", "elt_0_1", etc. The following code just forwards those parameters to the newly
+ * created transform; it does not change the operation.
+ */
+ if (parameterized instanceof ParameterizedAffine && !(mt instanceof ParameterizedAffine)) {
+ mt = ((ParameterizedAffine) parameterized).newTransform(mt);
+ }
+ return mt;
+ }
+
+ /**
+ * Checks whether {@link #swapAndScaleAxes(MathTransform, Context)} should accept to adjust the number of
+ * transform dimensions. Current implementation accepts only addition or removal of ellipsoidal height,
+ * but future version may expand the list of accepted cases. The intent for this method is to catch errors
+ * caused by wrong coordinate systems associated to a parameterized transform, keeping in mind that it is
+ * not {@link DefaultMathTransformFactory} job to handle changes between arbitrary CRS (those changes are
+ * handled by {@link org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory} instead).
+ *
+ * <h4>Implementation note</h4>
+ * The {@code parameterized} transform is a black box receiving inputs in
+ * any CS and producing outputs in any CS, not necessarily of the same kind. For that reason, we cannot use
+ * {@link CoordinateSystems#swapAndScaleAxes(CoordinateSystem, CoordinateSystem)} between the normalized CS.
+ * We have to trust that the caller know that the coordinate systems (s)he provided are correct for the work
+ * done by the transform.
+ *
+ * @param parameterized the parameterized transform, for producing an error message if needed.
+ * @param context the source and target coordinate system.
+ * @param change number of dimensions to add (if positive) or remove (if negative).
+ * @param resultDim number of dimensions after the change.
+ */
+ private static void ensureDimensionChangeAllowed(final MathTransform parameterized,
+ final Context context, final int change, final int resultDim) throws FactoryException
+ {
+ if (Math.abs(change) == 1 && resultDim >= 2 && resultDim <= 3) {
+ if (context.getSourceCS() instanceof EllipsoidalCS ||
+ context.getTargetCS() instanceof EllipsoidalCS)
+ {
+ return;
+ }
+ }
+ /*
+ * Creates the error message for a transform that cannot be associated with given coordinate systems.
+ */
+ String name = null;
+ if (parameterized instanceof Parameterized) {
+ name = IdentifiedObjects.getDisplayName(((Parameterized) parameterized).getParameterDescriptors(), null);
+ }
+ if (name == null) {
+ name = Classes.getShortClassName(parameterized);
+ }
+ final StringBuilder b = new StringBuilder();
+ CoordinateSystem cs = context.getSourceCS();
+ if (cs != null) b.append(cs.getDimension()).append("D → ");
+ b.append("tr(").append(parameterized.getSourceDimensions()).append("D → ")
+ .append(parameterized.getTargetDimensions()).append("D)");
+ cs = context.getTargetCS();
+ if (cs != null) b.append(" → ").append(cs.getDimension()).append('D');
+ throw new InvalidGeodeticParameterException(Resources.format(Resources.Keys.CanNotAssociateToCS_2, name, b));
+ }
+
+ /**
+ * Creates a transform from a base CRS to a derived CS using the given parameters.
+ * If this method needs to set the values of {@code "semi_major"} and {@code "semi_minor"} parameters,
+ * then it sets those values directly on the given {@code parameters} instance – not on a clone – for
+ * allowing the caller to get back the complete parameter values.
+ * However, this method only fills missing values, it never modify existing values.
+ *
+ * @param baseCRS the source coordinate reference system.
+ * @param parameters the parameter values for the transform.
+ * @param derivedCS the target coordinate system.
+ * @return the parameterized transform from {@code baseCRS} to {@code derivedCS},
+ * including unit conversions and axis swapping.
+ * @throws NoSuchIdentifierException if there is no transform registered for the coordinate operation method.
+ * @throws FactoryException if the object creation failed. This exception is thrown
+ * if some required parameter has not been supplied, or has illegal value.
+ *
+ * @deprecated Replaced by {@link #createParameterizedTransform(ParameterValueGroup, Context)}.
+ */
+ @Override
+ @Deprecated(since="0.7")
+ public MathTransform createBaseToDerived(final CoordinateReferenceSystem baseCRS,
+ final ParameterValueGroup parameters, final CoordinateSystem derivedCS)
+ throws NoSuchIdentifierException, FactoryException
+ {
+ ArgumentChecks.ensureNonNull("baseCRS", baseCRS);
+ ArgumentChecks.ensureNonNull("parameters", parameters);
+ ArgumentChecks.ensureNonNull("derivedCS", derivedCS);
+ final Context context = ReferencingUtilities.createTransformContext(baseCRS, null);
+ context.setTarget(derivedCS);
+ return createParameterizedTransform(parameters, context);
+ }
+
+ /**
+ * Creates a math transform that represent a change of coordinate system. If exactly one argument is
+ * an {@linkplain org.apache.sis.referencing.cs.DefaultEllipsoidalCS ellipsoidal coordinate systems},
+ * then the {@code ellipsoid} argument is mandatory. In all other cases (including the case where both
+ * coordinate systems are ellipsoidal), the ellipsoid argument is ignored and can be {@code null}.
+ *
+ * <h4>Design note</h4>
+ * This method does not accept separated ellipsoid arguments for {@code source} and {@code target} because
+ * this method should not be used for datum shifts. If the two given coordinate systems are ellipsoidal,
+ * then they are assumed to use the same ellipsoid. If different ellipsoids are desired, then a
+ * {@linkplain #createParameterizedTransform parameterized transform} like <cite>"Molodensky"</cite>,
+ * <cite>"Geocentric translations"</cite>, <cite>"Coordinate Frame Rotation"</cite> or
+ * <cite>"Position Vector transformation"</cite> should be used instead.
+ *
+ * @param source the source coordinate system.
+ * @param target the target coordinate system.
+ * @param ellipsoid the ellipsoid of {@code EllipsoidalCS}, or {@code null} if none.
+ * @return a conversion from the given source to the given target coordinate system.
+ * @throws FactoryException if the conversion cannot be created.
+ *
+ * @since 0.8
+ */
+ public MathTransform createCoordinateSystemChange(final CoordinateSystem source, final CoordinateSystem target,
+ final Ellipsoid ellipsoid) throws FactoryException
+ {
+ ArgumentChecks.ensureNonNull("source", source);
+ ArgumentChecks.ensureNonNull("target", target);
+ lastMethod.remove(); // In case an exception is thrown before completion.
+ if (ellipsoid != null) {
+ final boolean isEllipsoidalSource = (source instanceof EllipsoidalCS);
+ if (isEllipsoidalSource != (target instanceof EllipsoidalCS)) {
+ /*
+ * For now we support only conversion between EllipsoidalCS and CartesianCS.
+ * But future Apache SIS versions could add support for conversions between
+ * EllipsoidalCS and SphericalCS or other coordinate systems.
+ */
+ if ((isEllipsoidalSource ? target : source) instanceof CartesianCS) {
+ final Context context = new Context();
+ final EllipsoidalCS cs;
+ final String operation;
+ if (isEllipsoidalSource) {
+ operation = GeographicToGeocentric.NAME;
+ context.setSource(cs = (EllipsoidalCS) source);
+ context.setTarget(target);
+ context.sourceEllipsoid = ellipsoid;
+ } else {
+ operation = GeocentricToGeographic.NAME;
+ context.setSource(source);
+ context.setTarget(cs = (EllipsoidalCS) target);
+ context.targetEllipsoid = ellipsoid;
+ }
+ final ParameterValueGroup pg = getDefaultParameters(operation);
+ if (cs.getDimension() < 3) {
+ pg.parameter(Constants.DIM).setValue(2); // Apache SIS specific parameter.
+ }
+ return createParameterizedTransform(pg, context);
+ }
+ }
+ }
+ return CoordinateSystemTransform.create(this, source, target, lastMethod);
+ // No need to use unique(…) here.
+ }
+
+ /**
+ * Creates an affine transform from a matrix. If the transform input dimension is {@code M},
+ * and output dimension is {@code N}, then the matrix will have size {@code [N+1][M+1]}. The
+ * +1 in the matrix dimensions allows the matrix to do a shift, as well as a rotation. The
+ * {@code [M][j]} element of the matrix will be the j'th coordinate of the moved origin. The
+ * {@code [i][N]} element of the matrix will be 0 for <var>i</var> less than {@code M}, and 1
+ * for <var>i</var> equals {@code M}.
+ *
+ * @param matrix the matrix used to define the affine transform.
+ * @return the affine transform.
+ * @throws FactoryException if the object creation failed.
+ *
+ * @see MathTransforms#linear(Matrix)
+ */
+ @Override
+ public MathTransform createAffineTransform(final Matrix matrix) throws FactoryException {
+ /*
+ * Performance note: we could set lastMethod to the "Affine" operation method provider, but we do not
+ * because setting this value is not free (e.g. it depends on matrix size) and it is rarely needed.
+ */
+ lastMethod.remove();
+ return unique(MathTransforms.linear(matrix));
+ }
+
+ /**
+ * Creates a transform by concatenating two existing transforms.
+ * A concatenated transform acts in the same way as applying two transforms, one after the other.
+ *
+ * <p>The dimension of the output space of the first transform must match the dimension of the input space
+ * in the second transform. In order to concatenate more than two transforms, use this constructor repeatedly.</p>
+ *
+ * @param tr1 the first transform to apply to points.
+ * @param tr2 the second transform to apply to points.
+ * @return the concatenated transform.
+ * @throws FactoryException if the object creation failed.
+ *
+ * @see MathTransforms#concatenate(MathTransform, MathTransform)
+ */
+ @Override
+ public MathTransform createConcatenatedTransform(final MathTransform tr1,
+ final MathTransform tr2)
+ throws FactoryException
+ {
+ lastMethod.remove();
+ ArgumentChecks.ensureNonNull("tr1", tr1);
+ ArgumentChecks.ensureNonNull("tr2", tr2);
+ final MathTransform tr;
+ try {
+ tr = ConcatenatedTransform.create(tr1, tr2, this);
+ } catch (IllegalArgumentException exception) {
+ throw new InvalidGeodeticParameterException(exception.getLocalizedMessage(), exception);
+ }
+ assert MathTransforms.isValid(MathTransforms.getSteps(tr)) : tr;
+ return unique(tr);
+ }
+
+ /**
+ * Creates a transform which passes through a subset of coordinates to another transform.
+ * This allows transforms to operate on a subset of coordinates.
+ * The resulting transform will have the following dimensions:
+ *
+ * {@snippet lang="java" :
+ * int sourceDim = firstAffectedCoordinate + subTransform.getSourceDimensions() + numTrailingCoordinates;
+ * int targetDim = firstAffectedCoordinate + subTransform.getTargetDimensions() + numTrailingCoordinates;
+ * }
+ *
+ * <h4>Example</h4>
+ * Giving (<var>latitude</var>, <var>longitude</var>, <var>height</var>) coordinates,
+ * a pass through transform can convert the height values from meters to feet without
+ * affecting the (<var>latitude</var>, <var>longitude</var>) values.
+ *
+ * @param firstAffectedCoordinate the lowest index of the affected coordinates.
+ * @param subTransform transform to use for affected coordinates.
+ * @param numTrailingCoordinates number of trailing coordinates to pass through. Affected coordinates will range
+ * from {@code firstAffectedCoordinate} inclusive to {@code dimTarget-numTrailingCoordinates} exclusive.
+ * @return a pass through transform.
+ * @throws FactoryException if the object creation failed.
+ */
+ @Override
+ public MathTransform createPassThroughTransform(final int firstAffectedCoordinate,
+ final MathTransform subTransform,
+ final int numTrailingCoordinates)
+ throws FactoryException
+ {
+ lastMethod.remove();
+ final MathTransform tr;
+ try {
+ tr = MathTransforms.passThrough(firstAffectedCoordinate, subTransform, numTrailingCoordinates);
+ } catch (IllegalArgumentException exception) {
+ throw new InvalidGeodeticParameterException(exception.getLocalizedMessage(), exception);
+ }
+ return unique(tr);
+ }
+
++ /**
++ * There is no XML format for math transforms.
++ *
++ * @param xml math transform encoded in XML format.
++ * @throws FactoryException if the object creation failed.
++ */
++ @Override
++ @Deprecated
++ public MathTransform createFromXML(String xml) throws FactoryException {
++ lastMethod.remove();
++ throw new FactoryException(Errors.format(Errors.Keys.UnsupportedOperation_1, "createFromXML"));
++ }
++
+ /**
+ * Creates a math transform object from a
+ * <a href="http://www.geoapi.org/snapshot/javadoc/org/opengis/referencing/doc-files/WKT.html"><cite>Well
+ * Known Text</cite> (WKT)</a>.
+ * If the given text contains non-fatal anomalies (unknown or unsupported WKT elements,
+ * inconsistent unit definitions, <i>etc.</i>), warnings may be reported in a
+ * {@linkplain java.util.logging.Logger logger} named {@code "org.apache.sis.io.wkt"}.
+ *
+ * <p>Note that the WKT format is not always lossless. A {@code MathTransform} recreated from WKT may be
+ * non-invertible even if the original transform was invertible. For example if an "Affine" operation is
+ * defined by a non-square matrix, Apache SIS implementation sometimes has "hidden" information about the
+ * inverse matrix but those information are lost at WKT formatting time. A similar "hidden" information
+ * lost may also happen with {@link WraparoundTransform}, also making that transform non-invertible.</p>
+ *
+ * @param text math transform encoded in Well-Known Text format.
+ * @return the math transform (never {@code null}).
+ * @throws FactoryException if the Well-Known Text cannot be parsed,
+ * or if the math transform creation failed from some other reason.
+ */
+ @Override
+ public MathTransform createFromWKT(final String text) throws FactoryException {
+ lastMethod.remove();
+ ArgumentChecks.ensureNonEmpty("text", text);
+ Parser p = parser.getAndSet(null);
+ if (p == null) try {
+ Constructor<? extends Parser> c = parserConstructor;
+ if (c == null) {
+ c = Class.forName("org.apache.sis.io.wkt.MathTransformParser").asSubclass(Parser.class)
+ .getConstructor(MathTransformFactory.class);
+ c.setAccessible(true);
+ parserConstructor = c;
+ }
+ p = c.newInstance(this);
+ } catch (ReflectiveOperationException e) {
+ throw new FactoryException(e);
+ }
+ /*
+ * No need to check the type of the parsed object, because MathTransformParser
+ * should return only instance of MathTransform.
+ */
+ final Object object;
+ try {
+ object = p.createFromWKT(text);
+ } catch (FactoryException e) {
+ /*
+ * The parsing may fail because a operation parameter is not known to SIS. If this happen, replace
+ * the generic exception thrown be the parser (which is FactoryException) by a more specific one.
+ * Note that InvalidGeodeticParameterException is defined only in this `org.apache.sis.referencing` module,
+ * so we could not throw it from the `org.apache.sis.metadata` module that contain the parser.
+ */
+ Throwable cause = e.getCause();
+ while (cause != null) {
+ if (cause instanceof ParameterNotFoundException) {
+ throw new InvalidGeodeticParameterException(e.getLocalizedMessage(), cause);
+ }
+ cause = cause.getCause();
+ }
+ throw e;
+ }
+ parser.set(p);
+ return (MathTransform) object;
+ }
+
+ /**
+ * Replaces the given transform by a unique instance, if one already exists.
+ */
+ private MathTransform unique(final MathTransform tr) {
+ return (pool != null) ? pool.unique(tr) : tr;
+ }
+
+ /**
+ * Returns the operation method used by the latest call to a {@code create(…)} constructor
+ * in the currently running thread. Returns {@code null} if not applicable.
+ *
+ * <p>Invoking {@code getLastMethodUsed()} can be useful after a call to
+ * {@link #createParameterizedTransform createParameterizedTransform(…)}.</p>
+ *
+ * @return the last method used by a {@code create(…)} constructor, or {@code null} if unknown of unsupported.
+ *
+ * @see #createParameterizedTransform(ParameterValueGroup, Context)
+ * @see Context#getMethodUsed()
+ */
+ @Override
+ public OperationMethod getLastMethodUsed() {
+ return lastMethod.get();
+ }
+
+ /**
+ * Notifies this factory that the elements provided by the {@code Iterable<OperationMethod>} may have changed.
+ * This method performs the following steps:
+ *
+ * <ul>
+ * <li>Clears all caches.</li>
+ * <li>If the {@code Iterable} given at construction time is an instance of {@link ServiceLoader},
+ * invokes its {@code reload()} method.</li>
+ * </ul>
+ *
+ * This method is useful to sophisticated applications which dynamically make new plug-ins available at runtime,
+ * for example following changes of the application module path.
+ *
+ * @see #DefaultMathTransformFactory(Iterable)
+ * @see ServiceLoader#reload()
+ */
+ public void reload() {
+ synchronized (methods) {
+ methodsByName.clear();
+ final Iterable<? extends OperationMethod> m = methods;
+ if (m instanceof ServiceLoader<?>) {
+ ((ServiceLoader<?>) m).reload();
+ }
+ synchronized (methodsByType) {
+ for (final OperationMethodSet c : methodsByType.values()) {
+ c.reset();
+ }
+ }
+ if (pool != null) {
+ pool.clear();
+ }
+ }
+ }
+ }
diff --cc endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java
index 0000000000,3dc54663a8..e55ffc2b34
mode 000000,100644..100644
--- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java
+++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java
@@@ -1,0 -1,1080 +1,1083 @@@
+ /*
+ * 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.netcdf;
+
+ import java.net.URI;
+ import java.net.URISyntaxException;
+ import java.util.Date;
+ import java.util.List;
+ import java.util.Set;
+ import java.util.Map;
+ import java.util.LinkedHashSet;
+ import java.util.LinkedHashMap;
+ import java.util.Arrays;
+ import java.util.ArrayList;
+ import java.util.Collection;
+ import java.io.IOException;
+ import javax.measure.Unit;
+ import javax.measure.UnitConverter;
+ import javax.measure.IncommensurableException;
+ import javax.measure.format.MeasurementParseException;
+
+ import org.opengis.util.CodeList;
+ import org.opengis.util.NameFactory;
+ import org.opengis.util.InternationalString;
+ import org.opengis.metadata.Metadata;
+ import org.opengis.metadata.Identifier;
+ import org.opengis.metadata.spatial.*;
+ import org.opengis.metadata.content.*;
+ import org.opengis.metadata.citation.*;
+ import org.opengis.metadata.identification.*;
+ import org.opengis.metadata.maintenance.ScopeCode;
+ import org.opengis.metadata.constraint.Restriction;
+ import org.opengis.referencing.cs.AxisDirection;
+ import org.opengis.referencing.crs.VerticalCRS;
+ import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+ import org.apache.sis.util.iso.Types;
+ import org.apache.sis.storage.DataStoreException;
+ import org.apache.sis.storage.event.StoreListeners;
+ import org.apache.sis.metadata.iso.DefaultMetadata;
+ import org.apache.sis.metadata.iso.citation.*;
+ import org.apache.sis.metadata.iso.identification.*;
+ import org.apache.sis.metadata.sql.MetadataStoreException;
+ import org.apache.sis.internal.netcdf.Axis;
+ import org.apache.sis.internal.netcdf.Decoder;
+ import org.apache.sis.internal.netcdf.Variable;
+ import org.apache.sis.internal.netcdf.VariableRole;
+ import org.apache.sis.internal.netcdf.Dimension;
+ import org.apache.sis.internal.netcdf.Grid;
+ import org.apache.sis.internal.storage.io.IOUtilities;
+ import org.apache.sis.internal.storage.MetadataBuilder;
+ import org.apache.sis.internal.storage.wkt.StoreFormat;
+ import org.apache.sis.internal.referencing.AxisDirections;
+ import org.apache.sis.internal.system.Configuration;
+ import org.apache.sis.internal.util.CollectionsExt;
+ import org.apache.sis.internal.util.Strings;
+ import org.apache.sis.util.resources.Errors;
+ import org.apache.sis.util.CharSequences;
+ import org.apache.sis.referencing.CRS;
+ import org.apache.sis.measure.Units;
+ import org.apache.sis.math.Vector;
+
+ // The following dependency is used only for static final String constants.
+ // Consequently, the compiled class files should not have this dependency.
+ import ucar.nc2.constants.ACDD;
+ import ucar.nc2.constants.CDM;
+ import ucar.nc2.constants.CF;
+
+ import static org.apache.sis.storage.netcdf.AttributeNames.*;
+ import static org.apache.sis.internal.util.CollectionsExt.first;
+
+
+ /**
+ * Mapping from netCDF metadata to ISO 19115-2 metadata. The {@link String} constants declared in
+ * the {@linkplain AttributeNames parent class} are the name of attributes examined by this class.
+ * The current implementation searches the attribute values in the following places, in that order:
+ *
+ * <ol>
+ * <li>{@code "NCISOMetadata"} group</li>
+ * <li>{@code "CFMetadata"} group</li>
+ * <li>Global attributes</li>
+ * <li>{@code "THREDDSMetadata"} group</li>
+ * </ol>
+ *
+ * The {@code "CFMetadata"} group has precedence over the global attributes because the
+ * {@linkplain AttributeNames#LONGITUDE longitude} and {@linkplain AttributeNames#LATITUDE latitude}
+ * resolutions are often more accurate in that group.
+ *
+ * <h2>Known limitations</h2>
+ * <ul>
+ * <li>{@code "degrees_west"} and {@code "degrees_south"} units not correctly handled.</li>
+ * <li>Units of measurement not yet declared in the {@link Band} elements.</li>
+ * <li>{@link AttributeNames#FLAG_VALUES} and {@link AttributeNames#FLAG_MASKS}
+ * not yet included in the {@link RangeElementDescription} elements.</li>
+ * <li>Services (WMS, WCS, OPeNDAP, THREDDS) <i>etc.</i>) and transfer options not yet declared.</li>
+ * </ul>
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @author Thi Phuong Hao Nguyen (VNSC)
+ * @author Alexis Manin (Geomatys)
+ * @version 1.3
+ * @since 0.3
+ */
+ final class MetadataReader extends MetadataBuilder {
+ /**
+ * Whether the reader should include experimental fields.
+ * They are fields for which we are unsure of the proper ISO 19115 location.
+ */
+ @Configuration
+ private static final boolean EXPERIMENTAL = true;
+
+ /**
+ * Names of global attributes identifying services.
+ */
+ private static final String[] SERVICES = {"wms_service", "wcs_service"};
+
+ /**
+ * The character to use as a separator in comma-separated list. This separator is used for parsing the
+ * {@link AttributeNames#KEYWORDS} attribute value for instance.
+ */
+ private static final char SEPARATOR = ',';
+
+ /**
+ * The character to use for quoting strings in a comma-separated list. Quoted strings may contain comma.
+ *
+ * <h4>Example</h4>
+ * John Doe, Jane Lee, "L J Smith, Jr."
+ */
+ private static final char QUOTE = '"';
+
+ /**
+ * The source of netCDF attributes from which to infer ISO metadata.
+ * This source is set at construction time.
+ *
+ * <p>This {@code MetadataReader} class does <strong>not</strong> close this source.
+ * Closing this source after usage is the user responsibility.</p>
+ */
+ private final Decoder decoder;
+
+ /**
+ * The actual search path, as a subset of {@link org.apache.sis.internal.netcdf.Convention#SEARCH_PATH}
+ * with only the name of the groups which have been found in the NeCDF file.
+ */
+ private final String[] searchPath;
+
+ /**
+ * The contact, used at metadata creation time for avoiding to construct identical objects
+ * more than once.
+ *
+ * <p>The point of contact is stored in the two following places. The semantic of those two
+ * contacts is not strictly identical, but the distinction is not used in netCDF file:</p>
+ *
+ * <ul>
+ * <li>{@link DefaultMetadata#getContacts()}</li>
+ * <li>{@link DefaultDataIdentification#getPointOfContacts()}</li>
+ * </ul>
+ *
+ * An object very similar is used as the creator. The point of contact and the creator
+ * are often identical except for their role attribute.
+ */
- private transient Responsibility pointOfContact;
++ private transient ResponsibleParty pointOfContact;
+
+ /**
+ * The vertical coordinate reference system to be given to the object created by {@link #addExtent()}.
+ * This is set to the first vertical CRS found.
+ */
+ private VerticalCRS verticalCRS;
+
+ /**
+ * Whether at least one grid coverage has been found during iteration over variables.
+ */
+ private boolean hasGridCoverages;
+
+ /**
+ * Creates a new <cite>netCDF to ISO</cite> mapper for the given source.
+ *
+ * @param decoder the source of netCDF attributes.
+ */
+ MetadataReader(final Decoder decoder) {
+ this.decoder = decoder;
+ decoder.setSearchPath(decoder.convention().getSearchPath());
+ searchPath = decoder.getSearchPath();
+ }
+
+ /**
+ * Invoked when a non-fatal exception occurred while reading metadata.
+ * This method sends a record to the registered listeners if any,
+ * or logs the record otherwise.
+ */
+ private void warning(final Exception e) {
+ decoder.listeners.warning(e);
+ }
+
+ /**
+ * Logs a warning using the localized error resource bundle for the locale given by
+ * {@link StoreListeners#getLocale()}.
+ *
+ * @param key one of {@link Errors.Keys} values.
+ */
+ private void warning(final short key, final Object p1, final Object p2, final Exception e) {
+ final StoreListeners listeners = decoder.listeners;
+ listeners.warning(Errors.getResources(listeners.getLocale()).getString(key, p1, p2), e);
+ }
+
+ /**
+ * Splits comma-separated values. Leading and trailing spaces are removed for each item
+ * unless the item is between double quotes. Empty strings are ignored unless between double quotes.
+ * If a value begin with double quotes, all content will be copied verbatim until the closing double quote.
+ * A double quote is considered as a closing double quote if just before a comma separator (ignoring spaces).
+ */
+ static List<String> split(final String value) {
+ if (value == null) {
+ return List.of();
+ }
+ final List<String> items = new ArrayList<>();
+ int start = 0; // Index of the first character of the next item to add in the list.
+ int end; // Index after the last character of the next item to add in the list.
+ int next; // Index of the next separator (comma) after `end`.
+ final int length = CharSequences.skipTrailingWhitespaces(value, 0, value.length());
+ split: while ((start = CharSequences.skipLeadingWhitespaces(value, start, length)) < length) {
+ if (value.charAt(start) == QUOTE) {
+ next = ++start; // Skip the quote character.
+ do {
+ end = value.indexOf(QUOTE, next); // End of quoted text, may have comma separator before.
+ if (end < 0) break split;
+ next = CharSequences.skipLeadingWhitespaces(value, end+1, length);
+ } while (next < length && value.charAt(next) != SEPARATOR);
+ } else {
+ next = value.indexOf(SEPARATOR, start); // Unquoted text - comma is the item separator.
+ if (next < 0) break;
+ end = CharSequences.skipTrailingWhitespaces(value, start, next);
+ }
+ if (start != end) {
+ items.add(value.substring(start, end));
+ }
+ start = next+1;
+ }
+ if (start < length) {
+ items.add(value.substring(start, length));
+ }
+ return items;
+ }
+
+ /**
+ * Reads the attribute value for the given name, then trims the leading and trailing spaces.
+ * If the value is null, empty or contains only spaces, then this method returns {@code null}.
+ */
+ private String stringValue(final String name) {
+ return Strings.trimOrNull(decoder.stringValue(name));
+ }
+
+ /**
+ * Reads the numeric value for the given value, or returns {@code NaN} if none.
+ */
+ private double numericValue(final String name) {
+ final Number v = decoder.numericValue(name);
+ return (v != null) ? v.doubleValue() : Double.NaN;
+ }
+
+ /**
+ * Returns the enumeration constant for the given name, or {@code null} if the given name is not recognized.
+ * In the latter case, this method emits a warning.
+ */
+ private <T extends Enum<T>> T forEnumName(final Class<T> enumType, final String name) {
+ final T code = Types.forEnumName(enumType, name);
+ if (code == null && name != null) {
+ warning(Errors.Keys.UnknownEnumValue_2, enumType, name, null);
+ }
+ return code;
+ }
+
+ /**
+ * Returns the code value for the given name, or {@code null} if the given name is not recognized.
+ * In the latter case, this method emits a warning.
+ */
+ private <T extends CodeList<T>> T forCodeName(final Class<T> codeType, final String name) {
+ final T code = Types.forCodeName(codeType, name, false);
+ if (code == null && name != null) {
+ /*
+ * CodeLists are not enums, but using the error message for enums is not completly wrong since
+ * if we did not allowed CodeList to create new elements, then we are using it like an enum.
+ */
+ warning(Errors.Keys.UnknownEnumValue_2, codeType, name, null);
+ }
+ return code;
+ }
+
+ /**
+ * Adds the given element in the given collection if the element is non-null.
+ * If the element is non-null and the collection is null, a new collection is
+ * created. The given collection, or the new collection if it has been created,
+ * is returned.
+ */
+ private static <T> Set<T> addIfNonNull(Set<T> collection, final T element) {
+ if (element != null) {
+ if (collection == null) {
+ collection = new LinkedHashSet<>(4);
+ }
+ collection.add(element);
+ }
+ return collection;
+ }
+
+ /**
+ * Returns {@code true} if the given netCDF attribute is either null or equals to the
+ * string value of the given metadata value.
+ *
+ * @param metadata The value stored in the metadata object.
+ * @param attribute The value parsed from the netCDF file.
+ */
+ private static boolean canShare(final CharSequence metadata, final String attribute) {
+ return (attribute == null) || (metadata != null && metadata.toString().equals(attribute));
+ }
+
+ /**
+ * Returns {@code true} if the given netCDF attribute is either null or equals to one
+ * of the values in the given collection.
+ *
+ * @param metadata the value stored in the metadata object.
+ * @param attribute the value parsed from the netCDF file.
+ */
+ private static boolean canShare(final Collection<String> metadata, final String attribute) {
+ return (attribute == null) || metadata.contains(attribute);
+ }
+
+ /**
+ * Returns {@code true} if the given URL is null, or if the given resource contains that URL.
+ *
+ * @param resource the value stored in the metadata object.
+ * @param url the value parsed from the netCDF file.
+ */
+ private static boolean canShare(final OnlineResource resource, final String url) {
+ return (url == null) || (resource != null && canShare(resource.getLinkage().toString(), url));
+ }
+
+ /**
+ * Returns {@code true} if the given email is null, or if the given address contains that email.
+ *
+ * @param address the value stored in the metadata object.
+ * @param email the value parsed from the netCDF file.
+ */
+ private static boolean canShare(final Address address, final String email) {
+ return (email == null) || (address != null && canShare(address.getElectronicMailAddresses(), email));
+ }
+
+ /**
+ * Creates a URI form the given path, or returns {@code null} if the given URL is null or cannot be parsed.
+ * In the latter case, a warning will be emitted.
+ */
+ private URI createURI(final String url) {
+ if (url != null) try {
+ return new URI(url);
+ } catch (URISyntaxException e) {
+ warning(e);
+ }
+ return null;
+ }
+
+ /**
+ * Creates an {@code OnlineResource} element if the given URL is not null. Since ISO 19115
+ * declares the URL as a mandatory attribute, this method will ignore all other attributes
+ * if the given URL is null.
+ *
+ * @param url the URL (mandatory - if {@code null}, no resource will be created).
+ * @return the online resource, or {@code null} if the URL was null.
+ */
+ private OnlineResource createOnlineResource(final String url) {
+ final URI uri = createURI(url);
+ if (uri == null) {
+ return null;
+ }
+ final DefaultOnlineResource resource = new DefaultOnlineResource(uri);
+ final String protocol = uri.getScheme();
+ resource.setProtocol(protocol);
+ if (IOUtilities.isHTTP(protocol)) {
+ resource.setApplicationProfile("web browser");
+ }
+ resource.setFunction(OnLineFunction.INFORMATION);
+ return resource;
+ }
+
+ /**
+ * Creates an {@code Address} element if at least one of the given attributes is non-null.
+ */
+ private static Address createAddress(final String email) {
+ if (email != null) {
+ final DefaultAddress address = new DefaultAddress();
+ address.setElectronicMailAddresses(Set.of(email));
+ return address;
+ }
+ return null;
+ }
+
+ /**
+ * Creates a {@code Contact} element if at least one of the given attributes is non-null.
+ */
+ private static Contact createContact(final Address address, final OnlineResource url) {
+ if (address != null || url != null) {
+ final DefaultContact contact = new DefaultContact();
+ if (address != null) contact.setAddresses(Set.of(address));
+ if (url != null) contact.setOnlineResources(Set.of(url));
+ return contact;
+ }
+ return null;
+ }
+
+ /**
+ * Creates a {@code Responsibility} element if at least one of the name, email or URL attributes is defined.
+ * For more consistent results, the caller should restrict the {@linkplain Decoder#setSearchPath search path}
+ * to a single group before invoking this method.
+ *
+ * <p>Implementation note: this method tries to reuse the existing {@link #pointOfContact} instance,
+ * or part of it, if it is suitable.</p>
+ *
+ * @param keys the group of attribute names to use for fetching the values.
+ * @param isPointOfContact {@code true} if this responsible party is the "main" one. This will force the
+ * role to {@link Role#POINT_OF_CONTACT} and enable the use of {@code "institution"} attribute as
+ * a fallback if there is no value for {@link Responsible#INSTITUTION}.
+ * @return the responsible party, or {@code null} if none.
+ *
+ * @see AttributeNames#CREATOR
+ * @see AttributeNames#CONTRIBUTOR
+ * @see AttributeNames#PUBLISHER
+ */
- private Responsibility createResponsibleParty(final Responsible keys, final boolean isPointOfContact) {
++ private ResponsibleParty createResponsibleParty(final Responsible keys, final boolean isPointOfContact) {
+ String individualName = stringValue(keys.NAME);
+ String organisationName = stringValue(keys.INSTITUTION);
+ final String email = stringValue(keys.EMAIL);
+ final String url = stringValue(keys.URL);
+ if (organisationName == null && isPointOfContact) {
+ organisationName = stringValue("institution");
+ }
+ if (individualName == null && organisationName == null && email == null && url == null) {
+ return null;
+ }
+ /*
+ * The "individual" name may actually be an institution name, either because a "*_type" attribute
+ * said so or because the "individual" name is the same than the institution name. In such cases,
+ * reorganize the names in order to avoid duplication.
+ */
+ if (organisationName == null) {
+ if (isOrganisation(keys)) {
+ organisationName = individualName;
+ individualName = null;
+ }
+ } else if (organisationName.equalsIgnoreCase(individualName)) {
+ individualName = null;
+ }
+ Role role = forCodeName(Role.class, stringValue(keys.ROLE));
+ if (role == null) {
+ role = isPointOfContact ? Role.POINT_OF_CONTACT : keys.DEFAULT_ROLE;
+ }
+ /*
+ * Verify if we can share the existing `pointOfContact` instance. This is often the case in practice.
+ * If we cannot share the whole existing instance, we usually can share parts of it like the address.
+ */
- Responsibility responsibility = pointOfContact;
++ ResponsibleParty responsibility = pointOfContact;
+ Contact contact = null;
+ Address address = null;
+ OnlineResource resource = null;
+ if (responsibility != null) {
+ final Party party = first(responsibility.getParties());
+ if (party != null) {
+ contact = first(party.getContactInfo());
+ if (contact != null) {
+ address = first(contact.getAddresses());
+ resource = first(contact.getOnlineResources());
+ }
+ if (!canShare(resource, url)) {
+ resource = null;
+ contact = null; // Clear the parents all the way up to the root.
+ responsibility = null;
+ }
+ if (!canShare(address, email)) {
+ address = null;
+ contact = null; // Clear the parents all the way up to the root.
+ responsibility = null;
+ }
+ if (responsibility != null) {
+ if (party instanceof Organisation) {
+ // Individual (if any) is considered an organisation member. See comment in next block.
+ if (!canShare(party.getName(), organisationName) ||
+ !canShare(first(((Organisation) party).getIndividual()).getName(), individualName))
+ {
+ responsibility = null;
+ }
+ } else if (!canShare(party.getName(), individualName)) {
+ responsibility = null;
+ }
+ }
+ }
+ }
+ /*
+ * If we cannot share the exiting instance, we have to build a new one. If there is both
+ * an individual and organisation name, then the individual is considered a member of the
+ * organisation. This structure shall be kept consistent with the check in the above block.
+ */
+ if (responsibility == null) {
+ if (contact == null) {
+ if (address == null) address = createAddress(email);
+ if (resource == null) resource = createOnlineResource(url);
+ contact = createContact(address, resource);
+ }
+ if (individualName != null || organisationName != null || contact != null) { // Do not test role.
+ AbstractParty party = null;
+ if (individualName != null) party = new DefaultIndividual(individualName, null, null);
+ if (organisationName != null) party = new DefaultOrganisation(organisationName, null, (Individual) party, null);
+ if (party == null) party = isOrganisation(keys) ? new DefaultOrganisation() : new DefaultIndividual();
+ if (contact != null) party.setContactInfo(Set.of(contact));
- responsibility = new DefaultResponsibility(role, null, party);
++ responsibility = new DefaultResponsibleParty(role);
++ if (party != null) {
++ ((DefaultResponsibleParty) responsibility).setParties(Set.of(party));
++ }
+ }
+ }
+ return responsibility;
+ }
+
+ /**
+ * Returns {@code true} if the responsible party described by the given keys is an organization.
+ * In case of doubt, this method returns {@code false}. This is consistent with ACDD recommendation,
+ * which set the default value to {@code "person"}.
+ */
+ private boolean isOrganisation(final Responsible keys) {
+ final String type = stringValue(keys.TYPE);
+ return "institution".equalsIgnoreCase(type) || "group".equalsIgnoreCase(type);
+ }
+
+ /**
+ * Adds a {@code DataIdentification/Citation} element if at least one of the required attributes is non-null.
+ * This method will initialize the {@link #pointOfContact} field, then reuses it if non-null and suitable.
+ *
+ * <p>This method opportunistically collects the name of all publishers.
+ * Those names are useful to {@link #addIdentificationInfo(Set)}.</p>
+ *
+ * @return the name of all publishers, or {@code null} if none.
+ */
+ private Set<InternationalString> addCitation() {
+ String title = stringValue(TITLE);
+ if (title == null) {
+ title = stringValue("full_name"); // THREDDS attribute documented in TITLE javadoc.
+ if (title == null) {
+ title = stringValue("name"); // THREDDS attribute documented in TITLE javadoc.
+ if (title == null) {
+ title = decoder.getTitle();
+ }
+ }
+ }
+ addTitle(title);
+ addEdition(stringValue(PRODUCT_VERSION));
+ addOtherCitationDetails(stringValue(REFERENCES));
+ addCitationDate(decoder.dateValue(METADATA_CREATION), DateType.CREATION, Scope.ALL);
+ addCitationDate(decoder.dateValue(METADATA_MODIFIED), DateType.REVISION, Scope.ALL);
+ addCitationDate(decoder.dateValue(DATE_CREATED), DateType.CREATION, Scope.RESOURCE);
+ addCitationDate(decoder.dateValue(DATE_MODIFIED), DateType.REVISION, Scope.RESOURCE);
+ addCitationDate(decoder.dateValue(DATE_ISSUED), DateType.PUBLICATION, Scope.RESOURCE);
+ /*
+ * Add the responsible party which is declared in global attributes, or in
+ * the THREDDS attributes if no information was found in global attributes.
+ * This responsible party is taken as the point of contact.
+ */
+ for (final String path : searchPath) {
+ decoder.setSearchPath(path);
- final Responsibility party = createResponsibleParty(CREATOR, true);
++ final ResponsibleParty party = createResponsibleParty(CREATOR, true);
+ if (party != pointOfContact) {
+ addPointOfContact(party, Scope.RESOURCE);
+ if (pointOfContact == null) {
+ pointOfContact = party;
+ }
+ }
+ }
+ /*
+ * There is no distinction in netCDF files between "point of contact" and "creator".
+ * We take the first one as the data originator.
+ */
+ addCitedResponsibleParty(pointOfContact, Role.ORIGINATOR);
+ /*
+ * Add the contributors only after we did one full pass over the creators. We keep those two
+ * loops separated in order to increase the chances that pointOfContact has been initialized
+ * (it may not have been initialized on the first pass).
+ */
+ Set<InternationalString> publisher = null;
+ for (final String path : searchPath) {
+ decoder.setSearchPath(path);
- final Responsibility contributor = createResponsibleParty(CONTRIBUTOR, false);
++ final ResponsibleParty contributor = createResponsibleParty(CONTRIBUTOR, false);
+ if (contributor != pointOfContact) {
+ addCitedResponsibleParty(contributor, null);
+ }
- final Responsibility r = createResponsibleParty(PUBLISHER, false);
++ final ResponsibleParty r = createResponsibleParty(PUBLISHER, false);
+ if (r != null) {
+ addDistributor(r);
+ for (final Party party : r.getParties()) {
+ publisher = addIfNonNull(publisher, party.getName());
+ }
+ }
+ }
+ decoder.setSearchPath(searchPath);
+ return publisher;
+ }
+
+ /**
+ * Adds a {@code DataIdentification} element if at least one of the required attributes is non-null.
+ *
+ * @param publisher the publisher names, built by the caller in an opportunist way.
+ */
+ private void addIdentificationInfo(final Set<InternationalString> publisher) throws IOException, DataStoreException {
+ boolean hasExtent = false;
+ Set<String> project = null;
+ Set<String> standard = null;
+ final Set<String> keywords = new LinkedHashSet<>();
+ for (final String path : searchPath) {
+ decoder.setSearchPath(path);
+ keywords.addAll(split(stringValue(KEYWORDS.TEXT)));
+ standard = addIfNonNull(standard, stringValue(STANDARD_NAME.TEXT));
+ project = addIfNonNull(project, stringValue(PROJECT));
+ for (final String keyword : split(stringValue(ACCESS_CONSTRAINT))) {
+ addAccessConstraint(forCodeName(Restriction.class, keyword));
+ }
- addTopicCategory(forEnumName(TopicCategory.class, stringValue(TOPIC_CATEGORY)));
++ addTopicCategory(forCodeName(TopicCategory.class, stringValue(TOPIC_CATEGORY)));
+ addSpatialRepresentation(forCodeName(SpatialRepresentationType.class, stringValue(DATA_TYPE)));
+ if (!hasExtent) {
+ /*
+ * Takes only ONE extent, because a netCDF file may declare many time the same
+ * extent with different precision. The groups are ordered in such a way that
+ * the first extent should be the most accurate one.
+ */
+ hasExtent = addExtent();
+ }
+ }
+ /*
+ * For the following properties, use only the first non-empty attribute value found on the search path.
+ */
+ decoder.setSearchPath(searchPath);
+ addAbstract (stringValue(SUMMARY));
+ addPurpose (stringValue(PURPOSE));
+ addSupplementalInformation(stringValue(COMMENT));
+ addCredits (stringValue(ACKNOWLEDGEMENT));
+ addCredits (stringValue("acknowledgment")); // Legacy spelling.
+ addUseLimitation (stringValue(LICENSE));
+ addKeywords(standard, KeywordType.THEME, stringValue(STANDARD_NAME.VOCABULARY));
+ addKeywords(keywords, KeywordType.THEME, stringValue(KEYWORDS.VOCABULARY));
+ addKeywords(project, KeywordType.PROJECT, null);
+ addKeywords(publisher, KeywordType.DATA_CENTRE, null);
+ /*
+ * Add geospatial bounds as a geometric object. This optional operation requires
+ * an external library (ESRI or JTS) to be present on the module path.
+ */
+ final String wkt = stringValue(GEOSPATIAL_BOUNDS);
+ if (wkt != null) {
+ addBoundingPolygon(new StoreFormat(null, null, decoder.geomlib, decoder.listeners).parseGeometry(wkt,
+ stringValue(GEOSPATIAL_BOUNDS + "_crs"), stringValue(GEOSPATIAL_BOUNDS + "_vertical_crs")));
+ }
+ final String[] format = decoder.getFormatDescription();
+ String id = format[0];
+ if (NetcdfStoreProvider.NAME.equalsIgnoreCase(id)) try {
+ setPredefinedFormat(NetcdfStoreProvider.NAME);
+ id = null;
+ } catch (MetadataStoreException e) {
+ // Will add `id` at the end of this method.
+ warning(e);
+ }
+ if (format.length >= 2) {
+ addFormatName(format[1]);
+ if (format.length >= 3) {
+ setFormatEdition(format[2]);
+ }
+ }
+ addFormatName(id); // Do nothing is `id` is null.
+ }
+
+ /**
+ * Adds information about axes and cell geometry.
+ * This is the {@code <mdb:spatialRepresentationInfo>} element in XML.
+ * We work on grid axes instead of Coordinate Reference System axes because
+ * {@code metadata/spatialRepresentationInfo/axisDimensionProperties/dimensionSize} seems to imply that.
+ *
+ * @param cs the grid geometry (related to the netCDF coordinate system).
+ * @throws ArithmeticException if the size of an axis exceeds {@link Integer#MAX_VALUE}, or other overflow occurs.
+ */
+ private void addSpatialRepresentationInfo(final Axis[] axes) throws IOException, DataStoreException {
+ for (int i=0; i<axes.length; i++) {
+ final Axis axis = axes[i];
+ /*
+ * Axes usually have exactly one dimension. However, some netCDF axes are backed by a two-dimensional
+ * conversion grid. In such case, our Axis constructor should have ensured that the first element in
+ * the `sourceDimensions` and `sourceSizes` arrays are for the grid dimension which is most closely
+ * oriented toward the axis direction.
+ */
+ final int d = i; // Because lambda expressions want final variable.
+ axis.getMainSize().ifPresent((s) -> setAxisSize(d, s));
+ final AttributeNames.Dimension attributeNames;
+ switch (axis.abbreviation) {
+ case 'λ': case 'θ': attributeNames = AttributeNames.LONGITUDE; break;
+ case 'φ': case 'Ω': attributeNames = AttributeNames.LATITUDE; break;
+ case 'h': case 'H': case 'D': attributeNames = AttributeNames.VERTICAL; break;
+ case 't': case 'T': attributeNames = AttributeNames.TIME; break;
+ default : continue;
+ }
+ final DimensionNameType name = attributeNames.DEFAULT_NAME_TYPE;
+ setAxisName(i, name);
+ final String res = stringValue(attributeNames.RESOLUTION);
+ if (res != null) try {
+ /*
+ * ACDD convention recommends to write units after the resolution.
+ * Examples: "100 meters", "0.1 degree".
+ */
+ final int s = res.indexOf(' ');
+ final double value;
+ Unit<?> units = null;
+ if (s < 0) {
+ value = numericValue(attributeNames.RESOLUTION);
+ } else {
+ value = Double.parseDouble(res.substring(0, s).trim());
+ final String symbol = res.substring(s+1).trim();
+ if (!symbol.isEmpty()) try {
+ units = Units.valueOf(symbol);
+ } catch (MeasurementParseException e) {
+ warning(Errors.Keys.CanNotAssignUnitToDimension_2, name, units, e);
+ }
+ }
+ setAxisResolution(i, value, units);
+ } catch (NumberFormatException e) {
+ warning(e);
+ }
+ }
+ setCellGeometry(CellGeometry.AREA);
+ }
+
+ /**
+ * Adds the extent declared in the current group. For more consistent results, the caller should restrict
+ * the {@linkplain Decoder#setSearchPath search path} to a single group before invoking this method.
+ * The {@link #verticalCRS} field should have been set before to invoke this method.
+ *
+ * @return {@code true} if at least one numerical value has been added.
+ */
+ private boolean addExtent() {
+ addExtent(stringValue(GEOGRAPHIC_IDENTIFIER));
+ final double[] extent = new double[4];
+ /*
+ * If at least one geographic coordinate is available, add a GeographicBoundingBox.
+ */
+ boolean hasExtent;
+ hasExtent = fillExtent(LONGITUDE, Units.DEGREE, AxisDirection.EAST, extent, 0);
+ hasExtent |= fillExtent(LATITUDE, Units.DEGREE, AxisDirection.NORTH, extent, 2);
+ if (hasExtent) {
+ addExtent(extent, 0);
+ hasExtent = true;
+ }
+ /*
+ * If at least one vertical coordinate is available, add a VerticalExtent.
+ */
+ if (fillExtent(VERTICAL, Units.METRE, null, extent, 0)) {
+ addVerticalExtent(extent[0], extent[1], verticalCRS);
+ hasExtent = true;
+ }
+ /*
+ * Get the start and end times as Date objects if available, or as numeric values otherwise.
+ * In the latter case, the unit symbol tells how to convert to Date objects.
+ */
+ Date startTime = decoder.dateValue(TIME.MINIMUM);
+ Date endTime = decoder.dateValue(TIME.MAXIMUM);
+ if (startTime == null && endTime == null) {
+ final Number tmin = decoder.numericValue(TIME.MINIMUM);
+ final Number tmax = decoder.numericValue(TIME.MAXIMUM);
+ if (tmin != null || tmax != null) {
+ final String symbol = stringValue(TIME.UNITS);
+ if (symbol != null) {
+ final Date[] dates = decoder.numberToDate(symbol, tmin, tmax);
+ startTime = dates[0];
+ endTime = dates[1];
+ }
+ }
+ }
+ /*
+ * If at least one time value above is available, add a temporal extent.
+ */
+ if (startTime != null || endTime != null) {
+ addTemporalExtent(startTime, endTime);
+ hasExtent = true;
+ }
+ return hasExtent;
+ }
+
+ /**
+ * Fills one dimension of the geographic bounding box or vertical extent.
+ * The extent values are written in the given {@code extent} array.
+ *
+ * @param dim the dimension for which to get the extent.
+ * @param targetUnit the destination unit of the extent.
+ * @param positive the direction considered positive, or {@code null} if the unit symbol is not expected to contain a direction.
+ * @param extent where to store the minimum and maximum values.
+ * @param index index where to store the minimum value in {@code extent}. The maximum value is stored at {@code index+1}.
+ * @return {@code true} if a minimum or a maximum value has been found.
+ */
+ private boolean fillExtent(final AttributeNames.Dimension dim, final Unit<?> targetUnit, final AxisDirection positive,
+ final double[] extent, final int index)
+ {
+ double min = numericValue(dim.MINIMUM);
+ double max = numericValue(dim.MAXIMUM);
+ boolean hasExtent = !Double.isNaN(min) || !Double.isNaN(max);
+ if (hasExtent) {
+ final String symbol = stringValue(dim.UNITS);
+ if (symbol != null) {
+ try {
+ final UnitConverter c = Units.valueOf(symbol).getConverterToAny(targetUnit);
+ min = c.convert(min);
+ max = c.convert(max);
+ } catch (MeasurementParseException | IncommensurableException e) {
+ warning(e);
+ }
+ boolean reverse = false;
+ if (positive != null) {
+ reverse = AxisDirections.opposite(positive).equals(Axis.direction(symbol));
+ } else if (dim.POSITIVE != null) {
+ // For now, only the vertical axis have a "positive" attribute.
+ reverse = CF.POSITIVE_DOWN.equals(stringValue(dim.POSITIVE));
+ }
+ if (reverse) {
+ final double tmp = min;
+ min = -max;
+ max = -tmp;
+ }
+ }
+ }
+ extent[index ] = min;
+ extent[index+1] = max;
+ return hasExtent;
+ }
+
+ /**
+ * Adds information about acquisition (program, platform).
+ */
+ private void addAcquisitionInfo() {
+ final Term[] attributes = {
+ AttributeNames.PROGRAM,
+ AttributeNames.PLATFORM,
+ AttributeNames.INSTRUMENT
+ };
+ for (int i=0; i<attributes.length; i++) {
+ final Term at = attributes[i];
+ final String authority = stringValue(at.VOCABULARY);
+ for (final String keyword : split(stringValue(at.TEXT))) {
+ switch (i) {
+ case 0: {
+ if (EXPERIMENTAL) {
+ addAcquisitionOperation(authority, keyword);
+ }
+ break;
+ }
+ case 1: addPlatform (authority, keyword); break;
+ case 2: addInstrument(authority, keyword); break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds information about all netCDF variables. This is the {@code <mdb:contentInfo>} element in XML.
+ * This method groups variables by their domains, i.e. variables having the same set of axes are grouped together.
+ */
+ private void addContentInfo() {
+ /*
+ * Prepare a list of features and coverages, but without writing metadata now.
+ * We differ metadata writing for giving us a chance to group related contents.
+ */
+ final Set<Dimension> features = new LinkedHashSet<>();
+ final Map<List<String>, List<Variable>> coverages = new LinkedHashMap<>(4);
+ for (final Variable variable : decoder.getVariables()) {
+ if (VariableRole.isCoverage(variable)) {
+ final List<org.apache.sis.internal.netcdf.Dimension> dimensions = variable.getGridDimensions();
+ final String[] names = new String[dimensions.size()];
+ for (int i=0; i<names.length; i++) {
+ names[i] = dimensions.get(i).getName();
+ }
+ CollectionsExt.addToMultiValuesMap(coverages, Arrays.asList(names), variable);
+ hasGridCoverages = true;
+ } else if (variable.getRole() == VariableRole.FEATURE_PROPERTY) {
+ /*
+ * For feature property, we should take only the first dimension.
+ * If a second dimension exists, it is for character strings.
+ */
+ features.add(variable.getGridDimensions().get(0));
+ }
+ }
+ /*
+ * Now write the metadata. Note that the spatial repersentation types added below are actually
+ * parts of `DataIdentification` instead of `ContentInformation`, but we add them here because
+ * we have the information here.
+ */
+ if (!features .isEmpty()) addSpatialRepresentation(SpatialRepresentationType.TEXT_TABLE);
+ if (!coverages.isEmpty()) addSpatialRepresentation(SpatialRepresentationType.GRID);
+ for (final Dimension feature : features) {
+ final String name = feature.getName();
+ if (name != null) {
+ addFeatureType(decoder.nameFactory.createLocalName(decoder.namespace, name), feature.length());
+ }
+ }
+ final String processingLevel = stringValue(PROCESSING_LEVEL);
+ for (final List<Variable> group : coverages.values()) {
+ /*
+ * Instantiate a CoverageDescription for each distinct set of netCDF dimensions
+ * (e.g. longitude,latitude,time). This separation is based on the fact that a
+ * coverage has only one domain for every range of values.
+ */
+ newCoverage(false);
+ setProcessingLevelCode(null, processingLevel);
+ for (final Variable variable : group) {
+ addSampleDimension(variable);
+ final CharSequence[] names = variable.getAttributeAsStrings(FLAG_NAMES, ' ');
+ final CharSequence[] meanings = variable.getAttributeAsStrings(FLAG_MEANINGS, ' ');
+ final Vector masks = variable.getAttributeAsVector (FLAG_MASKS);
+ final Vector values = variable.getAttributeAsVector (FLAG_VALUES);
+ final int s1 = (names != null) ? names.length : 0;
+ final int s2 = (meanings != null) ? meanings.length : 0;
+ final int s3 = (masks != null) ? masks .size() : 0;
+ final int s4 = (values != null) ? values.size() : 0;
+ final int length = Math.max(s1, Math.max(s2, Math.max(s3, s4)));
+ for (int i=0; i<length; i++) {
+ addSampleValueDescription(variable,
+ (i < s1) ? names [i] : null,
+ (i < s2) ? meanings [i] : null,
+ (i < s3) ? masks .get(i) : null,
+ (i < s4) ? values.get(i) : null);
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds metadata about a sample dimension (or band) from the given variable.
+ * This is the {@code <mrc:dimension>} element in XML.
+ *
+ * @param variable the netCDF variable.
+ */
+ private void addSampleDimension(final Variable variable) {
+ newSampleDimension();
+ final String name = Strings.trimOrNull(variable.getName());
+ if (name != null) {
+ final NameFactory f = decoder.nameFactory;
+ final StringBuilder buffer = new StringBuilder(20);
+ variable.writeDataTypeName(buffer);
+ setBandIdentifier(f.createMemberName(null, name, f.createTypeName(null, buffer.toString())));
+ }
+ final String id = Strings.trimOrNull(variable.getStandardName());
+ if (!id.equals(name)) {
+ addBandName(variable.getAttributeAsString(ACDD.standard_name_vocabulary), id);
+ }
+ final String description = Strings.trimOrNull(variable.getDescription());
+ if (description != null && !description.equals(name) && !description.equals(id)) {
+ addBandDescription(description);
+ }
+ setSampleUnits(variable.getUnit());
+ setTransferFunction(variable.getAttributeAsDouble(CDM.SCALE_FACTOR),
+ variable.getAttributeAsDouble(CDM.ADD_OFFSET));
+ addContentType(forCodeName(CoverageContentType.class, stringValue(ACDD.coverage_content_type)));
+ }
+
+ /**
+ * Adds metadata about the meaning of a sample value.
+ * This is the {@code <mrc:rangeElementDescription>} element in XML.
+ *
+ * <p><b>Note:</b> ISO 19115 range elements are approximately equivalent to
+ * {@code org.apache.sis.coverage.Category} in the {@code sis-coverage} module.</p>
+ *
+ * @param variable the netCDF variable.
+ * @param name one of the elements in the {@link AttributeNames#FLAG_NAMES} attribute, or {@code null}.
+ * @param meaning one of the elements in the {@link AttributeNames#FLAG_MEANINGS} attribute or {@code null}.
+ * @param mask one of the elements in the {@link AttributeNames#FLAG_MASKS} attribute or {@code null}.
+ * @param value one of the elements in the {@link AttributeNames#FLAG_VALUES} attribute or {@code null}.
+ */
+ private void addSampleValueDescription(final Variable variable,
+ final CharSequence name, final CharSequence meaning, final Number mask, final Number value)
+ {
+ addSampleValueDescription(name, meaning);
+ // TODO: create a record from values (and possibly from the masks).
+ // if (pixel & mask == value) then we have that range element.
+ }
+
+ /**
+ * Adds a globally unique identifier for the current netCDF {@linkplain #decoder}.
+ * The current implementation builds the identifier from the following attributes:
+ *
+ * <ul>
+ * <li>{@code AttributeNames.IDENTIFIER.VOCABULARY} used as the {@linkplain Identifier#getAuthority() authority}.</li>
+ * <li>{@code AttributeNames.IDENTIFIER.TEXT}, or {@link ucar.nc2.NetcdfFile#getId()} if no identifier attribute was found,
+ * or the filename without extension if {@code getId()} returned nothing.</li>
+ * </ul>
+ *
+ * This method should be invoked last, after we made our best effort to set the title.
+ */
+ private void addFileIdentifier() {
+ String identifier = stringValue(IDENTIFIER.TEXT);
+ String authority;
+ if (identifier != null) {
+ authority = stringValue(IDENTIFIER.VOCABULARY);
+ } else {
+ identifier = decoder.getId();
+ if (identifier == null) {
+ identifier = IOUtilities.filenameWithoutExtension(decoder.getFilename());
+ if (identifier == null) {
+ return;
+ }
+ }
+ authority = null;
+ }
+ if (authority == null) {
+ addTitleOrIdentifier(identifier, Scope.RESOURCE);
+ } else {
+ addIdentifier(authority, identifier, Scope.RESOURCE);
+ }
+ }
+
+ /**
+ * Creates an ISO {@code Metadata} object from the information found in the netCDF file.
+ * The returned metadata is unmodifiable, for allowing the caller to share a unique instance.
+ *
+ * @return the ISO metadata object.
+ * @throws IOException if an I/O operation was necessary but failed.
+ * @throws DataStoreException if a logical error occurred.
+ * @throws ArithmeticException if the size of an axis exceeds {@link Integer#MAX_VALUE}, or other overflow occurs.
+ */
+ public Metadata read() throws IOException, DataStoreException {
+ for (final CoordinateReferenceSystem crs : decoder.getReferenceSystemInfo()) {
+ addReferenceSystem(crs);
+ if (verticalCRS == null) {
+ verticalCRS = CRS.getVerticalComponent(crs, false);
+ }
+ }
+ addResourceScope(ScopeCode.DATASET, null);
+ addIdentificationInfo(addCitation());
+ for (final String service : SERVICES) {
+ final String name = stringValue(service);
+ if (name != null) {
+ addResourceScope(ScopeCode.SERVICE, name);
+ }
+ }
+ addAcquisitionInfo();
+ addContentInfo();
+ /*
+ * Add the dimension information, if any. This metadata node
+ * is built from the netCDF CoordinateSystem objects.
+ */
+ for (final Grid cs : decoder.getGridCandidates()) {
+ if (cs.getSourceDimensions() >= Grid.MIN_DIMENSION) {
+ final Axis[] axes = cs.getAxes(decoder);
+ if (axes.length >= Grid.MIN_DIMENSION) {
+ addSpatialRepresentationInfo(axes);
+ }
+ }
+ }
+ setISOStandards(hasGridCoverages);
+ addFileIdentifier();
+ /*
+ * Departure: UnidataDD2MI.xsl puts the source in Metadata.dataQualityInfo.lineage.statement.
+ * However, since ISO 19115:2014, Metadata.resourceLineage.statement seems a more appropriate place.
+ * See https://issues.apache.org/jira/browse/SIS-361
+ */
+ for (final String path : searchPath) {
+ decoder.setSearchPath(path);
+ addLineage(stringValue(HISTORY));
+ addSource(stringValue(SOURCE), null, null);
+ }
+ decoder.setSearchPath(searchPath);
+ final DefaultMetadata metadata = build();
+ addCompleteMetadata(createURI(stringValue(METADATA_LINK)));
+ metadata.transitionTo(DefaultMetadata.State.FINAL);
+ return metadata;
+ }
+ }
diff --cc incubator/build.gradle.kts
index 0000000000,d78d2f957e..48d2fe0a41
mode 000000,100644..100644
--- a/incubator/build.gradle.kts
+++ b/incubator/build.gradle.kts
@@@ -1,0 -1,144 +1,144 @@@
+ /*
+ * 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.
+ */
+ group = "org.apache.sis"
-version = "2.0-SNAPSHOT"
++version = "1.x-SNAPSHOT"
+
+ /*
+ * "org.apache.sis.buildtools" is a custom Gradle plugin for building a project with Module Source Hierarchy.
+ * See the Gradle build script in the `endorsed` directory for more information.
+ */
+ plugins {
+ `java-library`
+ `maven-publish` // For local deployment only. Not to be published on Maven Central.
+ id("org.apache.sis.buildtools")
+ antlr
+ }
+
+ /*
+ * All JAR files that may potentially be used by a module.
+ * For each Apache SIS module, the dependencies actually
+ * used are declared in the `module-info.java` file.
+ */
+ dependencies {
+ // Mandatory dependencies
+ api(libs.units)
+ api(libs.geoapi)
+ api(libs.jaxb.api) // Transitive dependency.
+ api(libs.jts.core) // Should be an optional dependency.
+ api(libs.esri.geometry) // Idem.
+ api(files("../endorsed/build/classes/java/main/org.apache.sis.util"))
+ api(files("../endorsed/build/classes/java/main/org.apache.sis.metadata"))
+ api(files("../endorsed/build/classes/java/main/org.apache.sis.referencing"))
+ api(files("../endorsed/build/classes/java/main/org.apache.sis.feature"))
+ api(files("../endorsed/build/classes/java/main/org.apache.sis.storage"))
+
+ // Test dependencies
+ testImplementation(tests.geoapi)
+ testImplementation(tests.junit4)
+ testRuntimeOnly (tests.junit)
+ testRuntimeOnly (tests.junitLauncher)
+ /*
+ * Dependencies used only by incubated modules. The dependencies are not declared
+ * in the global `settings.gradle.kts` because incubated modules are not released.
+ */
+ implementation(group = "org.antlr", name = "antlr4-maven-plugin", version = "4.11.1")
+ compileOnly (group = "jakarta.servlet", name = "jakarta.servlet-api", version = "6.0.0")
+ compileOnly (group = "org.osgi", name = "osgi.core", version = "8.0.0")
+ antlr (group = "org.antlr", name = "antlr4", version = "4.11.1")
+ }
+
+ /*
+ * Generate ANTLR4 source files, then compile main and tests classes from Module Source Hierarchy.
+ * The test classes require some additional dependencies declared in the `org.apache.sis.test.incubator` module.
+ *
+ * Note: as of Gradle 8.2, the ANTLR task does not work well with arbitrary source directories.
+ * We have to keep default convention even if it does not fit well in Module Source Hierarchy.
+ * Another problem is that we didn't found the right compiler options for combining a directory
+ * of generated sources with the main sources in a Module Source Hierarchy, so we have to write
+ * the output directly in main source directory. This is hopefully temporary, since we hope to
+ * replace ANTLR generated code by hand-written code in a future version.
+ */
+ var srcDir = file("src") // Must be the same as the hard-coded value in `BuildHelper.java`.
+ tasks.generateGrammarSource {
+ setOutputDirectory(file("${srcDir}/org.apache.sis.cql/main"))
+ }
+ tasks.compileJava {
+ dependsOn(":endorsed:compileJava")
+ options.release.set(11) // The version of both Java source code and compiled byte code.
+ }
+ tasks.compileTestJava {
+ srcDir.list().forEach {
+ addRead(options.compilerArgs, it, "org.apache.sis.test.incubator,junit")
+ }
+ }
+
+ /*
+ * Adds a JVM argument for adding dependencies to a module.
+ * This is for dependencies not declared in `module-info`
+ * but needed for test compilation or test execution.
+ */
+ fun addRead(args : MutableList<String>, module : String, dependencies : String) {
+ args.add("--add-reads")
+ args.add(module + '=' + dependencies)
+ }
+
+ /*
+ * Discover and execute JUnit-based tests.
+ */
+ tasks.test {
+ val args = mutableListOf("-enableassertions")
+ setAllJvmArgs(args)
+ testLogging {
+ events("FAILED", "STANDARD_OUT", "STANDARD_ERROR")
+ setExceptionFormat("FULL")
+ }
+ }
+
+ /*
+ * Configuration of the modules to deploy as Maven artifacts.
+ */
+ publishing {
+ publications {
+ create<MavenPublication>("cql") {
+ groupId = "org.apache.sis.core"
+ artifactId = "sis-cql"
+ artifact(file("${buildDir}/libs/org.apache.sis.cql.jar"))
+ pom {
+ name = "Apache SIS CQL"
+ description = "CQL parser."
+ }
+ }
+ create<MavenPublication>("storage.shapefile") {
+ groupId = "org.apache.sis.storage"
+ artifactId = "sis-shapefile"
+ artifact(file("${buildDir}/libs/org.apache.sis.storage.shapefile.jar"))
+ pom {
+ name = "Apache SIS Shapefile storage"
+ description = "Read and write files in the Shapefile format."
+ }
+ }
+ create<MavenPublication>("webapp") {
+ groupId = "org.apache.sis.application"
+ artifactId = "sis-webapp"
+ artifact(file("${buildDir}/libs/org.apache.sis.webapp.jar"))
+ pom {
+ name = "Apache SIS web services layer"
+ description = "Placeholder for future developments."
+ }
+ }
+ }
+ }
diff --cc optional/build.gradle.kts
index 0000000000,0dbdae7fc9..c0cada5da4
mode 000000,100644..100644
--- a/optional/build.gradle.kts
+++ b/optional/build.gradle.kts
@@@ -1,0 -1,168 +1,168 @@@
+ /*
+ * 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.
... 705 lines suppressed ...