/* * 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.Map; import java.util.Set; import java.util.LinkedHashSet; import java.util.Collection; import java.awt.RenderingHints; import org.opengis.referencing.*; import org.geotools.factory.Hints; /** * The base class for authority factories that create referencing object directly. This is * in contrast with other factories like the {@linkplain AuthorityFactoryAdapter adapter} * or {@linkplain BufferedAuthorityFactory buffered} ones, which delegates their work to * an other factory. * * @since 2.3 * * @source $URL$ * @version $Id$ * @author Martin Desruisseaux (IRD) */ public abstract class DirectAuthorityFactory extends AbstractAuthorityFactory { // IMPLEMENTATION NOTE: The reason why this class exist is that we don't want "indirect" // factories like BufferedAuthorityFactory to inherit the factories field. If this field // existed in their super-class, then the super-class constructor could try to initialize // it while in fact BufferedAuthorityFactory don't need it. Experience with Geotools 2.2 // suggest that it can lead to tricky recursivity problems in FactoryFinder, because most // factories registered in META-INF/services are some kind of BufferedAuthorityFactory. /** * The underlying factories used for objects creation. */ protected final ReferencingFactoryContainer factories; /** * Tells if {@link ReferencingFactoryContainer#hints} has been invoked. It must be * invoked exactly once, but can't be invoked in the constructor because it causes * a {@link StackOverflowError} in some situations. */ private boolean hintsInitialized; /** * Constructs an instance using the specified set of factories. * * @param factories The low-level factories to use. * @param priority The priority for this factory, as a number between * {@link #MINIMUM_PRIORITY MINIMUM_PRIORITY} and * {@link #MAXIMUM_PRIORITY MAXIMUM_PRIORITY} inclusive. */ protected DirectAuthorityFactory(final ReferencingFactoryContainer factories, final int priority) { super(priority); this.factories = factories; ensureNonNull("factories", factories); } /** * Constructs an instance using the specified hints. This constructor recognizes the * {@link Hints#CRS_FACTORY CRS}, {@link Hints#CS_FACTORY CS}, {@link Hints#DATUM_FACTORY DATUM} * and {@link Hints#MATH_TRANSFORM_FACTORY MATH_TRANSFORM} {@code FACTORY} hints. * * @param hints The hints, or {@code null} if none. * @param priority The priority for this factory, as a number between * {@link #MINIMUM_PRIORITY MINIMUM_PRIORITY} and * {@link #MAXIMUM_PRIORITY MAXIMUM_PRIORITY} inclusive. */ protected DirectAuthorityFactory(final Hints hints, final int priority) { super(priority); factories = ReferencingFactoryContainer.instance(hints); // Do not copies the user-provided hints to this.hints, because // this is up to sub-classes to decide which hints are relevant. } /** * Returns the implementation hints for this factory. The returned map contains values for * {@link Hints#CRS_FACTORY CRS}, {@link Hints#CS_FACTORY CS}, {@link Hints#DATUM_FACTORY DATUM} * and {@link Hints#MATH_TRANSFORM_FACTORY MATH_TRANSFORM} {@code FACTORY} hints. Other values * may be provided as well, at implementation choice. */ @Override public Map<RenderingHints.Key,?> getImplementationHints() { synchronized (hints) { // Note: avoid lock on public object. if (!hintsInitialized) { hintsInitialized = true; hints.putAll(factories.getImplementationHints()); } } return super.getImplementationHints(); } /** * Returns the direct {@linkplain Factory factory} dependencies. */ @Override Collection<? super AuthorityFactory> dependencies() { if (factories != null) { final Set<Object> dependencies = new LinkedHashSet<Object>(8); dependencies.add(factories.getCRSFactory()); dependencies.add(factories.getCSFactory()); dependencies.add(factories.getDatumFactory()); return dependencies; } return super.dependencies(); } }