/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-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.
*/
package org.geotools.factory;
import java.util.Map;
import java.awt.RenderingHints;
/**
* Base interface for Geotools factories (i.e. service discovery).
*
* <p>This interfaces forms the core of the Geotools plug-in system, by which capabilities
* can be added to the library at runtime. Each sub-interface defines a <cite>service</cite>.
* Most services are set up with concrete implementation being registered for use in
* a <cite>service registry</cite>, which acts as a container for service implementations.</p>
*
* <p>Service registries don't need to be a Geotools implementation. They can be (but are not
* limited to) any {@link javax.imageio.spi.ServiceRegistry} subclass. If the standard
* {@code ServiceRegistry} (or its Geotools extension {@link FactoryRegistry}) is selected
* as a container for services, then factory implementations should be declared as below
* (select only one way):</p>
*
* <ul>
* <li><strong>Register for automatic discovery</strong></li>
* <ul>
* <li>Provide a public no-arguments constructor.</li>
* <li>Add the fully qualified name of the <u>implementation</u> class in the
* {@code META-INF/services/}<var>classname</var> file where <var>classname</var>
* is the fully qualified name of the service <u>interface</u>.</li>
* <li>The factory implementations will be discovered when
* {@link FactoryRegistry#scanForPlugins} will be invoked.</li>
* </ul>
* <li><strong><u>Or</u> register explicitly by application code</strong></li>
* <ul>
* <li>Invoke {@link ServiceRegistry#registerServiceProvider} in application code.</li>
* </ul>
* </ul>
*
* <p>In addition, it is recommended that implementations provide a constructor expecting
* a single {@link Hints} argument. This optional argument gives to the user some control
* of the factory's low-level details. The amount of control is factory specific. The geotools
* library defines a global class called {@link Hints} that is ment as API (i.e. you can assume
* these hints are supported). Factories may also provide information on their own custom hints
* as part of their javadoc class description.</p>
*
* <strong>Examples:</strong>
* <ul>
* <li><p>An application supplied a {@linkplain Hints#DATUM_FACTORY datum factory hint}, being
* passed to a {@linkplain org.opengis.referencing.datum.DatumAuthorityFactory datum authority
* factory} so that all datum created from an authority code will come from the supplied datum
* factory.</p></li>
*
* <li><p>An application supplied a {@link org.geotools.feature.FeatureFactory} (ensuring all
* constructed features support the Eclipse's {@code IAdaptable} interface), being passed to a
* {@link org.geotools.feature.FeatureTypeFactory} so that all {@code FeatureTypes}
* constructed will produce features supporting the indicated interface.<p></li>
* </ul>
*
* <p>As seen in those examples this concept of a hint becomes more interesting when
* the operation being controlled is discovery of other services used by the Factory.
* By supplying appropriate hints one can chain together several factories and retarget
* them to an application specific task.</p>
*
* @author Ian Schneider
* @author Martin Desruisseaux
* @author Jody Garnett
*
* @source $URL$
* @version $Id$
*
* @see Hints
* @see FactoryRegistry
*/
public interface Factory {
/**
* Map of hints (maybe {@linkplain java.util.Collections#unmodifiableMap unmodifiable})
* used by this factory to customize its use. This map is <strong>not</strong> guaranteed
* to contains all the hints supplied by the user; it may be only a subset. Consequently,
* hints provided here are usually not suitable for creating new factories, unless the
* implementation make some additional garantees
* (e.g. {@link FactoryUsingVolatileDependencies}).
* <p>
* The primary purpose of this method is to determine if an <strong>existing</strong>
* factory instance can be reused for a set of user-supplied hints. This method is invoked by
* {@link FactoryRegistry} in order to compare this factory's hints against user's hints.
* This is dependency introspection only; {@code FactoryRegistry} <strong>never</strong>
* invokes this method for creating new factories.
* <p>
* Keys are usually static constants from the {@link Hints} class, while values are
* instances of some key-dependent class. The {@linkplain Map#keySet key set} must contains
* at least all hints impacting functionality. While the key set may contains all hints
* supplied by the user, it is recommended to limit the set to only the hints used by this
* particular factory instance. A minimal set will helps {@link FactoryRegistry} to compare
* only hints that matter and avoid the creation of unnecessary instances of this factory.
* <p>
* The hint values may be different than the one supplied by the user. If a user supplied a
* hint as a {@link Class} object, this method shall replace it by the actual instance used,
* if possible.
* <p>
* Implementations of this method are usually quite simple. For example if a
* {@linkplain org.opengis.referencing.datum.DatumAuthorityFactory datum authority factory}
* uses an ordinary {@linkplain org.opengis.referencing.datum.DatumFactory datum factory},
* its method could be implemented as below (note that we should not check if the datum
* factory is null, since key with null value is the expected behaviour in this case).
* Example:
*
* <pre><code>
* Map hints = new HashMap();
* hints.put({@linkplain Hints#DATUM_FACTORY}, datumFactory);
* return hints;
* </code></pre>
*
* @return The map of hints, or an {@linkplain java.util.Collections#EMPTY_MAP empty map}
* if none.
*/
Map<RenderingHints.Key, ?> getImplementationHints();
}