001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2004-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.crs;
017:
018: // J2SE dependencies
019: import java.io.File;
020: import java.io.FileInputStream;
021: import java.io.IOException;
022: import java.net.URL;
023: import java.util.Hashtable;
024: import java.util.Properties;
025: import java.util.Set;
026: import java.util.logging.Level;
027: import java.util.logging.Logger;
028:
029: // OpenGIS dependencies
030: import org.opengis.metadata.citation.Citation;
031: import org.opengis.referencing.FactoryException;
032: import org.opengis.referencing.IdentifiedObject;
033: import org.opengis.referencing.NoSuchAuthorityCodeException;
034: import org.opengis.referencing.ObjectFactory;
035: import org.opengis.referencing.crs.CRSAuthorityFactory;
036: import org.opengis.referencing.crs.CRSFactory;
037: import org.opengis.referencing.crs.CoordinateReferenceSystem;
038: import org.opengis.referencing.crs.GeographicCRS;
039: import org.opengis.referencing.crs.ProjectedCRS;
040: import org.opengis.util.InternationalString;
041:
042: // Geotools dependencies
043: import org.geotools.util.logging.Logging;
044: import org.geotools.metadata.iso.citation.Citations;
045: import org.geotools.referencing.ReferencingFactoryFinder;
046:
047: /**
048: * Default implementation for a coordinate reference system authority factory backed
049: * by the EPSG property file. This gives most of the benifits of using the EPSG
050: * database backed authority factory, in a nice, portable property file.
051: *
052: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/plugin/epsg-wkt/src/main/java/org/geotools/referencing/crs/EPSGCRSAuthorityFactory.java $
053: * @version $Id: EPSGCRSAuthorityFactory.java 27862 2007-11-12 19:51:19Z desruisseaux $
054: * @author Jody Garnett
055: * @author Rueben Schulz
056: *
057: * @deprecated Uses one of the other EPSG factories backed by a database instead.
058: */
059: //not quite sure how I am going to create a new factory (what should the geoapi method be)
060: public class EPSGCRSAuthorityFactory implements CRSAuthorityFactory {
061:
062: private static final Logger LOGGER = Logging
063: .getLogger("org.geotools.referencing.crs.EPSGCRSAuthorityFactory");
064:
065: public static final String AUTHORITY = "EPSG";
066: public static final String AUTHORITY_PREFIX = "EPSG:";
067: //would be nice to cache crs objects for codes that have already been requested
068:
069: /**
070: * The default coordinate system authority factory.
071: * Will be constructed only when first requested.
072: */
073: protected static EPSGCRSAuthorityFactory DEFAULT;
074:
075: /**
076: * The properties object for our properties file. Keys are the EPSG
077: * code for a coordinate reference system and the associated value is a
078: * WKT string for the CRS.
079: */
080: protected Properties epsg = new Properties();
081:
082: //object factory
083: protected CRSFactory crsFactory;
084:
085: /** Cache of parsed CoordinateReferenceSystem WKT by EPSG_NUMBER */
086: private Hashtable cache = new Hashtable();
087:
088: /**
089: * Loads from epsg.properties if the file exists, defaults to internal defintions
090: * exported from postgis and cubeworks.
091: */
092: public EPSGCRSAuthorityFactory() {
093: this (ReferencingFactoryFinder.getCRSFactory(null));
094: }
095:
096: /**
097: * Loads from epsg.properties if the file exists, defaults to internal defintions
098: * exported from postgis and cubeworks.
099: */
100: protected EPSGCRSAuthorityFactory(final CRSFactory factory) {
101: this .crsFactory = factory;
102: try {
103: loadDefault();
104: } catch (IOException oops) {
105: System.err.println("Could not load epsg.properties" + oops);
106: }
107: }
108:
109: /**
110: *
111: */
112: protected EPSGCRSAuthorityFactory(final CRSFactory factory,
113: URL definition) throws FactoryException {
114: this (factory);
115:
116: try {
117: epsg.load(definition.openStream());
118: } catch (IOException io) {
119: // could not load properties file
120: throw new FactoryException(
121: "Could not load properties file: " + definition);
122: }
123: }
124:
125: /**
126: * Loads from epsg.properties if the file exists, defaults to internal defintions
127: * exported from postgis and cubeworks.
128: *
129: * @throws IOException
130: */
131: protected void loadDefault() throws IOException {
132: // Check the application directory first
133: //
134: File file = new File("epsg.properties");
135: if (file.exists()) {
136: epsg.load(new FileInputStream(file));
137: }
138: // Use the built-in property defintions
139: //
140: URL url = EPSGCRSAuthorityFactory.class
141: .getResource("epsg.properties");
142: epsg.load(url.openStream());
143: }
144:
145: /**
146: * Returns a default coordinate system factory backed by the EPSG property file.
147: *
148: * @return The default factory.
149: * @throws SQLException if the connection to the database can't be etablished.
150: */
151: public synchronized static CRSAuthorityFactory getDefault() {
152: if (DEFAULT == null) {
153: DEFAULT = new EPSGCRSAuthorityFactory();
154: }
155: return DEFAULT;
156: }
157:
158: public synchronized CoordinateReferenceSystem createCoordinateReferenceSystem(
159: String code) throws FactoryException {
160: if (code == null) {
161: return null;
162: }
163: if (!code.startsWith(AUTHORITY_PREFIX)) {
164: throw new NoSuchAuthorityCodeException(
165: "This factory only understand EPSG codes",
166: AUTHORITY, code);
167: }
168: final String EPSG_NUMBER = code
169: .substring(code.indexOf(':') + 1).trim();
170:
171: if (cache.containsKey(EPSG_NUMBER)) {
172: Object value = cache.get(EPSG_NUMBER);
173: if (value instanceof Throwable) {
174: throw new FactoryException("WKT for " + code
175: + " could not be parsed", (Throwable) value);
176: }
177: if (value instanceof CoordinateReferenceSystem) {
178: return (CoordinateReferenceSystem) value;
179: }
180: }
181: String wkt = epsg.getProperty(EPSG_NUMBER);
182: if (wkt == null) {
183: throw new NoSuchAuthorityCodeException(
184: "Unknown EPSG_NUMBER", AUTHORITY, code);
185: }
186: if (wkt.indexOf(EPSG_NUMBER) == -1) {
187: wkt = wkt.trim();
188: wkt = wkt.substring(0, wkt.length() - 1);
189: wkt += ",AUTHORITY[\"EPSG\",\"" + EPSG_NUMBER + "\"]]";
190: LOGGER
191: .log(
192: Level.WARNING,
193: "EPSG:"
194: + EPSG_NUMBER
195: + " lacks a proper identifying authority in its Well-Known Text. It is being added programmatically.");
196: }
197: try {
198: CoordinateReferenceSystem crs = crsFactory
199: .createFromWKT(wkt);
200: cache.put(EPSG_NUMBER, crs);
201: return crs;
202: } catch (FactoryException fex) {
203: cache.put(EPSG_NUMBER, fex);
204: throw fex;
205: }
206: }
207:
208: public IdentifiedObject createObject(String code)
209: throws FactoryException {
210: return createCoordinateReferenceSystem(code);
211: }
212:
213: public ProjectedCRS createProjectedCRS(String code)
214: throws FactoryException {
215: return (ProjectedCRS) createCoordinateReferenceSystem(code);
216: }
217:
218: public GeographicCRS createGeographicCRS(String code)
219: throws FactoryException {
220: return (GeographicCRS) createCoordinateReferenceSystem(code);
221: }
222:
223: public Citation getAuthority() {
224: return Citations.EPSG;
225: }
226:
227: /**
228: * Returns the set of authority codes of the given type. The type
229: * argument specify the base class. For example if this factory is
230: * an instance of CRSAuthorityFactory, then:
231: * <ul>
232: * <li>CoordinateReferenceSystem.class asks for all authority codes accepted
233: * by createGeographicCRS, createProjectedCRS, createVerticalCRS, createTemporalCRS and their friends.</li>
234: * <li>ProjectedCRS.class asks only for authority codes accepted by createProjectedCRS.</li>
235: * </ul>
236: *
237: * The following implementaiton filters the set of codes based on the
238: * "PROJCS" and "GEOGCS" at the start of the WKT strings. It is assumed
239: * that we only have GeographicCRS and ProjectedCRS's here.
240: *
241: * @param clazz The spatial reference objects type (may be Object.class).
242: * @return The set of authority codes for spatial reference objects of the given type.
243: * If this factory doesn't contains any object of the given type, then this method returns
244: * an empty set.
245: * @throws FactoryException if access to the underlying database failed.
246: */
247: public Set getAuthorityCodes(Class clazz) throws FactoryException {
248: //could cashe this info if it is time consuming to filter
249: if (clazz.getName().equalsIgnoreCase(
250: CoordinateReferenceSystem.class.getName())) {
251: Set all = new java.util.TreeSet();
252: for (java.util.Iterator i = epsg.keySet().iterator(); i
253: .hasNext();) {
254: String code = (String) i.next();
255: all.add(AUTHORITY_PREFIX + code);
256: }
257: return all;
258: } else if (clazz.getName().equalsIgnoreCase(
259: GeographicCRS.class.getName())) {
260: Set all = epsg.keySet();
261: Set geoCRS = new java.util.TreeSet();
262: for (java.util.Iterator i = all.iterator(); i.hasNext();) {
263: String code = (String) i.next();
264: String wkt = epsg.getProperty(code);
265: if (wkt.startsWith("GEOGCS")) {
266: geoCRS.add(AUTHORITY_PREFIX + code);
267: }
268: }
269: return geoCRS;
270:
271: } else if (clazz.getName().equalsIgnoreCase(
272: ProjectedCRS.class.getName())) {
273: Set all = epsg.keySet();
274: Set projCRS = new java.util.TreeSet();
275: for (java.util.Iterator i = all.iterator(); i.hasNext();) {
276: String code = (String) i.next();
277: String wkt = epsg.getProperty(code);
278: if (wkt.startsWith("PROJCS")) {
279: projCRS.add(AUTHORITY_PREFIX + code);
280: }
281: }
282: return projCRS;
283:
284: } else {
285: return new java.util.TreeSet();
286: }
287: }
288:
289: public ObjectFactory getObjectFactory() {
290: return crsFactory;
291: }
292:
293: public Citation getVendor() {
294: return Citations.GEOTOOLS;
295: }
296:
297: public InternationalString getDescriptionText(String code)
298: throws FactoryException {
299: if (code == null) {
300: return null;
301: }
302: if (code.startsWith("EPSG:")) { // EPSG:26907
303: code = code.substring(5);
304: }
305: code = code.trim();
306: String wkt = epsg.getProperty(code);
307: if (wkt == null) {
308: throw new FactoryException("Unknonwn EPSG code: '" + code
309: + "'");
310: }
311: wkt = wkt.trim();
312: int start = wkt.indexOf('"');
313: int end = wkt.indexOf('"', start + 1);
314: return new org.geotools.util.SimpleInternationalString(wkt
315: .substring(start + 1, end));
316: }
317:
318: public org.opengis.referencing.crs.CompoundCRS createCompoundCRS(
319: String str) throws FactoryException {
320: throw new FactoryException("Not implemented");
321: }
322:
323: public org.opengis.referencing.crs.DerivedCRS createDerivedCRS(
324: String str) throws FactoryException {
325: throw new FactoryException("Not implemented");
326: }
327:
328: public org.opengis.referencing.crs.EngineeringCRS createEngineeringCRS(
329: String str) throws FactoryException {
330: throw new FactoryException("Not implemented");
331: }
332:
333: public org.opengis.referencing.crs.GeocentricCRS createGeocentricCRS(
334: String str) throws FactoryException {
335: throw new FactoryException("Not implemented");
336: }
337:
338: public org.opengis.referencing.crs.ImageCRS createImageCRS(
339: String str) throws FactoryException {
340: throw new FactoryException("Not implemented");
341: }
342:
343: public org.opengis.referencing.crs.TemporalCRS createTemporalCRS(
344: String str) throws FactoryException {
345: throw new FactoryException("Not implemented");
346: }
347:
348: public org.opengis.referencing.crs.VerticalCRS createVerticalCRS(
349: String str) throws FactoryException {
350: throw new FactoryException("Not implemented");
351: }
352: }
|