001: /*
002: * Geotools2 - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002, 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: */
017: package org.geotools.data.gml;
018:
019: import java.io.IOException;
020: import java.net.URI;
021:
022: import org.geotools.data.AbstractDataStore;
023: import org.geotools.data.FeatureReader;
024: import org.geotools.data.Query;
025: import org.geotools.feature.AttributeType;
026: import org.geotools.feature.AttributeTypeFactory;
027: import org.geotools.feature.Feature;
028: import org.geotools.feature.FeatureType;
029: import org.geotools.feature.FeatureTypeBuilder;
030: import org.geotools.feature.SchemaException;
031: import org.geotools.filter.Filter;
032: import org.geotools.referencing.CRS;
033: import org.geotools.xml.gml.FCBuffer;
034: import org.opengis.referencing.NoSuchAuthorityCodeException;
035: import org.opengis.referencing.crs.CoordinateReferenceSystem;
036: import org.xml.sax.SAXException;
037:
038: import com.vividsolutions.jts.geom.Envelope;
039: import com.vividsolutions.jts.geom.Geometry;
040:
041: /**
042: *
043: * DataStore class for handling a single GML file/stream.
044: *
045: * The datastore is "Read Only" as it should only be used
046: * to open GML files.
047: *
048: * @author jeichar
049: *
050: * TODO Check for a cleaner way to do
051: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/gml/src/main/java/org/geotools/data/gml/FileGMLDataStore.java $
052: */
053: public class FileGMLDataStore extends AbstractDataStore {
054:
055: /** URI to a location (doesn't have to be a file) containing GML data*/
056: private URI uri;
057: private volatile FCBuffer fcbuffer = null;
058: /** the number of features that are cached */
059: private int bufferSize;
060: /** length of time before the datastore gives up. */
061: private int timeout;
062: private FeatureType schema;
063:
064: /**
065: * New instance
066: *
067: * @param uri URI to a file containing GML data
068: * @param featureBufferSize the number of features that are cached
069: * @param timeout length of time before the datastore gives up.
070: */
071: public FileGMLDataStore(URI uri, int featureBufferSize, int timeout) {
072: super (false); //does not allow writing
073: this .uri = uri;
074: this .bufferSize = featureBufferSize;
075: this .timeout = timeout;
076: }
077:
078: /**
079: * Create the type name of the single FeatureType this DataStore
080: * represents.<BR/> For example, if the urls path is
081: * file:///home/billy/mytheme.shp, the type name will be mytheme.
082: *
083: * @return A name based upon the last path component of the url minus the
084: * extension.
085: */
086: protected String createFeatureTypeName() {
087: String path = uri.getPath();
088: int slash = Math.max(0, path.lastIndexOf('/') + 1);
089: int dot = path.indexOf('.', slash);
090:
091: if (dot < 0) {
092: dot = path.length();
093: }
094:
095: return path.substring(slash, dot);
096: }
097:
098: /* Gets the name of all the layers from the filenames
099: * in the directory.
100: * @see org.geotools.data.DataStore#getTypeNames()
101: */
102: public String[] getTypeNames() throws IOException {
103: return new String[] { (fcbuffer == null) ? createFeatureTypeName()
104: : fcbuffer.getFeatureType().getTypeName() };
105: }
106:
107: /* Provides access to a FeatureType referenced by a type name.
108: *
109: * Basically it parses the file using SAX, gets the featureReader
110: * and returns the result of the getFeatureType() method of
111: * the featureReader.
112: *
113: * @see org.geotools.data.DataStore#getSchema(java.lang.String)
114: */
115: public FeatureType getSchema(String typeName) throws IOException {
116: if (!getTypeNames()[0].equals(typeName))
117: throw new IOException("Feature type " + typeName
118: + " does not exist. This datastore only has "
119: + getTypeNames()[0]);
120:
121: return getSchema();
122: }
123:
124: /* Returns a reference on the featureReader of the current FCBuffer.
125: *
126: * @see org.geotools.data.AbstractDataStore#getFeatureReader(java.lang.String)
127: */
128: protected FeatureReader getFeatureReader(String typeName)
129: throws IOException {
130: //Q: FCBuffer never closed : memory leak?
131: //A: this is not a concern, as the http connection will clean up after itself,
132: //and the buffer is not cached, so it will clean up too (just make sure as a
133: //user you don't cache the reader ...
134:
135: //XMLSAXHandler.setLogLevel(Level.FINEST);
136: //XSISAXHandler.setLogLevel(Level.FINEST);
137: //XMLElementHandler.setLogLevel(Level.FINEST);
138: //XSIElementHandler.setLogLevel(Level.FINEST);
139:
140: if (!getTypeNames()[0].equals(typeName))
141: throw new IOException("Feature type " + typeName
142: + " does not exist. This datastore only has "
143: + getTypeNames()[0]);
144:
145: try {
146: return (FeatureReader) FCBuffer.getFeatureReader(uri,
147: bufferSize, timeout);
148: } catch (SAXException sxe) {
149: sxe.printStackTrace();
150: return null;
151: }
152: }
153:
154: public FeatureType getSchema() throws IOException {
155: if (fcbuffer == null) {
156: synchronized (this ) {
157: if (fcbuffer == null) {
158: try {
159: fcbuffer = (FCBuffer) FCBuffer
160: .getFeatureReader(uri, bufferSize,
161: timeout);
162: try {
163: if (fcbuffer.hasNext()) {
164: Feature f = fcbuffer.next();
165: try {
166: schema = createFinalSchema(f);
167: } catch (SchemaException e) {
168: LOGGER.warning(e
169: .getLocalizedMessage());
170: schema = fcbuffer.getFeatureType();
171: }
172: }
173: } finally {
174: fcbuffer.close();
175: }
176: } catch (SAXException e) {
177: throw new IOException(e.toString());
178: }
179: }
180: }
181: }
182:
183: return schema;
184: }
185:
186: private FeatureType createFinalSchema(Feature f)
187: throws SchemaException {
188: FeatureTypeBuilder builder = FeatureTypeBuilder.newInstance(f
189: .getFeatureType().getTypeName());
190: for (int i = 0; i < f.getNumberOfAttributes(); i++) {
191: AttributeType att = f.getFeatureType().getAttributeType(i);
192: if (!Geometry.class.isAssignableFrom(att.getType())) {
193: builder.addType(att);
194: } else {
195: Geometry geom = (Geometry) f.getAttribute(i);
196: Object data = geom.getUserData();
197: if (data instanceof CoordinateReferenceSystem) {
198: builder.addType(AttributeTypeFactory
199: .newAttributeType(att.getName(), att
200: .getType(), att.isNillable(), att
201: .getRestriction(), att
202: .createDefaultValue(), data));
203: } else if (data instanceof String) {
204: String string = (String) data;
205: String[] parts = string.split("#");
206: Object crs;
207: if (parts[0]
208: .equals("http://www.opengis.net/gml/srs/epsg.xml")) {
209: try {
210: crs = CRS.decode("EPSG:" + parts[1]);
211: } catch (NoSuchAuthorityCodeException e) {
212: LOGGER.warning(e.getLocalizedMessage());
213: crs = null;
214: } catch (org.opengis.referencing.FactoryException fe) {
215: LOGGER.warning(fe.getLocalizedMessage());
216: crs = null;
217: }
218: } else {
219: crs = null;
220: }
221: builder.addType(AttributeTypeFactory
222: .newAttributeType(att.getName(), att
223: .getType(), att.isNillable(), att
224: .getRestriction(), att
225: .createDefaultValue(), crs));
226: }
227: }
228: }
229: return builder.getFeatureType();
230: }
231:
232: protected Envelope getBounds(Query query) throws IOException {
233: if (query == Query.ALL
234: || query.getFilter().equals(Filter.INCLUDE)) {
235: //TODO parse out bounds
236: return null;
237: } else {
238: // to expensive!
239: return null;
240: }
241: }
242:
243: }
|