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.data.wfs;
017:
018: import java.io.IOException;
019: import java.util.logging.Level;
020:
021: import org.geotools.data.DefaultQuery;
022: import org.geotools.data.EmptyFeatureReader;
023: import org.geotools.data.FeatureReader;
024: import org.geotools.data.FilteringFeatureReader;
025: import org.geotools.data.Query;
026: import org.geotools.data.Transaction;
027: import org.geotools.data.crs.ForceCoordinateSystemFeatureReader;
028: import org.geotools.data.ows.FeatureSetDescription;
029: import org.geotools.data.ows.WFSCapabilities;
030: import org.geotools.feature.SchemaException;
031: import org.opengis.filter.Filter;
032: import org.geotools.filter.Filters;
033: import org.geotools.filter.visitor.PostPreProcessFilterSplittingVisitor.WFSBBoxFilterVisitor;
034: import org.geotools.geometry.jts.JTS;
035: import org.geotools.referencing.CRS;
036: import org.geotools.referencing.crs.DefaultGeographicCRS;
037: import org.opengis.referencing.FactoryException;
038: import org.opengis.referencing.crs.CoordinateReferenceSystem;
039: import org.opengis.referencing.operation.MathTransform;
040: import org.opengis.referencing.operation.TransformException;
041: import org.opengis.geometry.MismatchedDimensionException;
042: import org.xml.sax.SAXException;
043:
044: import com.vividsolutions.jts.geom.Envelope;
045:
046: /**
047: * A version that is not strict about its filter compliance. It can be used with geoserver but no other servers.
048: * @author Jesse
049: *
050: */
051: class NonStrictWFSStrategy implements WFSStrategy {
052:
053: protected WFSDataStore store;
054:
055: public NonStrictWFSStrategy(WFSDataStore store) {
056: this .store = store;
057: }
058:
059: public FeatureReader getFeatureReader(Query query2,
060: Transaction transaction) throws IOException {
061: Query query = new DefaultQuery(query2);
062: Filter processedFilter = store.processFilter(query.getFilter());
063: // process the filter to update fidfilters using the transaction.
064: ((DefaultQuery) query).setFilter(processedFilter);
065: Filter serverFilter;
066: Filter postFilter;
067: {
068: Filter[] filters1 = store.splitFilters(query, transaction); // [server][post]
069: Filter[] filters = filters1;
070: serverFilter = filters[0];
071: postFilter = filters[1];
072: }
073:
074: CoordinateReferenceSystem dataCRS = clipBBox(query,
075: serverFilter);
076:
077: ((DefaultQuery) query).setFilter(serverFilter);
078: FeatureReader reader = createFeatureReader(transaction, query);
079:
080: if (reader.hasNext()) { // opportunity to throw exception
081:
082: if (reader.getFeatureType() != null) {
083: reader = wrapWithFilteringFeatureReader(postFilter,
084: reader, processedFilter);
085: reader = applyReprojectionDecorator(reader, query,
086: dataCRS);
087: return reader;
088: }
089: throw new IOException(
090: "There are features but no feature type ... odd");
091: }
092:
093: return new EmptyFeatureReader(store.getSchema(query
094: .getTypeName()));
095: }
096:
097: protected FeatureReader wrapWithFilteringFeatureReader(
098: Filter postFilter, FeatureReader reader,
099: Filter processedFilter) {
100: if (!postFilter.equals(Filter.INCLUDE)) {
101: return new FilteringFeatureReader(reader, postFilter);
102: }
103: return reader;
104: }
105:
106: protected FeatureReader createFeatureReader(
107: Transaction transaction, Query query) throws IOException {
108: Data data;
109: data = createFeatureReaderPOST(query, transaction);
110:
111: if (data.reader == null)
112: data = createFeatureReaderGET(query, transaction);
113:
114: if (data.reader == null && data.saxException != null)
115: throw new IOException(data.saxException.toString());
116: if (data.reader == null && data.ioException != null)
117: throw data.ioException;
118:
119: return data.reader;
120: }
121:
122: protected Data createFeatureReaderPOST(Query query,
123: Transaction transaction) {
124: Data data = new Data();
125: if (((store.protocol & WFSDataStore.POST_PROTOCOL) == WFSDataStore.POST_PROTOCOL)) {
126: try {
127: data.reader = store.getFeatureReaderPost(query,
128: transaction);
129: if (data.reader != null)
130: data.reader.hasNext(); // throws spot
131: } catch (SAXException e) {
132: data.reader = null;
133: WFSDataStoreFactory.logger.warning(e.toString());
134: data.saxException = e;
135: } catch (IOException e) {
136: data.reader = null;
137: WFSDataStoreFactory.logger.warning(e.toString());
138: data.ioException = e;
139: }
140: }
141: return data;
142: }
143:
144: protected Data createFeatureReaderGET(Query query,
145: Transaction transaction) {
146: Data data = new Data();
147: if (((store.protocol & WFSDataStore.GET_PROTOCOL) == WFSDataStore.GET_PROTOCOL)) {
148: try {
149: data.reader = store.getFeatureReaderGet(query,
150: transaction);
151: if (data.reader != null)
152: data.reader.hasNext(); // throws spot
153: } catch (SAXException e) {
154: data.reader = null;
155: WFSDataStoreFactory.logger.warning(e.toString());
156: data.saxException = e;
157: } catch (IOException e) {
158: data.reader = null;
159: WFSDataStoreFactory.logger.warning(e.toString());
160: data.ioException = e;
161: }
162: }
163: return data;
164: }
165:
166: protected FeatureReader applyReprojectionDecorator(
167: FeatureReader reader, Query query,
168: CoordinateReferenceSystem dataCRS) {
169: FeatureReader tmp = reader;
170: if (query.getCoordinateSystem() != null
171: && !query.getCoordinateSystem().equals(
172: reader.getFeatureType().getDefaultGeometry()
173: .getCoordinateSystem())) {
174: try {
175: reader = new ForceCoordinateSystemFeatureReader(reader,
176: query.getCoordinateSystem());
177: } catch (SchemaException e) {
178: WFSDataStoreFactory.logger.warning(e.toString());
179: reader = tmp;
180: }
181: } else {
182: if (reader.getFeatureType().getDefaultGeometry() != null
183: && dataCRS != null
184: && reader.getFeatureType().getDefaultGeometry()
185: .getCoordinateSystem() == null) {
186: // set up crs
187: try {
188: reader = new ForceCoordinateSystemFeatureReader(
189: reader, dataCRS);
190: } catch (SchemaException e) {
191: WFSDataStoreFactory.logger.warning(e.toString());
192: reader = tmp;
193: }
194: }
195: }
196: return reader;
197: }
198:
199: protected CoordinateReferenceSystem clipBBox(Query query,
200: Filter serverFilter) {
201: // TODO modify bbox requests here
202: FeatureSetDescription fsd = WFSCapabilities
203: .getFeatureSetDescription(store.capabilities, query
204: .getTypeName());
205:
206: Envelope maxbbox = null;
207: CoordinateReferenceSystem dataCRS = null;
208: if (fsd.getSRS() != null) {
209: // reproject this
210: try {
211: dataCRS = CRS.decode(fsd.getSRS());
212: MathTransform toDataCRS = CRS.findMathTransform(
213: DefaultGeographicCRS.WGS84, dataCRS);
214: maxbbox = JTS.transform(fsd.getLatLongBoundingBox(),
215: null, toDataCRS, 10);
216: } catch (FactoryException e) {
217: WFSDataStoreFactory.logger.warning(e.getMessage());
218: maxbbox = null;
219: } catch (MismatchedDimensionException e) {
220: WFSDataStoreFactory.logger.warning(e.getMessage());
221: maxbbox = null;
222: } catch (TransformException e) {
223: WFSDataStoreFactory.logger.warning(e.getMessage());
224: maxbbox = null;
225: }
226: } else {
227: maxbbox = fsd.getLatLongBoundingBox();
228: }
229: // Rewrite request if we have a mxxbox
230: if (maxbbox != null) {
231: WFSBBoxFilterVisitor clipVisitor = new WFSBBoxFilterVisitor(
232: maxbbox);
233: Filters.accept(serverFilter, clipVisitor);
234: } else { // give up an request everything
235: WFSDataStoreFactory.logger
236: .log(Level.FINE,
237: "Unable to clip your query against the latlongboundingbox element");
238: // filters[0] = Filter.EXCLUDE; // uncoment this line to just give up
239: }
240: return dataCRS;
241: }
242:
243: protected class Data {
244: IOException ioException;
245: SAXException saxException;
246: FeatureReader reader;
247: }
248:
249: }
|