/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-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.property;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import org.geotools.data.AbstractFeatureLocking;
import org.geotools.data.DataStore;
import org.geotools.data.FeatureEvent;
import org.geotools.data.FeatureListener;
import org.geotools.data.Query;
import org.geotools.data.QueryCapabilities;
import org.geotools.data.Transaction;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
/**
* Implementation used for writeable property files.
* Supports limited caching of number of features and bounds.
*
* @source $URL: http://svn.osgeo.org/geotools/trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyFeatureStore.java $
*/
public class PropertyFeatureStore extends AbstractFeatureLocking {
String typeName;
SimpleFeatureType featureType;
PropertyDataStore store;
long cacheTimestamp = 0;
ReferencedEnvelope cacheBounds = null;
int cacheCount = -1;
FeatureListener watcher = new FeatureListener() {
public void changed(FeatureEvent featureEvent) {
if (cacheBounds != null) {
if (featureEvent.getType() == FeatureEvent.Type.ADDED) {
cacheBounds.expandToInclude(featureEvent.getBounds());
} else {
cacheBounds = null;
}
}
cacheCount = -1;
}
};
PropertyFeatureStore( PropertyDataStore propertyDataStore, String typeName ) throws IOException{
this.store = propertyDataStore;
this.typeName = typeName;
this.featureType = store.getSchema( typeName );
store.listenerManager.addFeatureListener( this, watcher);
this.queryCapabilities = new QueryCapabilities() {
public boolean isUseProvidedFIDSupported() {
return true;
}
};
}
// constructor end
// implementation start
public PropertyDataStore getDataStore() {
return store;
}
public void addFeatureListener(FeatureListener listener) {
store.listenerManager.addFeatureListener(this, listener);
}
public void removeFeatureListener(
FeatureListener listener) {
store.listenerManager.removeFeatureListener(this, listener);
}
public SimpleFeatureType getSchema() {
return featureType;
}
// implementation end
// getCount start
public int getCount(Query query) throws IOException {
if( Filter.INCLUDE == query.getFilter() && getTransaction() == Transaction.AUTO_COMMIT ){
File file = new File( store.directory, typeName+".properties" );
if( cacheCount != -1 && file.lastModified() == cacheTimestamp){
return cacheCount;
}
cacheCount = PropertyDataStore.countFile(file);
cacheTimestamp = file.lastModified();
return cacheCount;
}
return -1;
// return super.getCount(query); // super class checks transaction state diff
}
// getCount end
// getBounds start
public ReferencedEnvelope getBounds() {
File file = new File( store.directory, typeName+".properties" );
if( cacheBounds != null && file.lastModified() == cacheTimestamp ){
// we have the cache
return cacheBounds;
}
try {
// calculate and store in cache
cacheBounds = getFeatures().getBounds();
cacheTimestamp = file.lastModified();
return cacheBounds;
} catch (IOException e) {
}
// bounds are unavailable!
return null;
}
// getBounds end
}