001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 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.referencing;
017:
018: // J2SE dependencies
019: import java.util.Collection;
020: import java.util.Set;
021: import java.util.Iterator;
022: import java.util.Collections;
023: import java.util.ArrayList;
024: import java.util.Collection;
025: import java.util.LinkedHashSet;
026:
027: // OpenGIS dependencies
028: import org.opengis.metadata.citation.Citation;
029: import org.opengis.referencing.crs.CRSAuthorityFactory;
030: import org.opengis.referencing.crs.CoordinateReferenceSystem;
031:
032: // Geotools dependencies
033: import org.geotools.factory.GeoTools;
034: import org.geotools.factory.Hints;
035: import org.geotools.factory.GeoTools;
036: import org.geotools.metadata.iso.citation.Citations;
037: import org.geotools.referencing.factory.AbstractAuthorityFactory;
038: import org.geotools.referencing.factory.ManyAuthoritiesFactory;
039: import org.geotools.referencing.factory.BufferedAuthorityFactory;
040:
041: /**
042: * The default authority factory to be used by {@link CRS#decode}.
043: * <p>
044: * This class gathers together a lot of logic in order to capture the following ideas:
045: * <ul>
046: * <li>Uses {@link Hints#FORCE_LONGITUDE_FIRST_AXIS_ORDER} to swap ordinate order if needed.</li>
047: * <li>Uses {@link ManyAuthoritiesFactory} to access CRSAuthorities in the environment.</li>
048: * </ul>
049: *
050: * @since 2.3
051: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/DefaultAuthorityFactory.java $
052: * @version $Id: DefaultAuthorityFactory.java 29058 2008-02-03 17:47:07Z desruisseaux $
053: * @author Martin Desruisseaux
054: * @author Andrea Aime
055: */
056: final class DefaultAuthorityFactory extends BufferedAuthorityFactory
057: implements CRSAuthorityFactory {
058: /**
059: * Creates a new authority factory.
060: */
061: DefaultAuthorityFactory(final boolean longitudeFirst) {
062: super (getBackingFactory(longitudeFirst));
063: }
064:
065: /**
066: * Work around for RFE #4093999 in Sun's bug database
067: * ("Relax constraint on placement of this()/super() call in constructors").
068: */
069: private static AbstractAuthorityFactory getBackingFactory(
070: final boolean longitudeFirst) {
071: final Hints hints = GeoTools.getDefaultHints();
072: if (longitudeFirst) {
073: hints.put(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER,
074: Boolean.TRUE);
075: } else {
076: /*
077: * Do NOT set the hint to false. If 'longitudeFirst' is false, this means
078: * "use the system default", not "latitude first". The longitude may or may
079: * not be first depending the value of "org.geotools.referencing.forcexy"
080: * system property. This state is included in GeoTools.getDefaultHints().
081: */
082: }
083: Collection factories = ReferencingFactoryFinder
084: .getCRSAuthorityFactories(hints);
085: if (Boolean.TRUE.equals(hints.put(
086: Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.FALSE))) {
087: /*
088: * If hints contain a requirement for "longitude first", then we may loose some
089: * authorities like "URN:OGC:...". Search again without such requirement and add
090: * any new authorities found.
091: */
092: factories = new ArrayList(factories);
093: final Set authorities = new LinkedHashSet();
094: for (final Iterator it = factories.iterator(); it.hasNext();) {
095: authorities.add(((CRSAuthorityFactory) it.next())
096: .getAuthority());
097: }
098: searchNews: for (final Iterator it = ReferencingFactoryFinder
099: .getCRSAuthorityFactories(hints).iterator(); it
100: .hasNext();) {
101: final CRSAuthorityFactory factory = (CRSAuthorityFactory) it
102: .next();
103: final Citation authority = factory.getAuthority();
104: if (authorities.contains(authority)) {
105: continue;
106: }
107: for (final Iterator it2 = authorities.iterator(); it2
108: .hasNext();) {
109: if (Citations.identifierMatches(authority,
110: (Citation) it2.next())) {
111: continue searchNews;
112: }
113: }
114: factories.add(factory);
115: }
116: }
117: return new ManyAuthoritiesFactory(factories);
118: }
119:
120: /**
121: * Implementation of {@link CRS#getSupportedCodes}. Provided here in order to reduce the
122: * amount of class loading when using {@link CRS} for other purpose than CRS decoding.
123: */
124: static Set/*<String>*/getSupportedCodes(final String authority) {
125: Set result = Collections.EMPTY_SET;
126: boolean isSetCopied = false;
127: for (final Iterator i = ReferencingFactoryFinder
128: .getCRSAuthorityFactories(null).iterator(); i.hasNext();) {
129: final CRSAuthorityFactory factory = (CRSAuthorityFactory) i
130: .next();
131: if (Citations.identifierMatches(factory.getAuthority(),
132: authority)) {
133: final Set codes;
134: try {
135: codes = factory
136: .getAuthorityCodes(CoordinateReferenceSystem.class);
137: } catch (Exception exception) {
138: /*
139: * Failed to fetch the codes either because of a database connection problem
140: * (FactoryException), or because we are using a simple factory that doesn't
141: * support this operation (UnsupportedOperationException), or any unexpected
142: * reason. No codes from this factory will be added to the set.
143: */
144: CRS.unexpectedException("getSupportedCodes",
145: exception);
146: continue;
147: }
148: if (codes != null && !codes.isEmpty()) {
149: if (result.isEmpty()) {
150: result = codes;
151: } else {
152: if (!isSetCopied) {
153: result = new LinkedHashSet(result);
154: isSetCopied = true;
155: }
156: result.addAll(codes);
157: }
158: }
159: }
160: }
161: return result;
162: }
163:
164: /**
165: * Implementation of {@link CRS#getSupportedAuthorities}. Provided here in order to reduce the
166: * amount of class loading when using {@link CRS} for other purpose than CRS decoding.
167: */
168: static Set/*<String>*/getSupportedAuthorities(
169: final boolean returnAliases) {
170: final Set authorityFactories = ReferencingFactoryFinder
171: .getCRSAuthorityFactories(null);
172: final Set result = new LinkedHashSet();
173: for (final Iterator i = authorityFactories.iterator(); i
174: .hasNext();) {
175: final CRSAuthorityFactory factory = (CRSAuthorityFactory) i
176: .next();
177: final Collection identifiers = factory.getAuthority()
178: .getIdentifiers();
179: for (final Iterator j = identifiers.iterator(); j.hasNext();) {
180: result.add(j.next());
181: if (!returnAliases) {
182: break;
183: }
184: }
185: }
186: return result;
187: }
188: }
|