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&amp;<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 ...