/* * Geotools2 - OpenSource mapping toolkit * http://geotools.org * (C) 2002, Geotools Project Managment Committee (PMC) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * */ /* * FeatureCollectionIterator.java * * Created on March 26, 2003, 1:53 PM */ package org.geotools.feature; import java.util.Iterator; /** * The FeatureCollectionIteration provides a depth first traversal of a * FeatureCollection which will call the provided call-back Handler. Because * of the complex nature of Features, which may have other Features (or even a * collection of Features) as attributes, the handler is repsonsible for * maintaining its own state as to where in the traversal it is recieving * events from. Many handlers will not need to worry about state. * *
* Implementation Notes: The depth first visitation is implemented * through recursion. The limits to recursion depending on the settings in the * JVM, but some tests show a 2 argument recursive having a limit of ~50000 * method calls with a stack size of 512k (the standard setting). *
* * @author Ian Schneider, USDA-ARS * @author Chris Holmes, TOPP */ public class FeatureCollectionIteration { /** * A callback handler for the iteration of the contents of a * FeatureCollection. */ protected final Handler handler; /** The collection being iterated */ private final FeatureCollection collection; /** * Create a new FeatureCollectionIteration with the given handler and * collection. * * @param handler The handler to perform operations on this iteration. * @param collection The collection to iterate over. * * @throws NullPointerException If handler or collection are null. */ public FeatureCollectionIteration(Handler handler, FeatureCollection collection) throws NullPointerException { if (handler == null) { throw new NullPointerException("handler"); } if (collection == null) { throw new NullPointerException("collection"); } this.handler = handler; this.collection = collection; } /** * A convienience method for obtaining a new iteration and calling iterate. * * @param handler The handler to perform operations on this iteration. * @param collection The collection to iterate over. */ public static void iteration(Handler handler, FeatureCollection collection) { FeatureCollectionIteration iteration = new FeatureCollectionIteration(handler, collection); iteration.iterate(); } /** * Start the iteration. */ public void iterate() { walker(collection); } /** * Perform the iterative behavior on the given collection. This will alert * the handler with ahandleFeatureCollection
call, followed
* by an iterate()
, followed by a
* handler.endFeatureCollection()
call.
*
* @param collection The collection to iterate upon.
*/
protected void walker(FeatureCollection collection) {
handler.handleFeatureCollection(collection);
iterate(collection.iterator());
handler.endFeatureCollection(collection);
}
/**
* Perform the actual iteration on the Iterator which is provided.
*
* @param iterator The Iterator to iterate upon.
*/
protected void iterate(Iterator iterator) {
while (iterator.hasNext()) {
walker((Feature) iterator.next());
}
}
/**
* Perform the visitation of an individual Feature.
*
* @param feature The Feature to explore.
*/
protected void walker(Feature feature) {
final FeatureType schema = feature.getFeatureType();
final int cnt = schema.getAttributeCount();
handler.handleFeature(feature);
for (int i = 0; i < cnt; i++) {
AttributeType type = schema.getAttributeType(i);
// recurse if attribute type is another collection
if (FeatureCollection.class.isAssignableFrom(type.getType())) {
walker((FeatureCollection) feature.getAttribute(i));
} else if (type.isNested()) {
// recurse if attribute type is another feature
walker((Feature) feature.getAttribute(i));
} else {
// normal handling
handler.handleAttribute(type, feature.getAttribute(i));
}
}
handler.endFeature(feature);
}
/**
* A callback handler for the iteration of the contents of a
* FeatureCollection.
*/
public interface Handler {
/**
* The handler is visiting a FeatureCollection.
*
* @param fc The currently visited FeatureCollection.
*/
void handleFeatureCollection(FeatureCollection fc);
/**
* The handler is done visiting a FeatureCollection.
*
* @param fc The FeatureCollection which was visited.
*/
void endFeatureCollection(FeatureCollection fc);
/**
* The handler is visiting a Feature.
*
* @param f The Feature the handler is visiting.
*/
void handleFeature(Feature f);
/**
* The handler is ending its visit with a Feature.
*
* @param f The Feature that was visited.
*/
void endFeature(Feature f);
/**
* The handler is visiting an Attribute of a Feature.
*
* @param type The meta-data of the given attribute value.
* @param value The attribute value, may be null.
*/
void handleAttribute(AttributeType type, Object value);
}
}