Internals --------- The internals of ``gt-main`` provide assistance to those writing new format support for the DataStore API with a wealth of abstract classes to extend, and utility classes performing common functions. ContentDataStore ^^^^^^^^^^^^^^^^ ``ContentDataStore`` represents a ground up rewrite of "much loved" ``AbstractDataStore``. Since the form of that love was reflect in lots of workarounds, and extra methods, and complicated class interactions this is generally viewed as a good thing. .. image:: /images/content.PNG It offers a clear design with a small number of classes to implement. These classes are referenced by ``ContentDataStore`` as it goes about doing its job, as a result you are not responsible for many of the usual DataStore classes. There is a tutorial showing how to read a simple comma separated value file: * :doc:`/tutorial/datastore/index` (tutorial) Central to this design is the ``ContentEntry`` and ``ContentState`` classes. These classes are provided to you as you are implementing for general note keeping. You can override the instance of ``ContentState`` that is created if you need to track additional details cache information specific to your implementation. * ``ContentEntry`` stores all the notes needed for a ``featureSource`` to function. ``getName()`` ``getTypeName()`` These two methods identify a published ``FeatureType`` * ``getState( Transaction )`` Access to the ``ContentState`` for ongoing ``Transactions``. Two ``FeatureStores`` using the same Transaction will end up using the same ``ContentState``. * ``dispose()`` * ``getDataStore()`` * ``ContentState`` maintains all the information for an on going Transaction. * ``getEntry()`` * ``getTransaction()`` * ``setTransaction(Transaction)`` You can cache your generated schema and summary values here: * ``getFeatureType()`` * ``setFeatureType(SimpleFeatureType)`` * ``getCount()`` * ``setCount(int)`` * ``getBounds()`` * ``setBounds(ReferencedEnvelope)`` Listener information is gathered here where your ``FeatureStore`` can delegate to it. You can call these methods as modifications are made to your data. * ``addListener(FeatureListener)`` * ``removeListener(FeatureListener)`` * ``getBatchFeatureEvent()`` * ``hasListener()`` * ``fireFeatureUpdated(FeatureSource, Feature, ReferencedEnvelope)`` * ``fireFeatureAdded(FeatureSource, Feature)`` * ``fireFeatureRemoved(FeatureSource, Feature)`` * ``fireFeatureEvent(FeatureEvent)`` * ``fireBatchFeatureEvent(boolean)`` Care and feeding: * ``flush()`` * ``close()`` * ``copy()`` - used when copying the ``Transaction.AUTO_COMMI`` ``ContentState`` at the start of a ``Transaction`` DirectoryDataStore ^^^^^^^^^^^^^^^^^^ ``DirectoryDataStore`` is used to allow file based ``DataStores`` (such as shapefile) to smoothly represent a directory of files in one fell swoop. Here is an example for "CSV" files:: /** Extend a CSVDataStoreFactory for a Directory of files */ public class CSVDirectoryFactory extends CSVDataStoreFactory { /** The directory to be scanned for file data stores */ public static final Param URLP = new Param("url", URL.class, "Directory containing geospatial files", true); public String getDisplayName() { return "Directory of spatial files (csv)"; } public String getDescription() { return "Takes a directory of csv and exposes it as a data store"; } public boolean canProcess(Map params) { // we don't try to steal single csv away from the main factory if (super.canProcess(params)) { try { URL url = (URL) URLP.lookUp(params); File f = URLs.urlToFile(url); return f != null && f.exists() && f.isDirectory(); } catch (Exception e) { return false; } } else { return false; } } public DataStore createNewDataStore(Map params) throws IOException { URL url = (URL) URLP.lookUp(params); File dir = URLs.urlToFile(url); if(dir != null && dir.isDirectory()) { return new DirectoryDataStore(URLs.urlToFile(url), new CSVDataStoreFactory(this, params)); } else { throw new DataSourceException("Not a directory "+dir ); } } }