package org.geotools.data.csv;
import java.io.IOException;
import org.geotools.data.FeatureReader;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Query;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.store.ContentEntry;
import org.geotools.data.store.ContentFeatureCollection;
import org.geotools.data.store.ContentFeatureStore;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import com.csvreader.CsvReader;
import com.vividsolutions.jts.geom.Point;
@SuppressWarnings("unchecked")
public class CSVFeatureSource extends ContentFeatureStore {
public CSVFeatureSource(ContentEntry entry, Query query) {
super(entry,query);
}
/**
* Access parent CSVDataStore
*/
public CSVDataStore getDataStore(){
return (CSVDataStore) super.getDataStore();
}
/**
* Implementation that generates the total bounds
* (many file formats record this information in the header)
*/
protected ReferencedEnvelope getBoundsInternal(Query query) throws IOException {
ReferencedEnvelope bounds = new ReferencedEnvelope( getSchema().getCoordinateReferenceSystem() );
FeatureReader<SimpleFeatureType, SimpleFeature> featureReader = getReaderInternal(query);
try {
while( featureReader.hasNext() ){
SimpleFeature feature = featureReader.next();
bounds.include( feature.getBounds() );
}
}
finally {
featureReader.close();
}
return bounds;
}
protected int getCountInternal(Query query) throws IOException {
ContentFeatureCollection cfc = this.getFeatures(query);
int count = 0;
SimpleFeatureIterator iter = cfc.features();
while(iter.hasNext()) {
iter.next();
count++;
}
iter.close();
return count;
//
//
// CsvReader reader = getDataStore().read();
// try {
// boolean connect = reader.readHeaders();
// if( connect == false ){
// throw new IOException("Unable to connect");
// }
// int count = 0;
// while( reader.readRecord() ){
// count += 1;
// }
// return count;
// }
// finally {
// reader.close();
// }
}
protected FeatureReader<SimpleFeatureType, SimpleFeature> getReaderInternal(Query query)
throws IOException {
// Note we ignore 'query' because querying/filtering is handled in superclasses.
return new CSVFeatureReader( getState() );
}
protected SimpleFeatureType buildFeatureType() throws IOException {
SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
builder.setName( entry.getName() );
// read headers
CsvReader reader = getDataStore().read();
try {
boolean success = reader.readHeaders();
if( success == false ){
throw new IOException("Header of CSV file not available");
}
// we are going to hard code a point location
// columns like lat and lon will be gathered into a
// Point called Location
builder.setCRS(DefaultGeographicCRS.WGS84); // <- Coordinate reference system
builder.add("Location", Point.class );
for( String column : reader.getHeaders() ){
if( "lat".equalsIgnoreCase(column)){
continue; // skip as it is part of Location
}
if( "lon".equalsIgnoreCase(column)){
continue; // skip as it is part of Location
}
builder.add(column, String.class);
}
// build the type (it is immutable and cannot be modified)
final SimpleFeatureType SCHEMA = builder.buildFeatureType();
return SCHEMA;
}
finally {
reader.close();
}
}
@Override
protected FeatureWriter<SimpleFeatureType, SimpleFeature> getWriterInternal(Query query, int flags) throws IOException {
// TODO Perhaps: make separate writers for update and append.
return new CSVFeatureWriter(getState(), query, (flags | WRITER_ADD) == WRITER_ADD);
}
}