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.Arrays;
020: import java.util.HashSet;
021: import java.util.NoSuchElementException;
022: import java.util.Set;
023:
024: import org.geotools.data.DefaultQuery;
025: import org.geotools.data.FeatureReader;
026: import org.geotools.data.FilteringFeatureReader;
027: import org.geotools.data.Query;
028: import org.geotools.data.Transaction;
029: import org.geotools.feature.Feature;
030: import org.geotools.feature.FeatureType;
031: import org.geotools.feature.IllegalAttributeException;
032: import org.geotools.filter.FidFilter;
033: import org.opengis.filter.Filter;
034: import org.geotools.filter.FilterAttributeExtractor;
035: import org.geotools.filter.Filters;
036: import org.geotools.xml.XMLHandlerHints;
037: import org.geotools.xml.filter.FilterEncodingPreProcessor;
038:
039: /**
040: * A version that is very strict about its filter compliance.
041: * @author Jesse
042: *
043: */
044: class StrictWFSStrategy extends NonStrictWFSStrategy {
045:
046: /**
047: * This just splits fid filters from non-fid filters. The {@link StrictFeatureReader} is what does the rest of the
048: * compliance to high compliance.
049: */
050: protected static final Integer COMPLIANCE_LEVEL = XMLHandlerHints.VALUE_FILTER_COMPLIANCE_MEDIUM;
051:
052: public StrictWFSStrategy(WFSDataStore store) {
053: super (store);
054: }
055:
056: protected FeatureReader wrapWithFilteringFeatureReader(
057: Filter postFilter, FeatureReader reader,
058: Filter processedFilter) {
059: FilterEncodingPreProcessor visitor = new FilterEncodingPreProcessor(
060: COMPLIANCE_LEVEL);
061: Filters.accept(processedFilter, visitor);
062:
063: if (visitor.requiresPostProcessing())
064: return new FilteringFeatureReader(reader, processedFilter);
065: else
066: return new FilteringFeatureReader(reader, postFilter);
067:
068: }
069:
070: protected FeatureReader createFeatureReader(
071: Transaction transaction, Query query) throws IOException {
072: return new StrictFeatureReader(transaction, query,
073: COMPLIANCE_LEVEL);
074: }
075:
076: /**
077: * Makes seperate requests between fetching the features using a normal filter and a seperate request for fetching features using
078: * the FID filter.
079: *
080: * @author Jesse
081: */
082: protected class StrictFeatureReader implements FeatureReader {
083:
084: private FeatureReader delegate;
085: protected Filter filter;
086: private Query query;
087: private Transaction transaction;
088: private Set foundFids = new HashSet();
089: private Feature next;
090:
091: public StrictFeatureReader(Transaction transaction,
092: Query query, Integer level) throws IOException {
093: init(transaction, query, level);
094: }
095:
096: protected void init(Transaction transaction, Query query,
097: Integer level) throws IOException {
098: FilterEncodingPreProcessor visitor = new FilterEncodingPreProcessor(
099: level);
100: Filters.accept(query.getFilter(), visitor);
101:
102: this .transaction = transaction;
103: if (visitor.requiresPostProcessing()
104: && query.getPropertyNames() != Query.ALL_NAMES) {
105: FilterAttributeExtractor attributeExtractor = new FilterAttributeExtractor();
106: query.getFilter().accept(attributeExtractor, null);
107: Set properties = new HashSet(attributeExtractor
108: .getAttributeNameSet());
109: properties.addAll(Arrays.asList(query
110: .getPropertyNames()));
111: this .query = new DefaultQuery(query.getTypeName(),
112: query.getFilter(), query.getMaxFeatures(),
113: (String[]) properties.toArray(new String[0]),
114: query.getHandle());
115: } else
116: this .query = query;
117:
118: this .filter = visitor.getFilter();
119:
120: DefaultQuery nonFidQuery = new DefaultQuery(query);
121: FidFilter fidFilter = visitor.getFidFilter();
122: nonFidQuery.setFilter(fidFilter);
123: if (fidFilter.getFids().length > 0) {
124: delegate = StrictWFSStrategy.super .createFeatureReader(
125: transaction, nonFidQuery);
126: } else {
127: delegate = nextReader();
128: }
129: }
130:
131: public void close() throws IOException {
132: if (delegate != null)
133: delegate.close();
134: }
135:
136: public FeatureType getFeatureType() {
137: return delegate.getFeatureType();
138: }
139:
140: public boolean hasNext() throws IOException {
141: if (next != null)
142: return true;
143:
144: if (delegate == null)
145: return false;
146:
147: if (!delegate.hasNext()) {
148: delegate.close();
149: delegate = null;
150: delegate = nextReader();
151: if (delegate == null)
152: return false;
153: }
154:
155: try {
156: while (next == null) {
157: if (!delegate.hasNext())
158: return false;
159:
160: next = delegate.next();
161: if (this .foundFids.contains(next.getID()))
162: next = null;
163: }
164: } catch (IllegalAttributeException e) {
165: throw new IOException(e.getLocalizedMessage());
166: }
167:
168: return next != null;
169: }
170:
171: private FeatureReader nextReader() throws IOException {
172: if (filter == null || filter == Filter.EXCLUDE)
173: return null;
174:
175: DefaultQuery query2 = new DefaultQuery(query);
176: query2.setFilter(filter);
177:
178: FeatureReader nextReader = StrictWFSStrategy.super
179: .createFeatureReader(transaction, query2);
180:
181: filter = null;
182: return nextReader;
183: }
184:
185: public Feature next() throws IOException,
186: IllegalAttributeException, NoSuchElementException {
187: if (!hasNext())
188: throw new NoSuchElementException();
189:
190: Feature tmp = next;
191: foundFids.add(tmp.getID());
192: next = null;
193: return tmp;
194: }
195:
196: }
197:
198: }
|