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 7b2d3f110f56efe17cca07a3b0302de60f9e9bc6 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Thu Oct 3 15:18:30 2024 +0200 Replace byte constants in `MultiAuthoritiesFactory` by an enumeration. This change does not resolve bugs, but makes debugging easier. --- .../factory/AuthorityFactoryIdentifier.java | 104 ++++++++------ .../referencing/factory/AuthorityFactoryProxy.java | 77 ++++++----- .../factory/IdentifiedObjectFinder.java | 3 +- .../factory/LazySynchronizedIterator.java | 46 +++---- .../factory/MultiAuthoritiesFactory.java | 152 ++++++++++----------- .../sis/storage/sql/feature/InfoStatements.java | 8 +- 6 files changed, 201 insertions(+), 189 deletions(-) diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java index fcb7b15719..96f01812d3 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java @@ -47,54 +47,68 @@ final class AuthorityFactoryIdentifier { private static final Locale IDENTIFIER_LOCALE = Locale.US; /** - * Factory needed is {@link CRSAuthorityFactory}. + * The type of the authority factory. Order matter: specialized factories shall be first. + * If two factories are equally specialized, the most frequently used ones should be first. + * + * @see MultiAuthoritiesFactory#providers */ - static final byte CRS = 0; + static enum Type { + /** + * Factory needed is {@link CRSAuthorityFactory}. + */ + CRS(CRSAuthorityFactory.class), - /** - * Factory needed is {@link CSAuthorityFactory}. - */ - static final byte CS = 1; + /** + * Factory needed is {@link CSAuthorityFactory}. + */ + CS(CSAuthorityFactory.class), - /** - * Factory needed is {@link DatumAuthorityFactory}. - */ - static final byte DATUM = 2; + /** + * Factory needed is {@link DatumAuthorityFactory}. + */ + DATUM(DatumAuthorityFactory.class), - /** - * Factory needed is {@link CoordinateOperationAuthorityFactory}. - */ - static final byte OPERATION = 3; + /** + * Factory needed is {@link CoordinateOperationAuthorityFactory}. + */ + OPERATION(CoordinateOperationAuthorityFactory.class), - /** - * Factory needed is the Apache-SIS specific {@link GeodeticAuthorityFactory}. - */ - static final byte GEODETIC = 4; + /** + * Factory needed is the Apache-SIS specific {@link GeodeticAuthorityFactory}. + */ + GEODETIC(GeodeticAuthorityFactory.class), - /** - * Factory needed is {@link AuthorityFactory}, the base interface of all factories. - */ - static final byte ANY = 5; + /** + * Factory needed is {@link AuthorityFactory}, the base interface of all factories. + */ + ANY(AuthorityFactory.class); - /** - * The interfaces or abstract base classes for the above constants. - */ - @SuppressWarnings({"unchecked", "rawtypes"}) - private static final Class<? extends AuthorityFactory>[] TYPES = new Class[6]; - static { - TYPES[CRS] = CRSAuthorityFactory.class; - TYPES[CS] = CSAuthorityFactory.class; - TYPES[DATUM] = DatumAuthorityFactory.class; - TYPES[OPERATION] = CoordinateOperationAuthorityFactory.class; - TYPES[GEODETIC] = GeodeticAuthorityFactory.class; - TYPES[ANY] = AuthorityFactory.class; + /** + * The interface of the authority factory. + */ + final Class<? extends AuthorityFactory> api; + + /** + * Creates a new enumeration value. + * + * @param base the interface of the authority factory. + */ + private Type(final Class<? extends AuthorityFactory> api) { + this.api = api; + } + + /** + * Returns whether the <abbr>API</abbr> can create any or unspecified type of objects. + */ + final boolean isGeneric() { + return ordinal() >= GEODETIC.ordinal(); + } } /** - * The type of the factory needed, as one of the {@link #CRS}, {@link #CS}, {@link #DATUM}, - * {@link #OPERATION}, {@link #GEODETIC} or {@link #ANY} constants. + * The type of the factory needed. */ - final byte type; + final Type type; /** * The authority of the factory, in upper case. The upper case policy should be kept @@ -126,7 +140,7 @@ final class AuthorityFactoryIdentifier { * The given authority shall be already in upper cases and the version in lower cases * (this is not verified by this constructor). */ - private AuthorityFactoryIdentifier(final byte type, final String authority, final String version) { + private AuthorityFactoryIdentifier(final Type type, final String authority, final String version) { this.type = type; this.authority = authority; this.version = version; @@ -139,8 +153,8 @@ final class AuthorityFactoryIdentifier { static AuthorityFactoryIdentifier create(final Class<? extends AuthorityFactory> type, final String authority, final String version) { - for (byte i=0; i<TYPES.length; i++) { - if (TYPES[i].isAssignableFrom(type)) { + for (Type i : Type.values()) { + if (i.api.isAssignableFrom(type)) { return create(i, authority, version); } } @@ -151,7 +165,7 @@ final class AuthorityFactoryIdentifier { * Creates a new identifier for a factory of the given type, authority and version. * Only the version can be null. */ - static AuthorityFactoryIdentifier create(final byte type, final String authority, final String version) { + static AuthorityFactoryIdentifier create(final Type type, final String authority, final String version) { return new AuthorityFactoryIdentifier(type, authority.toUpperCase(IDENTIFIER_LOCALE), (version == null) ? null : version.toLowerCase(IDENTIFIER_LOCALE)); } @@ -188,7 +202,7 @@ final class AuthorityFactoryIdentifier { /** * Creates a new identifier for the same authority and version than this identifier, but a different factory. */ - AuthorityFactoryIdentifier newType(final byte newType) { + AuthorityFactoryIdentifier newType(final Type newType) { return new AuthorityFactoryIdentifier(newType, authority, version); } @@ -209,7 +223,7 @@ final class AuthorityFactoryIdentifier { */ @Override public int hashCode() { - return type + 31*authority.hashCode() + Objects.hashCode(version); + return type.hashCode() + 31*authority.hashCode() + Objects.hashCode(version); } /** @@ -260,7 +274,7 @@ final class AuthorityFactoryIdentifier { */ void logConflict(final AuthorityFactory used) { log(Resources.forLocale(null).getLogRecord(Level.WARNING, Resources.Keys.IgnoredServiceProvider_3, - TYPES[type], getAuthorityAndVersion(), Classes.getClass(used))); + type.api, getAuthorityAndVersion(), Classes.getClass(used))); } /** @@ -288,7 +302,7 @@ final class AuthorityFactoryIdentifier { @Override public String toString() { final StringBuilder buffer = new StringBuilder(); - buffer.append(Classes.getShortName(TYPES[type])).append(Constants.DEFAULT_SEPARATOR).append(authority); + buffer.append(type).append(Constants.DEFAULT_SEPARATOR).append(authority); if (version != null) { buffer.append(Constants.DEFAULT_SEPARATOR).append(version); } 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 6e13333fcd..df276fe9ca 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 @@ -65,15 +65,14 @@ abstract class AuthorityFactoryProxy<T> { final Class<T> type; /** - * The type of factory needed for creating objects, - * as one of the constants defined in {@link AuthorityFactoryIdentifier}. + * The type of factory needed for creating objects. */ - final byte factoryType; + final AuthorityFactoryIdentifier.Type factoryType; /** * Creates a new proxy for objects of the given type. */ - AuthorityFactoryProxy(final Class<T> type, final byte factoryType) { + AuthorityFactoryProxy(final Class<T> type, final AuthorityFactoryIdentifier.Type factoryType) { this.type = type; this.factoryType = factoryType; } @@ -177,7 +176,7 @@ abstract class AuthorityFactoryProxy<T> { * @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.ANY) { + 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); } @@ -191,7 +190,7 @@ abstract class AuthorityFactoryProxy<T> { * The proxy for the {@link GeodeticAuthorityFactory#createObject(String)} method. */ static final AuthorityFactoryProxy<IdentifiedObject> OBJECT = - new AuthorityFactoryProxy<IdentifiedObject>(IdentifiedObject.class, AuthorityFactoryIdentifier.ANY) { + new AuthorityFactoryProxy<IdentifiedObject>(IdentifiedObject.class, AuthorityFactoryIdentifier.Type.ANY) { @Override IdentifiedObject create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createObject(code); } @@ -204,7 +203,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<Datum> DATUM = - new AuthorityFactoryProxy<Datum>(Datum.class, AuthorityFactoryIdentifier.DATUM) { + new AuthorityFactoryProxy<Datum>(Datum.class, AuthorityFactoryIdentifier.Type.DATUM) { @Override Datum create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createDatum(code); } @@ -214,7 +213,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<EngineeringDatum> ENGINEERING_DATUM = - new AuthorityFactoryProxy<EngineeringDatum>(EngineeringDatum.class, AuthorityFactoryIdentifier.DATUM) { + new AuthorityFactoryProxy<EngineeringDatum>(EngineeringDatum.class, AuthorityFactoryIdentifier.Type.DATUM) { @Override EngineeringDatum create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createEngineeringDatum(code); } @@ -224,7 +223,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<ParametricDatum> PARAMETRIC_DATUM = - new AuthorityFactoryProxy<ParametricDatum>(ParametricDatum.class, AuthorityFactoryIdentifier.DATUM) { + new AuthorityFactoryProxy<ParametricDatum>(ParametricDatum.class, AuthorityFactoryIdentifier.Type.DATUM) { @Override ParametricDatum create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createParametricDatum(code); } @@ -234,7 +233,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<VerticalDatum> VERTICAL_DATUM = - new AuthorityFactoryProxy<VerticalDatum>(VerticalDatum.class, AuthorityFactoryIdentifier.DATUM) { + new AuthorityFactoryProxy<VerticalDatum>(VerticalDatum.class, AuthorityFactoryIdentifier.Type.DATUM) { @Override VerticalDatum create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createVerticalDatum(code); } @@ -244,7 +243,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<TemporalDatum> TEMPORAL_DATUM = - new AuthorityFactoryProxy<TemporalDatum>(TemporalDatum.class, AuthorityFactoryIdentifier.DATUM) { + new AuthorityFactoryProxy<TemporalDatum>(TemporalDatum.class, AuthorityFactoryIdentifier.Type.DATUM) { @Override TemporalDatum create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createTemporalDatum(code); } @@ -254,7 +253,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<GeodeticDatum> GEODETIC_DATUM = - new AuthorityFactoryProxy<GeodeticDatum>(GeodeticDatum.class, AuthorityFactoryIdentifier.DATUM) { + new AuthorityFactoryProxy<GeodeticDatum>(GeodeticDatum.class, AuthorityFactoryIdentifier.Type.DATUM) { @Override GeodeticDatum create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createGeodeticDatum(code); } @@ -264,7 +263,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<Ellipsoid> ELLIPSOID = - new AuthorityFactoryProxy<Ellipsoid>(Ellipsoid.class, AuthorityFactoryIdentifier.DATUM) { + new AuthorityFactoryProxy<Ellipsoid>(Ellipsoid.class, AuthorityFactoryIdentifier.Type.DATUM) { @Override Ellipsoid create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createEllipsoid(code); } @@ -274,7 +273,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<PrimeMeridian> PRIME_MERIDIAN = - new AuthorityFactoryProxy<PrimeMeridian>(PrimeMeridian.class, AuthorityFactoryIdentifier.DATUM) { + new AuthorityFactoryProxy<PrimeMeridian>(PrimeMeridian.class, AuthorityFactoryIdentifier.Type.DATUM) { @Override PrimeMeridian create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createPrimeMeridian(code); } @@ -284,7 +283,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<Extent> EXTENT = - new AuthorityFactoryProxy<Extent>(Extent.class, AuthorityFactoryIdentifier.GEODETIC) { + new AuthorityFactoryProxy<Extent>(Extent.class, AuthorityFactoryIdentifier.Type.GEODETIC) { @Override Extent create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createExtent(code); } @@ -294,7 +293,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<CoordinateSystem> COORDINATE_SYSTEM = - new AuthorityFactoryProxy<CoordinateSystem>(CoordinateSystem.class, AuthorityFactoryIdentifier.CS) { + new AuthorityFactoryProxy<CoordinateSystem>(CoordinateSystem.class, AuthorityFactoryIdentifier.Type.CS) { @Override CoordinateSystem create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createCoordinateSystem(code); } @@ -304,7 +303,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<CartesianCS> CARTESIAN_CS = - new AuthorityFactoryProxy<CartesianCS>(CartesianCS.class, AuthorityFactoryIdentifier.CS) { + new AuthorityFactoryProxy<CartesianCS>(CartesianCS.class, AuthorityFactoryIdentifier.Type.CS) { @Override CartesianCS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createCartesianCS(code); } @@ -314,7 +313,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<PolarCS> POLAR_CS = - new AuthorityFactoryProxy<PolarCS>(PolarCS.class, AuthorityFactoryIdentifier.CS) { + new AuthorityFactoryProxy<PolarCS>(PolarCS.class, AuthorityFactoryIdentifier.Type.CS) { @Override PolarCS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createPolarCS(code); } @@ -324,7 +323,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<CylindricalCS> CYLINDRICAL_CS = - new AuthorityFactoryProxy<CylindricalCS>(CylindricalCS.class, AuthorityFactoryIdentifier.CS) { + new AuthorityFactoryProxy<CylindricalCS>(CylindricalCS.class, AuthorityFactoryIdentifier.Type.CS) { @Override CylindricalCS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createCylindricalCS(code); } @@ -334,7 +333,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<SphericalCS> SPHERICAL_CS = - new AuthorityFactoryProxy<SphericalCS>(SphericalCS.class, AuthorityFactoryIdentifier.CS) { + new AuthorityFactoryProxy<SphericalCS>(SphericalCS.class, AuthorityFactoryIdentifier.Type.CS) { @Override SphericalCS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createSphericalCS(code); } @@ -344,7 +343,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<EllipsoidalCS> ELLIPSOIDAL_CS = - new AuthorityFactoryProxy<EllipsoidalCS>(EllipsoidalCS.class, AuthorityFactoryIdentifier.CS) { + new AuthorityFactoryProxy<EllipsoidalCS>(EllipsoidalCS.class, AuthorityFactoryIdentifier.Type.CS) { @Override EllipsoidalCS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createEllipsoidalCS(code); } @@ -354,7 +353,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<VerticalCS> VERTICAL_CS = - new AuthorityFactoryProxy<VerticalCS>(VerticalCS.class, AuthorityFactoryIdentifier.CS) { + new AuthorityFactoryProxy<VerticalCS>(VerticalCS.class, AuthorityFactoryIdentifier.Type.CS) { @Override VerticalCS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createVerticalCS(code); } @@ -364,7 +363,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<TimeCS> TIME_CS = - new AuthorityFactoryProxy<TimeCS>(TimeCS.class, AuthorityFactoryIdentifier.CS) { + new AuthorityFactoryProxy<TimeCS>(TimeCS.class, AuthorityFactoryIdentifier.Type.CS) { @Override TimeCS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createTimeCS(code); } @@ -374,7 +373,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<ParametricCS> PARAMETRIC_CS = - new AuthorityFactoryProxy<ParametricCS>(ParametricCS.class, AuthorityFactoryIdentifier.CS) { + new AuthorityFactoryProxy<ParametricCS>(ParametricCS.class, AuthorityFactoryIdentifier.Type.CS) { @Override ParametricCS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createParametricCS(code); } @@ -384,7 +383,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<CoordinateSystemAxis> AXIS = - new AuthorityFactoryProxy<CoordinateSystemAxis>(CoordinateSystemAxis.class, AuthorityFactoryIdentifier.CS) { + new AuthorityFactoryProxy<CoordinateSystemAxis>(CoordinateSystemAxis.class, AuthorityFactoryIdentifier.Type.CS) { @Override CoordinateSystemAxis create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createCoordinateSystemAxis(code); } @@ -395,7 +394,7 @@ abstract class AuthorityFactoryProxy<T> { @SuppressWarnings({"rawtypes","unchecked"}) static final AuthorityFactoryProxy<Unit<?>> UNIT = - new AuthorityFactoryProxy<Unit<?>>((Class) Unit.class, AuthorityFactoryIdentifier.CS) { + new AuthorityFactoryProxy<Unit<?>>((Class) Unit.class, AuthorityFactoryIdentifier.Type.CS) { @Override Unit<?> create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createUnit(code); } @@ -405,7 +404,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<CoordinateReferenceSystem> CRS = - new AuthorityFactoryProxy<CoordinateReferenceSystem>(CoordinateReferenceSystem.class, AuthorityFactoryIdentifier.CRS) { + new AuthorityFactoryProxy<CoordinateReferenceSystem>(CoordinateReferenceSystem.class, AuthorityFactoryIdentifier.Type.CRS) { @Override CoordinateReferenceSystem create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createCoordinateReferenceSystem(code); } @@ -415,7 +414,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<CompoundCRS> COMPOUND_CRS = - new AuthorityFactoryProxy<CompoundCRS>(CompoundCRS.class, AuthorityFactoryIdentifier.CRS) { + new AuthorityFactoryProxy<CompoundCRS>(CompoundCRS.class, AuthorityFactoryIdentifier.Type.CRS) { @Override CompoundCRS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createCompoundCRS(code); } @@ -425,7 +424,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<DerivedCRS> DERIVED_CRS = - new AuthorityFactoryProxy<DerivedCRS>(DerivedCRS.class, AuthorityFactoryIdentifier.CRS) { + new AuthorityFactoryProxy<DerivedCRS>(DerivedCRS.class, AuthorityFactoryIdentifier.Type.CRS) { @Override DerivedCRS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createDerivedCRS(code); } @@ -435,7 +434,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<EngineeringCRS> ENGINEERING_CRS = - new AuthorityFactoryProxy<EngineeringCRS>(EngineeringCRS.class, AuthorityFactoryIdentifier.CRS) { + new AuthorityFactoryProxy<EngineeringCRS>(EngineeringCRS.class, AuthorityFactoryIdentifier.Type.CRS) { @Override EngineeringCRS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createEngineeringCRS(code); } @@ -445,7 +444,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<GeographicCRS> GEOGRAPHIC_CRS = - new AuthorityFactoryProxy<GeographicCRS>(GeographicCRS.class, AuthorityFactoryIdentifier.CRS) { + new AuthorityFactoryProxy<GeographicCRS>(GeographicCRS.class, AuthorityFactoryIdentifier.Type.CRS) { @Override GeographicCRS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createGeographicCRS(code); } @@ -455,7 +454,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<GeodeticCRS> GEODETIC_CRS = - new AuthorityFactoryProxy<GeodeticCRS>(GeodeticCRS.class, AuthorityFactoryIdentifier.CRS) { + new AuthorityFactoryProxy<GeodeticCRS>(GeodeticCRS.class, AuthorityFactoryIdentifier.Type.CRS) { @Override GeodeticCRS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createGeodeticCRS(code); } @@ -465,7 +464,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<ProjectedCRS> PROJECTED_CRS = - new AuthorityFactoryProxy<ProjectedCRS>(ProjectedCRS.class, AuthorityFactoryIdentifier.CRS) { + new AuthorityFactoryProxy<ProjectedCRS>(ProjectedCRS.class, AuthorityFactoryIdentifier.Type.CRS) { @Override ProjectedCRS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createProjectedCRS(code); } @@ -475,7 +474,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<TemporalCRS> TEMPORAL_CRS = - new AuthorityFactoryProxy<TemporalCRS>(TemporalCRS.class, AuthorityFactoryIdentifier.CRS) { + new AuthorityFactoryProxy<TemporalCRS>(TemporalCRS.class, AuthorityFactoryIdentifier.Type.CRS) { @Override TemporalCRS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createTemporalCRS(code); } @@ -485,7 +484,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<VerticalCRS> VERTICAL_CRS = - new AuthorityFactoryProxy<VerticalCRS>(VerticalCRS.class, AuthorityFactoryIdentifier.CRS) { + new AuthorityFactoryProxy<VerticalCRS>(VerticalCRS.class, AuthorityFactoryIdentifier.Type.CRS) { @Override VerticalCRS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createVerticalCRS(code); } @@ -495,7 +494,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<ParametricCRS> PARAMETRIC_CRS = - new AuthorityFactoryProxy<ParametricCRS>(ParametricCRS.class, AuthorityFactoryIdentifier.CRS) { + new AuthorityFactoryProxy<ParametricCRS>(ParametricCRS.class, AuthorityFactoryIdentifier.Type.CRS) { @Override ParametricCRS create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createParametricCRS(code); } @@ -506,7 +505,7 @@ abstract class AuthorityFactoryProxy<T> { @SuppressWarnings("rawtypes") static final AuthorityFactoryProxy<ParameterDescriptor> PARAMETER = - new AuthorityFactoryProxy<ParameterDescriptor>(ParameterDescriptor.class, AuthorityFactoryIdentifier.GEODETIC) { + new AuthorityFactoryProxy<ParameterDescriptor>(ParameterDescriptor.class, AuthorityFactoryIdentifier.Type.GEODETIC) { @Override ParameterDescriptor<?> create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createParameterDescriptor(code); } @@ -516,7 +515,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<OperationMethod> METHOD = - new AuthorityFactoryProxy<OperationMethod>(OperationMethod.class, AuthorityFactoryIdentifier.OPERATION) { + new AuthorityFactoryProxy<OperationMethod>(OperationMethod.class, AuthorityFactoryIdentifier.Type.OPERATION) { @Override OperationMethod create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createOperationMethod(code); } @@ -526,7 +525,7 @@ abstract class AuthorityFactoryProxy<T> { }; static final AuthorityFactoryProxy<CoordinateOperation> OPERATION = - new AuthorityFactoryProxy<CoordinateOperation>(CoordinateOperation.class, AuthorityFactoryIdentifier.OPERATION) { + new AuthorityFactoryProxy<CoordinateOperation>(CoordinateOperation.class, AuthorityFactoryIdentifier.Type.OPERATION) { @Override CoordinateOperation create(GeodeticAuthorityFactory factory, String code) throws FactoryException { return factory.createCoordinateOperation(code); } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java index 280e655457..387556425c 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java @@ -167,7 +167,7 @@ public class IdentifiedObjectFinder { * * @see #getSearchDomain() */ - private Domain domain = Domain.VALID_DATASET; + private Domain domain; /** * {@code true} if the search should ignore coordinate system axes. @@ -189,6 +189,7 @@ public class IdentifiedObjectFinder { */ protected IdentifiedObjectFinder(final AuthorityFactory factory) { this.factory = Objects.requireNonNull(factory); + this.domain = Domain.VALID_DATASET; } /** diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/LazySynchronizedIterator.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/LazySynchronizedIterator.java index 81df1a1e2a..c1bf055de5 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/LazySynchronizedIterator.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/LazySynchronizedIterator.java @@ -21,7 +21,7 @@ import org.apache.sis.util.privy.AbstractIterator; /** - * An iterator over all elements given by an array of {@code Iterable<E>}, skipping null elements. + * An iterator over all elements given by an array of {@code Iterable<E>}. * All uses of an {@code Iterable<E>} (including its iterator) is synchronized on that {@code Iterable} instance. * * <p>Note that despite the above-cited synchronization, this iterator is <strong>not</strong> thread-safe: @@ -35,16 +35,15 @@ import org.apache.sis.util.privy.AbstractIterator; */ final class LazySynchronizedIterator<E> extends AbstractIterator<E> { /** - * The providers of iterators. This array shall not be modified by {@code LazySynchronizedSetIterator}, - * since this is a direct reference to the array given to the constructor (not a copy). + * The providers of iterators. */ - private final Iterable<? extends E>[] providers; + private final Iterator<Iterable<? extends E>> providers; /** - * Index of the {@code Iterable<E>} instance that provides the {@link #it} value. + * The current instance that provides the {@link #it} value. * This is also the instance to use as a synchronization lock. */ - private int providerIndex; + private Iterable<? extends E> provider; /** * The iterator on which to delegate calls to {@link #hasNext()} and {@link #next()}. @@ -54,12 +53,15 @@ final class LazySynchronizedIterator<E> extends AbstractIterator<E> { /** * Creates a new iterator over all elements returned by the given providers. - * Null elements in the given array will be ignored. * - * @param providers the providers of iterators. This array is <strong>not</strong> cloned. + * @param providers the providers of iterators. */ - public LazySynchronizedIterator(final Iterable<? extends E>[] providers) { + public LazySynchronizedIterator(final Iterator<Iterable<? extends E>> providers) { this.providers = providers; + if (providers.hasNext()) { + provider = providers.next(); + it = provider.iterator(); + } } /** @@ -70,27 +72,25 @@ final class LazySynchronizedIterator<E> extends AbstractIterator<E> { * @return {@code true} if there is more elements to return. */ @Override + @SuppressWarnings("SynchronizeOnNonFinalField") public boolean hasNext() { if (next != null) { return true; } - while (providerIndex < providers.length) { - final Iterable<? extends E> provider = providers[providerIndex]; - if (provider != null) { - synchronized (provider) { - if (it == null) { - it = provider.iterator(); - } - while (it.hasNext()) { - next = it.next(); - if (next != null) { - return true; - } + while (it != null) { + synchronized (provider) { + while (it.hasNext()) { + next = it.next(); + if (next != null) { + return true; } - it = null; } + it = null; + } + if (providers.hasNext()) { + provider = providers.next(); + it = provider.iterator(); } - providerIndex++; } return false; } 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 b3a3d07594..02561e639f 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 @@ -25,6 +25,7 @@ import java.util.Arrays; import java.util.Iterator; import java.util.Set; import java.util.Map; +import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; @@ -158,19 +159,17 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements CSAuthorityFactory, DatumAuthorityFactory, CoordinateOperationAuthorityFactory { /** - * The factory providers given at construction time. Elements in the array are for {@link CRSAuthorityFactory}, + * The factory providers given at construction time. Elements in the map are for {@link CRSAuthorityFactory}, * {@link CSAuthorityFactory}, {@link DatumAuthorityFactory} and {@link CoordinateOperationAuthorityFactory} - * in that order. That order is defined by the constant values in {@link AuthorityFactoryIdentifier}. + * in that order. That order is defined by the constant values in {@link AuthorityFactoryIdentifier.Type}. + * Note that the map should not contain the last {@link AuthorityFactoryIdentifier.Type} values, + * which are handled in a special way. * - * <p>Note that this array is shorter than the number of {@link AuthorityFactoryIdentifier} values. - * The last {@link AuthorityFactoryIdentifier} values are handled in a special way.</p> - * - * <p>The array may contain {@code null} elements when there is no provider for a given type. - * Content of this array shall be immutable after construction time in order to avoid the need - * for synchronization when reading the array. However, usage of an {@code Iterable} element - * shall be synchronized on that {@code Iterable}.</p> + * <p>Content of this map shall be immutable after construction time in order to avoid the need + * for synchronization. However, usage of an {@code Iterable} element shall be synchronized on + * that {@code Iterable}.</p> */ - private final Iterable<? extends AuthorityFactory>[] providers; + private final EnumMap<AuthorityFactoryIdentifier.Type, Iterable<? extends AuthorityFactory>> providers; /** * The factories obtained from {@link #getAuthorityFactory(Class, String, String)} and similar methods. @@ -179,8 +178,12 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements /** * A bit masks identifying which providers have given us all their factories. - * The value {@code (1 << type)} is set when {@code MultiAuthoritiesFactory} - * has iterated until the end of {@code providers[type].iterator()}. + * For each iterator given by {@code providers.get(type).iterator()}, the value + * {@code (1 << type.ordinal())} is set when {@code MultiAuthoritiesFactory} has + * iterated until the end of that iterator. + * + * <p><b>Design note:</b> this is equivalent to {@link java.util.EnumSet}. + * But we use a bitmask for the convenience of using {@link AtomicInteger}.</p> */ private final AtomicInteger isIterationCompleted; @@ -240,25 +243,25 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements final Iterable<? extends DatumAuthorityFactory> datumFactories, final Iterable<? extends CoordinateOperationAuthorityFactory> copFactories) { - final Iterable<? extends AuthorityFactory>[] p = new Iterable[4]; - p[AuthorityFactoryIdentifier.CRS] = crsFactories; - p[AuthorityFactoryIdentifier.CS] = csFactories; - p[AuthorityFactoryIdentifier.DATUM] = datumFactories; - p[AuthorityFactoryIdentifier.OPERATION] = copFactories; + providers = new EnumMap<>(AuthorityFactoryIdentifier.Type.class); + providers.put(AuthorityFactoryIdentifier.Type.CRS, crsFactories); + providers.put(AuthorityFactoryIdentifier.Type.CS, csFactories); + providers.put(AuthorityFactoryIdentifier.Type.DATUM, datumFactories); + providers.put(AuthorityFactoryIdentifier.Type.OPERATION, copFactories); /* * Mark null Iterables as if we already iterated over all their elements. - * Opportunistically reduce the array size by trimming trailing null elements. - * The memory gain is negligible, but this will reduce the number of iterations in loops. */ - int length = 0, nullMask = 0; - for (int i=0; i < p.length; i++) { - if (p[i] != null) length = i+1; - else nullMask |= (1 << i); + int nullMask = 0; + for (final var it = providers.entrySet().iterator(); it.hasNext();) { + final var entry = it.next(); + if (entry.getValue() == null) { + nullMask |= (1 << entry.getKey().ordinal()); + it.remove(); + } } - providers = ArraysExt.resize(p, length); + isIterationCompleted = new AtomicInteger(nullMask); factories = new ConcurrentHashMap<>(); warnings = new HashMap<>(); - isIterationCompleted = new AtomicInteger(nullMask); } /** @@ -459,7 +462,7 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements * Used by {@link #contains(Object)} for delegating its work to the most appropriate factory. */ private final AuthorityFactoryProxy<Boolean> contains = - new AuthorityFactoryProxy<Boolean>(Boolean.class, AuthorityFactoryIdentifier.ANY) { + new AuthorityFactoryProxy<Boolean>(Boolean.class, AuthorityFactoryIdentifier.Type.ANY) { @Override Boolean createFromAPI(AuthorityFactory factory, String code) throws FactoryException { return getAuthorityCodes(factory).contains(code); } @@ -560,8 +563,8 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements * thread-safe: each thread needs to use its own iterator instance. However, provided that the above * condition is met, threads can safely use their iterators concurrently.</p> */ - final Iterator<AuthorityFactory> getAllFactories() { - return new LazySynchronizedIterator<>(providers); + private Iterator<AuthorityFactory> getAllFactories() { + return new LazySynchronizedIterator<>(providers.values().iterator()); } /** @@ -628,10 +631,10 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements * cached instances. */ int doneMask = isIterationCompleted.get(); - final int type = request.type; - if ((doneMask & (1 << type)) == 0) { - if (type >= 0 && type < providers.length) { - final Iterable<? extends AuthorityFactory> provider = providers[type]; + final int bitmask = (1 << request.type.ordinal()); + if ((doneMask & bitmask) == 0) { + final Iterable<? extends AuthorityFactory> provider = providers.get(request.type); + if (provider != null) { final Iterator<? extends AuthorityFactory> it; synchronized (provider) { // Should never be null because of the 'doneMask' check. it = provider.iterator(); @@ -691,25 +694,17 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements } } } - } else if (type >= AuthorityFactoryIdentifier.GEODETIC) { + } else if (request.type.isGeneric()) { /* * Special cases: if the requested factory is ANY, take the first factory that we can find * regardless of its type. We will try CRS, CS, DATUM and OPERATION factories in that order. * The GEODETIC type is like ANY except for the additional restriction that the factory shall * be an instance of the SIS-specific GeodeticAuthorityFactory class. */ - assert providers.length <= Math.min(type, Byte.MAX_VALUE) : type; - for (byte i=0; i < providers.length; i++) { - factory = getAuthorityFactory(request.newType(i)); - switch (type) { - case AuthorityFactoryIdentifier.ANY: { - return factory; - } - case AuthorityFactoryIdentifier.GEODETIC: { - if (factory instanceof GeodeticAuthorityFactory) { - return factory; - } - } + for (final var entry : providers.entrySet()) { + factory = getAuthorityFactory(request.newType(entry.getKey())); + if (request.type.api.isInstance(factory)) { + return factory; } } } @@ -718,7 +713,7 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements * Note that the mask values may also be modified in other threads for other providers, so we * need to atomically verify that the current value has not been modified before to set it. */ - while (!isIterationCompleted.compareAndSet(doneMask, doneMask | (1 << type))) { + while (!isIterationCompleted.compareAndSet(doneMask, doneMask | bitmask)) { doneMask = isIterationCompleted.get(); } } @@ -1504,7 +1499,7 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements * but instead stores information for later execution. */ private static final class Deferred extends AuthorityFactoryProxy<CoordinateOperationAuthorityFactory> { - Deferred() {super(CoordinateOperationAuthorityFactory.class, AuthorityFactoryIdentifier.OPERATION);} + Deferred() {super(CoordinateOperationAuthorityFactory.class, AuthorityFactoryIdentifier.Type.OPERATION);} /** The authority code saved by the {@code createFromAPI(…)} method. */ String code; @@ -1548,15 +1543,15 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements * then the array type will be downgraded to IdentifiedObject[]. The 'componentType' variable will keep * its non-null value only if the array stay of the expected sub-type. */ - final byte requestedType; + final AuthorityFactoryIdentifier.Type requestedType; IdentifiedObject[] components; Class<? extends IdentifiedObject> componentType; if (CoordinateReferenceSystem.class.isAssignableFrom(type)) { - requestedType = AuthorityFactoryIdentifier.CRS; + requestedType = AuthorityFactoryIdentifier.Type.CRS; componentType = CoordinateReferenceSystem.class; components = new CoordinateReferenceSystem[references.length]; // Intentional covariance. } else if (CoordinateOperation.class.isAssignableFrom(type)) { - requestedType = AuthorityFactoryIdentifier.OPERATION; + requestedType = AuthorityFactoryIdentifier.Type.OPERATION; componentType = CoordinateOperation.class; components = new CoordinateOperation[references.length]; // Intentional covariance. } else { @@ -1580,7 +1575,7 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements */ IdentifiedObject combined = null; switch (requestedType) { - case AuthorityFactoryIdentifier.OPERATION: { + case OPERATION: { if (componentType != null) { /* * URN combined references for concatenated operations. We build an operation name from @@ -1597,7 +1592,7 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements } break; } - case AuthorityFactoryIdentifier.CRS: { + case CRS: { if (componentType != null) { /* * URN combined references for compound coordinate reference systems. @@ -1819,37 +1814,36 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements * Java virtual machine.</p> */ public void reload() { - for (int type=0; type < providers.length; type++) { - final Iterable<?> provider = providers[type]; - if (provider != null) { - synchronized (provider) { - if (provider instanceof LazySet<?>) { - ((LazySet<?>) provider).reload(); - } - if (provider instanceof ServiceLoader<?>) { - ((ServiceLoader<?>) provider).reload(); - } - /* - * Clear the 'iterationCompleted' bit before to clear the cache so that if another thread - * invokes 'getAuthorityFactory(…)', it will block on the synchronized(provider) statement - * until we finished the cleanup. - */ - applyAndMask(~(1 << type)); - /* - * Clear the cache on a provider-by-provider basis, not by a call to factories.clear(). - * This is needed because this MultiAuthoritiesFactory instance may be used concurrently - * by other threads, and we have no global lock for the whole factory. - */ - final Iterator<AuthorityFactoryIdentifier> it = factories.keySet().iterator(); - while (it.hasNext()) { - if (it.next().type == type) { - it.remove(); - } + for (final var entry : providers.entrySet()) { + final Iterable<?> provider = entry.getValue(); + synchronized (provider) { + if (provider instanceof LazySet<?>) { + ((LazySet<?>) provider).reload(); + } else if (provider instanceof ServiceLoader<?>) { + ((ServiceLoader<?>) provider).reload(); + } + /* + * Clear the 'iterationCompleted' bit before to clear the cache so that if another thread + * invokes 'getAuthorityFactory(…)', it will block on the synchronized(provider) statement + * until we finished the cleanup. + */ + final int type = entry.getKey().ordinal(); + applyAndMask(~(1 << type)); + /* + * Clear the cache on a provider-by-provider basis, not by a call to factories.clear(). + * This is needed because this MultiAuthoritiesFactory instance may be used concurrently + * by other threads, and we have no global lock for the whole factory. + */ + final Iterator<AuthorityFactoryIdentifier> it = factories.keySet().iterator(); + while (it.hasNext()) { + if (it.next().type.ordinal() == type) { + it.remove(); } } } } - applyAndMask(providers.length - 1); // Clears all bits other than the bits for providers. + // Clears all bits other than the bits for providers. + applyAndMask((1 << AuthorityFactoryIdentifier.Type.GEODETIC.ordinal()) - 1); } /** diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/InfoStatements.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/InfoStatements.java index 35f9163eab..ce1545dd4f 100644 --- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/InfoStatements.java +++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/InfoStatements.java @@ -477,14 +477,13 @@ public class InfoStatements implements Localized, AutoCloseable { return 0; } final SRID result; - final Integer srid; synchronized (database.cacheOfSRID) { final Integer cached = database.cacheOfSRID.get(crs); if (cached != null) { return cached; } result = findOrAddCRS(crs); - database.cacheOfSRID.put(crs, srid = result.srid); + database.cacheOfSRID.put(crs, result.srid); } CommonExecutor.instance().submit((Runnable) result); return result.srid; @@ -619,6 +618,11 @@ public class InfoStatements implements Localized, AutoCloseable { boolean tryWithGivenCRS = true; final var sridFounInUse = new HashSet<Integer>(); final var done = new LinkedHashMap<SRID, Boolean>(); // Value tells whether the SRID may be valid. + /* + * The following loop begins with an iterator of only one element (which makes the loop + * apparently useless), but the iterator will be replaced by another iterator with more + * elements during the loop. + */ for (Iterator<IdentifiedObject> it = Set.<IdentifiedObject>of(crs).iterator(); it.hasNext();) { final IdentifiedObject candidate = it.next(); /*