001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, GeoTools Project Managment Committee (PMC)
005: * (C) 2005, Institut de Recherche pour le D�veloppement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation;
010: * version 2.1 of the License.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.referencing.factory;
018:
019: // J2SE dependencies
020: import java.util.Collection;
021: import java.util.Iterator;
022: import java.util.LinkedHashSet;
023: import java.util.Set;
024:
025: // OpenGIS dependencies
026: import org.opengis.referencing.AuthorityFactory;
027: import org.opengis.referencing.FactoryException;
028: import org.opengis.referencing.IdentifiedObject;
029: import org.opengis.referencing.crs.CRSAuthorityFactory;
030: import org.opengis.referencing.cs.CSAuthorityFactory;
031: import org.opengis.referencing.datum.DatumAuthorityFactory;
032: import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory;
033:
034: // Geotools dependencies
035: import org.geotools.factory.Hints;
036: import org.geotools.factory.FactoryRegistryException;
037: import org.geotools.referencing.ReferencingFactoryFinder;
038:
039: /**
040: * An authority factory that delegates the object creation to an other factory determined
041: * from the authority name in the code. This is similar to {@link ManyAuthoritiesFactory}
042: * except that the set of factories is determined by calls to
043: * <code>ReferencingFactoryFinder.{@linkplain ReferencingFactoryFinder#getCRSAuthorityFactory
044: * get<var>Foo</var>AuthorityFactory}(<var>authority</var>, {@linkplain #hints hints})</code>.
045: * <p>
046: * This class is not registered in {@link ReferencingFactoryFinder}. If this "authority" factory
047: * is wanted, then users need to refer explicitly to the {@link #DEFAULT} constant or to create
048: * their own instance.
049: *
050: * @since 2.2
051: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/factory/AllAuthoritiesFactory.java $
052: * @version $Id: AllAuthoritiesFactory.java 29058 2008-02-03 17:47:07Z desruisseaux $
053: * @author Martin Desruisseaux
054: */
055: public class AllAuthoritiesFactory extends ManyAuthoritiesFactory {
056: /**
057: * An instance of {@code AllAuthoritiesFactory} with the
058: * {@linkplain GenericName#DEFAULT_SEPARATOR default name separator} and no hints.
059: */
060: public static AllAuthoritiesFactory DEFAULT = new AllAuthoritiesFactory(
061: null);
062:
063: /**
064: * The authority names. Used in order to detect changes in the set of registered factories.
065: */
066: private Collection/*<String>*/authorityNames;
067:
068: /**
069: * Creates a new factory using the specified hints.
070: *
071: * @param hints An optional set of hints, or {@code null} if none.
072: */
073: public AllAuthoritiesFactory(final Hints hints) {
074: this (hints, null);
075: }
076:
077: /**
078: * Creates a new factory using the specified hints and a set of user factories.
079: * If {@code factories} is not null, then any call to a {@code createFoo(code)} method will
080: * first scan the supplied factories in their iteration order. The first factory implementing
081: * the appropriate interface and having the expected {@linkplain AuthorityFactory#getAuthority
082: * authority name} will be used. Only if no suitable factory is found, then this class delegates
083: * to {@link ReferencingFactoryFinder}.
084: * <p>
085: * If the {@code factories} collection contains more than one factory for the same authority
086: * and interface, then all additional factories will be {@linkplain FallbackAuthorityFactory
087: * fallbacks}, to be tried in iteration order only if the first acceptable factory failed to
088: * create the requested object.
089: *
090: * @param hints An optional set of hints, or {@code null} if none.
091: * @param factories A set of user-specified factories to try before to delegate
092: * to {@link ReferencingFactoryFinder}, or {@code null} if none.
093: *
094: * @deprecated This constructor will be removed in GeoTools 2.5.
095: */
096: public AllAuthoritiesFactory(final Hints hints,
097: final Collection/*<? extends AuthorityFactory>*/factories) {
098: this (hints, factories, (char) 0);
099: }
100:
101: /**
102: * Creates a new factory using the specified hints, user factories and name
103: * separator. The optional {@code factories} collection is handled as in the
104: * {@linkplain #AllAuthoritiesFactory(Hints, Collection) constructor above}.
105: *
106: * @param hints An optional set of hints, or {@code null} if none.
107: * @param factories A set of user-specified factories to try before to delegate
108: * to {@link ReferencingFactoryFinder}, or {@code null} if none.
109: * @param separator The separator between the authority name and the code.
110: *
111: * @deprecated This constructor will be removed in GeoTools 2.5.
112: */
113: public AllAuthoritiesFactory(final Hints hints,
114: final Collection/*<? extends AuthorityFactory>*/factories,
115: final char separator) {
116: super (hints, factories, separator);
117: if (hints != null) {
118: this .hints.putAll(hints);
119: }
120: }
121:
122: /**
123: * Returns the set of authority names.
124: *
125: * @since 2.4
126: */
127: //@Override
128: public Set/*<String>*/getAuthorityNames() {
129: // Do not use 'authorityNames' since it may be out-of-date.
130: return ReferencingFactoryFinder.getAuthorityNames();
131: }
132:
133: /**
134: * Returns the factories to be used by {@link ManyAuthoritiesFactory}. If the registered
135: * factories changed since the last time this method has been invoked, then this method
136: * recreate the set.
137: */
138: //@Override
139: synchronized Collection/*<AuthorityFactory>*/getFactories() {
140: final Collection/*<String>*/authorities = ReferencingFactoryFinder
141: .getAuthorityNames();
142: if (authorities != authorityNames) {
143: authorityNames = authorities;
144: final Hints hints = getHints();
145: final Set/*<AuthorityFactory>*/factories = new LinkedHashSet();
146: factories.addAll(ReferencingFactoryFinder
147: .getCRSAuthorityFactories(hints));
148: factories.addAll(ReferencingFactoryFinder
149: .getCSAuthorityFactories(hints));
150: factories.addAll(ReferencingFactoryFinder
151: .getDatumAuthorityFactories(hints));
152: factories.addAll(ReferencingFactoryFinder
153: .getCoordinateOperationAuthorityFactories(hints));
154: setFactories(factories);
155: }
156: return super .getFactories();
157: }
158:
159: /**
160: * Returns a factory for the specified authority and type.
161: */
162: //@Override
163: final AuthorityFactory fromFactoryRegistry(final String authority,
164: final Class/*<? extends AuthorityFactory>*/type)
165: throws FactoryRegistryException {
166: if (CRSAuthorityFactory.class.equals(type)) {
167: return ReferencingFactoryFinder.getCRSAuthorityFactory(
168: authority, getHints());
169: } else if (CSAuthorityFactory.class.equals(type)) {
170: return ReferencingFactoryFinder.getCSAuthorityFactory(
171: authority, getHints());
172: } else if (DatumAuthorityFactory.class.equals(type)) {
173: return ReferencingFactoryFinder.getDatumAuthorityFactory(
174: authority, getHints());
175: } else if (CoordinateOperationAuthorityFactory.class
176: .equals(type)) {
177: return ReferencingFactoryFinder
178: .getCoordinateOperationAuthorityFactory(authority,
179: getHints());
180: } else {
181: return super .fromFactoryRegistry(authority, type);
182: }
183: }
184:
185: /**
186: * Returns a copy of the hints specified by the user at construction time.
187: */
188: private Hints getHints() {
189: if (hints.isEmpty()) {
190: return ReferencingFactoryFinder.EMPTY_HINTS;
191: } else {
192: // Clones EMPTY_HINTS as a trick for getting a StricHints instance.
193: final Hints hints = (Hints) ReferencingFactoryFinder.EMPTY_HINTS
194: .clone();
195: hints.putAll(this .hints);
196: return hints;
197: }
198: }
199:
200: /**
201: * Returns a finder which can be used for looking up unidentified objects.
202: * The default implementation delegates the lookups to the underlying factories.
203: *
204: * @since 2.4
205: */
206: //@Override
207: public IdentifiedObjectFinder getIdentifiedObjectFinder(
208: final Class/*<? extends IdentifiedObject>*/type)
209: throws FactoryException {
210: return new Finder(this , type);
211: }
212:
213: /**
214: * A {@link IdentifiedObjectFinder} which tests every factories.
215: */
216: private static final class Finder extends
217: ManyAuthoritiesFactory.Finder {
218: /**
219: * Creates a finder for the specified type.
220: */
221: protected Finder(final ManyAuthoritiesFactory factory,
222: final Class/*<? extends IdentifiedObject>*/type) {
223: super (factory, type);
224: }
225:
226: /**
227: * Returns all factories to try.
228: */
229: private Set/*<AuthorityFactory>*/fromFactoryRegistry() {
230: final ManyAuthoritiesFactory factory = (ManyAuthoritiesFactory) proxy
231: .getAuthorityFactory();
232: final Class/*<? extends AuthorityFactory>*/type = proxy
233: .getType();
234: final Set factories = new LinkedHashSet();
235: for (final Iterator it = ReferencingFactoryFinder
236: .getAuthorityNames().iterator(); it.hasNext();) {
237: final String authority = (String) it.next();
238: factory.fromFactoryRegistry(authority, type, factories);
239: }
240: // Removes the factories already tried by super-class.
241: final Collection done = getFactories();
242: if (done != null) {
243: factories.removeAll(done);
244: }
245: return factories;
246: }
247:
248: /**
249: * Lookups for the specified object.
250: */
251: //@Override
252: public IdentifiedObject find(final IdentifiedObject object)
253: throws FactoryException {
254: IdentifiedObject candidate = super .find(object);
255: if (candidate != null) {
256: return candidate;
257: }
258: IdentifiedObjectFinder finder;
259: final Iterator it = fromFactoryRegistry().iterator();
260: while ((finder = next(it)) != null) {
261: candidate = finder.find(object);
262: if (candidate != null) {
263: break;
264: }
265: }
266: return candidate;
267: }
268:
269: /**
270: * Returns the identifier of the specified object, or {@code null} if none.
271: */
272: //@Override
273: public String findIdentifier(final IdentifiedObject object)
274: throws FactoryException {
275: String candidate = super .findIdentifier(object);
276: if (candidate != null) {
277: return candidate;
278: }
279: IdentifiedObjectFinder finder;
280: final Iterator it = fromFactoryRegistry().iterator();
281: while ((finder = next(it)) != null) {
282: candidate = finder.findIdentifier(object);
283: if (candidate != null) {
284: break;
285: }
286: }
287: return candidate;
288: }
289: }
290: }
|