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