/* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2010-2014, Open Source Geospatial Foundation (OSGeo)
*
* This file is hereby placed into the Public Domain. This means anyone is
* free to do whatever they wish with this file. Use it well and enjoy!
*/
package org.geotools.tutorial.csv2;
import java.io.IOException;
import java.util.NoSuchElementException;
import org.geotools.data.FeatureReader;
import org.geotools.data.Query;
import org.geotools.data.store.ContentState;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.opengis.feature.IllegalAttributeException;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import com.csvreader.CsvReader;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
/**
*
*
* @source $URL$
*/
public class CSVFeatureReader implements FeatureReader<SimpleFeatureType, SimpleFeature> {
/** State used when reading file */
protected ContentState state;
/**
* Current row number - used in the generation of FeatureId.
* TODO: Subclass ContentState to track row
*/
private int row;
protected CsvReader reader;
/** Utility class used to build features */
protected SimpleFeatureBuilder builder;
/** Factory class for goemetry creation */
private GeometryFactory geometryFactory;
public CSVFeatureReader(ContentState contentState, Query query) throws IOException {
this.state = contentState;
CSVDataStore csv = (CSVDataStore) contentState.getEntry().getDataStore();
reader = csv.read(); // this may throw an IOException if it could not connect
boolean header = reader.readHeaders();
if (! header ){
throw new IOException("Unable to read csv header");
}
builder = new SimpleFeatureBuilder( state.getFeatureType() );
geometryFactory = JTSFactoryFinder.getGeometryFactory(null);
row = 0;
}
/** Access FeatureType (documenting avaiable attributes) */
public SimpleFeatureType getFeatureType() {
return (SimpleFeatureType) state.getFeatureType();
}
// class definition end
// read start
/** The next feature */
private SimpleFeature next;
/**
* Access the next feature (if available).
*
* @return SimpleFeature read from property file
* @throws IOException If problem encountered reading file
* @throws IllegalAttributeException for invalid data
* @throws NoSuchElementException If hasNext() indicates no more features are available
*/
public SimpleFeature next() throws IOException, IllegalArgumentException,
NoSuchElementException {
SimpleFeature feature;
if( next != null ){
feature = next;
next = null;
}
else {
feature = readFeature();
}
return feature;
}
/**
* Check if additional content is available.
*
* @return <code>true</code> if additional content is available
* @throws IOException
*/
public boolean hasNext() throws IOException {
if( next != null ){
return true;
}
else if (reader == null ){
return false;
}
else {
next = readFeature(); // read next feature so we can check
return next != null;
}
}
// read end
// parse start
/** Read a line of content from CSVReader and parse into values */
SimpleFeature readFeature() throws IOException {
if( reader == null ){
throw new IOException("FeatureReader is closed; no additional features can be read");
}
boolean read = reader.readRecord(); // read the "next" record
if( read == false ){
close(); // automatic close to be nice
return null; // no additional features are available
}
Coordinate coordinate = new Coordinate();
for( String column : reader.getHeaders() ){
String value = reader.get(column);
if( "lat".equalsIgnoreCase(column)){
coordinate.y = Double.valueOf( value.trim() );
}
else if( "lon".equalsIgnoreCase(column)){
coordinate.x = Double.valueOf( value.trim() );
}
else {
builder.set(column, value );
}
}
builder.set("Location", geometryFactory.createPoint( coordinate ) );
return this.buildFeature();
}
/** Build feature using the current row number to generate FeatureId */
protected SimpleFeature buildFeature() {
row += 1;
return builder.buildFeature( state.getEntry().getTypeName()+"."+row );
}
// parse end
// close start
/**
* Close the FeatureReader when not in use.
*
* @throws IOException
*/
public void close() throws IOException {
if( reader != null ){
reader.close();
reader = null;
}
builder = null;
geometryFactory = null;
next = null;
}
// close start
}