/* 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.geojson;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.Collections;
import java.util.Map;
import io.jeo.data.Driver;
import io.jeo.data.FileData;
import io.jeo.geojson.parser.CRSFinder;
import io.jeo.geom.Bounds;
import io.jeo.json.parser.ParseException;
import io.jeo.util.Util;
import io.jeo.vector.FeatureAppendCursor;
import io.jeo.vector.FeatureCursor;
import io.jeo.vector.FeatureWriteCursor;
import io.jeo.vector.Features;
import io.jeo.vector.VectorQueryPlan;
import io.jeo.geojson.parser.RootHandler;
import io.jeo.json.parser.JSONParser;
import io.jeo.proj.Proj;
import io.jeo.util.Key;
import io.jeo.vector.Schema;
import io.jeo.vector.VectorDataset;
import io.jeo.vector.VectorQuery;
import org.osgeo.proj4j.CoordinateReferenceSystem;
public class GeoJSONDataset implements VectorDataset, FileData {
File file;
public GeoJSONDataset(File file) {
this.file = file;
}
@Override
public Driver<?> driver() {
return new GeoJSON();
}
@Override
public Map<Key<?>, Object> driverOptions() {
return (Map) Collections.singletonMap(GeoJSON.FILE, file);
}
@Override
public File file() {
return file;
}
@Override
public String name() {
return Util.base(file.getName());
}
@Override
public Schema schema() throws IOException {
return Features.schema(this).orElse(null);
}
@Override
public CoordinateReferenceSystem crs() throws IOException {
//TODO: probably should cache this
CoordinateReferenceSystem crs = null;
//first scan for a crs property
JSONParser p = new JSONParser();
Reader r = reader();
try {
CRSFinder f = new CRSFinder();
try {
p.parse(r, new RootHandler(f), true);
crs = f.getCRS();
} catch (ParseException e) {
throw new IOException(e);
}
}
finally {
r.close();
}
// GeoJSON actually specified that the data should be 4326 so fall back on that
return crs != null ? crs : Proj.EPSG_4326;
}
@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 {
return new VectorQueryPlan(q).apply(new GeoJSONCursor(reader()));
}
@Override
public FeatureWriteCursor update(VectorQuery q) throws IOException {
throw new IOException("Update cursor not supported");
}
@Override
public FeatureAppendCursor append(VectorQuery q) throws IOException {
if (!Util.isEmpty(file)) {
throw new IOException("Can't append to non empty dataset");
}
return new GeoJSONAppendCursor(writer());
}
@Override
public void close() {
}
Reader reader() throws IOException {
return Files.newBufferedReader(file.toPath(), Charset.forName("UTF8"));
}
Writer writer() throws IOException {
return Files.newBufferedWriter(file.toPath(), Charset.forName("UTF8"));
}
}