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.feature;
017:
018: import java.io.IOException;
019: import java.util.Iterator;
020: import org.opengis.filter.Filter;
021: import org.opengis.filter.sort.SortBy;
022: import org.geotools.data.FeatureListener;
023: import org.geotools.data.collection.ResourceCollection;
024: import org.geotools.feature.visitor.FeatureVisitor;
025: import org.geotools.util.ProgressListener;
026:
027: /**
028: * Represents a collection of features.
029: * <p>
030: * Implementations (and client code) should adhere to the rules set forth
031: * by java.util.Collection. That is, some methods are
032: * optional to implement, and may throw an UnsupportedOperationException.
033: * </p>
034: * <p>
035: * FeatureCollection house rules:
036: * <ul>
037: * <li>FeatureCollection.close( iterator ) must be called (see example below)
038: * <li>Features are not specifically ordered within the FeatureCollection (see FeatureList)
039: * <li>Two instances cannot exist with the same Feature ID (Feature contract)
040: * <li>(unsure) the same Instance can be in the collection more then once
041: * </ul>
042: * In programmer speak a FeatureCollection is a "Bag" with an index based ID.
043: * </p>
044: * <p>
045: * <h3>Life Cycle of Iterator</h3>
046: * <p>
047: * We have also adopted an additional constraint on the use of iterator.
048: * You must call FeatureCollection.close( iterator ) to allow FeatureCollection
049: * to clean up any operating system resources used to acces information.
050: * </p>
051: * <p>
052: * Example (safe) use:<pre><code>
053: * Iterator iterator = collection.iterator();
054: * try {
055: * for( Iterator i=collection.iterator(); i.hasNext();){
056: * Feature feature = (Feature) i.hasNext();
057: * System.out.println( feature.getID() );
058: * }
059: * }
060: * finally {
061: * collection.close( iterator );
062: * }
063: * </code></pre>
064: * </p>
065: * <p>
066: * Handy Tip: Although many resource backed collections will choose
067: * to release resources at when the iterator has reached the end of its contents
068: * this is not something you should rely on.
069: * </p>
070: * <h2>Notes for FeatureCollection Implementors</h2>
071: * <p>
072: * Many users will be treating this as a straight forward Collection,
073: * there code will break often enough due to latency - try and close
074: * up resources for them when you can detect that an Iterator is not
075: * useful anymore.
076: * </p>
077: * <p>
078: * Collections are used in two fashions, basically as you see them,
079: * and also as "range" for common opperations. You can see this with
080: * List.subCollection( Filter ). Existing RnD effort is
081: * going towards supporting this kind of use at the FeatureCollection
082: * level.
083: * </p>
084: *
085: * @see java.util.Collection, org.geotools.Feature
086: * @author Ian Turton, CCG
087: * @author Rob Hranac, VFNY
088: * @author Ian Schneider, USDA-ARS
089: * @author Jody Garnett, Refractions Research, Inc.
090: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/api/src/main/java/org/geotools/feature/FeatureCollection.java $
091: * @version $Id: FeatureCollection.java 28248 2007-12-04 17:47:43Z jgarnett $
092: */
093: public interface FeatureCollection extends ResourceCollection, Feature {
094: /**
095: * Obtain a FeatureIterator of the Features within this collection.
096: * <p>
097: * The implementation of Collection must adhere to the rules of
098: * fail-fast concurrent modification. In addition (to allow for
099: * resource backed collections, the <code>close( Iterator )</code>
100: * method must be called.
101: * <p>
102: *
103: * This is almost equivalent to:
104: * <ul>
105: * <li>a Type-Safe call to:
106: * <code>getAttribute(getFeatureType().getAttributeType(0).getName()).iterator();</code>.
107: * <li>A Java 5:<code>Iterator<Feature></code>
108: * </ul>
109: * </p>
110: * Example (safe) use:<pre><code>
111: * FeatureIterator iterator=collection.features();
112: * try {
113: * while( iterator.hasNext() ){
114: * Feature feature = iterator.next();
115: * System.out.println( feature.getID() );
116: * }
117: * }
118: * finally {
119: * collection.close( iterator );
120: * }
121: * </code></pre>
122: * </p>
123: *
124: * <p>
125: * GML Note: The contents of this iterator are considered to be defined by
126: * <b>featureMember</b> tags (and/or the single allowed <b>FeatureMembers</b> tag).
127: * Please see getFeatureType for more details.
128: * </p>
129: *
130: * @return A FeatureIterator.
131: */
132: FeatureIterator features();
133:
134: /**
135: * Clean up any resources assocaited with this iterator in a manner similar to JDO collections.
136: * <p>
137: * You must be sure to allow null values, this is because in a try/finally
138: * block client code may not be sure if they have actualy succeed in
139: * assign a value to an iterator they wish to ensure is closed.
140: * By permiting null as an api we prevent a null check in lots of finally
141: * statements.
142: * </p>
143: * <p>
144: * Note: Because of FeatureReader using an interator internally,
145: * there is only one implementation of this method that makes
146: * any sense:<pre><code>
147: * <b>public void</b> close( FeatureIterator iterator) {
148: * <b>if</b>( iterator != null ) iterator.close();
149: * }
150: * </code></pre>
151: * </p>
152: */
153: public void close(FeatureIterator close);
154:
155: /**
156: * Clean up after any resources assocaited with this itterator in a manner similar to JDO collections.
157: * </p>
158: * Example (safe) use:<pre><code>
159: * Iterator iterator = collection.iterator();
160: * try {
161: * for( Iterator i=collection.iterator(); i.hasNext();){
162: * Feature feature = (Feature) i.hasNext();
163: * System.out.println( feature.getID() );
164: * }
165: * }
166: * finally {
167: * collection.close( iterator );
168: * }
169: * </code></pre>
170: * </p>
171: * @param close
172: */
173: public void close(Iterator close);
174:
175: /**
176: * Adds a listener for collection events.
177: * <p>
178: * When this collection is backed by live data the event notification
179: * will follow the guidelines outlined by FeatureListner.
180: * </p>
181: *
182: * @param listener The listener to add
183: * @throws NullPointerException If the listener is null.
184: * @deprecated Please use FeatureSource.addFeatureListener(FeatureListener listener)
185: */
186: void addListener(CollectionListener listener)
187: throws NullPointerException;
188:
189: /**
190: * Removes a listener for collection events.
191: *
192: * @param listener The listener to remove
193: * @throws NullPointerException If the listener is null.
194: * @deprecated Please use FeatureSource.removeFeatureListener(FeatureListener listener)
195: */
196: void removeListener(CollectionListener listener)
197: throws NullPointerException;
198:
199: /**
200: * Gets a reference to the type of this feature collection.
201: * <p>
202: * There are several limitations on the use of FeatureType with respect to a FeatureCollection.
203: * </p>
204: * <p>
205: * GML 3.x: all FeatureCollections decend from gml:AbstractFeatureCollectionType:
206: * <ul>
207: * <li>featureMember 0..* allows _Feature or xlink:ref
208: * <li>featureMembers 0..1 contents treated as _Feature
209: * </ul>
210: * The contents defined in this manner is returned the collection
211: * iterator() method.
212: * </p>
213: * <p>
214: * GML 3.x: gml:AbstractFeatureCollectionType decends from gml:BoundedFeatureType:
215: * <ul>
216: * <li>metaDataProperty 0..*
217: * <li>description 0..1
218: * <li>name 0..*
219: * <li>boundedBy 1..1 (required)
220: * <li>location 0..1
221: * </ul>
222: * The value of the boundedBy attribute should be derived from the contents
223: * of the collection.
224: * </p>
225: * <h3>Implementation Notes</h3>
226: * <p>
227: * There is a difference between getFeatureType() and getSchema(), getSchema is named
228: * for historical reasons and reprensets the LCD FeatureType that best represents the
229: * contents of this collection.
230: * <ul>
231: * <li>The degenerate case returns the "_Feature" FeatureType, where the
232: * onlything known is that the contents are Features.
233: * <li>For a collection backed by a shapefiles (or database tables) the
234: * FeatureType returned by getSchema() will complete describe each and every child in the collection.
235: * <li>For mixed content FeatureCollections you will need to check the FeatureType
236: * of each Feature as it is retrived from the collection
237: * </ul>
238: * </p>
239: *
240: * @return A reference to this collections type
241: */
242: FeatureType getFeatureType();
243:
244: /**
245: * The schema for the child features of this collection.
246: * <p>
247: * There is a difference between getFeatureType() and getSchema()represents the LCD
248: * FeatureType that best represents the contents of this collection.
249: * <ul>
250: * <li>The degenerate case returns the "_Feature" FeatureType, where the
251: * onlything known is that the contents are Features.
252: * <li>For a collection backed by a shapefiles (or database tables) the FeatureType returned by getSchema() will
253: * complete describe each and every child in the collection.
254: * <li>For mixed content FeatureCollections you will need to check the FeatureType of each Feature as it
255: * is retrived from the collection
256: * </ul>
257: * </p>
258: * <p>
259: * The method getSchema() is named for compatability with the geotools 2.0 API. In the
260: * Geotools 2.2 time frame we should be able to replace this method with a careful check
261: * of getFeatureType() and its attributes.
262: * </p>
263: * @return FeatureType describing the "common" schema to all child features of this collection
264: */
265: FeatureType getSchema();
266:
267: /**
268: * Will visit the contents of the feature collection.
269: * <p>
270: * Note: When performing aggregate calculations please consider using
271: * the Filter/Expression/Function API as it may be optimized.
272: * </p>
273: * @param visitor
274: * @throws IOException
275: */
276: void accepts(FeatureVisitor visitor, ProgressListener progress)
277: throws IOException;
278:
279: /**
280: * FeatureCollection "view" indicated by provided filter.
281: * <p>
282: * The contents of the returned FeatureCollection are determined by
283: * applying the provider Filter to the entire contents of this
284: * FeatureCollection. The result is "live" and modifications will
285: * be shared.
286: * <p>
287: * This method is used cut down on the number of filter based methods
288: * required for a useful FeatureCollection construct. The FeatureCollections
289: * returned really should be considered as a temporary "view" used to
290: * control the range of a removeAll, or modify operation.
291: * <p>
292: * Example Use:
293: * <pre><code>
294: * collection.subCollection( filter ).clear();
295: * </code></pre>
296: * The above recommended use is agreement with the Collections API precident of
297: * List.subList( start, end ).
298: * <p>
299: * The results of subCollection:
300: * <ul>
301: * <li>are to be considered unordered
302: * <li>may be an ordered FeatureList if requested when sortBy is indicated
303: * </ul>
304: * </p>
305: * @see FeatureList
306: * @param filter
307: * @return FeatureCollection identified as subset.
308: */
309: public FeatureCollection subCollection(Filter filter);
310:
311: /**
312: * collection.subCollection( myFilter ).sort( {"foo","bar"} );
313: * collection.subCollection( myFilter ).sort( "bar" ).sort("foo")
314: * @param order
315: */
316: public FeatureList sort(SortBy order);
317: }
|