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 a0c8157ef69586deff69e11e68b1d88fd727daf0 Author: Martin Desruisseaux <[email protected]> AuthorDate: Tue Sep 9 12:27:30 2025 +0200 Remove the hack which were added for testing SIS with EPSG 9 or 12. Even if SIS should still be compatible with EPSG 9, the tests now assume EPSG 12. --- .../apache/sis/console/FormattedOutputCommand.java | 2 +- .../org/apache/sis/console/TransformCommand.java | 4 +- .../org/apache/sis/console/CRSCommandTest.java | 13 +++++ .../org/apache/sis/xml/bind/lan/PT_FreeText.java | 2 +- .../sis/openoffice/ReferencingFunctions.java | 10 +++- .../sis/openoffice/ReferencingFunctionsTest.java | 8 +-- .../apache/sis/io/wkt/GeodeticObjectParser.java | 4 +- .../referencing/factory/AuthorityFactoryProxy.java | 33 +++++++---- .../factory/MultiAuthoritiesFactory.java | 2 +- .../referencing/factory/sql/EPSGDataAccess.java | 12 +--- .../sis/io/wkt/GeodeticObjectParserTest.java | 7 ++- .../org/apache/sis/referencing/Assertions.java | 67 +--------------------- .../org/apache/sis/referencing/CommonCRSTest.java | 2 +- .../sis/referencing/GeodeticObjectVerifier.java | 10 +++- .../referencing/factory/sql/EPSGFactoryTest.java | 9 ++- .../referencing/operation/PassThroughOperation.xml | 4 +- .../report/CoordinateReferenceSystems.java | 4 +- .../sis/test/integration/ConsistencyTest.java | 41 +++---------- .../main/org/apache/sis/storage/base/CodeType.java | 25 +++++--- 19 files changed, 105 insertions(+), 154 deletions(-) diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/FormattedOutputCommand.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/FormattedOutputCommand.java index 5103b1fc6e..24eae3bcc9 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/FormattedOutputCommand.java +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/FormattedOutputCommand.java @@ -201,7 +201,7 @@ abstract class FormattedOutputCommand extends CommandRunner { final Object file = files.get(0); if (file instanceof CharSequence) { final String c = file.toString(); - if (CodeType.guess(c).isCRS) { + if (CodeType.guess(c).isAuthorityCode) { return CRS.forCode(c); } } diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TransformCommand.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TransformCommand.java index 9b116648f9..220a599de1 100644 --- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TransformCommand.java +++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TransformCommand.java @@ -207,7 +207,7 @@ final class TransformCommand extends FormattedOutputCommand { private void fetchOperation(Object identifier) throws Exception { if (identifier instanceof CharSequence) { final String c = identifier.toString(); - if (CodeType.guess(c).isCRS) try { + if (CodeType.guess(c).isAuthorityCode) try { var factory = (CoordinateOperationAuthorityFactory) CRS.getAuthorityFactory(null); operation = factory.createCoordinateOperation(c); return; @@ -239,7 +239,7 @@ final class TransformCommand extends FormattedOutputCommand { } if (identifier instanceof CharSequence) { final String c = identifier.toString(); - if (CodeType.guess(c).isCRS) try { + if (CodeType.guess(c).isAuthorityCode) try { return CRS.forCode(c); } catch (NoSuchAuthorityCodeException e) { throw illegalOptionValue(option, identifier, e); diff --git a/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/CRSCommandTest.java b/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/CRSCommandTest.java index 9fd80d809e..91f0aded84 100644 --- a/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/CRSCommandTest.java +++ b/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/CRSCommandTest.java @@ -21,6 +21,7 @@ import org.apache.sis.util.CharSequences; // Test dependencies import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assumptions.assumeFalse; import org.apache.sis.test.TestCase; @@ -66,6 +67,15 @@ public final class CRSCommandTest extends TestCase { WGS84 = CharSequences.replace(WGS84, "\n", System.lineSeparator()).toString(); } + /** + * Interrupts the test if the <abbr>EPSG</abbr> database does not seem present. + * We recognize this situation by the fact that the {@code CommonCRS} fallback + * defines the datum in the old way. + */ + private static void assumeEPSG(final String wkt) { + assumeFalse(wkt.contains("Datum[\"World Geodetic System 1984\""), "Requires EPSG geodetic database."); + } + /** * Tests fetching the CRS from a simple code ({@code "EPSG:4326"}). * @@ -76,6 +86,7 @@ public final class CRSCommandTest extends TestCase { var test = new CRSCommand(0, new String[] {CommandRunner.TEST, "EPSG:4326"}); test.run(); String wkt = test.outputBuffer.toString(); + assumeEPSG(wkt); assertTrue(wkt.matches(WGS84), wkt); } @@ -89,6 +100,7 @@ public final class CRSCommandTest extends TestCase { var test = new CRSCommand(0, new String[] {CommandRunner.TEST, "urn:ogc:def:crs:epsg::4326"}); test.run(); String wkt = test.outputBuffer.toString(); + assumeEPSG(wkt); assertTrue(wkt.matches(WGS84), wkt); } @@ -102,6 +114,7 @@ public final class CRSCommandTest extends TestCase { var test = new CRSCommand(0, new String[] {CommandRunner.TEST, "http://www.opengis.net/gml/srs/epsg.xml#4326"}); test.run(); String wkt = test.outputBuffer.toString(); + assumeEPSG(wkt); assertTrue(wkt.matches(WGS84), wkt); } } diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/lan/PT_FreeText.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/lan/PT_FreeText.java index 3059253daa..ae4c7aa1c7 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/lan/PT_FreeText.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/lan/PT_FreeText.java @@ -169,7 +169,7 @@ public final class PT_FreeText extends GO_CharacterString { * If the <gco:CharacterString> value is repeated in one of the * <lan:LocalisedCharacterString> elements, keep only the localized * version (because it specifies the locale, while the unlocalized - * string saids nothing on that matter). + * string said nothing on that matter). */ defaultValue = null; } diff --git a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java index 6384701b86..c5337d7ae0 100644 --- a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java +++ b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java @@ -130,7 +130,7 @@ public class ReferencingFunctions extends CalcAddins implements XReferencing { } else { object = factory.createCoordinateReferenceSystem(codeOrPath); } - } else if (type.isCRS) { + } else if (type.isAuthorityCode) { object = CRS.forCode(codeOrPath); } else { /* @@ -174,8 +174,12 @@ public class ReferencingFunctions extends CalcAddins implements XReferencing { try { final IdentifiedObject object; final CodeType type = CodeType.guess(codeOrPath); - if (type.isCRS) { + Class<? extends IdentifiedObject> classe = CoordinateReferenceSystem.class; + if (type.isAuthorityCode) { object = new CacheKey<>(IdentifiedObject.class, codeOrPath, null, null).peek(); + if (type.isURI) { + classe = IdentifiedObject.class; // The actual type will be detected from the URI. + } } else { object = getIdentifiedObject(codeOrPath, type); } @@ -183,7 +187,7 @@ public class ReferencingFunctions extends CalcAddins implements XReferencing { return object.getName().getCode(); } // In Apache SIS implementation, `getDescriptionText(…)` returns the identified object name. - name = CRS.getAuthorityFactory(null).getDescriptionText(CoordinateReferenceSystem.class, codeOrPath).orElse(null); + name = CRS.getAuthorityFactory(null).getDescriptionText(classe, codeOrPath).orElse(null); } catch (Exception exception) { return getLocalizedMessage(exception); } diff --git a/endorsed/src/org.apache.sis.openoffice/test/org/apache/sis/openoffice/ReferencingFunctionsTest.java b/endorsed/src/org.apache.sis.openoffice/test/org/apache/sis/openoffice/ReferencingFunctionsTest.java index 69a701b16b..9bf8f5783b 100644 --- a/endorsed/src/org.apache.sis.openoffice/test/org/apache/sis/openoffice/ReferencingFunctionsTest.java +++ b/endorsed/src/org.apache.sis.openoffice/test/org/apache/sis/openoffice/ReferencingFunctionsTest.java @@ -26,7 +26,6 @@ import org.junit.jupiter.api.TestInstance; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assumptions.assumeFalse; import org.apache.sis.test.TestCase; -import org.apache.sis.referencing.Assertions; /** @@ -67,7 +66,8 @@ public final class ReferencingFunctionsTest extends TestCase { assertEquals("WGS 84", instance.getName("urn:ogc:def:crs:epsg::4326")); assertEquals("WGS 84", instance.getName("http://www.opengis.net/gml/srs/epsg.xml#4326")); assertEquals("WGS 84", instance.getName("EPSG:4326")); - Assertions.assertLegacyEquals("World Geodetic System 1984", instance.getName("urn:ogc:def:datum:epsg::6326")); + String name = instance.getName("urn:ogc:def:datum:epsg::6326"); + assertTrue(name.startsWith("World Geodetic System 1984"), name); } /** @@ -89,8 +89,8 @@ public final class ReferencingFunctionsTest extends TestCase { assertEquals("Latitude (°)", instance.getAxis("EPSG:4326", 1)); assertEquals("Longitude (°)", instance.getAxis("EPSG:4326", 2)); assertEquals("Index 3 is out of bounds.", instance.getAxis("EPSG:4326", 3)); - Assertions.assertLegacyEquals("Expected “urn:ogc:def:datum:epsg::6326” to reference an instance of ‘CoordinateReferenceSystem’, " + - "but found an instance of ‘GeodeticDatum’.", instance.getAxis("urn:ogc:def:datum:epsg::6326", 1)); + assertEquals("Expected “urn:ogc:def:datum:epsg::6322” to reference an instance of ‘CoordinateReferenceSystem’, " + + "but found an instance of ‘GeodeticDatum’.", instance.getAxis("urn:ogc:def:datum:epsg::6322", 1)); } /** diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java index be3ca10f52..b1684dc0b2 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java @@ -529,7 +529,7 @@ class GeodeticObjectParser extends MathTransformParser implements Comparator<Coo * wrapped inside an {@code USAGE} element in <abbr>ISO</abbr> 19162:2019. * * <h4>Extension to <abbr>ISO</abbr> 19162 specification</h4> - * The specification saids that at most one extent of each type can appear in the same {@code USAGE}. + * The specification said that at most one extent of each type can appear in the same {@code USAGE}. * However, Apache <abbr>SIS</abbr> puts no limit on the number of occurrence of each extent type. * * <h4>Limitations</h4> @@ -1482,7 +1482,7 @@ class GeodeticObjectParser extends MathTransformParser implements Comparator<Coo if (ellipsoid != null) { // `memberType` may be `Datum` or `GeodeticDatum` member = datumFactory.createGeodeticDatum(properties, ellipsoid, meridian); } else if (vertical) { - member = datumFactory.createVerticalDatum(properties, null); + member = datumFactory.createVerticalDatum(properties, VerticalDatumTypes.fromDatum(name, null, null)); } else if (datumType == TemporalDatum.class) { member = datumFactory.createTemporalDatum(properties, null); } else if (datumType == ParametricDatum.class) { diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java index 96018ea2c8..392b1bace3 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java @@ -172,18 +172,31 @@ abstract class AuthorityFactoryProxy<T> { /** * The proxy for the {@link GeodeticAuthorityFactory#getDescriptionText(Class, String)} method. - * - * @param classe the type of object for which to get a description. */ - static final AuthorityFactoryProxy<InternationalString> description(final Class<? extends IdentifiedObject> classe) { - return new AuthorityFactoryProxy<InternationalString>(InternationalString.class, AuthorityFactoryIdentifier.Type.ANY) { - @Override InternationalString createFromAPI(AuthorityFactory factory, String code) throws FactoryException { - return factory.getDescriptionText(classe, code).orElse(null); - } - @Override AuthorityFactoryProxy<InternationalString> specialize(String typeName) { + static final class Description extends AuthorityFactoryProxy<InternationalString> { + /** The type of object for which to get a description. */ + private Class<? extends IdentifiedObject> typeToSearch; + + /** Creates a new proxy for fetching an object description. */ + Description(final Class<? extends IdentifiedObject> typeToSearch) { + super(InternationalString.class, AuthorityFactoryIdentifier.Type.ANY); + this.typeToSearch = typeToSearch; + } + + /** Creates the object for the given code using only GeoAPI interfaces. */ + @Override InternationalString createFromAPI(AuthorityFactory factory, String code) throws FactoryException { + return factory.getDescriptionText(typeToSearch, code).orElse(null); + } + + /** Specialize the type of object to search. */ + @Override AuthorityFactoryProxy<InternationalString> specialize(String typeName) { + final AuthorityFactoryProxy<?> c = BY_URN_TYPE.get(typeName.toLowerCase(Locale.US)); + if (c != null && typeToSearch.isAssignableFrom(c.type)) { + typeToSearch = c.type.asSubclass(IdentifiedObject.class); return this; } - }; + return null; // The given type is illegal. + } } /** @@ -627,7 +640,7 @@ abstract class AuthorityFactoryProxy<T> { } /** - * The proxy to use for a given type declared in a URN. + * The proxy to use for a given type declared in a <abbr>URN</abbr>. * For example in the {@code "urn:ogc:def:crs:EPSG::4326"} URN, the proxy to use is {@link #CRS}. * * @param typeName the name of URN type. diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java index 7a86244ee2..d20b762364 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java @@ -894,7 +894,7 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements public Optional<InternationalString> getDescriptionText(Class<? extends IdentifiedObject> type, String code) throws FactoryException { - return Optional.ofNullable(create(AuthorityFactoryProxy.description(type), code)); + return Optional.ofNullable(create(new AuthorityFactoryProxy.Description(type), code)); } /** diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java index 5cf8fe2fc9..a18d39d05b 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java @@ -1706,15 +1706,9 @@ search: try (ResultSet result = executeMetadataQuery("Deprecation", final boolean old = !deprecated || Semaphores.queryAndSet(Semaphores.SUSPEND_PARAMETER_CHECK); try { /* - * For a ProjectedCRS, the baseCRS is always geodetic. So in theory we would not - * need the `instanceof` check. However, the EPSG dataset version 8.9 also uses the - * "projected" type for CRS that are actually derived CRS. See EPSG:5820 and 5821. - * - * TODO: there is an ambiguity when the source CRS is geographic but the operation - * is nevertheless considered as not a map projection. It is the case of EPSG:5819. - * The problem is that the "COORD_REF_SYS_KIND" column still contains "Projected". - * We need to check if EPSG database 10+ has more specific information. - * See https://issues.apache.org/jira/browse/SIS-518 + * For a ProjectedCRS, the baseCRS is usually geodetic. However, geocentric CRS + * is also allowed, but not yet supported in the code below. We could also have + * a ProjectedCRS derived from another ProjectedCRS. */ if (baseCRS instanceof GeodeticCRS) { return factory.createProjectedCRS(metadata, (GeodeticCRS) baseCRS, fromBase, cs); diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java index 2ab3b9764b..74a0546aab 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java @@ -103,8 +103,7 @@ public final class GeodeticObjectParserTest extends EPSGDependentTestCase { final Object obj = parser.createFromWKT(text, position); assertEquals(-1, position.getErrorIndex(), "errorIndex"); assertEquals(text.length(), position.getIndex(), "index"); - assertInstanceOf(type, obj, "GeodeticObjectParser.parseObject"); - return type.cast(obj); + return assertInstanceOf(type, obj, "GeodeticObjectParser.parseObject"); } /** @@ -508,7 +507,7 @@ public final class GeodeticObjectParserTest extends EPSGDependentTestCase { public void testGeographicCRSWithEnsemble() throws ParseException { final GeographicCRS crs = parse(GeographicCRS.class, "GeodeticCRS[“WGS 84”,\n" + - " Ensemble[“World Geodetic System 1984”,\n" + + " Ensemble[“World Geodetic System 1984”,\n" + // No "ensemble" suffix because of `verifyGeographicCRS(…)` " Member[“World Geodetic System 1984 (Transit)”],\n" + " Member[“World Geodetic System 1984 (G730)”],\n" + " Member[“World Geodetic System 1984 (G873)”],\n" + @@ -1073,6 +1072,8 @@ public final class GeodeticObjectParserTest extends EPSGDependentTestCase { /** * Tests the parsing of a derived CRS from a WKT 2 string. + * Note: this test uses an example from an old <abbr>EPSG</abbr> + * geodetic dataset which is no longer present in more recent versions. * * @throws ParseException if the parsing failed. */ diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/Assertions.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/Assertions.java index 3c5556d432..aeac79e29b 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/Assertions.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/Assertions.java @@ -77,20 +77,6 @@ public final class Assertions extends Static { WKT_FORMAT.setSymbols(s); } - /** - * Replacements to perform in <abbr>WKT</abbr> strings for compatibility between different versions - * of the <abbr>EPSG</abbr> geodetic dataset. Values at even indexes are legacy names that may still - * be present in the tests. Values at odd indexes are the names as they may be formatted when using - * newer versions of the <abbr>EPSG</abbr> geodetic dataset. - * - * <p>We may remove this hack in a future <abbr>SIS</abbr> version if we abandon support of version 9 - * of <abbr>EPSG</abbr> dataset (the current version at the time of writing is 12).</p> - */ - private static final String[] REPLACEMENTS = { - "“World Geodetic System 1984”", "“World Geodetic System 1984 ensemble”", - "“NGF IGN69 height”", "“NGF-IGN69 height”" - }; - /** * Do not allow instantiation of this class. */ @@ -137,10 +123,10 @@ public final class Assertions extends Static { */ public static void assertEpsgIdentifierEquals(final String expected, final Identifier actual) { assertNotNull(actual); - assertLegacyEquals(expected, actual.getCode(), "code"); + assertEquals(expected, actual.getCode(), "code"); assertEquals(Constants.EPSG, actual.getCodeSpace(), "codeSpace"); assertEquals(Constants.EPSG, Citations.toCodeSpace(actual.getAuthority()), "authority"); - assertLegacyEquals(Constants.EPSG + Constants.DEFAULT_SEPARATOR + expected, IdentifiedObjects.toString(actual), "identifier"); + assertEquals(Constants.EPSG + Constants.DEFAULT_SEPARATOR + expected, IdentifiedObjects.toString(actual), "identifier"); } /** @@ -500,48 +486,6 @@ public final class Assertions extends Static { } } - /** - * Asserts that the given string is equal to the expected string, - * with a tolerance for name changes in <abbr>EPSG</abbr> database. - * If the expected string is a old name while the actual string is a new name, - * then they are considered equal. - * - * <p>We may remove this hack in a future <abbr>SIS</abbr> version if we abandon support of version 9 - * of <abbr>EPSG</abbr> dataset (the current version at the time of writing is 12). If this method is - * removed, it would be replaced by an ordinary {@code assertEquals}.</p> - * - * @param expected the expected string. - * @param actual the actual string. - */ - public static void assertLegacyEquals(final String expected, final String actual) { - assertLegacyEquals(expected, actual, null); - } - - static void assertLegacyEquals(String expected, final String actual, final String message) { - if (expected != null && actual != null) { - for (int i=0; i < REPLACEMENTS.length;) { - final String oldName = REPLACEMENTS[i++]; - final String newName = REPLACEMENTS[i++]; - final int ol = oldName.length() - 2; // Omit quotes. - final int nl = newName.length() - 2; - final int s = expected.length() - ol; - if (expected.regionMatches(s, oldName, 1, ol) && - actual.regionMatches(actual.length() - nl, newName, 1, nl)) - { - expected = expected.substring(0, s) + newName.substring(1, nl + 1); - } - } - if (expected.replace("GeodeticDatum", "DatumEnsemble").equals(actual)) { - return; - } - } - if (message != null) { - assertEquals(expected, actual, message); - } else { - assertEquals(expected, actual); - } - } - /** * Asserts that the WKT of the given object according the given convention is equal to the expected one. * This method expected the {@code “…”} quotation marks instead of {@code "…"} for easier readability of @@ -561,13 +505,6 @@ public final class Assertions extends Static { WKT_FORMAT.setConvention(convention); wkt = WKT_FORMAT.format(object); } - for (int i=0; i < REPLACEMENTS.length;) { - final String oldName = REPLACEMENTS[i++]; - final String newName = REPLACEMENTS[i++]; - if (expected.contains(oldName) && wkt.contains(newName)) { - expected = expected.replace(oldName, newName); - } - } assertMultilinesEquals(expected, wkt, (object instanceof IdentifiedObject) ? ((IdentifiedObject) object).getName().getCode() : object.getClass().getSimpleName()); } diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java index 7551ac1fe6..b49e9b122c 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java @@ -399,7 +399,7 @@ public final class CommonCRSTest extends EPSGDependentTestCase { */ @Test public void testFormat() { - Assertions.assertLegacyEquals("World Geodetic System 1984", String.format("%s", CommonCRS.WGS84.datum(true))); + assertTrue(String.format("%s", CommonCRS.WGS84.datum(true)).startsWith("World Geodetic System 1984")); assertTrue(String.format("%S", CommonCRS.WGS84.datum(true)).startsWith("WORLD GEODETIC SYSTEM 1984")); assertTrue(String.format("%#s", CommonCRS.WGS84.datum(true)).endsWith(":6326")); } diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/GeodeticObjectVerifier.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/GeodeticObjectVerifier.java index 4eee79a3ef..d9f5aca0fe 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/GeodeticObjectVerifier.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/GeodeticObjectVerifier.java @@ -41,6 +41,7 @@ import static org.junit.jupiter.api.Assertions.*; // Specific to the geoapi-3.1 and geoapi-4.0 branches: import org.opengis.referencing.ObjectDomain; +import org.opengis.referencing.datum.DatumEnsemble; /** @@ -206,7 +207,7 @@ public final class GeodeticObjectVerifier { * <caption>Verified properties</caption> * <tr><th>Property</th> <th>Expected value</th></tr> * <tr><td>{@linkplain Identifier#getCode() Code} of the {@linkplain GeodeticDatum#getName() name}</td> - * <td>{@code "World Geodetic System 1984"}</td></tr> + * <td>{@code "World Geodetic System 1984 [ensemble]"}</td></tr> * <tr><td>{@linkplain GeodeticDatum#getDomains() Domain of validity}</td> * <td>{@linkplain #assertIsWorld(GeographicBoundingBox) Is world} or absent</td></tr> * <tr><td>{@linkplain GeodeticDatum#getPrimeMeridian() Prime meridian}</td> @@ -220,7 +221,12 @@ public final class GeodeticObjectVerifier { * {@code Extent} element for the world, or {@code false} if optional. */ public static void assertIsWGS84(final GeodeticDatum datum, final boolean isExtentMandatory) { - Assertions.assertLegacyEquals("World Geodetic System 1984", datum.getName().getCode(), "name"); + final String name = datum.getName().getCode(); + String expected = "World Geodetic System 1984"; + if (datum instanceof DatumEnsemble<?>) { + expected += " ensemble"; + } + assertEquals (expected, name, "name"); assertIsWorld (datum, isExtentMandatory); assertIsGreenwich(datum.getPrimeMeridian()); assertIsWGS84 (datum.getEllipsoid()); diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java index 985c0fa85b..fa71a1af30 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java @@ -118,7 +118,10 @@ public final class EPSGFactoryTest extends TestCaseWithLogs { final EPSGFactory factory = dataEPSG.factory(); final GeographicCRS crs = factory.createGeographicCRS("EPSG:4326"); assertEpsgNameAndIdentifierEqual("WGS 84", 4326, crs); - assertEpsgNameAndIdentifierEqual("World Geodetic System 1984", 6326, DatumOrEnsemble.of(crs)); + + String expected = "World Geodetic System 1984"; + if (crs.getDatum() == null) expected += " ensemble"; + assertEpsgNameAndIdentifierEqual(expected, 6326, DatumOrEnsemble.of(crs)); assertAxisDirectionsEqual(crs.getCoordinateSystem(), AxisDirection.NORTH, AxisDirection.EAST); assertSame(crs, factory.createCoordinateReferenceSystem("4326"), "CRS shall be cached."); @@ -382,7 +385,7 @@ public final class EPSGFactoryTest extends TestCaseWithLogs { } /** - * Tests the "NTF (Paris) + NGF IGN69 height" compound CRS (EPSG:7400). + * Tests the "NTF (Paris) + NGF-IGN69 height" compound CRS (EPSG:7400). * This method tests also the domain of validity. * * @throws FactoryException if an error occurred while querying the factory. @@ -391,7 +394,7 @@ public final class EPSGFactoryTest extends TestCaseWithLogs { public void testCompound() throws FactoryException { final EPSGFactory factory = dataEPSG.factory(); final CompoundCRS crs = factory.createCompoundCRS("EPSG:7400"); - assertEpsgNameAndIdentifierEqual("NTF (Paris) + NGF IGN69 height", 7400, crs); + assertEpsgNameAndIdentifierEqual("NTF (Paris) + NGF-IGN69 height", 7400, crs); final List<CoordinateReferenceSystem> components = crs.getComponents(); assertEquals(2, components.size()); diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/PassThroughOperation.xml b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/PassThroughOperation.xml index 24a59a40f3..f4c7b31b94 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/PassThroughOperation.xml +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/PassThroughOperation.xml @@ -35,7 +35,7 @@ --> <gml:CompoundCRS gml:id="test-crs-source"> <gml:identifier codeSpace="test">source</gml:identifier> - <gml:name>NTF (Paris) + NGF IGN69 height</gml:name> + <gml:name>NTF (Paris) + NGF-IGN69 height</gml:name> <gml:scope>None.</gml:scope> <gml:componentReferenceSystem> <gml:GeodeticCRS gml:id="test-crs-paris"> @@ -133,7 +133,7 @@ <gml:targetCRS> <gml:CompoundCRS gml:id="test-crs-target"> <gml:identifier codeSpace="test">target</gml:identifier> - <gml:name>NTF + NGF IGN69 height</gml:name> + <gml:name>NTF + NGF-IGN69 height</gml:name> <gml:scope>None.</gml:scope> <gml:componentReferenceSystem> <gml:GeodeticCRS gml:id="test-crs-greenwich"> diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/report/CoordinateReferenceSystems.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/report/CoordinateReferenceSystems.java index 3e9e807f75..987773b132 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/report/CoordinateReferenceSystems.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/report/CoordinateReferenceSystems.java @@ -311,7 +311,7 @@ public final class CoordinateReferenceSystems extends AuthorityCodesReport { * we need to cut before those numbers in order to use sorting by EPSG codes instead. * * Note 2: if alphabetical sorting is okay for Roman numbers, it is actually preferable - * because it give better position of names with height like "zone II + NGF IGN69 height". + * because it give better position of names with height like "zone II + NGF-IGN69 height". */ private static final String[] CUT_AFTER = { " cs ", // "JGD2000 / Japan Plane Rectangular CS IX" @@ -321,7 +321,7 @@ public final class CoordinateReferenceSystems extends AuthorityCodesReport { " philippines zone ", // "Luzon 1911 / Philippines zone IV" " california zone ", // "NAD27 / California zone V" " ngo zone ", // "NGO 1948 (Oslo) / NGO zone I" - " lambert zone ", // "NTF (Paris) / Lambert zone II + NGF IGN69 height" + " lambert zone ", // "NTF (Paris) / Lambert zone II + NGF-IGN69 height" "fiji 1956 / utm zone " // Two zones: 60S and 1S with 60 before 1. }; diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/ConsistencyTest.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/ConsistencyTest.java index 487645a33a..c73e55f4e9 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/ConsistencyTest.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/ConsistencyTest.java @@ -22,11 +22,9 @@ import javax.measure.Quantity; import javax.measure.Unit; import javax.measure.UnitConverter; import org.opengis.metadata.Identifier; -import org.opengis.util.CodeList; import org.opengis.util.FactoryException; import org.opengis.util.NoSuchIdentifierException; import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.opengis.referencing.crs.VerticalCRS; import org.apache.sis.referencing.IdentifiedObjects; import org.apache.sis.referencing.CRS; import org.apache.sis.referencing.factory.FactoryDataException; @@ -66,8 +64,6 @@ public final class ConsistencyTest extends TestCase { */ private final Set<String> EXCLUDES = Set.of( "CRS:1", // Computer display: WKT parser alters the (i,j) axis names. - "EPSG:5819", // EPSG topocentric example A: DerivedCRS wrongly handled as a ProjectedCRS. See SIS-518. - "EPSG:5820", // EPSG topocentric example B. "AUTO2:42001", // This projection requires parameters, but we provide none. "AUTO2:42002", // This projection requires parameters, but we provide none. "AUTO2:42003", // This projection requires parameters, but we provide none. @@ -77,11 +73,16 @@ public final class ConsistencyTest extends TestCase { /** * Elements to ignore when comparing the <abbr>WKT</abbr> strings. * We ignore the vertical extent because in the current <abbr>SIS</abbr> implementation, - * the unit of measurement is inferred from the <abbr>CRS</abbr> and there is no east way + * the unit of measurement is inferred from the <abbr>CRS</abbr> and there is no easy way * to rebuild the <abbr>CRS</abbr> at parsing time. + * + * <p>We ignore also the vertical datum type when using <abbr>WKT</abbr> 1 because that + * element contained a "Vertical Datum Type" numerical code, which has been removed in + * more recent standards and is very difficult to preserve.</p> */ private final String[] WKT_TO_IGNORE = { - "VERTICALEXTENT" + "VERTICALEXTENT", + "VERT_DATUM" // WKT 1. }; /** @@ -114,26 +115,6 @@ public final class ConsistencyTest extends TestCase { lookup(parseAndFormat(format, code, crs), crs); } - /** - * Returns whether testing the given <abbr>CRS</abbr> requires the 2019 version of <abbr>WKT</abbr> format. - * We skip the vertical datum having the "local" realization method because this information is lost during - * the roundtrip with WKT or WKT 2 version 2015, and the WKT parser tries to guess the method from the axis - * abbreviation "d" which result in "tidal". - */ - private static boolean requiresWKT2019(final CoordinateReferenceSystem crs) { - final VerticalCRS c = CRS.getVerticalComponent(crs, false); - if (c != null) { - final var datum = c.getDatum(); - if (datum != null) { - final String method = datum.getRealizationMethod().map(CodeList::name).orElse(""); - if (method.equalsIgnoreCase("local")) { - return true; - } - } - } - return false; - } - /** * Verifies the WKT consistency of all CRS instances. * @@ -165,14 +146,6 @@ public final class ConsistencyTest extends TestCase { } lookup(parseAndFormat(v2, code, crs), crs); lookup(parseAndFormat(v2s, code, crs), crs); - /* - * There is more information lost in WKT 1 than in WKT 2, so we cannot test everything. - * For example, we cannot format fully three-dimensional geographic CRS because the unit - * is not the same for all axes. We cannot format neither some axis directions. - */ - if (requiresWKT2019(crs)) { - continue; - } try { parseAndFormat(v1, code, crs); } catch (UnformattableObjectException e) { diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/CodeType.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/CodeType.java index 54155a39e8..818e9a770f 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/CodeType.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/CodeType.java @@ -36,50 +36,57 @@ public enum CodeType { * The code is a filename like {@code "/path/to/file"} or {@code "C:\path\to\file"}. * Could also be a directory name. */ - FILE(false), + FILE(false, false), /** * The code is a URL like {@code "http:"} or {@code "file:"}, * with the exception of HTTP in the "www.opengis.net" domain. * The latter case is identified by {@link #HTTP_OGC} instead of this enum. */ - URL(false), + URL(false, true), /** * The code is an authority code defined in the {@code "urn:"} namespace. */ - URN(true), + URN(true, true), /** * The code is an URL in the {@code "http://www.opengis.net"} namespace. */ - HTTP_OGC(true), + HTTP_OGC(true, true), /** * The code is not defined in the URN namespace but is nevertheless presumed to be an authority code. * Example: {@code "EPSG:4326"}. */ - IDENTIFIER(true), + IDENTIFIER(true, false), /** * Cannot resolve whether the code is a local file like {@code "myfile.wkt"} or an identifier without * authority like {@code "4326"}. Such code without cannot be decoded by {@code CRS.forCode(String)}, * but may be understood by a more specific authority factory. */ - UNKNOWN(false); + UNKNOWN(false, false); /** * Whether the code may be understood by the {@link org.apache.sis.referencing.CRS#forCode(String)}. * A value of {@code true} does not guaranteed the code is valid. It only said that there is some * chances that the code is valid. */ - public final boolean isCRS; + public final boolean isAuthorityCode; + + /** + * Whether the code is a <abbr>URL</abbr> or <abbr>URN</abbr>. + * This is not necessarily the <abbr>URI</abbr> of an authority code. + */ + public final boolean isURI; /** * Creates a new enum value. */ - private CodeType(final boolean isCRS) { - this.isCRS = isCRS; + private CodeType(final boolean isAuthorityCode, final boolean isURI) { + this.isAuthorityCode = isAuthorityCode; + this.isURI = isURI; } /**
