/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2003-2008, Open Source Geospatial Foundation (OSGeo) * * 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. */ package org.geotools.data; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.feature.FeatureTypes; import org.geotools.feature.NameImpl; import org.geotools.feature.SchemaException; import org.geotools.geometry.jts.ReferencedEnvelope; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.Name; import org.opengis.filter.Filter; /** * Represents a stating point for implementing your own DataStore. * *
* The goal is to have this class provide everything else if you can * only provide: *
* ** All remaining functionality is implemented against these methods, including * Transaction and Locking Support. These implementations will not be optimal * but they will work. *
* ** Pleae note that there may be a better place for you to start out from, (like * JDBCDataStore). *
* * @author jgarnett * * * @source $URL$ */ public abstract class AbstractDataStore implements DataStore { /** The logger for the filter module. */ protected static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geotools.data"); /** Manages listener lists for SimpleFeatureSource implementation */ public FeatureListenerManager listenerManager = new FeatureListenerManager(); /** * Flags AbstractDataStore to allow Modification. ** GetFeatureSource will return a FeatureStore is this is true. *
*/ protected final boolean isWriteable; /** * Manages InProcess locks for FeatureLocking implementations. * ** May be null if subclass is providing real locking. *
*/ private InProcessLockingManager lockingManager; /** Default (Writeable) DataStore */ public AbstractDataStore() { this(true); } /** * AbstractDataStore creation. * * @param isWriteable true for writable DataStore. */ public AbstractDataStore(boolean isWriteable) { this.isWriteable = isWriteable; lockingManager = createLockingManager(); } /** * Currently returns an InProcessLockingManager. * *
* Subclasses that implement real locking may override this method to
* return null
.
*
* CreateTypeEntry uses this method to aquire metadata information, * if available. *
*/ protected Map createMetadata( String typeName ) { return Collections.EMPTY_MAP; } /** helper method for retrieving all the names. */ public abstract String[] getTypeNames() throws IOException; public ServiceInfo getInfo() { DefaultServiceInfo info = new DefaultServiceInfo(); info.setDescription("Features from "+getClass().getSimpleName() ); info.setSchema( FeatureTypes.DEFAULT_NAMESPACE ); return info; } /** Retrive schema information for typeName */ public abstract SimpleFeatureType getSchema(String typeName) throws IOException; /** * Subclass must implement. * * @param typeName * * @return FeatureReaderA feature writer writes to the resource so it should considered to always be committing. * The transaction is passed in so that it can be known what FeatureListeners should be notified of the * changes. If the Transaction is AUTOCOMMIT then all listeners should be notified. If not * all listeners that are NOT registered with that transaction should be notified.
* @param typeName
* @param transaction a feature writer
* @return FeatureWriter over contents of typeName
* @throws IOException
*
* @throws IOException Subclass may throw IOException
* @throws UnsupportedOperationException Subclass may implement
*/
protected FeatureWriter
* We should be able to optimize this to only get the RowSet once
*
* A subclass that supports the creation of such an optimized FeatureReader
* shold override this method. Otherwise, it just returns
*
*/
protected FeatureReader
* If the complete filter is supported, the subclass must return
* By default a TransactionStateDiff will be created that holds
* any changes in memory.
*
* @param transaction
* @return TransactionStateDiff or null if subclass is handling differences
*/
protected TransactionStateDiff state(Transaction transaction) {
synchronized (transaction) {
TransactionStateDiff state = (TransactionStateDiff) transaction
.getState(this);
if (state == null) {
state = new TransactionStateDiff(this);
transaction.putState(this, state);
}
return state;
}
}
/* (non-Javadoc)
* @see org.geotools.data.DataStore#getFeatureWriter(java.lang.String, org.geotools.filter.Filter, org.geotools.data.Transaction)
*/
public FeatureWriter
* By default AbstractDataStore makes use of InProcessLockingManager.
*
* Will return null if there is not fast way to compute the bounds. Since
* it's based on some kind of header/cached information, it's not guaranteed
* to be real bound of the features
*
* If getBounds(Query) returns query
* getFeatureReader(typeName)
* Filter.INCLUDE
* -1
due to expense consider
* using getFeatures(Query).getCount()
as a an alternative.
* -1
* if count is too expensive to calculate or any errors or occur.
* @throws IOException
*
* @throws IOException if there are errors getting the count
*/
protected int getCount(Query query) throws IOException{
return -1; // too expensive
}
/**
* If you are using the automated FeatureSource/Store/Locking creation, this method
* allows for the specification of the supported hints.
* @return
*/
protected Set getSupportedHints() {
return Collections.EMPTY_SET;
}
/**
* Dummy implementation, it's a no-op. Subclasses holding to system resources must
* override this method and release them.
*/
public void dispose() {
// nothing to do
}
/**
* Delegates to {@link #getFeatureSource(String)} with
* {@code name.getLocalPart()}
*
* @since 2.5
* @see DataAccess#getFeatureSource(Name)
*/
public SimpleFeatureSource getFeatureSource(Name typeName)
throws IOException {
return getFeatureSource(typeName.getLocalPart());
}
/**
* Returns the same list of names than {@link #getTypeNames()} meaning the
* returned Names have no namespace set.
*
* @since 2.5
* @see DataAccess#getNames()
*/
public List