001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-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: * Created on March 26, 2003, 1:53 PM
017: */
018: package org.geotools.feature;
019:
020: import java.util.Iterator;
021:
022: /**
023: * The FeatureCollectionIteration provides a depth first traversal of a
024: * FeatureCollection which will call the provided call-back Handler. Because
025: * of the complex nature of Features, which may have other Features (or even a
026: * collection of Features) as attributes, the handler is repsonsible for
027: * maintaining its own state as to where in the traversal it is recieving
028: * events from. Many handlers will not need to worry about state.
029: *
030: * <p>
031: * <b>Implementation Notes:</b> The depth first visitation is implemented
032: * through recursion. The limits to recursion depending on the settings in the
033: * JVM, but some tests show a 2 argument recursive having a limit of ~50000
034: * method calls with a stack size of 512k (the standard setting).
035: * </p>
036: *
037: * @author Ian Schneider, USDA-ARS
038: * @author Chris Holmes, TOPP
039: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/feature/FeatureCollectionIteration.java $
040: */
041: public class FeatureCollectionIteration {
042: /**
043: * A callback handler for the iteration of the contents of a
044: * FeatureCollection.
045: */
046: protected final Handler handler;
047:
048: /** The collection being iterated */
049: private final FeatureCollection collection;
050:
051: /**
052: * Create a new FeatureCollectionIteration with the given handler and
053: * collection.
054: *
055: * @param handler The handler to perform operations on this iteration.
056: * @param collection The collection to iterate over.
057: *
058: * @throws NullPointerException If handler or collection are null.
059: */
060: public FeatureCollectionIteration(Handler handler,
061: FeatureCollection collection) throws NullPointerException {
062: if (handler == null) {
063: throw new NullPointerException("handler");
064: }
065:
066: if (collection == null) {
067: throw new NullPointerException("collection");
068: }
069:
070: this .handler = handler;
071: this .collection = collection;
072: }
073:
074: /**
075: * A convienience method for obtaining a new iteration and calling iterate.
076: *
077: * @param handler The handler to perform operations on this iteration.
078: * @param collection The collection to iterate over.
079: */
080: public static void iteration(Handler handler,
081: FeatureCollection collection) {
082: FeatureCollectionIteration iteration = new FeatureCollectionIteration(
083: handler, collection);
084: iteration.iterate();
085: }
086:
087: /**
088: * Start the iteration.
089: */
090: public void iterate() {
091: walker(collection);
092: }
093:
094: /**
095: * Perform the iterative behavior on the given collection. This will alert
096: * the handler with a <code>handleFeatureCollection</code> call, followed
097: * by an <code> iterate()</code>, followed by a
098: * <code>handler.endFeatureCollection()</code> call.
099: *
100: * @param collection The collection to iterate upon.
101: */
102: protected void walker(FeatureCollection collection) {
103: handler.handleFeatureCollection(collection);
104:
105: iterate(collection.iterator());
106:
107: handler.endFeatureCollection(collection);
108: }
109:
110: /**
111: * Perform the actual iteration on the Iterator which is provided.
112: *
113: * @param iterator The Iterator to iterate upon.
114: */
115: protected void iterate(Iterator iterator) {
116: while (iterator.hasNext()) {
117: walker((Feature) iterator.next());
118: }
119: }
120:
121: /**
122: * Perform the visitation of an individual Feature.
123: *
124: * @param feature The Feature to explore.
125: */
126: protected void walker(Feature feature) {
127: final FeatureType schema = feature.getFeatureType();
128: final int cnt = schema.getAttributeCount();
129:
130: handler.handleFeature(feature);
131:
132: for (int i = 0; i < cnt; i++) {
133: AttributeType type = schema.getAttributeType(i);
134:
135: // recurse if attribute type is another collection
136: if (FeatureCollection.class
137: .isAssignableFrom(type.getType())) {
138: walker((FeatureCollection) feature.getAttribute(i));
139: } else if (type instanceof FeatureType) {
140: // recurse if attribute type is another feature
141: walker((Feature) feature.getAttribute(i));
142: } else {
143: // normal handling
144: handler.handleAttribute(type, feature.getAttribute(i));
145: }
146: }
147:
148: handler.endFeature(feature);
149: }
150:
151: /**
152: * A callback handler for the iteration of the contents of a
153: * FeatureCollection.
154: */
155: public interface Handler {
156: /**
157: * The handler is visiting a FeatureCollection.
158: *
159: * @param fc The currently visited FeatureCollection.
160: */
161: void handleFeatureCollection(FeatureCollection fc);
162:
163: /**
164: * The handler is done visiting a FeatureCollection.
165: *
166: * @param fc The FeatureCollection which was visited.
167: */
168: void endFeatureCollection(FeatureCollection fc);
169:
170: /**
171: * The handler is visiting a Feature.
172: *
173: * @param f The Feature the handler is visiting.
174: */
175: void handleFeature(Feature f);
176:
177: /**
178: * The handler is ending its visit with a Feature.
179: *
180: * @param f The Feature that was visited.
181: */
182: void endFeature(Feature f);
183:
184: /**
185: * The handler is visiting an Attribute of a Feature.
186: *
187: * @param type The meta-data of the given attribute value.
188: * @param value The attribute value, may be null.
189: */
190: void handleAttribute(AttributeType type, Object value);
191: }
192: }
|