This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit e638f9ad48580b53be4ed510d2c22f918ebbbafd Author: Martin Desruisseaux <[email protected]> AuthorDate: Sat Jun 25 17:52:52 2022 +0200 Add a `GazetteerFactory` class using the name of reference system implementations. --- .../apache/sis/internal/gazetteer/Resources.java | 5 + .../sis/internal/gazetteer/Resources.properties | 1 + .../sis/internal/gazetteer/Resources_fr.properties | 1 + .../referencing/gazetteer/GazetteerFactory.java | 106 +++++++++++++++++++++ .../gazetteer/GeohashReferenceSystem.java | 24 ++++- .../gazetteer/MilitaryGridReferenceSystem.java | 23 ++++- .../gazetteer/ReferencingByIdentifiers.java | 9 +- .../gazetteer/GazetteerFactoryTest.java | 55 +++++++++++ .../suite/ReferencingByIdentifiersTestSuite.java | 5 +- .../org/apache/sis/internal/util/Constants.java | 2 +- .../org/apache/sis/internal/util/package-info.java | 2 +- 11 files changed, 224 insertions(+), 9 deletions(-) diff --git a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/internal/gazetteer/Resources.java b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/internal/gazetteer/Resources.java index 4d5046afa2..cb146809ed 100644 --- a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/internal/gazetteer/Resources.java +++ b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/internal/gazetteer/Resources.java @@ -130,6 +130,11 @@ public final class Resources extends IndexedResourceBundle { */ public static final short ParentAlreadyExists_1 = 9; + /** + * No Reference System named “{0}” has been found. + */ + public static final short ReferenceSystemNotFound_1 = 16; + /** * 100 km square identifier */ diff --git a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/internal/gazetteer/Resources.properties b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/internal/gazetteer/Resources.properties index 5bdd1a77a9..d5fdfc92a1 100644 --- a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/internal/gazetteer/Resources.properties +++ b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/internal/gazetteer/Resources.properties @@ -37,6 +37,7 @@ IllegalUTMZone_1 = \u201c{0}\u201d is not a valid Universal Tra InconsistentWithGZD_2 = Square identification in the \u201c{0}\u201d reference is inconsistent with the grid zone designation. A consistent zone would be \u201c{1}\u201d. LocationTypeCycle_1 = Location type \u201c{0}\u201d can not have itself as a children. LocationTypeNotFound_1 = No location type named \u201c{0}\u201d has been found. +ReferenceSystemNotFound_1 = No Reference System named \u201c{0}\u201d has been found. OddGridCoordinateLength_1 = Can not determine dimension of \u201c{0}\u201d because of odd number of characters. ParentAlreadyExists_1 = A location type parent named \u201c{0}\u201d already exists. ChildAlreadyExists_1 = Location type parent already has a child named \u201c{0}\u201d. diff --git a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/internal/gazetteer/Resources_fr.properties b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/internal/gazetteer/Resources_fr.properties index 780664de13..9466959d3c 100644 --- a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/internal/gazetteer/Resources_fr.properties +++ b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/internal/gazetteer/Resources_fr.properties @@ -42,6 +42,7 @@ IllegalUTMZone_1 = \u00ab\u202f{0}\u202f\u00bb n\u2019est pas u InconsistentWithGZD_2 = L\u2019identification du carr\u00e9 dans la r\u00e9f\u00e9rence \u00ab\u202f{0}\u202f\u00bb n\u2019est pas coh\u00e9rente avec la d\u00e9signation de la zone de la grille. Une zone coh\u00e9rente serait \u00ab\u202f{1}\u202f\u00bb. LocationTypeCycle_1 = Le type de location \u00ab\u202f{0}\u202f\u00bb ne doit pas appara\u00eetre comme un de ses propres enfants. LocationTypeNotFound_1 = Aucun type de location nomm\u00e9 \u00ab\u202f{0}\u202f\u00bb n\u2019a \u00e9t\u00e9 trouv\u00e9. +ReferenceSystemNotFound_1 = Aucun syst\u00e8me de r\u00e9f\u00e9rence nomm\u00e9 \u00ab\u202f{0}\u202f\u00bb n\u2019a \u00e9t\u00e9 trouv\u00e9. OddGridCoordinateLength_1 = Ne peut pas d\u00e9terminer la dimension de \u00ab\u202f{0}\u202f\u00bb \u00e0 cause du nombre impair de caract\u00e8res. ParentAlreadyExists_1 = Un type de location parent nomm\u00e9 \u00ab\u202f{0}\u202f\u00bb existe d\u00e9j\u00e0. ChildAlreadyExists_1 = Le type de location parent a d\u00e9j\u00e0 un enfant nomm\u00e9 \u00ab\u202f{0}\u202f\u00bb. diff --git a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/GazetteerFactory.java b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/GazetteerFactory.java new file mode 100644 index 0000000000..7c38152d48 --- /dev/null +++ b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/GazetteerFactory.java @@ -0,0 +1,106 @@ +/* + * 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.gazetteer; + +import java.util.Set; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Optional; +import org.apache.sis.internal.util.Constants; +import org.apache.sis.internal.gazetteer.Resources; +import org.apache.sis.util.iso.AbstractFactory; +import org.apache.sis.util.iso.DefaultNameSpace; + + +/** + * A factory of reference systems by identifiers implemented by the SIS library. + * Current implementation can instantiate shared instances of + * {@link MilitaryGridReferenceSystem} and + * {@link GeohashReferenceSystem}. + * + * MGRS and Geohash are not really "gazetteers", but we handle them in this class + * for having a unique framework for referencing by identifiers. + * Real gazetteers may be added in a future version. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.3 + * @since 1.3 + * @module + */ +public class GazetteerFactory extends AbstractFactory { + /** + * Creates a new factory. + */ + public GazetteerFactory() { + } + + /** + * Returns the name of referencing systems known to this factory. + * + * @return names of known reference systems. + */ + public Set<String> getSupportedNames() { + /* + * In current implementation of `sis-javafx` module, the order in this set determines the order + * of menu items. So we want a "nice" order and a `Set` implementation that preserve it. + */ + return new LinkedHashSet<>(Arrays.asList( + MilitaryGridReferenceSystem.IDENTIFIER, + GeohashReferenceSystem.IDENTIFIER)); + } + + /** + * Returns a shared instance of the reference system identified by the given name. + * The current implementation recognizes the following names (case-sensitive): + * + * <table class="sis"> + * <caption>Supported reference systems by identifiers</caption> + * <tr><th>Name</th> <th>Reference system class</th></tr> + * <tr><td>MGRS</td> <td>{@link MilitaryGridReferenceSystem}</td></tr> + * <tr><td>Geohash</td> <td>{@link GeohashReferenceSystem}</td></tr> + * </table> + * + * @param name name of the reference system to obtain. + * @return shared instance of the reference system for the given name. + * @throws GazetteerException if the reference system can not be obtained. + */ + public ReferencingByIdentifiers forName(final String name) throws GazetteerException { + return forNameIfKnown(name).orElseThrow(() -> + new GazetteerException(Resources.format(Resources.Keys.ReferenceSystemNotFound_1, name))); + } + + /** + * Optionally returns a shared instance of the reference system identified by the given name. + * This method performs the same work than {@link #forName(String)} but without throwing an + * exception if the given name is unknown. + * + * @param name name of the reference system to obtain. + * @return shared instance of the reference system for the given name. + * @throws GazetteerException if the reference system can not be obtained. + */ + public Optional<ReferencingByIdentifiers> forNameIfKnown(String name) throws GazetteerException { + final int s = name.lastIndexOf(DefaultNameSpace.DEFAULT_SEPARATOR); + if (s < 0 || name.substring(0, s).trim().equalsIgnoreCase(Constants.SIS)) { + name = name.substring(s + 1).trim(); + switch (name) { + case MilitaryGridReferenceSystem.IDENTIFIER: return Optional.of(MilitaryGridReferenceSystem.getInstance()); + case GeohashReferenceSystem .IDENTIFIER: return Optional.of(GeohashReferenceSystem .getInstance()); + } + } + return Optional.empty(); + } +} diff --git a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/GeohashReferenceSystem.java b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/GeohashReferenceSystem.java index 7340a140cc..185b8a1dde 100644 --- a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/GeohashReferenceSystem.java +++ b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/GeohashReferenceSystem.java @@ -74,6 +74,11 @@ public class GeohashReferenceSystem extends ReferencingByIdentifiers { */ private static final long serialVersionUID = 9162259764027168776L; + /** + * Identifier for this reference system. + */ + static final String IDENTIFIER = "Geohash"; + /** * The encoding format used by {@link GeohashReferenceSystem.Coder}. */ @@ -153,6 +158,21 @@ public class GeohashReferenceSystem extends ReferencingByIdentifiers { */ final CoordinateOperation denormalize; + /** + * The unique instance, created when first requested. + */ + private static GeohashReferenceSystem INSTANCE; + + /** + * Returns the unique instance. + */ + static synchronized GeohashReferenceSystem getInstance() throws GazetteerException { + if (INSTANCE == null) { + INSTANCE = new GeohashReferenceSystem(Format.BASE32, CommonCRS.WGS84.geographic()); + } + return INSTANCE; + } + /** * Creates a new geohash reference system for the given format and coordinate reference system. * @@ -161,7 +181,7 @@ public class GeohashReferenceSystem extends ReferencingByIdentifiers { * @throws GazetteerException if the reference system can not be created. */ public GeohashReferenceSystem(final Format format, final GeographicCRS crs) throws GazetteerException { - super(properties("Geohash", null), types()); + super(properties(IDENTIFIER, IDENTIFIER, null), types()); ArgumentChecks.ensureNonNull("format", format); ArgumentChecks.ensureNonNull("crs", crs); ArgumentChecks.ensureDimensionMatches("crs", 2, crs); @@ -180,7 +200,7 @@ public class GeohashReferenceSystem extends ReferencingByIdentifiers { */ @Workaround(library="JDK", version="1.8") private static LocationType[] types() { - final ModifiableLocationType gzd = new ModifiableLocationType("Geohash"); + final ModifiableLocationType gzd = new ModifiableLocationType(IDENTIFIER); gzd.addIdentification(Vocabulary.formatInternational(Vocabulary.Keys.Code)); return new LocationType[] {gzd}; } diff --git a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java index 1d62ed8acd..12ade70c13 100644 --- a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java +++ b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java @@ -160,6 +160,11 @@ public class MilitaryGridReferenceSystem extends ReferencingByIdentifiers { */ private static final long serialVersionUID = 8337394374656125471L; + /** + * Identifier for this reference system. + */ + static final String IDENTIFIER = "MGRS"; + /** * Height of latitude bands, in degrees. * Those bands are labeled from {@code 'C'} to {@code 'X'} inclusive, excluding {@code 'I'} and {@code 'O'}. @@ -251,6 +256,21 @@ public class MilitaryGridReferenceSystem extends ReferencingByIdentifiers { */ private transient short northOffset; + /** + * The unique instance, created when first requested. + */ + private static MilitaryGridReferenceSystem INSTANCE; + + /** + * Returns the unique instance. + */ + static synchronized MilitaryGridReferenceSystem getInstance() { + if (INSTANCE == null) { + INSTANCE = new MilitaryGridReferenceSystem(); + } + return INSTANCE; + } + /** * Creates a new Military Grid Reference System (MGRS) using the default datum. * The current Apache SIS version uses the {@linkplain CommonCRS#WGS84 WGS84} datum, @@ -290,7 +310,8 @@ public class MilitaryGridReferenceSystem extends ReferencingByIdentifiers { Logging.unexpectedException(getLogger(Modules.REFERENCING_BY_IDENTIFIERS), MilitaryGridReferenceSystem.class, "<init>", e); } - return properties(new NamedIdentifier(null, "NATO", Resources.formatInternational(Resources.Keys.MGRS), null, null), party); + NamedIdentifier name = new NamedIdentifier(null, "NATO", Resources.formatInternational(Resources.Keys.MGRS), null, null); + return properties(name, IDENTIFIER, party); } /** diff --git a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java index 1cebee5ba7..45477c973e 100644 --- a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java +++ b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java @@ -28,6 +28,7 @@ import org.opengis.util.InternationalString; import org.opengis.geometry.DirectPosition; import org.opengis.referencing.operation.TransformException; import org.apache.sis.referencing.AbstractReferenceSystem; +import org.apache.sis.referencing.ImmutableIdentifier; import org.apache.sis.util.collection.Containers; import org.apache.sis.util.logging.Logging; import org.apache.sis.util.ComparisonMode; @@ -37,8 +38,10 @@ import org.apache.sis.util.Debug; import org.apache.sis.io.wkt.Formatter; import org.apache.sis.io.wkt.ElementKind; import org.apache.sis.metadata.iso.extent.Extents; +import org.apache.sis.metadata.iso.citation.Citations; import org.apache.sis.internal.referencing.WKTUtilities; import org.apache.sis.internal.system.Modules; +import org.apache.sis.internal.util.Constants; import org.apache.sis.io.wkt.FormattableObject; import org.apache.sis.util.resources.Vocabulary; @@ -180,11 +183,13 @@ public abstract class ReferencingByIdentifiers extends AbstractReferenceSystem i * The returned properties have the domain of validity set to the whole word and the theme to "mapping". * * @param name the reference system name as an {@link org.opengis.metadata.Identifier} or a {@link String}. + * @param id an identifier for the reference system. Use SIS namespace until we find an authority for them. * @param party the overall owner, or {@code null} if none. */ - static Map<String,Object> properties(final Object name, final Party party) { - final Map<String,Object> properties = new HashMap<>(6); + static Map<String,Object> properties(final Object name, final String id, final Party party) { + final Map<String,Object> properties = new HashMap<>(8); properties.put(NAME_KEY, name); + properties.put(IDENTIFIERS_KEY, new ImmutableIdentifier(Citations.SIS, Constants.SIS, id)); properties.put(DOMAIN_OF_VALIDITY_KEY, Extents.WORLD); properties.put(THEME_KEY, Vocabulary.formatInternational(Vocabulary.Keys.Mapping)); properties.put(OVERALL_OWNER_KEY, party); diff --git a/core/sis-referencing-by-identifiers/src/test/java/org/apache/sis/referencing/gazetteer/GazetteerFactoryTest.java b/core/sis-referencing-by-identifiers/src/test/java/org/apache/sis/referencing/gazetteer/GazetteerFactoryTest.java new file mode 100644 index 0000000000..b791442e0e --- /dev/null +++ b/core/sis-referencing-by-identifiers/src/test/java/org/apache/sis/referencing/gazetteer/GazetteerFactoryTest.java @@ -0,0 +1,55 @@ +/* + * 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.gazetteer; + +import org.apache.sis.test.TestCase; +import org.junit.Test; + +import static org.apache.sis.test.Assert.*; + + +/** + * Tests {@link GazetteerFactory}. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.3 + * @since 1.3 + * @module + */ +public final strictfp class GazetteerFactoryTest extends TestCase { + /** + * Tests {@link ReferencingByIdentifiers#getInstance(String)}. + * + * @throws GazetteerException if a reference system can not be created. + */ + @Test + public void testGetInstance() throws GazetteerException { + final GazetteerFactory factory = new GazetteerFactory(); + final ReferencingByIdentifiers r1 = factory.forName("MGRS"); + final ReferencingByIdentifiers r2 = factory.forName("Geohash"); + assertInstanceOf("MGRS", MilitaryGridReferenceSystem.class, r1); + assertInstanceOf("Geohash", GeohashReferenceSystem.class, r2); + assertSame(r1, factory.forName("MGRS")); + assertSame(r2, factory.forName("Geohash")); + try { + factory.forName("Dummy"); + fail("Should have thrown an exception"); + } catch (GazetteerException e) { + assertTrue(e.getMessage().contains("Dummy")); + } + } +} diff --git a/core/sis-referencing-by-identifiers/src/test/java/org/apache/sis/test/suite/ReferencingByIdentifiersTestSuite.java b/core/sis-referencing-by-identifiers/src/test/java/org/apache/sis/test/suite/ReferencingByIdentifiersTestSuite.java index 3d1ea09f50..cb85f380aa 100644 --- a/core/sis-referencing-by-identifiers/src/test/java/org/apache/sis/test/suite/ReferencingByIdentifiersTestSuite.java +++ b/core/sis-referencing-by-identifiers/src/test/java/org/apache/sis/test/suite/ReferencingByIdentifiersTestSuite.java @@ -25,7 +25,7 @@ import org.junit.BeforeClass; * All tests from the {@code sis-referencing-by-identifiers} module, in rough dependency order. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.3 * @since 0.8 * @module */ @@ -34,7 +34,8 @@ import org.junit.BeforeClass; org.apache.sis.referencing.gazetteer.LocationTypeTest.class, org.apache.sis.referencing.gazetteer.ReferencingByIdentifiersTest.class, org.apache.sis.referencing.gazetteer.GeohashReferenceSystemTest.class, - org.apache.sis.referencing.gazetteer.MilitaryGridReferenceSystemTest.class + org.apache.sis.referencing.gazetteer.MilitaryGridReferenceSystemTest.class, + org.apache.sis.referencing.gazetteer.GazetteerFactoryTest.class }) public final strictfp class ReferencingByIdentifiersTestSuite extends TestSuite { /** diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java b/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java index e5e61a5d59..8dc4e61747 100644 --- a/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java +++ b/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java @@ -90,7 +90,7 @@ public final class Constants extends Static { /** * The {@value} code space. The project name is {@code "Proj.4"}, but this constant omits - * the dot because this name is used as a codes pace and we want to avoid risk of confusion. + * the dot because this name is used as a code space and we want to avoid risk of confusion. */ public static final String PROJ4 = "Proj4"; diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/util/package-info.java b/core/sis-utility/src/main/java/org/apache/sis/internal/util/package-info.java index 8d4ec29aba..0146bec0dd 100644 --- a/core/sis-utility/src/main/java/org/apache/sis/internal/util/package-info.java +++ b/core/sis-utility/src/main/java/org/apache/sis/internal/util/package-info.java @@ -30,7 +30,7 @@ * so some serialized classes still exist in this package. * * @author Martin Desruisseaux (Geomatys) - * @version 1.2 + * @version 1.3 * @since 0.3 * @module */
