Class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFactory>

Type Parameters:
DAO - the type of factory used as Data Access Object (DAO).
All Implemented Interfaces:
AutoCloseable, org.opengis.referencing.AuthorityFactory, org.opengis.util.Factory
Direct Known Subclasses:
EPSGFactory

public abstract class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFactory> extends GeodeticAuthorityFactory implements AutoCloseable
A concurrent authority factory that caches all objects created by another factory. All createFoo(String) methods first check if a previously created object exists for the given code. If such object exists, it is returned. Otherwise, the object creation is delegated to another factory given by newDataAccess() and the result is cached in this factory.

ConcurrentAuthorityFactory delays the call to newDataAccess() until first needed, and closes the factory used as a Data Access Object (DAO) after some timeout. This approach allows to establish a connection to a database (for example) and keep it only for a relatively short amount of time.

Caching strategy

Objects are cached by strong references, up to the amount of objects specified at construction time. If a greater amount of objects are cached, then the oldest ones will be retained through a weak reference instead of a strong one. This means that this caching factory will continue to return those objects as long as they are in use somewhere else in the Java virtual machine, but will be discarded (and recreated on the fly if needed) otherwise.

Multi-threading

The cache managed by this class is concurrent. However, the Data Access Objects (DAO) are assumed non-concurrent. If two or more threads are accessing this factory at the same time, then two or more Data Access Object instances may be created. The maximal amount of instances to create is specified at ConcurrentAuthorityFactory construction time. If more Data Access Object instances are needed, some of the threads will block until an instance become available.

Note for subclasses

This abstract class does not implement any of the DatumAuthorityFactory, CSAuthorityFactory, CRSAuthorityFactory and CoordinateOperationAuthorityFactory interfaces. Subclasses should select the interfaces that they choose to implement.
Since:
0.7
Version:
1.2
  • Field Details

    • DURATION_FOR_LOGGING

      private static final long DURATION_FOR_LOGGING
      Duration of data access operations that should be logged, in nanoseconds. Any operation that take longer than this amount of time to execute will have a message logged. The log level depends on the execution duration as specified in PerformanceLevel.
      Rational: we do not unconditionally log all creation messages because they are redundant with more detailed logs produced by GeodeticObjectFactory. Their only additional information is the creation duration, which is not very useful if too close to zero.
      See Also:
    • UNAVAILABLE

      private static final org.opengis.metadata.citation.Citation UNAVAILABLE
      Sentinel value when authority cannot be determined because the data access object cannot be constructed.
    • authority

      private transient volatile org.opengis.metadata.citation.Citation authority
      The authority, cached after first requested.
    • inherited

      private final Map<Class<?>,Boolean> inherited
      The createFoo(String) methods that are not overridden in the Data Access Object (DAO). This map is created at construction time and should not be modified after construction.
      See Also:
    • cache

      The pool of cached objects. Keys are (type, code) tuples; the type is stored because the same code may be used for different kinds of objects. Values are usually instances of IdentifiedObject, but can also be instances of unrelated types such as Extent.
    • findPool

      private final Map<org.opengis.referencing.IdentifiedObject,Set<org.opengis.referencing.IdentifiedObject>[]> findPool
      The pool of objects identified by ConcurrentAuthorityFactory.Finder.find(IdentifiedObject). Values may be an empty set if an object has been searched but has not been found.

      Keys are typically "foreigner" objects (not objects retained in the cache), otherwise we would not need to search for their authority code. Because keys are retained by weak references, some strong references to the identified objects should be kept outside. This is the purpose of findPoolLatestQueries.

      Every access to this pool must be synchronized on findPool.

    • findPoolLatestQueries

      private final ReferenceKeeper findPoolLatestQueries
      The most recently used objects stored or accessed in findPool, retained by strong references for preventing too early garbage collection. Instances put there are generally not in the cache because they are "foreigner" objects, possibly created by different authorities. Those strong references are automatically clearer in a background thread after an arbitrary delay.
    • currentDAO

      The Data Access Object in use by the current thread.
    • availableDAOs

      The Data Access Object instances previously created and released for future reuse. Last used factories must be added last. This is used as a LIFO stack.
    • remainingDAOs

      private int remainingDAOs
      The amount of Data Access Objects that can still be created. This number is decremented in a block synchronized on availableDAOs every time a Data Access Object is in use, and incremented once released.
    • isCleanScheduled

      private boolean isCleanScheduled
      true if the call to closeExpired() is scheduled for future execution in the background cleaner thread. A value of true implies that this factory contains at least one active data access. However, the reciprocal is not true: this field may be set to false while a DAO is currently in use because this field is set to true only when a worker factory is released.

      Note that we cannot use !availableDAOs.isEmpty() as a replacement of isCleanScheduled because the queue is empty if all Data Access Objects are currently in use.

      Every access to this field must be performed in a block synchronized on availableDAOs.

      See Also:
    • timeout

      private long timeout
      The delay of inactivity (in nanoseconds) before to close a Data Access Object. Every access to this field must be performed in a block synchronized on availableDAOs.
      See Also:
    • TIMEOUT_RESOLUTION

      static final long TIMEOUT_RESOLUTION
      The maximal difference between the scheduled time and the actual time in order to perform the factory disposal, in nanoseconds. This is used as a tolerance value for possible wait time inaccuracy.
      See Also:
  • Constructor Details

    • ConcurrentAuthorityFactory

      protected ConcurrentAuthorityFactory(Class<DAO> dataAccessClass)
      Constructs an instance with a default number of threads and a default number of entries to keep by strong references. Note that those default values may change in any future SIS versions based on experience gained.
      Parameters:
      dataAccessClass - the class of Data Access Object (DAO) created by newDataAccess().
    • ConcurrentAuthorityFactory

      protected ConcurrentAuthorityFactory(Class<DAO> dataAccessClass, int maxStrongReferences, int maxConcurrentQueries)
      Constructs an instance with the specified number of entries to keep by strong references. If a number of object greater than maxStrongReferences are created, then the strong references for the eldest objects will be replaced by weak references.
      Parameters:
      dataAccessClass - the class of Data Access Object (DAO) created by newDataAccess().
      maxStrongReferences - the maximum number of objects to keep by strong reference.
      maxConcurrentQueries - the maximal amount of Data Access Objects to use concurrently. If more than this amount of threads are querying this ConcurrentAuthorityFactory concurrently, additional threads will be blocked until a Data Access Object become available.
  • Method Details

    • countAvailableDataAccess

      @Debug final int countAvailableDataAccess()
      Returns the number of Data Access Objects available for reuse. This count does not include the Data Access Objects that are currently in use. This method is used only for testing purpose.
      See Also:
    • newDataAccess

      protected abstract DAO newDataAccess() throws UnavailableFactoryException, org.opengis.util.FactoryException
      Creates a factory which will perform the actual geodetic object creation work. This method is invoked the first time a createFoo(String) method is invoked. It may also be invoked again if additional factories are needed in different threads, or if all factories have been closed after the timeout.

      Multi-threading

      This method (but not necessarily the returned factory) needs to be thread-safe; ConcurrentAuthorityFactory does not hold any lock when invoking this method. Subclasses are responsible to apply their own synchronization if needed, but are encouraged to avoid doing so if possible. In addition, implementations should not invoke other ConcurrentAuthorityFactory methods during this method execution in order to avoid never-ending loop.
      Returns:
      Data Access Object (DAO) to use in createFoo(String) methods.
      Throws:
      UnavailableFactoryException - if the Data Access Object is unavailable because an optional resource is missing.
      org.opengis.util.FactoryException - if the creation of Data Access Object failed for another reason.
    • getDataAccess

      private DAO getDataAccess() throws org.opengis.util.FactoryException
      Returns a Data Access Object. This method must be used together with release(String, Class, String) in a try ... finally block.
      Returns:
      Data Access Object (DAO) to use in createFoo(String) methods.
      Throws:
      org.opengis.util.FactoryException - if the Data Access Object creation failed.
    • release

      private void release(String caller, Class<?> type, String code)
      Releases the Data Access Object previously obtained with getDataAccess(). This method marks the factory as available for reuse by other threads.

      All arguments given to this method are for logging purpose only.

      Parameters:
      caller - the caller method, or null for "create" + type.getSimpleName().
      type - the type of the created object, or null for performing no logging.
      code - the code of the created object, or null if none.
    • recycle

      private void recycle(ConcurrentAuthorityFactory.DataAccessRef<DAO> usage)
      Pushes the given DAO in the list of objects available for reuse.
    • isCleanScheduled

      @Debug final boolean isCleanScheduled()
      true if the call to closeExpired() is scheduled for future execution in the background cleaner thread. A value of true implies that this factory contains at least one active data access. However, the reciprocal is not true: this field may be set to false while a DAO is currently in use because this field is set to true only when a worker factory is released.

      This method is used only for testing purpose.

      See Also:
    • confirmClose

      private void confirmClose(List<DAO> factories)
      Confirms that the given factories can be closed. If any factory is still in use, it will be removed from that factories list and re-injected in the availableDAOs queue.
    • closeExpired

      private void closeExpired()
      Closes the expired Data Access Objects. This method should be invoked from a background task only. This method may reschedule the task again for another execution if it appears that at least one Data Access Object was not ready for disposal.
      See Also:
    • unexpectedException

      static void unexpectedException(String method, Exception exception)
      Invoked when an exception occurred while closing a factory and we cannot propagate the exception to the user. This situation happen when the factories are closed in a background thread. There is not much we can do except logging the problem. ConcurrentAuthorityFactory should be able to continue its work normally since the factory that we failed to close will not be used anymore.
      Parameters:
      method - the name of the method to report as the source of the problem.
      exception - the exception that occurred while closing a Data Access Object.
    • canClose

      protected boolean canClose(DAO factory)
      Returns true if the given Data Access Object (DAO) can be closed. This method is invoked automatically after the timeout if the given DAO has been idle during all that time. Subclasses can override this method and return false if they want to prevent the DAO disposal under some circumstances.

      The default implementation always returns true.

      Parameters:
      factory - the Data Access Object which is about to be closed.
      Returns:
      true if the given Data Access Object can be closed.
      See Also:
    • getTimeout

      public long getTimeout(TimeUnit unit)
      Returns the amount of time that ConcurrentAuthorityFactory will wait before to close a Data Access Object. This delay is measured from the last time the Data Access Object has been used by a createFoo(String) method.
      Parameters:
      unit - the desired unit of measurement for the timeout.
      Returns:
      the current timeout in the given unit of measurement.
    • setTimeout

      public void setTimeout(long delay, TimeUnit unit)
      Sets a timer for closing the Data Access Object after the specified amount of time of inactivity. If a new Data Access Object is needed after the disposal of the last one, then the newDataAccess() method will be invoked again.
      Parameters:
      delay - the delay of inactivity before to close a Data Access Object.
      unit - the unit of measurement of the given delay.
    • getAuthority

      public org.opengis.metadata.citation.Citation getAuthority()
      Returns the database or specification that defines the codes recognized by this factory. The default implementation performs the following steps:
      • Returns the cached value if it exists.
      • Otherwise:
        1. get an instance of the Data Access Object,
        2. delegate to its GeodeticAuthorityFactory.getAuthority() method,
        3. release the Data Access Object,
        4. cache the result.
      If this method cannot get a Data Access Object (for example because no database connection is available), then this method returns null.
      Specified by:
      getAuthority in interface org.opengis.referencing.AuthorityFactory
      Specified by:
      getAuthority in class GeodeticAuthorityFactory
      Returns:
      the organization responsible for definition of the database, or null if unavailable.
      See Also:
    • getAuthorityCodes

      public Set<String> getAuthorityCodes(Class<? extends org.opengis.referencing.IdentifiedObject> type) throws org.opengis.util.FactoryException
      Returns the set of authority codes for objects of the given type. The default implementation performs the following steps:
      1. get an instance of the Data Access Object,
      2. delegate to its AuthorityFactory.getAuthorityCodes(Class) method,
      3. release the Data Access Object.
      Specified by:
      getAuthorityCodes in interface org.opengis.referencing.AuthorityFactory
      Parameters:
      type - the spatial reference objects type (e.g. ProjectedCRS.class).
      Returns:
      the set of authority codes for spatial reference objects of the given type. If this factory does not contains any object of the given type, then this method returns an empty set.
      Throws:
      org.opengis.util.FactoryException - if access to the underlying database failed.
    • getDescriptionText

      public org.opengis.util.InternationalString getDescriptionText(String code) throws org.opengis.referencing.NoSuchAuthorityCodeException, org.opengis.util.FactoryException
      Gets a description of the object corresponding to a code. The default implementation performs the following steps:
      1. get an instance of the Data Access Object,
      2. delegate to its GeodeticAuthorityFactory.getDescriptionText(String) method,
      3. release the Data Access Object.
      Specified by:
      getDescriptionText in interface org.opengis.referencing.AuthorityFactory
      Overrides:
      getDescriptionText in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      a description of the object, or null if the object corresponding to the specified code has no description.
      Throws:
      org.opengis.referencing.NoSuchAuthorityCodeException - if the specified code was not found.
      org.opengis.util.FactoryException - if the query failed for some other reason.
    • isDefault

      private boolean isDefault(Class<?> type)
      Returns true if the Data Access Object (DAO) does not provide a create method for the given type of object. The intent is to decide if the caller should delegate to the DAO or delegate to a more generic method of this class (e.g. createCoordinateReferenceSystem(String) instead of createGeographicCRS(String)) in order to give to ConcurrentAuthorityFactory a chance to reuse a value presents in the cache.
    • normalizeCode

      protected String normalizeCode(String code) throws org.opengis.util.FactoryException
      Returns a code equivalent to the given code but with unnecessary elements eliminated. The normalized code is used as the key in the cache, and is also the code which will be passed to the Data Access Object (DAO).

      The default implementation performs the following steps:

      1. Removes the namespace if presents. For example if the codespace is EPSG and the given code starts with the "EPSG:" prefix, then that prefix is removed.
      2. Removes leading and trailing spaces.
      Subclasses can override this method for performing a different normalization work. It is okay to return internal codes completely different than the given codes, provided that the Data Access Objects will understand those internal codes.
      Parameters:
      code - the code to normalize.
      Returns:
      the normalized code.
      Throws:
      org.opengis.util.FactoryException - if an error occurred while normalizing the given code.
    • createObject

      public org.opengis.referencing.IdentifiedObject createObject(String code) throws org.opengis.util.FactoryException
      Returns an arbitrary object from a code. The default implementation performs the following steps:
      • Returns the cached instance for the given code if such instance already exists.
      • Otherwise:
        1. get an instance of the Data Access Object,
        2. delegate to its GeodeticAuthorityFactory.createObject(String) method,
        3. release the Data Access Object,
        4. cache the result.
      Specified by:
      createObject in interface org.opengis.referencing.AuthorityFactory
      Specified by:
      createObject in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the object for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createCoordinateReferenceSystem

      public org.opengis.referencing.crs.CoordinateReferenceSystem createCoordinateReferenceSystem(String code) throws org.opengis.util.FactoryException
      Returns an arbitrary coordinate reference system from a code. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createCoordinateReferenceSystem(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createCoordinateReferenceSystem(String) method in the parent class. This allows to check if the more generic createObject(String) method cached a value before to try that method.
      Overrides:
      createCoordinateReferenceSystem in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate reference system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createGeographicCRS

      public org.opengis.referencing.crs.GeographicCRS createGeographicCRS(String code) throws org.opengis.util.FactoryException
      Returns a 2- or 3-dimensional coordinate reference system based on an ellipsoidal approximation of the geoid. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createGeographicCRS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createGeographicCRS(String) method in the parent class. This allows to check if the more generic createCoordinateReferenceSystem(String) method cached a value before to try that method.
      Overrides:
      createGeographicCRS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate reference system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createGeocentricCRS

      public org.opengis.referencing.crs.GeocentricCRS createGeocentricCRS(String code) throws org.opengis.util.FactoryException
      Returns a 3-dimensional coordinate reference system with the origin at the approximate centre of mass of the earth. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createGeocentricCRS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createGeocentricCRS(String) method in the parent class. This allows to check if the more generic createCoordinateReferenceSystem(String) method cached a value before to try that method.
      Overrides:
      createGeocentricCRS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate reference system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createProjectedCRS

      public org.opengis.referencing.crs.ProjectedCRS createProjectedCRS(String code) throws org.opengis.util.FactoryException
      Returns a 2-dimensional coordinate reference system used to approximate the shape of the earth on a planar surface. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createProjectedCRS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createProjectedCRS(String) method in the parent class. This allows to check if the more generic createCoordinateReferenceSystem(String) method cached a value before to try that method.
      Overrides:
      createProjectedCRS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate reference system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createVerticalCRS

      public org.opengis.referencing.crs.VerticalCRS createVerticalCRS(String code) throws org.opengis.util.FactoryException
      Returns a 1-dimensional coordinate reference system used for recording heights or depths. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createVerticalCRS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createVerticalCRS(String) method in the parent class. This allows to check if the more generic createCoordinateReferenceSystem(String) method cached a value before to try that method.
      Overrides:
      createVerticalCRS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate reference system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createTemporalCRS

      public org.opengis.referencing.crs.TemporalCRS createTemporalCRS(String code) throws org.opengis.util.FactoryException
      Returns a 1-dimensional coordinate reference system used for the recording of time. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createTemporalCRS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createTemporalCRS(String) method in the parent class. This allows to check if the more generic createCoordinateReferenceSystem(String) method cached a value before to try that method.
      Overrides:
      createTemporalCRS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate reference system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createCompoundCRS

      public org.opengis.referencing.crs.CompoundCRS createCompoundCRS(String code) throws org.opengis.util.FactoryException
      Returns a CRS describing the position of points through two or more independent coordinate reference systems. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createCompoundCRS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createCompoundCRS(String) method in the parent class. This allows to check if the more generic createCoordinateReferenceSystem(String) method cached a value before to try that method.
      Overrides:
      createCompoundCRS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate reference system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createDerivedCRS

      public org.opengis.referencing.crs.DerivedCRS createDerivedCRS(String code) throws org.opengis.util.FactoryException
      Returns a CRS that is defined by its coordinate conversion from another CRS (not by a datum). The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createDerivedCRS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createDerivedCRS(String) method in the parent class. This allows to check if the more generic createCoordinateReferenceSystem(String) method cached a value before to try that method.
      Overrides:
      createDerivedCRS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate reference system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createEngineeringCRS

      public org.opengis.referencing.crs.EngineeringCRS createEngineeringCRS(String code) throws org.opengis.util.FactoryException
      Returns a 1-, 2- or 3-dimensional contextually local coordinate reference system. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createEngineeringCRS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createEngineeringCRS(String) method in the parent class. This allows to check if the more generic createCoordinateReferenceSystem(String) method cached a value before to try that method.
      Overrides:
      createEngineeringCRS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate reference system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createImageCRS

      public org.opengis.referencing.crs.ImageCRS createImageCRS(String code) throws org.opengis.util.FactoryException
      Returns a 2-dimensional engineering coordinate reference system applied to locations in images. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createImageCRS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createImageCRS(String) method in the parent class. This allows to check if the more generic createCoordinateReferenceSystem(String) method cached a value before to try that method.
      Overrides:
      createImageCRS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate reference system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createDatum

      public org.opengis.referencing.datum.Datum createDatum(String code) throws org.opengis.util.FactoryException
      Returns an arbitrary datum from a code. The returned object will typically be an The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createDatum(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createDatum(String) method in the parent class. This allows to check if the more generic createObject(String) method cached a value before to try that method.
      Overrides:
      createDatum in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the datum for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createGeodeticDatum

      public org.opengis.referencing.datum.GeodeticDatum createGeodeticDatum(String code) throws org.opengis.util.FactoryException
      Returns a datum defining the location and orientation of an ellipsoid that approximates the shape of the earth. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createGeodeticDatum(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createGeodeticDatum(String) method in the parent class. This allows to check if the more generic createDatum(String) method cached a value before to try that method.
      Overrides:
      createGeodeticDatum in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the datum for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createVerticalDatum

      public org.opengis.referencing.datum.VerticalDatum createVerticalDatum(String code) throws org.opengis.util.FactoryException
      Returns a datum identifying a particular reference level surface used as a zero-height surface. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createVerticalDatum(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createVerticalDatum(String) method in the parent class. This allows to check if the more generic createDatum(String) method cached a value before to try that method.
      Overrides:
      createVerticalDatum in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the datum for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createTemporalDatum

      public org.opengis.referencing.datum.TemporalDatum createTemporalDatum(String code) throws org.opengis.util.FactoryException
      Returns a datum defining the origin of a temporal coordinate reference system. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createTemporalDatum(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createTemporalDatum(String) method in the parent class. This allows to check if the more generic createDatum(String) method cached a value before to try that method.
      Overrides:
      createTemporalDatum in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the datum for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createEngineeringDatum

      public org.opengis.referencing.datum.EngineeringDatum createEngineeringDatum(String code) throws org.opengis.util.FactoryException
      Returns a datum defining the origin of an engineering coordinate reference system. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createEngineeringDatum(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createEngineeringDatum(String) method in the parent class. This allows to check if the more generic createDatum(String) method cached a value before to try that method.
      Overrides:
      createEngineeringDatum in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the datum for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createImageDatum

      public org.opengis.referencing.datum.ImageDatum createImageDatum(String code) throws org.opengis.util.FactoryException
      Returns a datum defining the origin of an image coordinate reference system. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createImageDatum(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createImageDatum(String) method in the parent class. This allows to check if the more generic createDatum(String) method cached a value before to try that method.
      Overrides:
      createImageDatum in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the datum for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createEllipsoid

      public org.opengis.referencing.datum.Ellipsoid createEllipsoid(String code) throws org.opengis.util.FactoryException
      Returns a geometric figure that can be used to describe the approximate shape of the earth. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createEllipsoid(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createEllipsoid(String) method in the parent class. This allows to check if the more generic createObject(String) method cached a value before to try that method.
      Overrides:
      createEllipsoid in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the ellipsoid for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createPrimeMeridian

      public org.opengis.referencing.datum.PrimeMeridian createPrimeMeridian(String code) throws org.opengis.util.FactoryException
      Returns a prime meridian defining the origin from which longitude values are determined. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createPrimeMeridian(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createPrimeMeridian(String) method in the parent class. This allows to check if the more generic createObject(String) method cached a value before to try that method.
      Overrides:
      createPrimeMeridian in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the prime meridian for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createExtent

      public org.opengis.metadata.extent.Extent createExtent(String code) throws org.opengis.util.FactoryException
      Returns information about spatial, vertical, and temporal extent (usually a domain of validity) from a code. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createExtent(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createExtent(String) method in the parent class.
      Overrides:
      createExtent in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the extent for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createCoordinateSystem

      public org.opengis.referencing.cs.CoordinateSystem createCoordinateSystem(String code) throws org.opengis.util.FactoryException
      Returns an arbitrary coordinate system from a code. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createCoordinateSystem(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createCoordinateSystem(String) method in the parent class. This allows to check if the more generic createObject(String) method cached a value before to try that method.
      Overrides:
      createCoordinateSystem in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createEllipsoidalCS

      public org.opengis.referencing.cs.EllipsoidalCS createEllipsoidalCS(String code) throws org.opengis.util.FactoryException
      Returns a 2- or 3-dimensional coordinate system for geodetic latitude and longitude, sometimes with ellipsoidal height. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createEllipsoidalCS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createEllipsoidalCS(String) method in the parent class. This allows to check if the more generic createCoordinateSystem(String) method cached a value before to try that method.
      Overrides:
      createEllipsoidalCS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createVerticalCS

      public org.opengis.referencing.cs.VerticalCS createVerticalCS(String code) throws org.opengis.util.FactoryException
      Returns a 1-dimensional coordinate system for heights or depths of points. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createVerticalCS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createVerticalCS(String) method in the parent class. This allows to check if the more generic createCoordinateSystem(String) method cached a value before to try that method.
      Overrides:
      createVerticalCS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createTimeCS

      public org.opengis.referencing.cs.TimeCS createTimeCS(String code) throws org.opengis.util.FactoryException
      Returns a 1-dimensional coordinate system for heights or depths of points. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createTimeCS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createTimeCS(String) method in the parent class. This allows to check if the more generic createCoordinateSystem(String) method cached a value before to try that method.
      Overrides:
      createTimeCS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createCartesianCS

      public org.opengis.referencing.cs.CartesianCS createCartesianCS(String code) throws org.opengis.util.FactoryException
      Returns a 2- or 3-dimensional Cartesian coordinate system made of straight orthogonal axes. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createCartesianCS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createCartesianCS(String) method in the parent class. This allows to check if the more generic createCoordinateSystem(String) method cached a value before to try that method.
      Overrides:
      createCartesianCS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createSphericalCS

      public org.opengis.referencing.cs.SphericalCS createSphericalCS(String code) throws org.opengis.util.FactoryException
      Returns a 3-dimensional coordinate system with one distance measured from the origin and two angular coordinates. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createSphericalCS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createSphericalCS(String) method in the parent class. This allows to check if the more generic createCoordinateSystem(String) method cached a value before to try that method.
      Overrides:
      createSphericalCS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createCylindricalCS

      public org.opengis.referencing.cs.CylindricalCS createCylindricalCS(String code) throws org.opengis.util.FactoryException
      Returns a 3-dimensional coordinate system made of a polar coordinate system extended by a straight perpendicular axis. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createCylindricalCS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createCylindricalCS(String) method in the parent class. This allows to check if the more generic createCoordinateSystem(String) method cached a value before to try that method.
      Overrides:
      createCylindricalCS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createPolarCS

      public org.opengis.referencing.cs.PolarCS createPolarCS(String code) throws org.opengis.util.FactoryException
      Returns a 2-dimensional coordinate system for coordinates represented by a distance from the origin and an angle from a fixed direction. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createPolarCS(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createPolarCS(String) method in the parent class. This allows to check if the more generic createCoordinateSystem(String) method cached a value before to try that method.
      Overrides:
      createPolarCS in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the coordinate system for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createCoordinateSystemAxis

      public org.opengis.referencing.cs.CoordinateSystemAxis createCoordinateSystemAxis(String code) throws org.opengis.util.FactoryException
      Returns a coordinate system axis with name, direction, unit and range of values. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createCoordinateSystemAxis(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createCoordinateSystemAxis(String) method in the parent class. This allows to check if the more generic createObject(String) method cached a value before to try that method.
      Overrides:
      createCoordinateSystemAxis in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the axis for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createUnit

      public javax.measure.Unit<?> createUnit(String code) throws org.opengis.util.FactoryException
      Returns an unit of measurement from a code. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createUnit(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createUnit(String) method in the parent class.
      Overrides:
      createUnit in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the unit of measurement for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createParameterDescriptor

      public org.opengis.parameter.ParameterDescriptor<?> createParameterDescriptor(String code) throws org.opengis.util.FactoryException
      Returns a definition of a single parameter used by an operation method. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createParameterDescriptor(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createParameterDescriptor(String) method in the parent class. This allows to check if the more generic createObject(String) method cached a value before to try that method.
      Overrides:
      createParameterDescriptor in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the parameter descriptor for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createOperationMethod

      public org.opengis.referencing.operation.OperationMethod createOperationMethod(String code) throws org.opengis.util.FactoryException
      Returns a description of the algorithm and parameters used to perform a coordinate operation. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createOperationMethod(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createOperationMethod(String) method in the parent class. This allows to check if the more generic createObject(String) method cached a value before to try that method.
      Overrides:
      createOperationMethod in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the operation method for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • createCoordinateOperation

      public org.opengis.referencing.operation.CoordinateOperation createCoordinateOperation(String code) throws org.opengis.util.FactoryException
      Returns an operation for transforming coordinates in the source CRS to coordinates in the target CRS. The default implementation performs the following steps:
      • Return the cached instance for the given code if such instance already exists.
      • Otherwise if the Data Access Object (DAO) overrides the createCoordinateOperation(String) method, invoke that method and cache the result for future use.
      • Otherwise delegate to the GeodeticAuthorityFactory.createCoordinateOperation(String) method in the parent class. This allows to check if the more generic createObject(String) method cached a value before to try that method.
      Overrides:
      createCoordinateOperation in class GeodeticAuthorityFactory
      Parameters:
      code - value allocated by authority.
      Returns:
      the operation for the given code.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
      See Also:
    • create

      private <T> T create(AuthorityFactoryProxy<T> proxy, String code) throws org.opengis.util.FactoryException
      Returns an object from a code using the given proxy. This method first checks in the cache. If no object exists in the cache for the given code, then a lock is created and the object creation is delegated to the Data Access Object. The result is then stored in the cache and returned.
      Type Parameters:
      T - the type of the object to be returned.
      Parameters:
      proxy - the proxy to use for creating the object.
      code - the code of the object to create.
      Returns:
      the object extracted from the cache or created.
      Throws:
      org.opengis.util.FactoryException - if an error occurred while creating the object.
    • createFromCoordinateReferenceSystemCodes

      public Set<org.opengis.referencing.operation.CoordinateOperation> createFromCoordinateReferenceSystemCodes(String sourceCRS, String targetCRS) throws org.opengis.util.FactoryException
      Returns operations from source and target coordinate reference system codes. The default implementation performs the following steps:
      • Returns the cached collection for the given pair of codes if such collection already exists.
      • Otherwise:
        1. get an instance of the Data Access Object,
        2. delegate to its GeodeticAuthorityFactory.createFromCoordinateReferenceSystemCodes(String, String) method,
        3. release the Data Access Object — this step assumes that the collection obtained at step 2 is still valid after the Data Access Object has been released,
        4. cache the result — this step assumes that the collection obtained at step 2 is immutable.
      Overrides:
      createFromCoordinateReferenceSystemCodes in class GeodeticAuthorityFactory
      Parameters:
      sourceCRS - coded value of source coordinate reference system.
      targetCRS - coded value of target coordinate reference system.
      Returns:
      the operations from sourceCRS to targetCRS.
      Throws:
      org.opengis.util.FactoryException - if the object creation failed.
    • newIdentifiedObjectFinder

      public IdentifiedObjectFinder newIdentifiedObjectFinder() throws org.opengis.util.FactoryException
      Returns a finder which can be used for looking up unidentified objects. The default implementation delegates lookup to the underlying Data Access Object and caches the result.
      Overrides:
      newIdentifiedObjectFinder in class GeodeticAuthorityFactory
      Returns:
      a finder to use for looking up unidentified objects.
      Throws:
      org.opengis.util.FactoryException - if the finder cannot be created.
      See Also:
    • isCacheable

      protected boolean isCacheable(String code, Object object)
      Returns whether the given object can be cached. This method is invoked after the Data Access Object created a new object not previously in the cache. If this isCacheable(…) method returns true, then the newly created object will be cached so that next calls to the same createFoo(String) method with the same code may return the same object. If this method returns false, then the newly created object will not be cached and next call to the createFoo(String) method with the same code will return a new object.

      The default implementation always returns true. Subclasses can override this method for filtering the objects to store in the cache.

      Parameters:
      code - the authority code specified by the caller for creating an object.
      object - the object created for the given authority code.
      Returns:
      whether the given object should be cached.
      Since:
      0.8
      See Also:
    • printCacheContent

      @Debug public void printCacheContent(PrintWriter out)
      Prints the cache content to the given writer. Keys are sorted by numerical order if possible, or alphabetical order otherwise. This method is used for debugging purpose only.
      Parameters:
      out - the output printer, or null for the standard output stream.
      See Also:
    • clear

      private static <DAO extends GeodeticAuthorityFactory> List<DAO> clear(Deque<ConcurrentAuthorityFactory.DataAccessRef<DAO>> availableDAOs)
      Clears the given queue and returns all DAO instances that it contained. The given queue shall be the availableDAOs queue.
      Parameters:
      availableDAOs - the queue of factories to close.
    • close

      private static <DAO extends GeodeticAuthorityFactory> void close(List<DAO> factories) throws Exception
      Invokes AutoCloseable.close() on all the given factories. Exceptions will be collected and rethrown only after all factories have been closed.
      Parameters:
      factories - the factories to close.
      Throws:
      Exception - the exception thrown by the first factory that failed to close.
    • close

      public void close() throws org.opengis.util.FactoryException
      Immediately closes all Data Access Objects that are closeable. This method does not clear the cache and does not disallow further usage of this factory: this ConcurrentAuthorityFactory can still be used as usual after it has been "closed". New Data Access Objects will be created if needed for replacing the ones closed by this method.

      The main purpose of this method is to force immediate release of JDBC connections or other kind of resources that Data Access Objects may hold. If this method is not invoked, Data Access Objects will be closed when this ConcurrentAuthorityFactory will be garbage collected or at JVM shutdown time, depending which event happen first.

      Specified by:
      close in interface AutoCloseable
      Throws:
      org.opengis.util.FactoryException - if an error occurred while closing the Data Access Objects.
      See Also:
    • toString

      public String toString()
      Returns a string representation of this factory for debugging purpose only. The string returned by this method may change in any future SIS version.
      Overrides:
      toString in class GeodeticAuthorityFactory
      Returns:
      a string representation for debugging purpose.
      See Also:
    • appendStringTo

      @Debug final void appendStringTo(StringBuilder buffer)
      Completes the string representation of this factory for debugging purpose only. The string formatted by this method may change in any future SIS version.
      Overrides:
      appendStringTo in class GeodeticAuthorityFactory