GeoTools : interface scratchpad Interfaces

The e-mails discussing the various data interfaces (DataStore, FeatureCollection, etc) get pretty lengthy. Hopefully this page can serve as a summary of what the interfaces might look like with the most current suggestions.

Note that Java generic syntax is used below in several places (i.e. List<QName>). This is used for clarity of writing, but may not actually be used in the "real" interfaces.

(Note: This was started by Chris Dillard in hopes that someone with a little more time would come along and finish filling things in...)
(Comments inline from James Macgill, marked JRM)

interface DataStore {
    // Gets a list of all the names of the types held in this DataStore.
    List<QName> getTypeNames();

    // Gets all features of the given type
    FeatureCollection getFeatures(QName type);

    // Gets all features of the given type that pass some Filter
    FeatureCollection getFeatures(QName type, Filter f);

    // Gets features of the given type that pass some query.
    // This allows for retrieving only a subset of the attributes (and
    // may allow for reprojection)
    FeatureCollection getFeatures(QName type, Query q);// should/could the type be part of the 
                                                       // query (JRM)

    // Shortcut for getting the FeatureCollection then calling setTransaction(t)
    FeatureCollection getFeatures(QName type, Query q, Transaction t);
interface Feature {
    FeatureType getFeatureType();
    FeatureCollection getParent(); //Back pointer is v.important. (JRM)
    // getBounds() can return null if Feature has no geometry
    Envelope getBounds();
    String getID();

    Object getAttribute(String path) throws IllegalAttributeException;
    Object getAttribute(int index) throws IndexOutOfBoundsException;
    void setAttribute(String path, Object value) throws IllegalAttributeException;
    void setAttribute(int index, Object value) throws IndexOutOfBoundsException;
interface FeatureCollection extends Feature, Collection {
    // Accessor methods, from Collection
    // Will always return FeatureIterator, shown below.
    Iterator<Feature> iterator();
// DZ - add a throws OperationNotSupported?
// CSD - Under what circumstances could these operations not be supported?
// DZ - the toArray() function may not be supported for large dataset. Also optionally returning null works.
    Object [] toArray();
    Object [] toArray(Object [] buffer);

    // Size methods, from Collection
    boolean isEmpty();
    // May return -1 if size is not known (streaming)
    int size();

    // Feature containment checking, from Collection
    boolean contains(Object o);
    boolean containsAll(Collection c);

    // Modification methods from Collection.  All may throw UnsupportedOperationException
    // This is in line with the Collections 'Unmodifiable' approach. (JRM)
    boolean add(Object o);
    boolean addAll(Collection c);
    void clear();
    boolean remove(Object o);
    boolean removeAll(Collection c);
    boolean retainAll(Collection c);

    // Do we need a close() operation?
    void close() throws IOException; // I don't think so, I don't see how a FeatureCollection
                                     // could ever be open or closed, it just is.  the class
                                     // returned by iterattor() would have to handle this. (JRM)
// DZ - hmm, very useful for many datastores, we can't rely on dispose to be executed in a 
// DZ - timely manner which could cause connection issues
// CSD - It seems FeatureCollection represents the result of a specific query, so you will
// CSD - need a close() operation to clean up.

    // If the add() methods are to work, we'll need a transaction somehow:
    void setTransaction(Transaction t);
    Transaction getTransaction();
    // The above is true iif modifications to a FeatureCollection are imidatly reflected in the 
    // orignating DataStore, this may or may not be the case.  Needs some thought. (JRM)

    // Listener methods
    public void addFeatureListener(FeatureListener fl);
    public void removeFeatureListener(FeatureListener fl);
interface FeatureType {
    // Include all the same stuff that's in FeatureType now.
    // Also include the following:

    // Returns true if Features of this type can be cast to FeatureCollection.
    boolean isCollection();

    // If isCollection() returns true, this method returns a non-empty
    // list of FeatureTypes that indicates what types of Features can be
    // elements of the collection.
    List<FeatureType> getChildTypes();
interface QName {
    // Get the namespace for your feature.
    public URI getNamespaceURI();
    // Get the name (without namespace or prefix)
    public String getLocalName();

    // This can return null if not known or data source doesn't care.
    // Note that this only applies when the features are encoded as XML.
    public String getPreferredPrefix();

As an example, suppose we have some feature xml that looks like this:

<xyz:MajorRoads xmlns:xyz="">

For a QName describing this Feature, getNamespaceURI() would return "", getLocalName() would return "MajorRoads", and getPreferredPrefix() could return "xyz".


It seems like we need some way of calling "close" on an iterator. Relying on garbage collection (and implementing finalize()) is a bad idea.

CSD - Do we want to extend ListIterator? I suspect not... Although nothing prevents a given DataStore from returning one if it can easily seek.

interface FeatureIterator extends Iterator {
    // For clarity, here are the methods from Iterator:
    boolean hasNext();
    Object next();
    void remove(); // Throws UnsuppOpException

    // And here's the reason for this interface to exist:
    public void close() throws IOException;
interface FeatureListener {
    public void featuresAdded(FeatureEvent e);
    public void featuresRemoved(FeatureEvent e);
    public void featuresChanged(FeatureEvent e);
class FeatureEvent extends java.util.EventObject {
    // IDs of the features that were affected
    private List<String> fids;

    public FeatureEvent(FeatureCollection source, List<String> fids) {

    public List<String> getFeatureIDs() {
        return fids;

    // Synonym for EventObject.getSource(), but does the cast for you
    public FeatureCollection getFeatureCollection() {
        return (FeatureCollection) getSource();


Examples of using the interfaces in common situations.

Reading features from a datastore
public class Test {
    public static void main(String [] args) {
        DataStore ds = ... ;

        FeatureCollection fc = null;
        FeatureIterator fi = null;

        try {
            fc = ds.getFeatures(new QName("Roads"));

            fi = (FeatureIterator) fc.iterator();
            while (fi.hasNext()) {
                Feature f = (Feature);
        finally {
            if (fi != null) fi.close();
            if (fc != null) fc.close();
Writing features to a new datastore
Appending features to an existing datastore