001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.factory;
017:
018: import java.util.Arrays;
019: import java.util.Set;
020:
021: import org.geotools.data.FeatureLockFactory;
022: import org.geotools.data.FileDataStoreFactorySpi;
023: import org.geotools.feature.AttributeTypeFactory;
024: import org.geotools.feature.DefaultFeatureTypeFactory;
025: import org.geotools.feature.FeatureCollections;
026: import org.geotools.feature.FeatureTypeFactory;
027: import org.geotools.filter.FunctionExpression;
028: import org.geotools.filter.FunctionImpl;
029: import org.geotools.resources.LazySet;
030: import org.geotools.styling.StyleFactory;
031: import org.opengis.filter.FilterFactory;
032: import org.opengis.filter.FilterFactory2;
033: import org.opengis.filter.expression.Function;
034:
035: /**
036: * Defines static methods used to access the application's default implementation for some
037: * common factories. Those "common" factories comprise the {@linkplain StyleFactory style}
038: * and {@linkplain FilterFactory filter} factories. Note that some specialized factories
039: * finder like {@linkplain org.geotools.referencing.ReferencingFactoryFinder referencing} and
040: * {@linkplain org.geotools.coverage.ReferencingFactoryFinder coverage} are defined in specialized
041: * classes.
042: * <p>
043: * <b>Tip:</b> The {@link BasicFactories} classes provides an other way to access the various
044: * factories from a central point.
045: *
046: * @since 2.4
047: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/factory/CommonFactoryFinder.java $
048: * @version $Id: CommonFactoryFinder.java 29058 2008-02-03 17:47:07Z desruisseaux $
049: * @author Martin Desruisseaux
050: * @author Jody Garnett
051: */
052: public final class CommonFactoryFinder extends FactoryFinder {
053: /**
054: * The service registry for this manager.
055: * Will be initialized only when first needed.
056: */
057: private static FactoryRegistry registry;
058:
059: /**
060: * Do not allows any instantiation of this class.
061: */
062: private CommonFactoryFinder() {
063: // singleton
064: }
065:
066: /**
067: * Returns the service registry. The registry will be created the first
068: * time this method is invoked.
069: */
070: private static FactoryRegistry getServiceRegistry() {
071: assert Thread.holdsLock(CommonFactoryFinder.class);
072: if (registry == null) {
073: registry = new FactoryCreator(Arrays
074: .asList(new Class[] {
075: StyleFactory.class,
076: FilterFactory.class,
077: FeatureLockFactory.class,
078: FileDataStoreFactorySpi.class,
079: FunctionImpl.class,
080: FunctionExpression.class,//TODO: remove
081: Function.class, AttributeTypeFactory.class,
082: FeatureCollections.class,
083: FeatureTypeFactory.class }));
084: }
085: return registry;
086: }
087:
088: /**
089: * Returns the first implementation of {@link StyleFactory} matching the specified hints.
090: * If no implementation matches, a new one is created if possible or an exception is thrown
091: * otherwise.
092: *
093: * @param hints An optional map of hints, or {@code null} if none.
094: * @return The first style factory that matches the supplied hints.
095: * @throws FactoryRegistryException if no implementation was found or can be created for the
096: * {@link StyleFactory} interface.
097: *
098: * @see Hints#STYLE_FACTORY
099: */
100: public static synchronized StyleFactory getStyleFactory(Hints hints)
101: throws FactoryRegistryException {
102: hints = mergeSystemHints(hints);
103: return (StyleFactory) getServiceRegistry().getServiceProvider(
104: StyleFactory.class, null, hints, Hints.STYLE_FACTORY);
105: }
106:
107: /**
108: * Returns a set of all available implementations for the {@link StyleFactory} interface.
109: *
110: * @param hints An optional map of hints, or {@code null} if none.
111: * @return Set of available style factory implementations.
112: */
113: public static synchronized Set getStyleFactories(Hints hints) {
114: hints = mergeSystemHints(hints);
115: return new LazySet(getServiceRegistry().getServiceProviders(
116: StyleFactory.class, null, hints));
117: }
118:
119: /**
120: * Returns a set of all available implementations for the {@link FunctionExpression} interface.
121: *
122: * @param hints An optional map of hints, or {@code null} if none.
123: * @return Set of available style factory implementations.
124: * @deprecated Use FunctionExpression is now @deprecated
125: */
126: public static synchronized Set getFunctionExpressions(Hints hints) {
127: hints = mergeSystemHints(hints);
128: return new LazySet(getServiceRegistry().getServiceProviders(
129: Function.class, null, hints));
130: }
131:
132: /**
133: * Returns a set of all available implementations for the {@link FunctionExpression} interface.
134: *
135: * @param hints An optional map of hints, or {@code null} if none.
136: * @return Set of available function expression implementations.
137: */
138: public static synchronized Set getFunctions(Hints hints) {
139: hints = mergeSystemHints(hints);
140: return new LazySet(getServiceRegistry().getServiceProviders(
141: FunctionImpl.class, null, hints));
142: }
143:
144: /**
145: * Returns the first implementation of {@link FeatureLockFactory} matching the specified hints.
146: * If no implementation matches, a new one is created if possible or an exception is thrown
147: * otherwise.
148: *
149: * @param hints An optional map of hints, or {@code null} if none.
150: * @return The first feature lock factory that matches the supplied hints.
151: * @throws FactoryRegistryException if no implementation was found or can be created for the
152: * {@link FeatureLockFactory} interface.
153: *
154: * @see Hints#FEATURE_LOCK_FACTORY
155: */
156: public static synchronized FeatureLockFactory getFeatureLockFactory(
157: Hints hints) {
158: hints = mergeSystemHints(hints);
159: return (FeatureLockFactory) getServiceRegistry()
160: .getServiceProvider(FeatureLockFactory.class, null,
161: hints, Hints.FEATURE_LOCK_FACTORY);
162: }
163:
164: /**
165: * Returns a set of all available implementations for the {@link FeatureLockFactory} interface.
166: *
167: * @param hints An optional map of hints, or {@code null} if none.
168: * @return Set<FeatureLockFactory> of available style factory implementations.
169: */
170: public static synchronized Set getFeatureLockFactories(Hints hints) {
171: hints = mergeSystemHints(hints);
172: return new LazySet(getServiceRegistry().getServiceProviders(
173: FeatureLockFactory.class, null, hints));
174: }
175:
176: /**
177: * Returns a set of all available implementations for the {@link FileDataStoreFactorySpi} interface.
178: *
179: * @param hints An optional map of hints, or {@code null} if none.
180: * @return Set of available file data store factory implementations.
181: */
182: public static synchronized Set getFileDataStoreFactories(Hints hints) {
183: hints = mergeSystemHints(hints);
184: return new LazySet(getServiceRegistry().getServiceProviders(
185: FileDataStoreFactorySpi.class, null, hints));
186: }
187:
188: /**
189: * Returns the first implementation of {@link AttributeTypeFactory} matching the specified hints.
190: * If no implementation matches, a new one is created if possible or an exception is thrown
191: * otherwise.
192: * <p>
193: * If no hints are provided, this method typically returns an instance of
194: * {@link org.geotools.feature.DefaultAttributeTypeFactory}.
195: *
196: * @param hints An optional map of hints, or {@code null} if none.
197: * @return The first attribute type factory that matches the supplied hints.
198: * @throws FactoryRegistryException if no implementation was found or can be created for the
199: * {@link AttributeTypeFactory} interface.
200: *
201: * @see Hints#ATTRIBUTE_TYPE_FACTORY
202: * @see org.geotools.feature.DefaultAttributeTypeFactory
203: */
204: public static synchronized AttributeTypeFactory getAttributeTypeFactory(
205: Hints hints) {
206: hints = mergeSystemHints(hints);
207: return (AttributeTypeFactory) getServiceRegistry()
208: .getServiceProvider(AttributeTypeFactory.class, null,
209: hints, Hints.ATTRIBUTE_TYPE_FACTORY);
210: }
211:
212: /**
213: * Returns a set of all available implementations for the {@link AttributeTypeFactory} interface.
214: *
215: * @param hints An optional map of hints, or {@code null} if none.
216: * @return Set of available attribute type factory implementations.
217: */
218: public static synchronized Set getAttributeTypeFactories(Hints hints) {
219: hints = mergeSystemHints(hints);
220: return new LazySet(getServiceRegistry().getServiceProviders(
221: AttributeTypeFactory.class, null, hints));
222: }
223:
224: /**
225: * Returns a set of all available implementations for the {@link FeatureTypeFactory} interface.
226: *
227: * @param hints An optional map of hints, or {@code null} if none.
228: * @return Set of available feature type factory implementations.
229: */
230: public static synchronized Set getAttributeFeatureFactories(
231: Hints hints) {
232: hints = mergeSystemHints(hints);
233: return new LazySet(getServiceRegistry().getServiceProviders(
234: FeatureTypeFactory.class, null, hints));
235: }
236:
237: /**
238: * The default AttributeTypeFactory.
239: * <p>
240: * You can use the following Hints:
241: * <ul>
242: * <li>FEATURE_TYPE_FACTORY - to control or reuse an implementation
243: * <li>FEATURE_TYPE_FACTORY_NAME - to supply a name for the returned factory
244: * </ul>
245: * GeoTools ships with a DefaultAttributeTypeFactory, although you can hook up
246: * your own implementation as needed.
247: * @return FeatureTypeFactory using Hints.FEATURE_TYPE_FACTORY_NAME
248: */
249: public static synchronized FeatureTypeFactory getFeatureTypeFactory(
250: Hints hints) {
251: hints = mergeSystemHints(hints);
252: FeatureTypeFactory factory = new DefaultFeatureTypeFactory();
253: factory.setName((String) hints
254: .get(Hints.FEATURE_TYPE_FACTORY_NAME));
255: return factory;
256:
257: //return (FeatureTypeFactory) getServiceRegistry().getServiceProvider(
258: // FeatureTypeFactory.class, null, hints, Hints.FEATURE_TYPE_FACTORY );
259: }
260:
261: /**
262: * Returns the first implementation of {@link FeatureCollections} matching the specified hints.
263: * If no implementation matches, a new one is created if possible or an exception is thrown
264: * otherwise.
265: *
266: * @param hints An optional map of hints, or {@code null} if none.
267: * @return The first feature collections that matches the supplied hints.
268: * @throws FactoryRegistryException if no implementation was found or can be created for the
269: * {@link FeatureCollections} interface.
270: *
271: * @see Hints#FEATURE_COLLECTIONS
272: */
273: public static synchronized FeatureCollections getFeatureCollections(
274: Hints hints) {
275: hints = mergeSystemHints(hints);
276: return (FeatureCollections) getServiceRegistry()
277: .getServiceProvider(FeatureCollections.class, null,
278: hints, Hints.FEATURE_COLLECTIONS);
279: }
280:
281: /**
282: * Returns a set of all available implementations for the {@link FeatureCollections} interface.
283: *
284: * @param hints An optional map of hints, or {@code null} if none.
285: * @return Set of available feature collections implementations.
286: */
287: public static synchronized Set getFeatureCollectionsSet(Hints hints) {
288: hints = mergeSystemHints(hints);
289: return new LazySet(getServiceRegistry().getServiceProviders(
290: FeatureCollections.class, null, hints));
291: }
292:
293: /**
294: * Returns the first implementation of {@link FilterFactory} matching the specified hints.
295: * If no implementation matches, a new one is created if possible or an exception is thrown
296: * otherwise.
297: *
298: * @param hints An optional map of hints, or {@code null} if none.
299: * @return The first filter factory that matches the supplied hints.
300: * @throws FactoryRegistryException if no implementation was found or can be created for the
301: * {@link FilterFactory} interface.
302: *
303: * @see Hints#FILTER_FACTORY
304: */
305: public static synchronized FilterFactory getFilterFactory(
306: Hints hints) throws FactoryRegistryException {
307: hints = mergeSystemHints(hints);
308: return (FilterFactory) getServiceRegistry().getServiceProvider(
309: FilterFactory.class, null, hints, Hints.FILTER_FACTORY);
310: }
311:
312: /**
313: * Returns a set of all available implementations for the {@link FilterFactory} interface.
314: *
315: * @param hints An optional map of hints, or {@code null} if none.
316: * @return Set of available filter factory implementations.
317: */
318: public static synchronized Set getFilterFactories(Hints hints) {
319: hints = mergeSystemHints(hints);
320: return new LazySet(getServiceRegistry().getServiceProviders(
321: FilterFactory.class, null, hints));
322: }
323:
324: /**
325: * Returns the first implementation of {@link FilterFactory2} matching the specified hints.
326: * This is a convenience method invoking {@link #getFilterFactory} with a hint value set
327: * for requerying a {@link FactoryFilter2} implementation.
328: *
329: * @param hints An optional map of hints, or {@code null} if none.
330: * @return The first filter factory that matches the supplied hints.
331: * @throws FactoryRegistryException if no implementation was found or can be created for the
332: * {@link FilterFactory2} interface.
333: *
334: * @see Hints#FILTER_FACTORY
335: */
336: public static FilterFactory2 getFilterFactory2(Hints hints)
337: throws FactoryRegistryException {
338: hints = mergeSystemHints(hints);
339: final Object h = hints.get(Hints.FILTER_FACTORY);
340: if (!(h instanceof Class ? FilterFactory2.class
341: .isAssignableFrom((Class) h)
342: : h instanceof FilterFactory2)) {
343: /*
344: * Add the hint value only if the user didn't provided a suitable hint.
345: * In any case, do not change the user-supplied hints; clone them first.
346: */
347: hints = new Hints(hints);
348: hints.put(Hints.FILTER_FACTORY, FilterFactory2.class);
349: }
350: return (FilterFactory2) getFilterFactory(hints);
351: }
352:
353: /**
354: * Scans for factory plug-ins on the application class path. This method is
355: * needed because the application class path can theoretically change, or
356: * additional plug-ins may become available. Rather than re-scanning the
357: * classpath on every invocation of the API, the class path is scanned
358: * automatically only on the first invocation. Clients can call this
359: * method to prompt a re-scan. Thus this method need only be invoked by
360: * sophisticated applications which dynamically make new plug-ins
361: * available at runtime.
362: */
363: public static synchronized void scanForPlugins() {
364: if (registry != null) {
365: registry.scanForPlugins();
366: }
367: }
368: }
|