Package org.geotools.referencing.factory

Source Code of org.geotools.referencing.factory.CachedAuthorityDecorator

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2005-2008, Open Source Geospatial Foundation (OSGeo)
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation;
*    version 2.1 of the License.
*
*    This library is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*
*    This package contains documentation from OpenGIS specifications.
*    OpenGIS consortium's work is fully acknowledged here.
*/
package org.geotools.referencing.factory;

import java.util.Set;

import javax.measure.unit.Unit;

import org.geotools.factory.BufferedFactory;
import org.geotools.factory.FactoryRegistryException;
import org.geotools.factory.GeoTools;
import org.geotools.factory.Hints;
import org.geotools.util.ObjectCache;
import org.geotools.util.ObjectCaches;
import org.opengis.metadata.citation.Citation;
import org.opengis.referencing.AuthorityFactory;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.IdentifiedObject;
import org.opengis.referencing.crs.CRSAuthorityFactory;
import org.opengis.referencing.crs.CompoundCRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.DerivedCRS;
import org.opengis.referencing.crs.EngineeringCRS;
import org.opengis.referencing.crs.GeocentricCRS;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.ImageCRS;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.crs.TemporalCRS;
import org.opengis.referencing.crs.VerticalCRS;
import org.opengis.referencing.cs.CSAuthorityFactory;
import org.opengis.referencing.cs.CartesianCS;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.cs.CylindricalCS;
import org.opengis.referencing.cs.EllipsoidalCS;
import org.opengis.referencing.cs.PolarCS;
import org.opengis.referencing.cs.SphericalCS;
import org.opengis.referencing.cs.TimeCS;
import org.opengis.referencing.cs.VerticalCS;
import org.opengis.referencing.datum.Datum;
import org.opengis.referencing.datum.DatumAuthorityFactory;
import org.opengis.referencing.datum.Ellipsoid;
import org.opengis.referencing.datum.EngineeringDatum;
import org.opengis.referencing.datum.GeodeticDatum;
import org.opengis.referencing.datum.ImageDatum;
import org.opengis.referencing.datum.PrimeMeridian;
import org.opengis.referencing.datum.TemporalDatum;
import org.opengis.referencing.datum.VerticalDatum;
import org.opengis.referencing.operation.CoordinateOperation;
import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory;
import org.opengis.util.InternationalString;


/**
* An authority factory that caches all objects created by delegate factories.
* This class is set up to cache the full complement of referencing objects:
* In many cases a single implementation will be used for several the authority factory
* interfaces - but this is not a requirement.
* </p>
* The behaviour of the {@code createFoo(String)} methods first looks if a
* previously created object exists for the given code. If such an object
* exists, it is returned directly. The testing of the cache is synchronized and
* may block if the referencing object is under construction.
* <p>
* If the object is not yet created, the definition is delegated to the
* appropriate the {@linkplain an AuthorityFactory authority factory} and the
* result is cached for next time.
* <p>
* This object is responsible for owning a {{ReferencingObjectCache}}; there are
* several implementations to choose from on construction.
* </p>
*
* @since 2.4
*
*
* @source $URL$
* @version $Id$
* @author Jody Garnett
*/
public final class CachedAuthorityDecorator extends AbstractAuthorityFactory
    implements AuthorityFactory, CRSAuthorityFactory, CSAuthorityFactory,
    DatumAuthorityFactory, CoordinateOperationAuthorityFactory,
    BufferedFactory {

  /** Cache to be used for referencing objects. */
  ObjectCache cache;

  /** The delegate authority. */
  private AuthorityFactory authority;

  /** The delegate authority for coordinate reference systems. */
  private CRSAuthorityFactory crsAuthority;

  /** The delegate authority for coordinate sytems. */
  private CSAuthorityFactory csAuthority;

  /** The delegate authority for datums. */
  private DatumAuthorityFactory datumAuthority;

  /** The delegate authority for coordinate operations. */
  private CoordinateOperationAuthorityFactory operationAuthority;

  /** The delegate authority for searching. */
    private AbstractAuthorityFactory delegate;

  /**
   * Constructs an instance wrapping the specified factory with a default
   * cache.
   * <p>
   * The provided authority factory must implement
   * {@link DatumAuthorityFactory}, {@link CSAuthorityFactory},
   * {@link CRSAuthorityFactory} and
   * {@link CoordinateOperationAuthorityFactory} .
   *
   * @param factory
   *            The factory to cache. Can not be {@code null}.
   */
  public CachedAuthorityDecorator(final AuthorityFactory factory) {
    this(factory, createCache(GeoTools.getDefaultHints()));
  }

  /**
   * Constructs an instance wrapping the specified factory. The
   * {@code maxStrongReferences} argument specify the maximum number of
   * objects to keep by strong reference. If a greater amount of objects are
   * created, then the strong references for the oldest ones are replaced by
   * weak references.
   * <p>
   * This constructor is protected because subclasses must declare which of
   * the {@link DatumAuthorityFactory}, {@link CSAuthorityFactory},
   * {@link CRSAuthorityFactory} {@link SearchableAuthorityFactory} and
   * {@link CoordinateOperationAuthorityFactory} interfaces they choose to
   * implement.
   *
   * @param factory
   *            The factory to cache. Can not be {@code null}.
   * @param maxStrongReferences
   *            The maximum number of objects to keep by strong reference.
   */
  protected CachedAuthorityDecorator(AuthorityFactory factory,
      ObjectCache cache) {
      super( ((ReferencingFactory)factory).getPriority() ); // TODO
    this.cache = cache;
    authority = factory;
    crsAuthority = (CRSAuthorityFactory) factory;
    csAuthority = (CSAuthorityFactory) factory;
    datumAuthority = (DatumAuthorityFactory) factory;
    operationAuthority = (CoordinateOperationAuthorityFactory) factory;
    this.delegate = (AbstractAuthorityFactory) factory;
  }

  /** Utility method used to produce cache based on hint */
  protected static ObjectCache createCache(final Hints hints)
      throws FactoryRegistryException {
    return ObjectCaches.create(hints);
  }

  //
  // Utility Methods and Cache Care and Feeding
  //
  protected String toKey(String code) {
    return ObjectCaches.toKey( getAuthority(), code);
  }

  //
  // AuthorityFactory
  //
  public IdentifiedObject createObject(String code) throws FactoryException {
    final String key = toKey(code);
    IdentifiedObject obj = (IdentifiedObject) cache.get(key);
    if (obj == null) {
      try {
        cache.writeLock(key);
        obj = (IdentifiedObject) cache.peek(key);
        if (obj == null) {
          obj = authority.createObject(code);
          cache.put(key, obj);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return obj;
  }

  public Citation getAuthority() {
    return authority.getAuthority();
  }

  public Set getAuthorityCodes(Class type) throws FactoryException {
    return authority.getAuthorityCodes(type);
  }

  public InternationalString getDescriptionText(String code)
      throws FactoryException {
    return authority.getDescriptionText(code);
  }

  //
  // CRSAuthority
  //
  public synchronized CompoundCRS createCompoundCRS(final String code)
      throws FactoryException {
    final String key = toKey(code);
    CompoundCRS crs = (CompoundCRS) cache.get(key);
    if (crs == null) {
      try {
        cache.writeLock(key);
        crs = (CompoundCRS) cache.peek(key);
        if (crs == null) {
          crs = crsAuthority.createCompoundCRS(code);
          cache.put(key, crs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return crs;
  }

  public CoordinateReferenceSystem createCoordinateReferenceSystem(String code)
      throws FactoryException {
    final String key = toKey(code);
    CoordinateReferenceSystem crs = (CoordinateReferenceSystem) cache
        .get(key);
    if (crs == null) {
      try {
        cache.writeLock(key);
        crs = (CoordinateReferenceSystem) cache.peek(key);
        if (crs == null) {
          crs = crsAuthority.createCoordinateReferenceSystem(code);
          cache.put(key, crs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return crs;
  }

  public DerivedCRS createDerivedCRS(String code) throws FactoryException {
    final String key = toKey(code);
    DerivedCRS crs = (DerivedCRS) cache.get(key);
    if (crs == null) {
      try {
        cache.writeLock(key);
        crs = (DerivedCRS) cache.peek(key);
        if (crs == null) {
          crs = crsAuthority.createDerivedCRS(code);
          cache.put(key, crs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return crs;
  }

  public EngineeringCRS createEngineeringCRS(String code)
      throws FactoryException {
    final String key = toKey(code);
    EngineeringCRS crs = (EngineeringCRS) cache.get(key);
    if (crs == null) {
      try {
        cache.writeLock(key);
        crs = (EngineeringCRS) cache.peek(key);
        if (crs == null) {
          crs = crsAuthority.createEngineeringCRS(code);
          cache.put(key, crs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return crs;
  }

  public GeocentricCRS createGeocentricCRS(String code)
      throws FactoryException {
    final String key = toKey(code);
    GeocentricCRS crs = (GeocentricCRS) cache.get(key);
    if (crs == null) {
      try {
        cache.writeLock(key);
        crs = (GeocentricCRS) cache.peek(key);
        if (crs == null) {
          crs = crsAuthority.createGeocentricCRS(code);
          cache.put(key, crs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return crs;
  }

  public GeographicCRS createGeographicCRS(String code)
      throws FactoryException {
    final String key = toKey(code);
    GeographicCRS crs = (GeographicCRS) cache.get(key);
    if (crs == null) {
      try {
        cache.writeLock(key);
        crs = (GeographicCRS) cache.peek(key);
        if (crs == null) {
          crs = crsAuthority.createGeographicCRS(code);
          cache.put(key, crs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return crs;
  }

  public ImageCRS createImageCRS(String code) throws FactoryException {
    final String key = toKey(code);
    ImageCRS crs = (ImageCRS) cache.get(key);
    if (crs == null) {
      try {
        cache.writeLock(key);
        crs = (ImageCRS) cache.peek(key);
        if (crs == null) {
          crs = crsAuthority.createImageCRS(code);
          cache.put(key, crs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return crs;
  }

  public ProjectedCRS createProjectedCRS(String code) throws FactoryException {
    final String key = toKey(code);
    ProjectedCRS crs = (ProjectedCRS) cache.get(key);
    if (crs == null) {
      try {
        cache.writeLock(key);
        crs = (ProjectedCRS) cache.peek(key);
        if (crs == null) {
          crs = crsAuthority.createProjectedCRS(code);
          cache.put(key, crs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return crs;
  }

  public TemporalCRS createTemporalCRS(String code) throws FactoryException {
    final String key = toKey(code);
    TemporalCRS crs = (TemporalCRS) cache.get(key);
    if (crs == null) {
      try {
        cache.writeLock(key);
        crs = (TemporalCRS) cache.peek(key);
        if (crs == null) {
          crs = crsAuthority.createTemporalCRS(code);
          cache.put(key, crs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return crs;
  }

  public VerticalCRS createVerticalCRS(String code) throws FactoryException {
    final String key = toKey(code);
    VerticalCRS crs = (VerticalCRS) cache.get(key);
    if (crs == null) {
      try {
        cache.writeLock(key);
        crs = (VerticalCRS) cache.peek(key);
        if (crs == null) {
          crs = crsAuthority.createVerticalCRS(code);
          cache.put(key, crs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return crs;
  }

  //
  // CSAuthority
  //
  public CartesianCS createCartesianCS(String code) throws FactoryException {
    final String key = toKey(code);
    CartesianCS cs = (CartesianCS) cache.get(key);
    if (cs == null) {
      try {
        cache.writeLock(key);
        cs = (CartesianCS) cache.peek(key);
        if (cs == null) {
          cs = csAuthority.createCartesianCS(code);
          cache.put(key, cs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return cs;
  }

  public CoordinateSystem createCoordinateSystem(String code)
      throws FactoryException {
    final String key = toKey(code);
    CoordinateSystem cs = (CoordinateSystem) cache.get(key);
    if (cs == null) {
      try {
        cache.writeLock(key);
        cs = (CoordinateSystem) cache.peek(key);
        if (cs == null) {
          cs = csAuthority.createCoordinateSystem(code);
          cache.put(key, cs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return cs;
  }

  // sample implemenation with get/test
  public CoordinateSystemAxis createCoordinateSystemAxis(String code)
      throws FactoryException {
    final String key = toKey(code);
    CoordinateSystemAxis axis = (CoordinateSystemAxis) cache.get(key);
    if (axis == null) {
      try {
        cache.writeLock(key);
        axis = (CoordinateSystemAxis) cache.peek(key);
        if (axis == null) {
          axis = csAuthority.createCoordinateSystemAxis(code);
          cache.put(key, axis);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return axis;
  }

  public CylindricalCS createCylindricalCS(String code)
      throws FactoryException {
    final String key = toKey(code);
    CylindricalCS cs = (CylindricalCS) cache.get(key);
    if (cs == null) {
      try {
        cache.writeLock(key);
        cs = (CylindricalCS) cache.peek(key);
        if (cs == null) {
          cs = csAuthority.createCylindricalCS(code);
          cache.put(key, cs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return cs;
  }

  public EllipsoidalCS createEllipsoidalCS(String code)
      throws FactoryException {
    final String key = toKey(code);
    EllipsoidalCS cs = (EllipsoidalCS) cache.get(key);
    if (cs == null) {
      try {
        cache.writeLock(key);
        cs = (EllipsoidalCS) cache.peek(key);
        if (cs == null) {
          cs = csAuthority.createEllipsoidalCS(code);
          cache.put(key, cs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return cs;
  }

  public PolarCS createPolarCS(String code) throws FactoryException {
    final String key = toKey(code);
    PolarCS cs = (PolarCS) cache.get(key);
    if (cs == null) {
      try {
        cache.writeLock(key);
        cs = (PolarCS) cache.peek(key);
        if (cs == null) {
          cs = csAuthority.createPolarCS(code);
          cache.put(key, cs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return cs;
  }

  public SphericalCS createSphericalCS(String code) throws FactoryException {
    final String key = toKey(code);
    SphericalCS cs = (SphericalCS) cache.get(key);
    if (cs == null) {
      try {
        cache.writeLock(key);
        cs = (SphericalCS) cache.peek(key);
        if (cs == null) {
          cs = csAuthority.createSphericalCS(code);
          cache.put(key, cs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return cs;
  }

  public TimeCS createTimeCS(String code) throws FactoryException {
    final String key = toKey(code);
    TimeCS cs = (TimeCS) cache.get(key);
    if (cs == null) {
      try {
        cache.writeLock(key);
        cs = (TimeCS) cache.peek(key);
        if (cs == null) {
          cs = csAuthority.createTimeCS(code);
          cache.put(key, cs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return cs;
  }

  public Unit<?> createUnit(String code) throws FactoryException {
    final String key = toKey(code);
    Unit<?> unit = (Unit) cache.get(key);
    if (unit == null) {
      try {
        cache.writeLock(key);
        unit = (Unit) cache.peek(key);
        if (unit == null) {
          unit = csAuthority.createUnit(code);
          cache.put(key, unit);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return unit;
  }

  public VerticalCS createVerticalCS(String code) throws FactoryException {
    final String key = toKey(code);
    VerticalCS cs = (VerticalCS) cache.get(key);
    if (cs == null) {
      try {
        cache.writeLock(key);
        cs = (VerticalCS) cache.peek(key);
        if (cs == null) {
          cs = csAuthority.createVerticalCS(code);
          cache.put(key, cs);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return cs;
  }

  //
  // DatumAuthorityFactory
  //
  public Datum createDatum(String code) throws FactoryException {
    final String key = toKey(code);
    Datum datum = (Datum) cache.get(key);
    if (datum == null) {
      try {
        cache.writeLock(key);
        datum = (Datum) cache.peek(key);
        if (datum == null) {
          datum = datumAuthority.createDatum(code);
          cache.put(key, datum);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return datum;
  }

  public Ellipsoid createEllipsoid(String code) throws FactoryException {
    final String key = toKey(code);
    Ellipsoid ellipsoid = (Ellipsoid) cache.get(key);
    if (ellipsoid == null) {
      try {
        cache.writeLock(key);
        ellipsoid = (Ellipsoid) cache.peek(key);
        if (ellipsoid == null) {
          ellipsoid = datumAuthority.createEllipsoid(code);
          cache.put(key, ellipsoid);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return ellipsoid;
  }

  public EngineeringDatum createEngineeringDatum(String code)
      throws FactoryException {
    final String key = toKey(code);
    EngineeringDatum datum = (EngineeringDatum) cache.get(key);
    if (datum == null) {
      try {
        cache.writeLock(key);
        datum = (EngineeringDatum) cache.peek(key);
        if (datum == null) {
          datum = datumAuthority.createEngineeringDatum(code);
          cache.put(key, datum);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return datum;
  }

  public GeodeticDatum createGeodeticDatum(String code)
      throws FactoryException {
    final String key = toKey(code);
    GeodeticDatum datum = (GeodeticDatum) cache.get(key);
    if (datum == null) {
      try {
        cache.writeLock(key);
        datum = (GeodeticDatum) cache.peek(key);
        if (datum == null) {
          datum = datumAuthority.createGeodeticDatum(code);
          cache.put(key, datum);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return datum;
  }

  public ImageDatum createImageDatum(String code) throws FactoryException {
    final String key = toKey(code);
    ImageDatum datum = (ImageDatum) cache.get(key);
    if (datum == null) {
      try {
        cache.writeLock(key);
        datum = (ImageDatum) cache.peek(key);
        if (datum == null) {
          datum = datumAuthority.createImageDatum(code);
          cache.put(key, datum);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return datum;
  }

  public PrimeMeridian createPrimeMeridian(String code)
      throws FactoryException {
    final String key = toKey(code);
    PrimeMeridian datum = (PrimeMeridian) cache.get(key);
    if (datum == null) {
      try {
        cache.writeLock(key);
        datum = (PrimeMeridian) cache.peek(key);
        if (datum == null) {
          datum = datumAuthority.createPrimeMeridian(code);
          cache.put(key, datum);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return datum;
  }

  public TemporalDatum createTemporalDatum(String code)
      throws FactoryException {
    final String key = toKey(code);
    TemporalDatum datum = (TemporalDatum) cache.get(key);
    if (datum == null) {
      try {
        cache.writeLock(key);
        datum = (TemporalDatum) cache.peek(key);
        if (datum == null) {
          datum = datumAuthority.createTemporalDatum(code);
          cache.put(key, datum);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return datum;
  }

  public VerticalDatum createVerticalDatum(String code)
      throws FactoryException {
    final String key = toKey(code);
    VerticalDatum datum = (VerticalDatum) cache.get(key);
    if (datum == null) {
      try {
        cache.writeLock(key);
        datum = (VerticalDatum) cache.peek(key);
        if (datum == null) {
          datum = datumAuthority.createVerticalDatum(code);
          cache.put(key, datum);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return datum;
  }

  public CoordinateOperation createCoordinateOperation(String code)
      throws FactoryException {
    final String key = toKey(code);
    CoordinateOperation operation = (CoordinateOperation) cache.get(key);
    if (operation == null) {
      try {
        cache.writeLock(key);
        operation = (CoordinateOperation) cache.peek(key);
        if (operation == null) {
          operation = operationAuthority
              .createCoordinateOperation(code);
          cache.put(key, operation);
        }
      } finally {
        cache.writeUnLock(key);
      }
    }
    return operation;
  }

  public synchronized Set/*<CoordinateOperation>*/ createFromCoordinateReferenceSystemCodes(
      final String sourceCode, final String targetCode)
      throws FactoryException {

    final Object key = ObjectCaches.toKey( getAuthority(),  sourceCode, targetCode );
    Set operations = (Set) cache.get(key);
    if (operations == null) {
      try {
        cache.writeLock(key);
        operations = (Set) cache.peek(key);
        if (operations == null) {
          operations = operationAuthority.createFromCoordinateReferenceSystemCodes( sourceCode, targetCode );
          // can we not trust operationAuthority to return us an unmodifiableSet ?
          //operations = Collections.unmodifiableSet( operations );

          cache.put( key, operations );
        }
      }
      finally {
        cache.writeUnLock(key);
      }
    }
    return operations;
  }
  //
  // AbstractAuthorityFactory
  //
    public IdentifiedObjectFinder getIdentifiedObjectFinder( Class type ) throws FactoryException {
        return delegate.getIdentifiedObjectFinder( type );
    }

    public void dispose() throws FactoryException {
        delegate.dispose();
        cache.clear();
        cache = null;
        delegate = null;
    }

    public String getBackingStoreDescription() throws FactoryException {
        return delegate.getBackingStoreDescription();
    }
}
TOP

Related Classes of org.geotools.referencing.factory.CachedAuthorityDecorator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.