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 2866e75668c04dc6a7a3f577714afd0183338b15 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Thu Oct 3 18:00:36 2024 +0200 Better detection of when EPSG data are not available and fallback should be used. This is needed for fixing test failures when SIS is built without local EPSG dataset. --- .../apache/sis/referencing/AuthorityFactories.java | 202 ++++++++++++--------- .../main/org/apache/sis/referencing/CRS.java | 5 +- .../main/org/apache/sis/referencing/CommonCRS.java | 10 +- .../apache/sis/referencing/IdentifiedObjects.java | 2 + .../factory/IdentifiedObjectFinder.java | 105 ++++++++++- .../factory/MultiAuthoritiesFactory.java | 16 +- .../sis/referencing/EPSGFactoryFallbackTest.java | 4 +- .../sis/storage/sql/feature/InfoStatements.java | 4 +- .../storage/sql/feature/InfoStatementsTest.java | 8 +- 9 files changed, 253 insertions(+), 103 deletions(-) diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AuthorityFactories.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AuthorityFactories.java index 064e7f6daa..8b5d66f2dd 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AuthorityFactories.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AuthorityFactories.java @@ -16,6 +16,7 @@ */ package org.apache.sis.referencing; +import java.util.Set; import java.util.Iterator; import java.util.ServiceLoader; import java.util.logging.Level; @@ -24,6 +25,7 @@ import java.util.logging.Logger; import java.sql.SQLTransientException; import org.opengis.util.FactoryException; import org.opengis.referencing.AuthorityFactory; +import org.opengis.referencing.IdentifiedObject; import org.opengis.referencing.cs.CSAuthorityFactory; import org.opengis.referencing.crs.CRSAuthorityFactory; import org.opengis.referencing.datum.DatumAuthorityFactory; @@ -37,6 +39,7 @@ import org.apache.sis.system.SystemListener; import org.apache.sis.referencing.internal.EPSGFactoryProxy; import org.apache.sis.referencing.factory.MultiAuthoritiesFactory; import org.apache.sis.referencing.factory.GeodeticAuthorityFactory; +import org.apache.sis.referencing.factory.IdentifiedObjectFinder; import org.apache.sis.referencing.factory.UnavailableFactoryException; import org.apache.sis.referencing.factory.sql.EPSGFactory; import org.apache.sis.util.logging.Logging; @@ -57,11 +60,10 @@ final class AuthorityFactories<T extends AuthorityFactory> extends LazySet<T> { static final Logger LOGGER = Logger.getLogger(Loggers.CRS_FACTORY); /** - * An array containing only the EPSG factory. Content of this array is initially null. + * The EPSG factory, or {@code null} if not yet initialized. * The EPSG factory will be created when first needed by {@link #initialValues()}. - * This array is returned directly (not cloned) by {@link #initialValues()}. */ - private static final GeodeticAuthorityFactory[] EPSG = new GeodeticAuthorityFactory[1]; + private static GeodeticAuthorityFactory EPSG; /** * The unique system-wide authority factory instance that contains all factories found on the module path, @@ -80,7 +82,7 @@ final class AuthorityFactories<T extends AuthorityFactory> extends LazySet<T> { @Override public void reload() { - EPSG(null); + setEPSG(null); super.reload(); } }; @@ -115,38 +117,59 @@ final class AuthorityFactories<T extends AuthorityFactory> extends LazySet<T> { return ServiceLoader.load(service, Reflect.getContextClassLoader()).iterator(); } + /** + * Invoked by {@link LazySet} for adding the EPSG factory before any other factory fetched by {@code ServiceLoader}. + * We put the EPSG factory first because it is often used anyway even for {@code CRS} and {@code AUTO} namespaces. + * This method tries to instantiate an {@link EPSGFactory} if possible, or an {@link EPSGFactoryFallback} otherwise. + * + * @return the EPSG factory in an array. + */ + @Override + @SuppressWarnings("unchecked") + protected T[] initialValues() { + return (T[]) new GeodeticAuthorityFactory[] {getEPSG()}; + } + + /** + * Invoked by {@link LazySet} for fetching the next element from the given iterator. + * Skips the {@link EPSGFactoryProxy} if possible, or returns {@code null} otherwise. + * Note that {@link MultiAuthoritiesFactory} is safe to null values. + */ + @Override + protected T next(final Iterator<? extends T> it) { + T e = it.next(); + if (e instanceof EPSGFactoryProxy) { + e = it.hasNext() ? it.next() : null; + } + return e; + } + /** * Sets the EPSG factory to the given value. + * + * @param factory the factory to use, or {@code null} for reloading. */ @Configuration - static void EPSG(final GeodeticAuthorityFactory factory) { - synchronized (EPSG) { - EPSG[0] = factory; - } + static synchronized void setEPSG(final GeodeticAuthorityFactory factory) { + EPSG = factory; } /** * Returns the factory connected to the EPSG geodetic dataset if possible, or the EPSG fallback otherwise. - * If an EPSG data source has been found, then this method returns an instance of {@link EPSGFactory} but - * there is no guarantee that attempts to use that factory will succeed; for example maybe the EPSG schema + * If an EPSG data source has been found, then this method returns an instance of {@link EPSGFactory}, but + * there is no guarantee that attempts to use that factory will succeed. For example, maybe the EPSG schema * does not exist. Callers should be prepared to either receive an {@link EPSGFactoryFallback} directly if * the EPSG data source does not exist, or replace the {@code EPSGFactory} by a {@code EPSGFactoryFallback} * later if attempt to use the returned factory fails. */ - static GeodeticAuthorityFactory EPSG() { - synchronized (EPSG) { - GeodeticAuthorityFactory factory = EPSG[0]; - if (factory == null) { - try { - factory = new EPSGFactory(null); - } catch (FactoryException e) { - log(e, false); - factory = EPSGFactoryFallback.INSTANCE; - } - EPSG[0] = factory; - } - return factory; + static synchronized GeodeticAuthorityFactory getEPSG() { + if (EPSG == null) try { + EPSG = new EPSGFactory(null); + } catch (FactoryException e) { + log(e, false); + EPSG = EPSGFactoryFallback.INSTANCE; } + return EPSG; } /** @@ -155,47 +178,42 @@ final class AuthorityFactories<T extends AuthorityFactory> extends LazySet<T> { * the same exception to be thrown and logged on every calls to {@link CRS#forCode(String)}. */ static GeodeticAuthorityFactory fallback(final UnavailableFactoryException e) throws UnavailableFactoryException { - final boolean isTransient = (e.getCause() instanceof SQLTransientException); final AuthorityFactory unavailable = e.getUnavailableFactory(); - GeodeticAuthorityFactory factory; - final boolean alreadyDone; - synchronized (EPSG) { - factory = EPSG[0]; - alreadyDone = (factory == EPSGFactoryFallback.INSTANCE); - if (!alreadyDone) { // May have been set in another thread (race condition). - if (unavailable != factory) { - throw e; // Exception did not come from a factory that we control. - } - factory = EPSGFactoryFallback.INSTANCE; - if (!isTransient) { - ALL.reload(); - EPSG[0] = factory; + if (unavailable instanceof EPSGFactoryFallback) { + throw e; + } + boolean isWarning = true; + if (!(e.getCause() instanceof SQLTransientException)) { + synchronized (AuthorityFactories.class) { + if (unavailable == EPSG) { + ALL.reload(); // Must be before setting the `EPSG` field. + EPSG = EPSGFactoryFallback.INSTANCE; + isWarning = false; // Use config level. } } } - if (!alreadyDone) { - log(e, true); - } - return factory; + log(e, isWarning); + return EPSGFactoryFallback.INSTANCE; // Do not return `EPSG` because it may still have the previous value. } /** - * Notifies that a factory is unavailable, but without giving a fallback and without logging. - * The caller is responsible for throwing an exception, or for logging a warning and provide its own fallback. + * Notifies that a factory is unavailable, but without logging. + * The callers are responsible for either throwing an exception, + * or for logging a warning and do their own fallback. * - * @return {@code false} if the caller can try again, or {@code true} if the failure can be considered final. + * @return {@code false} if the caller may want to try again, or + * {@code true} if the failure is considered definitive. */ - static boolean failure(final UnavailableFactoryException e) { - if (!(e.getCause() instanceof SQLTransientException)) { - final AuthorityFactory unavailable = e.getUnavailableFactory(); - synchronized (EPSG) { - final GeodeticAuthorityFactory factory = EPSG[0]; - if (factory == EPSGFactoryFallback.INSTANCE) { // May have been set in another thread. - return false; - } - if (unavailable == factory) { - ALL.reload(); - EPSG[0] = EPSGFactoryFallback.INSTANCE; + static boolean isUnavailable(final UnavailableFactoryException e) { + final AuthorityFactory unavailable = e.getUnavailableFactory(); + if (!(unavailable instanceof EPSGFactoryFallback)) { + if (e.getCause() instanceof SQLTransientException) { + return false; + } + synchronized (AuthorityFactories.class) { + if (unavailable == EPSG) { + ALL.reload(); // Must be before setting the `EPSG` field. + EPSG = EPSGFactoryFallback.INSTANCE; return false; } } @@ -205,14 +223,14 @@ final class AuthorityFactories<T extends AuthorityFactory> extends LazySet<T> { /** * Logs the given exception at the given level. This method pretends that the logging come from - * {@link CRS#getAuthorityFactory(String)}, which is the public facade for {@link #EPSG()}. + * {@link CRS#getAuthorityFactory(String)}, which is the public facade for {@link #getEPSG()}. */ private static void log(final Exception e, final boolean isWarning) { String message = e.getMessage(); // Prefer the locale of system administrator. if (message == null) { message = e.toString(); } - final LogRecord record = new LogRecord(isWarning ? Level.WARNING : Level.CONFIG, message); + final var record = new LogRecord(isWarning ? Level.WARNING : Level.CONFIG, message); if (isWarning && !(e instanceof UnavailableFactoryException)) { record.setThrown(e); } @@ -220,32 +238,54 @@ final class AuthorityFactories<T extends AuthorityFactory> extends LazySet<T> { } /** - * Invoked by {@link LazySet} for adding the EPSG factory before any other factory fetched by {@code ServiceLoader}. - * We put the EPSG factory first because it is often used anyway even for {@code CRS} and {@code AUTO} namespaces. + * Creates a finder which can be used for looking up unidentified objects using the EPSG database. + * The returned finder uses the fallback if the main <abbr>EPSG</abbr> factory appears to be unavailable. * - * <p>This method tries to instantiate an {@link EPSGFactory} if possible, - * or an {@link EPSGFactoryFallback} otherwise.</p> - * - * @return the EPSG factory in an array. Callers shall not modify the returned array. + * @return a finder to use for looking up unidentified objects. + * @throws FactoryException if the finder cannot be created. */ - @Override - @SuppressWarnings("unchecked") - protected T[] initialValues() { - EPSG(); // Force EPSGFactory instantiation if not already done. - return (T[]) EPSG; - } - - /** - * Invoked by {@link LazySet} for fetching the next element from the given iterator. - * Skips the {@link EPSGFactoryProxy} if possible, or returns {@code null} otherwise. - * Note that {@link MultiAuthoritiesFactory} is safe to null values. - */ - @Override - protected T next(final Iterator<? extends T> it) { - T e = it.next(); - if (e instanceof EPSGFactoryProxy) { - e = it.hasNext() ? it.next() : null; + static IdentifiedObjectFinder finderForEPSG() throws FactoryException { + final GeodeticAuthorityFactory factory = getEPSG(); + if (factory instanceof EPSGFactoryFallback) { + return ((EPSGFactoryFallback) factory).newIdentifiedObjectFinder(); } - return e; + return new IdentifiedObjectFinder.Wrapper(factory.newIdentifiedObjectFinder()) { + /** Whether the fallback has already been set. */ + private boolean isUsingFallback; + + /** Report that the main factory is not available and switch to the fallback. */ + private void report(UnavailableFactoryException e) throws FactoryException { + if (isUsingFallback) throw e; + isUsingFallback = true; + delegate(fallback(e).newIdentifiedObjectFinder()); + } + + /** Lookups objects which are approximately equal, using the fallback if necessary. */ + @Override public Set<IdentifiedObject> find(final IdentifiedObject object) throws FactoryException { + for (;;) try { // Executed at most twice. + return super.find(object); + } catch (UnavailableFactoryException e) { + report(e); + } + } + + /** Lookups an object which is approximately equal, using the fallback if necessary. */ + @Override public IdentifiedObject findSingleton(final IdentifiedObject object) throws FactoryException { + for (;;) try { // Executed at most twice. + return super.findSingleton(object); + } catch (UnavailableFactoryException e) { + report(e); + } + } + + /** Returns a set of authority codes, using the fallback if necessary. */ + @Override protected Set<String> getCodeCandidates(final IdentifiedObject object) throws FactoryException { + for (;;) try { // Executed at most twice. + return super.getCodeCandidates(object); + } catch (UnavailableFactoryException e) { + report(e); + } + } + }; } } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java index 98c9574f51..13609d693e 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java @@ -713,7 +713,7 @@ public final class CRS extends Static { try { return factory.createOperation(sourceCRS, targetCRS, context); } catch (UnavailableFactoryException e) { - if (AuthorityFactories.failure(e)) { + if (AuthorityFactories.isUnavailable(e)) { throw e; } else try { // Above method call replaced the EPSG factory by a fallback. Try again. @@ -755,9 +755,10 @@ public final class CRS extends Static { try { return factory.createOperations(sourceCRS, targetCRS, context); } catch (UnavailableFactoryException e) { - if (AuthorityFactories.failure(e)) { + if (AuthorityFactories.isUnavailable(e)) { throw e; } else try { + // Above method call replaced the EPSG factory by a fallback. Try again. return List.of(factory.createOperation(sourceCRS, targetCRS, context)); } catch (FactoryException ex) { ex.addSuppressed(e); diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java index cb5394aeac..68d218eee4 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java @@ -2121,7 +2121,7 @@ public enum CommonCRS { * Returns the same properties as the given object, except for the identifier which is set to the given code. */ private static Map<String,?> properties(final IdentifiedObject template, final short code) { - final Map<String,Object> properties = new HashMap<>(IdentifiedObjects.getProperties(template, exclude())); + final var properties = new HashMap<String,Object>(IdentifiedObjects.getProperties(template, exclude())); properties.put(GeographicCRS.IDENTIFIERS_KEY, new NamedIdentifier(Citations.EPSG, String.valueOf(code))); return properties; } @@ -2139,7 +2139,7 @@ public enum CommonCRS { */ private static GeodeticAuthorityFactory factory() { if (!EPSGFactoryFallback.FORCE_HARDCODED) { - final GeodeticAuthorityFactory factory = AuthorityFactories.EPSG(); + final GeodeticAuthorityFactory factory = AuthorityFactories.getEPSG(); if (!(factory instanceof EPSGFactoryFallback)) { return factory; } @@ -2154,9 +2154,9 @@ public enum CommonCRS { private static void failure(final Object caller, final String method, final FactoryException e, final int code) { String message = Resources.format(Resources.Keys.CanNotInstantiateGeodeticObject_1, (Constants.EPSG + ':') + code); message = Exceptions.formatChainedMessages(null, message, e); - final LogRecord record = new LogRecord(Level.WARNING, message); - if (!(e instanceof UnavailableFactoryException) || AuthorityFactories.failure((UnavailableFactoryException) e)) { - // Append the stack trace only if the exception is the one we expect when the factory is not available. + final var record = new LogRecord(Level.WARNING, message); + if (!(e instanceof UnavailableFactoryException && AuthorityFactories.isUnavailable((UnavailableFactoryException) e))) { + // Append the stack trace only if the exception is for a reason different than unavailable factory. record.setThrown(e); } Logging.completeAndLog(AuthorityFactories.LOGGER, caller.getClass(), method, record); diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/IdentifiedObjects.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/IdentifiedObjects.java index c8b2c0c321..18cfc6617d 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/IdentifiedObjects.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/IdentifiedObjects.java @@ -713,6 +713,8 @@ public final class IdentifiedObjects extends Static { final GeodeticAuthorityFactory factory; if (authority == null) { factory = AuthorityFactories.ALL; + } else if (authority.equalsIgnoreCase(Constants.EPSG)) { + return AuthorityFactories.finderForEPSG(); } else { factory = AuthorityFactories.ALL.getAuthorityFactory(GeodeticAuthorityFactory.class, authority, null); } 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 387556425c..4f179926bf 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 @@ -554,7 +554,7 @@ public class IdentifiedObjectFinder { } /** - * Returns a set of authority codes that <strong>may</strong> identify the same object as the specified one. + * Returns a set of authority codes that <em>may</em> identify the same object as the specified one. * The returned set must contains <em>at least</em> the code of every objects that are * {@link ComparisonMode#APPROXIMATE approximately equal} to the specified one. * However, the set may conservatively contains the code for more objects if an exact search is too expensive. @@ -590,4 +590,107 @@ public class IdentifiedObjectFinder { Logging.completeAndLog(GeodeticAuthorityFactory.LOGGER, IdentifiedObjectFinder.class, "find", new LogRecord(Level.FINER, exception.getMessage())); } + + /** + * An object finder which delegates some or all work to another object finder. + * The default implementation of all {@code Wrapper} methods delegates the work to the object finder + * specified at construction time or in the last call to {@link #delegate(IdentifiedObjectFinder)}. + * Subclasses can override methods for modifying some find operations. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.5 + * @since 1.5 + */ + public static abstract class Wrapper extends IdentifiedObjectFinder { + /** + * The finder doing the actual work, or {@code this} for using the + * default method implementation provided by the parent class. + */ + private IdentifiedObjectFinder delegate; + + /** + * Creates a new object finder which will delegate the actual work to the given finder. + * + * @param finder the object finder to which to delegate the work. + */ + protected Wrapper(final IdentifiedObjectFinder finder) { + super(finder.factory); + delegate = finder; + } + + /** + * Sets a new finder to which to delegate the actual search operations. + * If the specified finder is {@code this}, then this class will delegate to the default + * method implementations provided by the {@code IdentifiedObjectFinder} parent class. + * Otherwise, the specified finder should be a new instance not in use by other code. + * + * @param finder the object finder to which to delegate the work. Can be {@code this}. + * @throws FactoryException if the delegate cannot be set. + */ + protected void delegate(final IdentifiedObjectFinder finder) throws FactoryException { + if (delegate != null) { + delegate.wrapper = null; + } + delegate = Objects.requireNonNull(finder); + } + + /** + * Returns the object finder to which to delegate the actual search operations. + * If this method returns {@code this}, then the search operations will be delegated + * to the default methods provided by the {@code IdentifiedObjectFinder} parent class. + * + * @return the object finder to which to delegate the work. May be {@code this}. + * @throws FactoryException if the delegate cannot be created. + */ + protected IdentifiedObjectFinder delegate() throws FactoryException { + if (delegate != this) { + delegate.setWrapper(this); // Done on each call because it also copies the configuration. + } + return delegate; + } + + /** + * Lookups objects which are approximately equal to the specified object. + * The default method implementation delegates the work to the finder specified by {@link #delegate()}. + */ + @Override + public Set<IdentifiedObject> find(final IdentifiedObject object) throws FactoryException { + @SuppressWarnings("LocalVariableHidesMemberVariable") + final IdentifiedObjectFinder delegate = delegate(); + return (delegate != this) ? delegate.find(object) : super.find(object); + } + + /** + * Lookups only one object which is approximately equal to the specified object. + * The default method implementation delegates the work to the finder specified by {@link #delegate()}. + */ + @Override + public IdentifiedObject findSingleton(final IdentifiedObject object) throws FactoryException { + @SuppressWarnings("LocalVariableHidesMemberVariable") + final IdentifiedObjectFinder delegate = delegate(); + return (delegate != this) ? delegate.findSingleton(object) : super.findSingleton(object); + } + + /** + * Creates an object equals (optionally ignoring metadata), to the specified object. + * The default method implementation delegates the work to the finder specified by {@link #delegate()}. + */ + @Override + Set<IdentifiedObject> createFromCodes(final IdentifiedObject object) throws FactoryException { + @SuppressWarnings("LocalVariableHidesMemberVariable") + final IdentifiedObjectFinder delegate = delegate(); + return (delegate != this) ? delegate.createFromCodes(object) : super.createFromCodes(object); + } + + /** + * Returns a set of authority codes that <em>may</em> identify the same object as the specified one. + * The default method implementation delegates the work to the finder specified by {@link #delegate()}. + */ + @Override + protected Set<String> getCodeCandidates(final IdentifiedObject object) throws FactoryException { + @SuppressWarnings("LocalVariableHidesMemberVariable") + final IdentifiedObjectFinder delegate = delegate(); + return (delegate != this) ? delegate.getCodeCandidates(object) : super.getCodeCandidates(object); + } + } } 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 02561e639f..682ea459d2 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 @@ -581,8 +581,8 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements */ /* * This method is declared final for avoiding the false impression than overriding this method would change - * the behavior of MultiAuthoritiesFactory. It would not because the 'create(…)' method invokes the private - * 'getAuthorityFactory(…)' instead of the public one. + * the behavior of MultiAuthoritiesFactory. It would not because the `create(…)` method invokes the private + * `getAuthorityFactory(…)` instead of the public one. */ public final <T extends AuthorityFactory> T getAuthorityFactory(final Class<T> type, final String authority, final String version) throws NoSuchAuthorityFactoryException @@ -636,7 +636,7 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements 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. + synchronized (provider) { // Should never be null because of the `doneMask` check. it = provider.iterator(); while (it.hasNext()) { factory = it.next(); @@ -664,7 +664,7 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements /* * Before to cache the factory with a key containing the factory version, make sure * that we took in account the version of the default factory. This will prevent the - * call to 'cache(versioned, factory)' to overwrite the default factory. + * call to `cache(versioned, factory)` to overwrite the default factory. */ if (factory != cached) { cache(unversioned.versionOf(cached.getAuthority()), cached); @@ -786,7 +786,7 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements * is present. The remainder steps are the same as if the user gave a simple code (e.g. "EPSG:4326"). */ if (uri.authority == null) { - // We want this check before the 'code' value is modified below. + // We want this check before the `code` value is modified below. throw new NoSuchAuthorityCodeException( Resources.format(Resources.Keys.MissingAuthority_1, code), null, uri.code, code); } @@ -1540,7 +1540,7 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements /* * Identify the type requested by the user and create all components with the assumption that they will * be of that type. This is the most common case. If during iteration we find an object of another kind, - * then the array type will be downgraded to IdentifiedObject[]. The 'componentType' variable will keep + * 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 AuthorityFactoryIdentifier.Type requestedType; @@ -1823,8 +1823,8 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements ((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 + * 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(); diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/EPSGFactoryFallbackTest.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/EPSGFactoryFallbackTest.java index dc82cff0f2..30ef5d3382 100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/EPSGFactoryFallbackTest.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/EPSGFactoryFallbackTest.java @@ -241,7 +241,7 @@ public final class EPSGFactoryFallbackTest extends TestCaseWithLogs { */ @Configuration private static void setEPSGFactory(final GeodeticAuthorityFactory factory) { - AuthorityFactories.EPSG(factory); + AuthorityFactories.setEPSG(factory); for (final CommonCRS crs : CommonCRS .values()) crs.clear(); for (final CommonCRS.Vertical crs : CommonCRS.Vertical.values()) crs.clear(); for (final CommonCRS.Temporal crs : CommonCRS.Temporal.values()) crs.clear(); @@ -255,7 +255,7 @@ public final class EPSGFactoryFallbackTest extends TestCaseWithLogs { */ @Test public void compareAllCodes() throws FactoryException { - final GeodeticAuthorityFactory EPSG = AuthorityFactories.EPSG(); + final GeodeticAuthorityFactory EPSG = AuthorityFactories.getEPSG(); try { setEPSGFactory(EPSGFactoryFallback.INSTANCE); final var codes = new ArrayList<String>(EPSGFactoryFallback.INSTANCE.getAuthorityCodes(CoordinateReferenceSystem.class)); 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 ce1545dd4f..111d0ae99f 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 @@ -641,11 +641,11 @@ public class InfoStatements implements Localized, AutoCloseable { if (error == null) error = e; else error.addSuppressed(e); } - continue; // Ignore codes that are not integers. + continue; // Ignore codes that are not integers. } final SRID search = new SRID(crs, authority, code); if (done.putIfAbsent(search, code > 0) != null) { - continue; // Skip "authority:code" that we already tried. + continue; // Skip "authority:code" that we already tried. } /* * Found an "authority:code" pair that we did not tested before. diff --git a/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/feature/InfoStatementsTest.java b/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/feature/InfoStatementsTest.java index 7a3f333d12..c84a671fa1 100644 --- a/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/feature/InfoStatementsTest.java +++ b/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/feature/InfoStatementsTest.java @@ -139,8 +139,12 @@ public final class InfoStatementsTest extends TestCase { CoordinateReferenceSystem.IDENTIFIERS_KEY, new ImmutableIdentifier(null, "FOO", "4326")), HardCodedDatum.SPHERE, null, HardCodedCS.GEODETIC_2D); - c.setReadOnly(false); assertEquals(1, info.findSRID(clash)); - c.setReadOnly(true); assertEquals(1, info.findSRID(clash)); + c.setReadOnly(false); + final int code = info.findSRID(clash); + assertNotEquals(4326, code); + assertTrue(code > 0); + c.setReadOnly(true); + assertEquals(code, info.findSRID(clash)); } }