001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-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.feature.collection;
017:
018: import java.io.IOException;
019: import java.util.Iterator;
020:
021: import org.geotools.data.FeatureReader;
022: import org.geotools.data.collection.DelegateFeatureReader;
023: import org.geotools.feature.CollectionListener;
024: import org.geotools.feature.Feature;
025: import org.geotools.feature.FeatureCollection;
026: import org.geotools.feature.FeatureIterator;
027: import org.geotools.feature.FeatureList;
028: import org.geotools.feature.FeatureType;
029: import org.geotools.feature.IllegalAttributeException;
030: import org.geotools.feature.visitor.FeatureVisitor;
031: import org.geotools.geometry.jts.ReferencedEnvelope;
032: import org.opengis.filter.Filter;
033: import org.opengis.filter.sort.SortBy;
034: import org.geotools.util.ProgressListener;
035:
036: import com.vividsolutions.jts.geom.Envelope;
037: import com.vividsolutions.jts.geom.Geometry;
038:
039: /**
040: * Implement a feature collection just based on provision of iterator.
041: * <p>
042: * Your subclass will need to provide an internal "state" stratagy object
043: * used to access collection attributes - see the two protected constructors
044: * for details.
045: * </p>
046: * @author Jody Garnett, Refractions Research Inc.
047: */
048: public abstract class AbstractFeatureCollection extends
049: AbstractResourceCollection implements FeatureCollection {
050: FeatureState state;
051:
052: /**
053: * Feature methods will be delegated to provided state.
054: * <p>
055: * You can use this implemenation with a choice of stratagy objects:
056: * <ul>
057: * <li>BaseFeatureState - when this collection is independent
058: * <li>SubFeatureState - when this collection delegates content
059: * </ul>
060: */
061: protected AbstractFeatureCollection(FeatureState state) {
062: this .state = state;
063: }
064:
065: /**
066: * Creates an AbstractFeatureCollection delegating the FeatureState
067: * implementaion content to iterator() and close( iterator ).
068: *
069: * @param schema
070: */
071: public AbstractFeatureCollection(FeatureType schema) {
072: state = new BaseFeatureState(this , schema);
073: }
074:
075: //
076: // FeatureCollection - Feature methods
077: //
078: public FeatureCollection getParent() {
079: return state.getParent();
080: }
081:
082: public void setParent(FeatureCollection collection) {
083: state.setParent(collection);
084: }
085:
086: public FeatureType getFeatureType() {
087: return state.getFeatureType();
088: }
089:
090: public String getID() {
091: return state.getId();
092: }
093:
094: public Object[] getAttributes(Object[] attributes) {
095: return state.getAttributes(attributes);
096: }
097:
098: public Object getAttribute(String xPath) {
099: return state.getAttribute(xPath);
100: }
101:
102: public Object getAttribute(int index) {
103: return state.getAttribute(index);
104: }
105:
106: public void setAttribute(int position, Object val)
107: throws IllegalAttributeException,
108: ArrayIndexOutOfBoundsException {
109: state.setAttribute(position, val);
110: }
111:
112: public int getNumberOfAttributes() {
113: return state.getNumberOfAttributes();
114: }
115:
116: public void setAttribute(String xPath, Object attribute)
117: throws IllegalAttributeException {
118: state.setAttribute(xPath, attribute);
119: }
120:
121: public Geometry getDefaultGeometry() {
122: return state.getDefaultGeometry();
123: }
124:
125: public void setDefaultGeometry(Geometry geometry)
126: throws IllegalAttributeException {
127: state.setDefaultGeometry(geometry);
128: }
129:
130: public ReferencedEnvelope getBounds() {
131: return ReferencedEnvelope.reference(state.getBounds());
132: }
133:
134: public FeatureType getSchema() {
135: return state.getChildFeatureType();
136: }
137:
138: //
139: // FeatureCollection - Events
140: //
141: public void addListener(CollectionListener listener) {
142: state.addListener(listener);
143: }
144:
145: public void removeListener(CollectionListener listener)
146: throws NullPointerException {
147: state.removeListener(listener);
148: }
149:
150: //
151: // FeatureCollection - Feature Access
152: //
153: public FeatureIterator features() {
154: FeatureIterator iter = new DelegateFeatureIterator(this ,
155: openIterator());
156: open.add(iter);
157: return iter;
158: }
159:
160: public void close(FeatureIterator close) {
161: closeIterator(close);
162: open.remove(close);
163: }
164:
165: public void closeIterator(FeatureIterator close) {
166: DelegateFeatureIterator iter = (DelegateFeatureIterator) close;
167: closeIterator(iter.delegate);
168: iter.close();
169: }
170:
171: public void purge() {
172: for (Iterator i = open.iterator(); i.hasNext();) {
173: Object resource = i.next();
174: if (resource instanceof FeatureIterator) {
175: FeatureIterator resourceIterator = (FeatureIterator) resource;
176: try {
177: closeIterator(resourceIterator);
178: } catch (Throwable e) {
179: // TODO: Log e = ln
180: } finally {
181: i.remove();
182: }
183: }
184: }
185: super .purge();
186: }
187:
188: /**
189: * Accepts a visitor, which then visits each feature in the collection.
190: * @throws IOException
191: */
192: public void accepts(FeatureVisitor visitor,
193: ProgressListener progress) throws IOException {
194: Iterator iterator = null;
195: // if( progress == null ) progress = new NullProgressListener();
196: try {
197: float size = size();
198: float position = 0;
199: progress.started();
200: for (iterator = iterator(); !progress.isCanceled()
201: && iterator.hasNext();) {
202: if (size > 0)
203: progress.progress(position++ / size);
204: try {
205: Feature feature = (Feature) iterator.next();
206: visitor.visit(feature);
207: } catch (Exception erp) {
208: progress.exceptionOccurred(erp);
209: }
210: }
211: } finally {
212: progress.complete();
213: close(iterator);
214: }
215: }
216:
217: //
218: // Feature Collections API
219: //
220: public FeatureList subList(Filter filter) {
221: return new SubFeatureList(this , filter);
222: }
223:
224: public FeatureCollection subCollection(Filter filter) {
225: if (filter == Filter.INCLUDE) {
226: return this ;
227: }
228: return new SubFeatureCollection(this , filter);
229: }
230:
231: public FeatureList sort(SortBy order) {
232: return new SubFeatureList(this , order);
233: }
234:
235: //
236: // FeatureCollection - Legacy
237: //
238: /*
239: public FeatureReader reader() throws IOException {
240: return new DelegateFeatureReader( getSchema(), features() );
241: }
242: public int getCount() throws IOException {
243: return size();
244: }
245: public FeatureCollection collection() throws IOException {
246: return this;
247: }
248: */
249: }
|