This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/sis.git
commit be4deee44bac509bc7a8f21e15f4aadfde6941ed Merge: 92cb82585e 14ecaa6557 Author: Martin Desruisseaux <[email protected]> AuthorDate: Thu Sep 11 14:20:12 2025 +0200 Merge branch 'geoapi-3.1' .../apache/sis/console/FormattedOutputCommand.java | 2 +- .../org/apache/sis/console/TransformCommand.java | 4 +- .../org/apache/sis/console/CRSCommandTest.java | 13 + .../sis/coverage/grid/ClippedGridCoverageTest.java | 2 +- .../org/apache/sis/xml/bind/lan/PT_FreeText.java | 2 +- .../sis/openoffice/ReferencingFunctions.java | 22 +- .../sis/openoffice/ReferencingFunctionsTest.java | 8 +- .../apache/sis/io/wkt/GeodeticObjectParser.java | 171 +++++++++---- .../referencing/datum/DefaultDatumEnsemble.java | 15 ++ .../referencing/factory/AuthorityFactoryProxy.java | 40 +-- .../factory/ConcurrentAuthorityFactory.java | 5 +- .../factory/MultiAuthoritiesFactory.java | 2 +- .../referencing/factory/sql/EPSGDataAccess.java | 12 +- .../operation/AbstractCoordinateOperation.java | 58 ++--- .../operation/DefaultConcatenatedOperation.java | 43 +++- .../DefaultCoordinateOperationFactory.java | 40 ++- .../referencing/operation/projection/Mercator.java | 11 +- .../operation/provider/AbstractLambert.java | 2 + .../operation/provider/AbstractMercator.java | 2 + .../operation/provider/AbstractStereographic.java | 2 + .../operation/provider/AxisOrderReversal.java | 4 +- .../operation/provider/AxisOrderReversal3D.java | 4 +- .../operation/provider/CassiniSoldner.java | 4 + .../operation/provider/Equirectangular.java | 10 +- .../provider/FranceGeocentricInterpolation.java | 6 +- .../operation/provider/GeocentricAffine.java | 31 ++- .../operation/provider/GeocentricTranslation.java | 1 + .../provider/GeographicAndVerticalOffsets.java | 5 +- .../operation/provider/GeographicOffsets.java | 3 +- .../provider/LambertAzimuthalEqualArea.java | 4 + .../operation/provider/LambertConformal1SP.java | 3 + .../operation/provider/LambertConformal2SP.java | 8 +- .../provider/LambertConformalMichigan.java | 4 +- .../operation/provider/LambertConformalWest.java | 1 + .../provider/LambertCylindricalEqualArea.java | 4 + .../operation/provider/MapProjection.java | 16 +- .../operation/provider/Mercator1SP.java | 2 + .../provider/ModifiedAzimuthalEquidistant.java | 4 + .../referencing/operation/provider/Mollweide.java | 2 +- .../operation/provider/ObliqueMercator.java | 2 + .../operation/provider/ObliqueStereographic.java | 2 + .../operation/provider/Orthographic.java | 4 + .../operation/provider/PolarStereographicA.java | 2 + .../referencing/operation/provider/Polyconic.java | 4 + .../operation/provider/RegionalMercator.java | 36 ++- .../operation/provider/TransverseMercator.java | 2 + .../provider/ZonedTransverseMercator.java | 2 + .../apache/sis/referencing/privy/WKTKeywords.java | 267 ++++++++------------- .../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 +- .../DefaultConcatenatedOperationTest.java | 75 +++++- .../operation/DefaultTransformationTest.java | 3 +- .../referencing/operation/PassThroughOperation.xml | 4 +- .../operation/provider/ProvidersTest.java | 121 +++++++++- .../sis/test/integration/ConsistencyTest.java | 39 +-- .../main/org/apache/sis/storage/base/CodeType.java | 25 +- .../test/org/apache/sis/test/Assertions.java | 13 +- .../org/apache/sis/test/ProjectDirectories.java | 79 ++---- 61 files changed, 808 insertions(+), 539 deletions(-) diff --cc endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java index 88ca0e81a1,e9a7a679a5..ad6c648d21 --- 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 @@@ -42,10 -43,8 +43,13 @@@ import org.apache.sis.storage.DataStore import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.base.CodeType; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.referencing.ObjectDomain; ++// Specific to the main and geoapi-4.0 branches: ++import org.apache.sis.referencing.factory.GeodeticAuthorityFactory; ++ +// Specific to the main branch: +import org.apache.sis.referencing.DefaultObjectDomain; +import org.apache.sis.referencing.datum.DefaultDatumEnsemble; +import org.apache.sis.referencing.internal.Legacy; /** @@@ -176,7 -181,7 +185,12 @@@ public class ReferencingFunctions exten return object.getName().getCode(); } // In Apache SIS implementation, `getDescriptionText(…)` returns the identified object name. - name = CRS.getAuthorityFactory(null).getDescriptionText(codeOrPath); - name = CRS.getAuthorityFactory(null).getDescriptionText(classe, codeOrPath).orElse(null); ++ final CRSAuthorityFactory factory = CRS.getAuthorityFactory(null); ++ if (factory instanceof GeodeticAuthorityFactory) { ++ name = ((GeodeticAuthorityFactory) factory).getDescriptionText(classe, codeOrPath).orElse(null); ++ } else { ++ name = factory.getDescriptionText(codeOrPath); ++ } } catch (Exception exception) { return getLocalizedMessage(exception); } diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java index 186903334b,930c73cec9..772d4e7487 --- 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 @@@ -393,6 -387,25 +402,25 @@@ class GeodeticObjectParser extends Math return crs; } + /** + * Parses a {@code "CoordinateMetadata"} element. + * + * @param mode {@link #FIRST}, {@link #OPTIONAL} or {@link #MANDATORY}. + * @param parent the parent element. + * @return the {@code "CoordinateMetadata"} element. + * @throws ParseException if the {@code "CoordinateMetadata"} element cannot be parsed. + */ - private CoordinateMetadata parseCoordinateMetadata(final int mode, final Element parent) throws ParseException { ++ private DefaultCoordinateMetadata parseCoordinateMetadata(final int mode, final Element parent) throws ParseException { + final Element element = parent.pullElement(mode, WKTKeywords.CoordinateMetadata); + if (element == null) { + return null; + } + final CoordinateReferenceSystem crs = parseCoordinateReferenceSystem(element, true); + final Temporal epoch = parseEpoch(OPTIONAL, element, WKTKeywords.Epoch); + element.close(ignoredElements); + return new DefaultCoordinateMetadata(crs, epoch); + } + /** * Returns the value associated to {@link IdentifiedObject#IDENTIFIERS_KEY} as an {@code Identifier} object. * This method shall accept all value types that {@link #parseMetadataAndClose(Element, String, IdentifiedObject)} @@@ -1456,20 -1466,33 +1485,33 @@@ return epoch; } + /** + * Parses the datum {@code ANCHOR[]} element and pass the values to the {@link #parseMetadataAndClose(Element, + * String, IdentifiedObject)} method. If an anchor has been found, its value is stored in the returned map. + */ + private Map<String,Object> parseAnchorAndClose(final Element element, final String name) throws ParseException { + String anchor = pullElementAsString(element, WKTKeywords.Anchor); + Temporal epoch = parseEpoch(OPTIONAL, element, WKTKeywords.AnchorEpoch); + final Map<String,Object> properties = parseMetadataAndClose(element, name, null); - if (anchor != null) properties.put(Datum.ANCHOR_DEFINITION_KEY, anchor); - if (epoch != null) properties.put(Datum.ANCHOR_EPOCH_KEY, epoch); ++ if (anchor != null) properties.put(AbstractDatum.ANCHOR_DEFINITION_KEY, anchor); ++ if (epoch != null) properties.put(AbstractDatum.ANCHOR_EPOCH_KEY, epoch); + return properties; + } + /** * Parses an {@code "Ensemble"} (WKT 2) element. * * @param mode {@link #FIRST}, {@link #OPTIONAL} or {@link #MANDATORY}. * @param parent the parent element. - * @param datumType GeoAPI interface of the type of datum to create. * @param meridian the prime meridian, or {@code null} if the ensemble is not geodetic. + * @param datumType GeoAPI interface of the type of datum to create. - * @return the {@code "Ensemble"} element as a {@link DatumEnsemble} object. + * @return the {@code "Ensemble"} element as a {@code DatumEnsemble} object. * @throws ParseException if the {@code "Ensemble"} element cannot be parsed. * * @see org.apache.sis.referencing.datum.DefaultDatumEnsemble#formatTo(Formatter) */ - private <D extends Datum> DatumEnsemble<D> parseEnsemble(final int mode, final Element parent, + private <D extends Datum> DefaultDatumEnsemble<D> parseEnsemble(final int mode, final Element parent, - final Class<D> datumType, final PrimeMeridian meridian) throws ParseException + final PrimeMeridian meridian, final Class<D> datumType) throws ParseException { final Element ensemble = parent.pullElement(mode, WKTKeywords.Ensemble); if (ensemble == null) { @@@ -2017,7 -2042,7 +2059,7 @@@ meridian = greenwich(); } final Temporal epoch = parseDynamic(element); - final DefaultDatumEnsemble<GeodeticDatum> ensemble = parseEnsemble(OPTIONAL, element, GeodeticDatum.class, meridian); - final DatumEnsemble<GeodeticDatum> ensemble = parseEnsemble(OPTIONAL, element, meridian, GeodeticDatum.class); ++ final DefaultDatumEnsemble<GeodeticDatum> ensemble = parseEnsemble(OPTIONAL, element, meridian, GeodeticDatum.class); final GeodeticDatum datum = parseDatum(ensemble == null ? MANDATORY : OPTIONAL, element, meridian, epoch); final IdentifiedObject datumOrEnsemble = (datum != null) ? datum : ensemble; final Map<String,?> properties = parseMetadataAndClose(element, name, datumOrEnsemble); @@@ -2244,7 -2270,7 +2286,7 @@@ } } if (baseCRS == null) { // The most usual case. - ensemble = parseEnsemble(OPTIONAL, element, DefaultParametricDatum.class, null); - ensemble = parseEnsemble(OPTIONAL, element, null, ParametricDatum.class); ++ ensemble = parseEnsemble(OPTIONAL, element, null, DefaultParametricDatum.class); datum = parseParametricDatum(ensemble == null ? MANDATORY : OPTIONAL, element); } final IdentifiedObject datumOrEnsemble = (datum != null) ? datum : ensemble; diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java index e53f7d944c,43b851e5bc..5889f96778 --- 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 @@@ -175,24 -172,31 +175,34 @@@ 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 create(GeodeticAuthorityFactory factory, String code) throws FactoryException { - return factory.getDescriptionText(classe, code).orElse(null); - } - @Override InternationalString createFromAPI(AuthorityFactory factory, String code) throws FactoryException { - if (factory instanceof GeodeticAuthorityFactory) { - return ((GeodeticAuthorityFactory) factory).getDescriptionText(classe, code).orElse(null); - } - return factory.getDescriptionText(code); + 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); ++ if (factory instanceof GeodeticAuthorityFactory) { ++ return ((GeodeticAuthorityFactory) factory).getDescriptionText(typeToSearch, code).orElse(null); + } - @Override AuthorityFactoryProxy<InternationalString> specialize(String typeName) { ++ return factory.getDescriptionText(code); + } + + /** 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. + } } /** diff --cc endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java index 7d74482934,303e0353fd..50e42e872c --- 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 @@@ -515,9 -508,9 +514,9 @@@ public final class GeodeticObjectParser */ @Test public void testGeographicCRSWithEnsemble() throws ParseException { - final GeographicCRS crs = parse(GeographicCRS.class, + final var crs = parse(DefaultGeographicCRS.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" + diff --cc endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/Assertions.java index f9c3c02003,73deaaf9fa..f99d377086 --- 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 @@@ -140,10 -123,10 +126,10 @@@ public final class Assertions extends S */ 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, (actual instanceof ReferenceIdentifier) ? ((ReferenceIdentifier) actual).getCodeSpace() : null, "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"); } /** diff --cc endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/GeodeticObjectVerifier.java index 1e8c56bfb8,d9f5aca0fe..50e5b51fbf --- 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 @@@ -39,10 -39,9 +39,11 @@@ import org.apache.sis.measure.Units // Test dependencies 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; +// Specific to the main branch: +import org.opengis.referencing.ReferenceSystem; +import org.opengis.referencing.datum.Datum; ++import org.apache.sis.referencing.datum.DefaultDatumEnsemble; +import org.opengis.referencing.operation.CoordinateOperation; /** @@@ -228,7 -221,12 +229,12 @@@ public final class GeodeticObjectVerifi * {@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<?>) { ++ if (datum instanceof DefaultDatumEnsemble<?>) { + expected += " ensemble"; + } + assertEquals (expected, name, "name"); assertIsWorld (datum, isExtentMandatory); assertIsGreenwich(datum.getPrimeMeridian()); assertIsWGS84 (datum.getEllipsoid()); diff --cc endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java index 9ad9c35bd7,f1c4f1e982..3e5585ed99 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java @@@ -28,11 -39,12 +39,13 @@@ import org.apache.sis.referencing.facto // Test dependencies import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; + import static org.junit.jupiter.api.Assumptions.abort; + import static org.junit.jupiter.api.Assumptions.assumeTrue; import org.apache.sis.test.TestCase; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import static org.opengis.test.Assertions.assertBetween; +// Specific to the main branch: +import org.apache.sis.parameter.DefaultParameterDescriptor; +import static org.apache.sis.test.GeoapiAssert.assertBetween; /** @@@ -234,8 -246,110 +247,110 @@@ public final class ProvidersTest extend */ @Test public void testDescription() { - assertNotEquals(0, SatelliteTracking.SATELLITE_ORBIT_INCLINATION.getDescription().orElseThrow().length()); - assertNotEquals(0, SatelliteTracking.SATELLITE_ORBITAL_PERIOD .getDescription().orElseThrow().length()); - assertNotEquals(0, SatelliteTracking.ASCENDING_NODE_PERIOD .getDescription().orElseThrow().length()); + assertNotEquals(0, ((DefaultParameterDescriptor<Double>) SatelliteTracking.SATELLITE_ORBIT_INCLINATION).getDescription().orElseThrow().length()); + assertNotEquals(0, ((DefaultParameterDescriptor<Double>) SatelliteTracking.SATELLITE_ORBITAL_PERIOD ).getDescription().orElseThrow().length()); + assertNotEquals(0, ((DefaultParameterDescriptor<Double>) SatelliteTracking.ASCENDING_NODE_PERIOD ).getDescription().orElseThrow().length()); } + + /** + * Compares the method and parameter names against the declarations in the <abbr>EPSG</abbr> database. + * + * @throws ReflectiveOperationException if the instantiation of a service provider failed. + * @throws FactoryException if an error occurred while using the <abbr>EPSG</abbr> database. + */ + @Test + public void compareWithEPSG() throws ReflectiveOperationException, FactoryException { + assumeTrue(RUN_EXTENSIVE_TESTS, "Extensive tests not enabled."); + final EPSGFactory factory; + try { + factory = (EPSGFactory) CRS.getAuthorityFactory(Constants.EPSG); + } catch (ClassCastException e) { + abort("This test requires the EPSG geodetic dataset."); + throw e; + } + final var methodAliases = new HashMap<AbstractProvider, String[]>(256); + final var aliasUsageCount = new HashMap<String, Integer>(256); + for (final Class<?> c : methods()) { + final AbstractProvider method = instance(c); + final String identifier = getCodeEPSG(method); + if (identifier != null) { + final OperationMethod authoritative = factory.createOperationMethod(identifier); + final String[] aliases = getAliases(authoritative); + for (final String alias : aliases) { + aliasUsageCount.merge(alias, 1, Math::addExact); + } + /* + * Verify that the name of the operation method is identical to the name used in the EPSG database. + * Aliases will be checked later, after we know which aliases are used multiple times. + */ + final String classe = c.getName(); + assertNull(methodAliases.put(method, aliases), classe); + assertEquals(authoritative.getName().getCode(), method.getName().getCode(), classe); + /* + * Verify that all parameters declared in the EPSG database are present with an identical name. + * The Apache SIS's method provider may contain additional parameters. They will be ignored. + */ + int index = 0; + final List<GeneralParameterDescriptor> parameters = method.getParameters().descriptors(); + for (GeneralParameterDescriptor expected : authoritative.getParameters().descriptors()) { + final String name = expected.getName().getCode(); + GeneralParameterDescriptor parameter; + do { + if (index >= parameters.size()) { + fail("Parameter \"" + name + "\" not found or not in expected order in class " + classe); + } + parameter = parameters.get(index++); + } while (!name.equals(parameter.getName().getCode())); + /* + * Found a match. The EPSG code must be identical. + * Check also the aliases, ignoring the deprecated ones. + */ + assertEquals(getCodeEPSG(expected), getCodeEPSG(parameter), name); + final var hardCoded = new HashSet<String>(Arrays.asList(getAliases(parameter))); + for (final String alias : getAliases(expected)) { + assertTrue(hardCoded.remove(alias), + () -> "Alias \"" + alias + "\" not found in parameter \"" + name + "\" of class " + classe); + } + assertTrue(hardCoded.isEmpty(), + () -> "Unexpected alias \"" + hardCoded.iterator().next() + + "\" in parameter \"" + name + "\" of class " + classe); + } + } + } + /* + * AFter we checked all operation methods, execute a second loop for checking method aliases. + * We need to ignore the aliases that are used by more than one method. + */ + for (final Map.Entry<AbstractProvider, String[]> entry : methodAliases.entrySet()) { + final AbstractProvider method = entry.getKey(); + final String classe = method.getClass().getName(); + final var hardCoded = new HashSet<String>(Arrays.asList(getAliases(method))); + for (final String alias : entry.getValue()) { + if (aliasUsageCount.get(alias) == 1) { + assertTrue(hardCoded.remove(alias), () -> "Alias \"" + alias + "\" not found in class " + classe); + } + } + assertTrue(hardCoded.isEmpty(), + () -> "Unexpected alias \"" + hardCoded.iterator().next() + "\" in " + classe); + } + } + + /** + * Returns the identifier code in <abbr>EPSG</abbr> namespace for the given object, or {@code null} if none. + */ + private static String getCodeEPSG(final IdentifiedObject object) { + Identifier identifier = IdentifiedObjects.getIdentifier(object, Citations.EPSG); + return (identifier != null) ? identifier.getCode() : null; + } + + /** + * Returns the collection of <abbr>EPSG</abbr> aliases or abbreviations for the given object. + */ + private static String[] getAliases(final IdentifiedObject object) { + return object.getAlias() + .stream() + .filter((alias) -> alias.scope().name().toString().startsWith(Constants.EPSG)) + .map(GenericName::toString) + .toArray(String[]::new); + } }
