/* Copyright 2013 The jeo project. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.jeo.csv; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Map; import io.jeo.data.FileData; import io.jeo.geom.Bounds; import io.jeo.util.Key; import io.jeo.util.Util; import io.jeo.vector.Feature; import io.jeo.vector.FeatureAppendCursor; import io.jeo.vector.FeatureCursor; import io.jeo.vector.FeatureWriteCursor; import io.jeo.vector.ListFeature; import io.jeo.vector.Schema; import io.jeo.vector.SchemaBuilder; import io.jeo.vector.VectorDataset; import io.jeo.vector.VectorQuery; import io.jeo.vector.VectorQueryPlan; import org.osgeo.proj4j.CoordinateReferenceSystem; import com.csvreader.CsvReader; import com.vividsolutions.jts.geom.Geometry; public class CSVDataset implements VectorDataset, FileData { /** the csv file */ File file; /** csv stuff */ CSVOpts opts; /** the feature schema */ Schema schema; /** handler for specific csv flavor */ CSVHandler handler; public CSVDataset(File file) throws IOException { this(file, new CSVOpts()); } public CSVDataset(File file, CSVOpts opts) throws IOException { this.file = file; this.opts = opts; handler = opts.handler(); init(); } @Override public CSV driver() { return new CSV(); } @Override public Map<Key<?>, Object> driverOptions() { return opts.toMap(); } @Override public File file() { return file; } void init() throws IOException { SchemaBuilder sb = Schema.build(name()); sb.field("geometry", Geometry.class); if (opts.header()) { //read first row CsvReader r = reader(); r.readHeaders(); try { handler.header(r); for (String col : r.getHeaders()) { sb.field(col, Object.class); } } finally { r.close(); } } schema = sb.schema(); } @Override public String name() { return Util.base(file.getName()); } @Override public Schema schema() throws IOException { return schema; } @Override public CoordinateReferenceSystem crs() { // TODO: support a .prj file return null; } @Override public Bounds bounds() throws IOException { return read(new VectorQuery()).bounds(); } @Override public long count(VectorQuery q) throws IOException { return read(q).count(); } @Override public FeatureCursor read(VectorQuery q) throws IOException { CsvReader reader = reader(); if (opts.header()) { reader.readHeaders(); } return new VectorQueryPlan(q).apply(new CSVCursor(reader, this)); } @Override public FeatureWriteCursor update(VectorQuery q) throws IOException { throw new UnsupportedOperationException(); } @Override public FeatureAppendCursor append(VectorQuery q) throws IOException { throw new UnsupportedOperationException(); } public void close() { } CsvReader reader() throws IOException { return new CsvReader(Files.newBufferedReader(file.toPath(), Util.UTF_8), opts.delimiter()); } Feature feature(int i, CsvReader r) throws IOException { List<Object> values = new ArrayList<Object>(); values.add(handler.geom(r)); for (String val : r.getValues()) { Object parsed = null; try { parsed = Integer.parseInt(val); } catch(NumberFormatException e1) { try { parsed = Double.parseDouble(val); } catch(NumberFormatException e2) { parsed = val; } } values.add(parsed); } return new ListFeature(String.valueOf(i), schema, values); } }