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 cb9d0cfae49be66866f7f35054140b4a02ab9dd6 Author: Martin Desruisseaux <[email protected]> AuthorDate: Wed Sep 10 19:28:50 2025 +0200 Adjust the operation method providers for changes in EPSG database. --- .../referencing/datum/DefaultDatumEnsemble.java | 15 +++ .../factory/ConcurrentAuthorityFactory.java | 5 +- .../referencing/operation/projection/Mercator.java | 11 ++- .../operation/provider/AxisOrderReversal.java | 4 +- .../operation/provider/AxisOrderReversal3D.java | 4 +- .../operation/provider/Equirectangular.java | 2 +- .../provider/FranceGeocentricInterpolation.java | 2 + .../operation/provider/GeocentricTranslation.java | 1 + .../provider/GeographicAndVerticalOffsets.java | 5 +- .../operation/provider/LambertConformal1SP.java | 1 + .../operation/provider/LambertConformal2SP.java | 8 +- .../referencing/operation/provider/Mollweide.java | 2 +- .../operation/provider/ObliqueMercator.java | 2 + .../operation/provider/RegionalMercator.java | 36 ++++++- .../provider/ZonedTransverseMercator.java | 2 + .../provider/ParameterNameTableGenerator.java | 16 +++- .../operation/provider/ProvidersTest.java | 103 ++++++++++++++++++++- .../test/org/apache/sis/test/Assertions.java | 13 ++- 18 files changed, 194 insertions(+), 38 deletions(-) diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java index 6a216fc196..6d0d482208 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java @@ -45,6 +45,7 @@ import org.apache.sis.referencing.internal.Resources; import org.apache.sis.referencing.privy.WKTKeywords; import org.apache.sis.referencing.privy.WKTUtilities; import org.apache.sis.referencing.internal.PositionalAccuracyConstant; +import org.apache.sis.metadata.privy.NameToIdentifier; import org.apache.sis.metadata.privy.SecondaryTrait; import org.apache.sis.util.ArgumentChecks; import org.apache.sis.util.Classes; @@ -465,6 +466,20 @@ check: if (it.hasNext()) { return value; } + /** + * Returns {@code true} if either the {@linkplain #getName() primary name} or at least + * one {@linkplain #getAlias() alias} matches the given string according heuristic rules. + * This method performs the comparison documented in the + * {@linkplain AbstractDatum#isHeuristicMatchForName(String) datum-class}. + * + * @param name the name to compare. + * @return {@code true} if the primary name or at least one alias matches the specified {@code name}. + */ + @Override + public boolean isHeuristicMatchForName(final String name) { + return NameToIdentifier.isHeuristicMatchForName(super.getName(), super.getAlias(), name, AbstractDatum.Simplifier.INSTANCE); + } + /** * Compares the specified object with this ensemble for equality. * diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java index 62f0b9b3f7..abe0119030 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java @@ -2010,12 +2010,15 @@ public abstract class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFa * Used in lambda expression and defined as a separated method because of generic type. * The {@code object} argument is present only for having the required method signature. * + * <p>The array length is {@value #DOMAIN_COUNT} × 2 for whether axes are ignored or not, + * and ×2 again for whether a singleton is searched instead of the collection.</p> + * * @param object the user-specified object which was searched. * @return a new array to use as a cache for the specified object. */ @SuppressWarnings({"unchecked", "rawtypes"}) // Generic array creation. private static Set<IdentifiedObject>[] createCacheEntry(IdentifiedObject object) { - return new Set[DOMAIN_COUNT * 3]; + return new Set[DOMAIN_COUNT * 4]; } /** diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Mercator.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Mercator.java index 6000cc9d50..f14c532a7a 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Mercator.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Mercator.java @@ -195,8 +195,10 @@ public class Mercator extends ConformalProjection { * The "scale factor" is not formally a "Mercator 2SP" argument, but we accept it anyway * for all Mercator projections because it may be used in some Well Known Text (WKT). */ - roles.put(ParameterRole.SCALE_FACTOR, Mercator1SP.SCALE_FACTOR); - roles.put(ParameterRole.CENTRAL_MERIDIAN, Mercator1SP.LONGITUDE_OF_ORIGIN); + roles.put(ParameterRole.SCALE_FACTOR, Mercator1SP.SCALE_FACTOR); + roles.put(ParameterRole.CENTRAL_MERIDIAN, + (variant == Variant.REGIONAL) ? RegionalMercator.LONGITUDE_OF_FALSE_ORIGIN + : Mercator1SP.LONGITUDE_OF_ORIGIN); switch (variant) { case REGIONAL: { roles.put(ParameterRole.FALSE_EASTING, RegionalMercator.EASTING_AT_FALSE_ORIGIN); @@ -252,8 +254,9 @@ public class Mercator extends ConformalProjection { * "Latitude of origin" cannot have a non-zero value, if it still have non-zero value we will process as * for "Latitude of false origin". */ - final double φ0 = toRadians(initializer.getAndStore((variant == Variant.REGIONAL) - ? RegionalMercator.LATITUDE_OF_FALSE_ORIGIN : Mercator1SP.LATITUDE_OF_ORIGIN)); + final double φ0 = toRadians(initializer.getAndStore( + (variant == Variant.REGIONAL) ? RegionalMercator.LATITUDE_OF_FALSE_ORIGIN + : Mercator1SP.LATITUDE_OF_ORIGIN)); /* * In theory, the "Latitude of 1st standard parallel" and the "Scale factor at natural origin" parameters * are mutually exclusive. The former is for projections of category "2SP" (namely variant B and C) while diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal.java index d7e63bafa9..0e6d254349 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal.java @@ -27,7 +27,7 @@ import org.apache.sis.referencing.operation.matrix.MatrixSIS; /** - * The provider for <q>axis order reversal (2D)</q> (EPSG:9843). + * The provider for <q>Axis Order Reversal (2D)</q> (EPSG:9843). * This is a trivial operation that just swap the two first axes. * The inverse operation is this operation itself. * @@ -44,7 +44,7 @@ public class AxisOrderReversal extends AbstractProvider { * The group of all parameters expected by this coordinate operation (in this case, none). */ private static final ParameterDescriptorGroup PARAMETERS = builder() - .addIdentifier("9843").addName("Axis order reversal (2D)").createGroup(); + .addIdentifier("9843").addName("Axis Order Reversal (2D)").createGroup(); /** * The canonical instance of this operation method. diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal3D.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal3D.java index eb844247ad..744c9e0499 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal3D.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal3D.java @@ -21,7 +21,7 @@ import org.opengis.parameter.ParameterDescriptorGroup; /** - * The provider for <q>axis order reversal (geographic3D horizontal)</q> (EPSG:9844). + * The provider for <q>Axis Order Reversal (Geographic3D horizontal)</q> (EPSG:9844). * This is a trivial operation that just swap the two first axes. * The inverse operation is this operation itself. * @@ -38,7 +38,7 @@ public final class AxisOrderReversal3D extends AxisOrderReversal { * The group of all parameters expected by this coordinate operation (in this case, none). */ private static final ParameterDescriptorGroup PARAMETERS = builder() - .addIdentifier("9844").addName("Axis order reversal (geographic3D horizontal)").createGroup(); + .addIdentifier("9844").addName("Axis Order Reversal (Geographic3D horizontal)").createGroup(); /** * The canonical instance of this operation method. diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Equirectangular.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Equirectangular.java index e297bab69d..7a70dae255 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Equirectangular.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Equirectangular.java @@ -250,9 +250,9 @@ public final class Equirectangular extends AbstractProvider { // for avoiding confusion with EPSG "Equidistant Cylindrical" ellipsoidal projection. PARAMETERS = addIdentifierAndLegacy(builder, "1029", "9823") // 9823 uses deprecated parameter names. .addName( NAME) - .addName( "Plate Carrée") // Not formally defined by EPSG, but cited in documentation. .addName(Citations.OGC, "Equirectangular") .addName(Citations.ESRI, "Plate_Carree") + .addName(Citations.SIS, "Plate Carrée") // Not formally defined by EPSG, but cited in documentation. .createGroupForMapProjection( STANDARD_PARALLEL, LATITUDE_OF_ORIGIN, // Not formally an Equirectangular parameter. diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/FranceGeocentricInterpolation.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/FranceGeocentricInterpolation.java index 31a06e311f..031ad2931d 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/FranceGeocentricInterpolation.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/FranceGeocentricInterpolation.java @@ -167,6 +167,7 @@ public final class FranceGeocentricInterpolation extends AbstractProvider { * <!-- Generated by ParameterNameTableGenerator --> * <table class="sis"> * <caption>Parameter names</caption> + * <tr><td> EPSG: </td><td> EPSG code for standard transformation T0 </td></tr> * <tr><td> EPSG: </td><td> EPSG code for "standard" CT </td></tr> * <tr><td> EPSG: </td><td> Standard CT code </td></tr> * </table> @@ -196,6 +197,7 @@ public final class FranceGeocentricInterpolation extends AbstractProvider { .create(Integer.class, null); STANDARD_CT = builder .addIdentifier("1062") + .addName("EPSG code for standard transformation T0") .addName("EPSG code for \"standard\" CT") .addName("Standard CT code") .create(Integer.class, null); diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeocentricTranslation.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeocentricTranslation.java index d078d711a1..9f5620f5b0 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeocentricTranslation.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeocentricTranslation.java @@ -42,6 +42,7 @@ public final class GeocentricTranslation extends GeocentricAffine { PARAMETERS = builder() .addIdentifier("1031") .addName("Geocentric translations (geocentric domain)") + .addName("Geocentric translations") .createGroup(TX, TY, TZ); } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeographicAndVerticalOffsets.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeographicAndVerticalOffsets.java index 107d4884b3..20377286c3 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeographicAndVerticalOffsets.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeographicAndVerticalOffsets.java @@ -47,13 +47,14 @@ public final class GeographicAndVerticalOffsets extends GeographicOffsets { private static final long serialVersionUID = 7822664525013018023L; /** - * The operation parameter descriptor for the <q>Geoid undulation</q> parameter value. + * The operation parameter descriptor for the <q>Geoid height</q> parameter value. * * @see #TZ * * <!-- Generated by ParameterNameTableGenerator --> * <table class="sis"> * <caption>Parameter names</caption> + * <tr><td> EPSG: </td><td> Geoid height </td></tr> * <tr><td> EPSG: </td><td> Geoid undulation </td></tr> * </table> */ @@ -65,7 +66,7 @@ public final class GeographicAndVerticalOffsets extends GeographicOffsets { private static final ParameterDescriptorGroup PARAMETERS; static { final ParameterBuilder builder = builder(); - TH = builder.addIdentifier("8604").addName("Geoid undulation").create(0, Units.METRE); + TH = builder.addIdentifier("8604").addName("Geoid height").addName("Geoid undulation").create(0, Units.METRE); PARAMETERS = builder().addIdentifier("9618").addName("Geographic2D with Height Offsets").createGroup(TY, TX, TH); } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal1SP.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal1SP.java index b1da184dd3..57444bca81 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal1SP.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal1SP.java @@ -111,6 +111,7 @@ public final class LambertConformal1SP extends AbstractLambert { PARAMETERS = builder .addIdentifier(IDENTIFIER) .addName( "Lambert Conic Conformal (1SP)") + .addName( "Lambert Conic Conformal (1SP variant A)") .addName(Citations.OGC, "Lambert_Conformal_Conic_1SP") .addName(Citations.GEOTIFF, "CT_LambertConfConic_1SP") .addName(Citations.PROJ4, "lcc") diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal2SP.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal2SP.java index b73d4e94ad..5669dacdd5 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal2SP.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal2SP.java @@ -178,12 +178,8 @@ public final class LambertConformal2SP extends AbstractLambert { * GeoTIFF: FalseOriginLong */ LONGITUDE_OF_FALSE_ORIGIN = createLongitude(builder - .addNamesAndIdentifiers(LambertConformal1SP.LONGITUDE_OF_ORIGIN) - .rename(Citations.EPSG, "Longitude of false origin") - .rename(Citations.NETCDF, "longitude_of_central_meridian") - .rename(Citations.GEOTIFF, "FalseOriginLong") - .reidentify(Citations.EPSG, "8822") - .reidentify(Citations.GEOTIFF, "3084")); + .addNamesAndIdentifiers(RegionalMercator.LONGITUDE_OF_FALSE_ORIGIN) + .rename(Citations.NETCDF, "longitude_of_central_meridian")); /* * EPSG: Latitude of 1st standard parallel * OGC: standard_parallel_1 diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mollweide.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mollweide.java index 5a7ba1f070..035d942d08 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mollweide.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mollweide.java @@ -53,7 +53,7 @@ public final class Mollweide extends MapProjection { * <tr><td> OGC: </td><td> central_meridian </td></tr> * <tr><td> GeoTIFF: </td><td> CenterLong </td></tr> * <tr><td> Proj4: </td><td> lon_0 </td></tr> - * <tr><td> EPSG: </td><td> Longitude of projection centre </td></tr> + * <tr><td> EPSG: </td><td> Longitude of natural origin </td></tr> * </table> */ public static final ParameterDescriptor<Double> CENTRAL_MERIDIAN = Sinusoidal.CENTRAL_MERIDIAN; diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ObliqueMercator.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ObliqueMercator.java index d4674077ae..9d86f93e38 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ObliqueMercator.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ObliqueMercator.java @@ -94,6 +94,7 @@ public class ObliqueMercator extends AbstractMercator { * <table class="sis"> * <caption>Parameter names</caption> * <tr><td> EPSG: </td><td> Azimuth at projection centre </td></tr> + * <tr><td> EPSG: </td><td> Azimuth of initial line </td></tr> * <tr><td> OGC: </td><td> azimuth </td></tr> * <tr><td> ESRI: </td><td> Azimuth </td></tr> * <tr><td> GeoTIFF: </td><td> AzimuthAngle </td></tr> @@ -140,6 +141,7 @@ public class ObliqueMercator extends AbstractMercator { * <tr><td> ESRI: </td><td> Scale_Factor </td></tr> * <tr><td> GeoTIFF: </td><td> ScaleAtCenter </td></tr> * <tr><td> Proj4: </td><td> k </td></tr> + * <tr><td> EPSG: </td><td> Scale factor on initial line </td></tr> * </table> */ public static final ParameterDescriptor<Double> SCALE_FACTOR; diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/RegionalMercator.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/RegionalMercator.java index 4bddb0107d..a19bf3f2af 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/RegionalMercator.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/RegionalMercator.java @@ -24,7 +24,7 @@ import org.apache.sis.parameter.ParameterBuilder; /** - * The provider for <q>Mercator (variant C)</q> projection (EPSG:1044). + * The provider for <q>Mercator (variant C)</q> projection (EPSG:1108). * * <h2>Note on naming</h2> * The "Regional Mercator" class name is inspired by MapInfo practice, while not exactly the same projection. @@ -43,7 +43,7 @@ public class RegionalMercator extends AbstractMercator { /** * The EPSG identifier, to be preferred to the name when available. */ - public static final String IDENTIFIER = "1044"; + public static final String IDENTIFIER = "1108"; /** * The operation parameter descriptor for the <cite>Latitude of false origin</cite> (φf) parameter value. @@ -66,6 +66,24 @@ public class RegionalMercator extends AbstractMercator { */ public static final ParameterDescriptor<Double> LATITUDE_OF_FALSE_ORIGIN; + /** + * The operation parameter descriptor for the <cite>Longitude of false origin</cite> (λf) parameter value. + * Valid values range is [-180 … 180]° and default value is 0°. + * + * <!-- Generated by ParameterNameTableGenerator --> + * <table class="sis"> + * <caption>Parameter names</caption> + * <tr><td> EPSG: </td><td> Longitude of false origin </td></tr> + * <tr><td> OGC: </td><td> central_meridian </td></tr> + * <tr><td> ESRI: </td><td> Central_Meridian </td></tr> + * <tr><td> NetCDF: </td><td> longitude_of_projection_origin </td></tr> + * <tr><td> GeoTIFF: </td><td> FalseOriginLong </td></tr> + * <tr><td> Proj4: </td><td> lon_0 </td></tr> + * <tr><td> EPSG: </td><td> <del>Longitude of natural origin</del> </td></tr> + * </table> + */ + public static final ParameterDescriptor<Double> LONGITUDE_OF_FALSE_ORIGIN; + /** * The operation parameter descriptor for the <cite>Easting at false origin</cite> (Ef) parameter value. * Valid values range is unrestricted and default value is 0 metre. @@ -114,6 +132,15 @@ public class RegionalMercator extends AbstractMercator { .reidentify(Citations.EPSG, "8821") .reidentify(Citations.GEOTIFF, "3085"), false); + LONGITUDE_OF_FALSE_ORIGIN = createLongitude(builder + .addNamesAndIdentifiers(Mercator1SP.LONGITUDE_OF_ORIGIN) + .rename(Citations.EPSG, "Longitude of false origin") + .rename(Citations.GEOTIFF, "FalseOriginLong") + .reidentify(Citations.EPSG, "8822") + .reidentify(Citations.GEOTIFF, "3084") + .setDeprecated(true).addName(Citations.EPSG, "Longitude of natural origin") + .setDeprecated(false)); + EASTING_AT_FALSE_ORIGIN = createShift(builder .addNamesAndIdentifiers(FALSE_EASTING) .rename(Citations.EPSG, "Easting at false origin") @@ -131,10 +158,11 @@ public class RegionalMercator extends AbstractMercator { PARAMETERS = builder .addIdentifier(IDENTIFIER) .addName("Mercator (variant C)") - .createGroupForMapProjection( + .setDeprecated(true).addIdentifier("1044") // Legacy identifer with "longitude of natural origin". + .setDeprecated(false).createGroupForMapProjection( Mercator2SP.STANDARD_PARALLEL, - Mercator1SP.LONGITUDE_OF_ORIGIN, // Really "natural origin", not "false origin". LATITUDE_OF_FALSE_ORIGIN, + LONGITUDE_OF_FALSE_ORIGIN, EASTING_AT_FALSE_ORIGIN, NORTHING_AT_FALSE_ORIGIN); } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ZonedTransverseMercator.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ZonedTransverseMercator.java index 0c63480b63..ab202ef277 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ZonedTransverseMercator.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ZonedTransverseMercator.java @@ -89,6 +89,8 @@ public final class ZonedTransverseMercator extends AbstractProvider { PARAMETERS = builder .addIdentifier("9824") .addName("Transverse Mercator Zoned Grid System") + .addName("UTM grid system") + .addName("UTM") .createGroupForMapProjection( TransverseMercator.LATITUDE_OF_ORIGIN, INITIAL_LONGITUDE, diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ParameterNameTableGenerator.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ParameterNameTableGenerator.java index 26a2875e41..d37068740d 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ParameterNameTableGenerator.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ParameterNameTableGenerator.java @@ -37,6 +37,7 @@ import org.apache.sis.measure.Longitude; import org.apache.sis.measure.Range; import org.apache.sis.util.CharSequences; import org.apache.sis.util.StringBuilders; +import org.apache.sis.util.Deprecable; // Test dependencies import static org.junit.jupiter.api.Assertions.*; @@ -99,7 +100,7 @@ public final class ParameterNameTableGenerator extends SimpleFileVisitor<Path> { * @throws IOException if an error occurred while reading or writing a file. */ public static void main(final String[] args) throws IOException { - final ParameterNameTableGenerator cg = new ParameterNameTableGenerator(); + final var cg = new ParameterNameTableGenerator(); Files.walkFileTree(cg.directory, cg); } @@ -198,9 +199,10 @@ public final class ParameterNameTableGenerator extends SimpleFileVisitor<Path> { write(insertAt++, "<!-- Generated by ParameterNameTableGenerator -->"); write(insertAt++, "<table class=\"sis\">"); write(insertAt++, " <caption>Parameter names</caption>"); - write(insertAt++, descriptor.getName()); + write(insertAt++, descriptor.getName(), false); for (final GenericName alias : descriptor.getAlias()) { - write(insertAt++, (alias instanceof Identifier) ? (Identifier) alias : new NamedIdentifier(alias)); + write(insertAt++, (alias instanceof Identifier) ? (Identifier) alias : new NamedIdentifier(alias), + alias instanceof Deprecable && ((Deprecable) alias).isDeprecated()); } write(insertAt++, "</table>"); /* @@ -311,12 +313,16 @@ public final class ParameterNameTableGenerator extends SimpleFileVisitor<Path> { * Appends the given authority and name at the given position. This method writes the margin * (typically spaces followed by {@code '*'} and a single space) before the line. */ - private void write(final int insertAt, final Identifier id) { + private void write(final int insertAt, final Identifier id, final boolean isDeprecated) { final int p = buffer.length(); final String authority = id.getCodeSpace(); buffer.append(" <tr><td> ").append(authority).append(':') .append(CharSequences.spaces(8 - authority.length())) - .append("</td><td> ").append(id.getCode()).append(" </td></tr>"); + .append("</td><td> "); + if (isDeprecated) buffer.append("<del>"); + buffer.append(id.getCode()); + if (isDeprecated) buffer.append("</del>"); + buffer.append(" </td></tr>"); lines.add(insertAt, buffer.toString()); buffer.setLength(p); } diff --git 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 index 09febc881e..19ba3a4126 100644 --- 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 @@ -16,18 +16,31 @@ */ package org.apache.sis.referencing.operation.provider; +import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.HashMap; +import java.util.HashSet; import java.util.IdentityHashMap; import org.opengis.util.GenericName; +import org.opengis.util.FactoryException; import org.opengis.metadata.Identifier; +import org.opengis.referencing.IdentifiedObject; import org.opengis.referencing.cs.VerticalCS; +import org.opengis.referencing.operation.OperationMethod; import org.opengis.parameter.GeneralParameterDescriptor; import org.opengis.parameter.ParameterDescriptorGroup; +import org.apache.sis.metadata.iso.citation.Citations; +import org.apache.sis.util.privy.Constants; +import org.apache.sis.referencing.CRS; +import org.apache.sis.referencing.IdentifiedObjects; +import org.apache.sis.referencing.factory.sql.EPSGFactory; // 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: @@ -152,9 +165,9 @@ public final class ProvidersTest extends TestCase { */ @Test public void ensureParameterUniqueness() throws ReflectiveOperationException { - final Map<GeneralParameterDescriptor, String> groupNames = new IdentityHashMap<>(); - final Map<GeneralParameterDescriptor, GeneralParameterDescriptor> parameters = new HashMap<>(); - final Map<Object, Object> namesAndIdentifiers = new HashMap<>(); + final var groupNames = new IdentityHashMap<GeneralParameterDescriptor, String>(); + final var parameters = new HashMap<GeneralParameterDescriptor, GeneralParameterDescriptor>(); + final var namesAndIdentifiers = new HashMap<Object, Object>(); for (final Class<?> c : methods()) { final AbstractProvider method = instance(c); final ParameterDescriptorGroup group = method.getParameters(); @@ -237,4 +250,88 @@ public final class ProvidersTest extends TestCase { assertNotEquals(0, SatelliteTracking.SATELLITE_ORBITAL_PERIOD .getDescription().orElseThrow().length()); assertNotEquals(0, 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 Identifier identifier = IdentifiedObjects.getIdentifier(method, Citations.EPSG); + if (identifier != null) { + final OperationMethod authoritative = factory.createOperationMethod(identifier.getCode()); + 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 " + classe); + } + parameter = parameters.get(index++); + } while (!name.equals(parameter.getName().getCode())); + } + } + } + /* + * 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) { + if (!hardCoded.remove(alias)) { + fail("Alias \"" + alias + "\" not found or not in expected order in " + classe); + } + } + } + if (!hardCoded.isEmpty()) { + fail("Unexpected alias \"" + hardCoded.iterator().next() + "\" in " + classe); + } + } + } + + /** + * 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); + } } diff --git a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/Assertions.java b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/Assertions.java index 13c92950c7..ff0b32b86b 100644 --- a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/Assertions.java +++ b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/Assertions.java @@ -25,7 +25,6 @@ import java.util.LinkedHashSet; import java.util.LinkedHashMap; import java.util.stream.Stream; import java.util.function.Consumer; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentHashMap; import java.io.IOException; import java.io.ObjectInputStream; @@ -225,7 +224,7 @@ public final class Assertions extends Static { */ public static <E> void assertParallelStreamEquals(final Iterator<E> expected, final Stream<E> actual) { final Integer ONE = 1; // For doing autoboxing only once. - final ConcurrentMap<E,Integer> count = new ConcurrentHashMap<>(); + final var count = new ConcurrentHashMap<E,Integer>(); while (expected.hasNext()) { count.merge(expected.next(), ONE, (old, one) -> old + 1); } @@ -266,7 +265,7 @@ public final class Assertions extends Static { */ public static void assertSetEquals(final Collection<?> expected, final Collection<?> actual) { if (expected != null && actual != null && !expected.isEmpty()) { - final Set<Object> r = new LinkedHashSet<>(expected); + final var r = new LinkedHashSet<Object>(expected); assertTrue(r.removeAll(actual), "The two sets are disjoint."); assertTrue(r.isEmpty(), "The set is missing elements: " + r); assertTrue(r.addAll(actual), "The set unexpectedly became empty."); @@ -288,7 +287,7 @@ public final class Assertions extends Static { */ public static void assertMapEquals(final Map<?,?> expected, final Map<?,?> actual) { if (expected != null && actual != null && !expected.isEmpty()) { - final Map<Object,Object> r = new LinkedHashMap<>(expected); + final var r = new LinkedHashMap<Object,Object>(expected); for (final Map.Entry<?,?> entry : actual.entrySet()) { final Object key = entry.getKey(); if (!r.containsKey(key)) { @@ -337,13 +336,13 @@ public final class Assertions extends Static { Objects.requireNonNull(object); final Object deserialized; try { - final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - try (ObjectOutputStream out = new ObjectOutputStream(buffer)) { + final var buffer = new ByteArrayOutputStream(); + try (var out = new ObjectOutputStream(buffer)) { out.writeObject(object); } // Now reads the object we just serialized. final byte[] data = buffer.toByteArray(); - try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data))) { + try (var in = new ObjectInputStream(new ByteArrayInputStream(data))) { try { deserialized = in.readObject(); } catch (ClassNotFoundException e) {
