Here are some stats before you get going:
- four: number of classes representing a set of Features
- one: class to control workflow
- four: number of classes listing feature collections
- zero: number of datastores that support metadata at this time
- sixteen: number plugins connecting geotools to the world
- three: number of classes needed to implement a new datastore
- thirty: times, speed improvement of previous implementation
- five: number of times locking API has changed
Data Discovery and Catalog
We have defined a Catalog API based on the Catalog version 1.0 document. This API consists of the following interfaces:
interface Catalog { void add( CatalogEntry ); void iterator(); QueryResult query( QueryDefinition query ); void remove( CatalogEntry ); } interface CatalogEntry { String getDataName(); Map(<String>,<Metadata>) metadata(); Object getResource(); }
MetadataEntity is a placeholder for Metadata Information.
DataStore Read
DataStore is the Geotools API for data source access. It is used to access both file and Service information. Wide ranges of data sources are supported from simple Shapefile access through to Database and Web Feature Services.
DataStore operates on an OGC Feature Model notable in its use of XPATH queries to access nested attribute type information. Creation of everything from FeatureTypes to Filter Expression is controlled by the use of Factories.

(picture from Data access basic)
As the above diagram illustrates, there are two APIs for access to spatial information:
- FeatureReader: an iterator of Features (sequential access), basically an iterator that is allowed to throw IOExceptions
- FeatureSource: provides getBounds, getCount and getFeatures operations. For most DataStore implementations these are optimized to make use of the native functionality of the underlying service.
Note: In addition to the API above many DataStores implement Catalog to provide access to Metadata based FeatureType queries. In this case the CatalogEntry.getResource() returns the FeatureSource associated with the FeatureType.
FeatureSource is very similar to the geotools FeatureCollection, the difference is:
- FeatureCollection - represents an in memory collection of features, FeatureIterator does not throw Exceptions
- FeatureSource - represents an external source of Features, FeatureReader throws IOExceptions
- FeatureSource provides the read-only representation of an external source of Features, complete with event notification (events changes by BBox and FID).
public interface FeatureSource<T extends FeatureType, F extends Feature> { Name getName() Envelope getBounds() Envelope getBounds(Query query) int getCount(Query query) DataAccess<T, F> getDataStore() FeatureCollection<T, F> getFeatures() FeatureCollection<T, F> getFeatures(Filter filter) FeatureCollection<T, F> getFeatures(Query query) T getSchema() void addFeatureListener(FeatureListener listener) void removeFeatureListener(FeatureListener listener) }
DataStore Write
DataStore offers a comprehensive writing API with support for Transactions and optimized updates.

(picture from Data access basic)
This time there are four classes to consider:
- Transaction: offers workflow control and rollback. Can be used with several DataStores at once.
- FeatureWriter: an iterator of Features supporting modification.
- FeatureStore: provides add, update and remove as high level requests that are optimized for most DataStores.
- FeatureLocking: offers locking for the duration of a Transaction and WFS Style Long Term Transaction support.
- FeatureStore extends FeaturesSource with modification and "Transaction" support
interface FeatureStore<T extends FeatureType, F extends Feature> extends FeatureSource<T, F> { Set addFeatures(FeatureCollection<T, F> reader) void modifyFeatures(AttributeType[] type, Object[] value, Filter filter) void modifyFeatures(AttributeType type, Object value, Filter filter) void removeFeatures(Filter filter) void setFeatures(FeatureReader<T, F> reader) Transaction getTransaction() void setTransaction(Transaction transaction) }
- Transaction works as a cross cutting control mechanism for client code. A single Transaction can be used to commit/rollback multiple FeatureStores in one go. This is impemented by allowing implementotrs to externalize there State information as a Momento under Transaction control. A jdbc implementation can have Transaction remember the "current" database connection, a Shapefile could have the Transaction remember a Map of differences, or the name of a temporary file.
- see Transaction
- FeatureLocking extends FeatureStore with locking support. Uses WFS style long term locking support. Locks that last as long as the current transaction are also supported. To opperate on a locked feature the current Transaction must be supplied with an AuthorizationID.
public interface FeatureLocking<T extends FeatureType, F extends Feature> extends FeatureStore<T, F> { int lockFeatures() int lockFeatures(Filter filter) int lockFeatures(Query query) void setFeatureLock(FeatureLock lock) void unLockFeatures() void unLockFeatures(Filter filter) void unLockFeatures(Query query) }
- Unfortantly UnLocking must occur at the level of a Catalog that "knows" all the FeatureSources invloved in the opperation.
DataStore Creation
As promised, even DataStore creation is controlled by use of a Factory.
interface DataAccessFactory extends Factory { boolean canProcess(java.util.Map<String, Serializable> params); DataAccess<? extends FeatureType, ? extends Feature> createDataStore(Map<String, Serializable> params); DataStore createNewDataStore( Map params ); String getDescription(); Param[] getParametersInfo(); ParameterGroupDescriptor getParameterGroup(); } interface DataStoreFactorySpi extends DataAccessFactory{ DataStore createDataStore( Map params ); }
DataAccessFactory provides access to both (complex) Feature and SimpleFeature capable content providers. DataStore specializes in serving SimpleFeature.
The map used to create a DataStore is described by:
- A legacy getParametersInfo() method
- ParameterValueGroup adapted for general use by GeoAPI
There are several difficulties with this approach:
- A Map is not optimal ? for drag and drop support we would like to use a File or URL directly
- The ParameterValueGroup is difficult to understand
- ISO 19119 is designed to describe Services
The plug-in system FactorySPI is used to ?discover? the appropriate DataStoreFactory based on a Map of parameters. In practice many DataStoreFactory implementations require a ?magic? key be entered in Map to support this functionality.
It is likely that DataStore will be simplified over the coming weeks to take these factors into consideration.
Repository
Offers cross DataStore operations, and FeatureSource access by namespace URI and type name irrespective of DataStore.
interface Repository { Map getDataStores(); SortedMap getFeatureSources(); Set getPrefixes(); boolean lockExists(String lockID); boolean lockRefresh(String lockID, Transaction transaction) boolean lockRelease(String lockID, Transaction transaction) FeatureSource source(URI namespace, String typeName) }
It is an interesting consequence of Locks being held across DataStores that a central Repository is required to unlock them safely.
Grid Coverage Exchange
Grid Coverage Exchange provides access to Grid Coverage information. This has been assembled as part of the uDig project, and has been donated to the GeoAPI project.
interface GridCoverageExchange { void dispose(); Format[] getFormats() GridCoverageReader getReader(Object source) GridCoverageWriter getWriter(Object destination, Format format) } interface Format { String getDescription() String getDocURL() String getName() ParameterValueGroup getReadParameters() String getVendor() String getVersion() ParameterValueGroup getWriteParameters() } interface GridCoverageReader { String getCurrentSubname() Format getFormat() GridCoverage read(GeneralParameterValue[] parameters) } interface GridCoverageWriter { Object getDestination() Format getFormat() void write(GridCoverage coverage, GeneralParameterValue[] parameters) }
The one difficulty with the above API is that one gets no indication what the source parameter is when acquiring a GridCoverageReader. Once again Catalog has stepped in to the rescue. Many GCE implementations are using the Catalog API to provide client code with an avenue to discover a source parameter (based on a remote Web Map Server, or a local file system).
The complete API also provides facilities for GridCoverageReader and GridCoverageWriter to be used with streamed content. This has been omitted for brevity.
The Future
Now for where we want to go - David Zwiers is starting the process of simplifing this API - here is what I remember:
- Simplify Creation
- Make the provider of FeatureSource GeoAPI Catalog based
- Provided a simplified starting point for File based FeatureSource implementors
- Better GridCoverage intergration with Catalog
- Intergrate the idea of FeatureResults and FeatureReader
- Consider adding support for Random Access, or Spatial Index based queries
- Consider making FID creation stratagy objects (from JDBC DataStore) part of the public API
David Zwiers is thinking about these ideas now, I am going to be away on Holiday for most of November (so the above list should not be considered complete or a promise).
Compare and Contrast
Degree also has a DataStore API (I think each DataStore represents a FeatureSource in our model), the code is based on hibernate and is quite cool (comments based on http://deegree.sourceforge.net/deegree2/index.html).
interface DataStore extends Handler { void describeFeatureType(DescribeFeatureType request) void getFeature(GetFeature request) void getFeatureWithLock(WFSGetFeatureWithLockRequest request) boolean isKnownFeatureType(String featureType) void lockFeature(LockFeature request) void registerFeatureType(String featureType) void removeFeatureType(String featureType) void transaction(Transaction request) }
ESRI has a ContentProvider class that works in this same domain.