/*
* 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.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.LineNumberReader;
import java.net.URI;
import java.net.URISyntaxException;
import org.geotools.data.AbstractDataStore;
import org.geotools.data.DataSourceException;
import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultServiceInfo;
import org.geotools.data.FeatureReader;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Query;
import org.geotools.data.ServiceInfo;
import org.geotools.data.Transaction;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.FeatureTypes;
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.filter.Filter;
/**
* Sample DataStore implementation, please see formal tutorial included with
* users docs.
*
* @author Jody Garnett, Refractions Research Inc.
*
* @source $URL$
*/
public class PropertyDataStore extends AbstractDataStore {
protected File directory;
protected String namespaceURI;
public PropertyDataStore(File dir) {
this(dir, null);
}
// constructor start
public PropertyDataStore(File dir, String namespaceURI) {
super(true); // true indicates we implement getFeatureWriter
if (!dir.isDirectory()) {
throw new IllegalArgumentException(dir + " is not a directory");
}
if (namespaceURI == null) {
namespaceURI = dir.getName();
}
directory = dir;
this.namespaceURI = namespaceURI;
}
// constructor end
// createSchema start
public void createSchema(SimpleFeatureType featureType) throws IOException {
String typeName = featureType.getTypeName();
File file = new File(directory, typeName + ".properties");
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
writer.write("_=");
writer.write(DataUtilities.spec(featureType));
writer.flush();
writer.close();
}
// createSchema end
// info start
public ServiceInfo getInfo() {
DefaultServiceInfo info = new DefaultServiceInfo();
info.setDescription("Features from Directory " + directory);
info.setSchema(FeatureTypes.DEFAULT_NAMESPACE);
info.setSource(directory.toURI());
try {
info.setPublisher(new URI(System.getProperty("user.name")));
} catch (URISyntaxException e) {
}
return info;
}
// info end
public void setNamespaceURI(String namespaceURI) {
this.namespaceURI = namespaceURI;
}
public String[] getTypeNames() {
String list[] = directory.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".properties");
}
});
for (int i = 0; i < list.length; i++) {
list[i] = list[i].substring(0, list[i].lastIndexOf('.'));
}
return list;
}
// START SNIPPET: getSchema
public SimpleFeatureType getSchema(String typeName) throws IOException {
// look for type name
String typeSpec = property(typeName, "_");
try {
return DataUtilities.createType(namespaceURI, typeName, typeSpec);
} catch (SchemaException e) {
e.printStackTrace();
throw new DataSourceException(typeName + " schema not available", e);
}
}
// END SNIPPET: getSchema
private String property(String typeName, String key) throws IOException {
File file = new File(directory, typeName + ".properties");
BufferedReader reader = new BufferedReader(new FileReader(file));
try {
for (String line = reader.readLine(); line != null; line = reader
.readLine()) {
if (line.startsWith(key + "=")) {
return line.substring(key.length() + 1);
}
}
} finally {
reader.close();
}
return null;
}
protected FeatureReader<SimpleFeatureType, SimpleFeature> getFeatureReader(
String typeName) throws IOException {
return new PropertyFeatureReader(directory, typeName);
}
// getFeatureWriter start
protected FeatureWriter<SimpleFeatureType, SimpleFeature> createFeatureWriter(String typeName,
Transaction transaction) throws IOException {
return new PropertyFeatureWriter(this, typeName);
}
// getFeatureWriter end
// protected FeatureWriter<SimpleFeatureType, SimpleFeature> getFeatureWriter(
// String typeName) throws IOException {
//return new PropertyFeatureWriter(this, typeName);
//}
// getCount start
int cacheCount;
long cacheTimestamp;
protected int getCount(Query query) throws IOException {
if (query.getFilter() == Filter.INCLUDE) {
String typeName = query.getTypeName();
File file = new File(directory, typeName + ".properties");
if (cacheCount != -1 && file.lastModified() == cacheTimestamp) {
return cacheCount;
}
cacheCount = PropertyDataStore.countFile(file);
cacheTimestamp = file.lastModified();
return cacheCount;
}
else {
return -1; // too expensive count the features
}
}
/** Used to carefully count the lines in the provided properties file */
static int countFile(File file) {
LineNumberReader reader = null;
try {
int skip=1; // header
reader = new LineNumberReader(new FileReader(file));
String line;
while ((line = reader.readLine()) != null){
if( line.startsWith("#")||line.startsWith("!")){
skip++; // comment
}
if( line.endsWith("\\") ){
skip++; // multiline
}
}
return reader.getLineNumber() - skip;
} catch (IOException e) {
return -1; // could not quickly determine length
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// we tried
}
}
}
}
// getCount end
// getBounds start
protected ReferencedEnvelope getBounds(Query query) throws IOException {
return null; // to expensive - calculate by visiting all the features
}
// getBounds end
// getFeatureSource start
public SimpleFeatureSource getFeatureSource(final String typeName)
throws IOException {
File file = new File( this.directory, typeName+".properties");
if( !file.exists()){
throw new FileNotFoundException( file.getAbsolutePath() );
}
if( file.canWrite() ){
return new PropertyFeatureStore(this, typeName);
//return new PropertyFeatureLocking(this, typeName);
}
else {
return new PropertyFeatureSource(this, typeName);
}
//return super.getFeatureSource(typeName);
}
// getFeatureSource stop
}