/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2010, 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.geojson.feature;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geojson.DelegatingHandler;
import org.geotools.geojson.IContentHandler;
import org.geotools.geojson.geom.GeometryHandler;
import org.json.simple.parser.ParseException;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
public class FeatureHandler extends DelegatingHandler<SimpleFeature> {
String id;
Geometry geometry;
List<Object> values;
List<String> properties;
CoordinateReferenceSystem crs;
SimpleFeatureBuilder builder;
AttributeIO attio;
SimpleFeature feature;
public FeatureHandler(SimpleFeatureBuilder builder, AttributeIO attio) {
this.builder = builder;
this.attio = attio;
}
@Override
public boolean startObject() throws ParseException, IOException {
if (properties == NULL_LIST) {
properties = new ArrayList();
}
else if (properties != null) {
//start of a new object in properties means a geometry
delegate = new GeometryHandler(new GeometryFactory());
}
return super.startObject();
}
public boolean startObjectEntry(String key) throws ParseException, IOException {
if ("id".equals(key)) {
id = "";
return true;
}
else if ("crs".equals(key)) {
delegate = new CRSHandler();
return true;
}
else if ("geometry".equals(key)) {
delegate = new GeometryHandler(new GeometryFactory());
return true;
}
else if ("properties".equals(key) && delegate == NULL) {
properties = NULL_LIST;
values = new ArrayList();
}
else if (properties != null && delegate == NULL) {
properties.add(key);
return true;
}
return super.startObjectEntry(key);
}
@Override
public boolean startArray() throws ParseException, IOException {
if (properties != null && delegate == NULL) {
//array inside of properties
delegate = new ArrayHandler();
}
return super.startArray();
}
@Override
public boolean endArray() throws ParseException, IOException {
if (delegate instanceof ArrayHandler) {
super.endArray();
values.add(((ArrayHandler) delegate).getValue());
delegate = NULL;
}
return super.endArray();
}
@Override
public boolean endObject() throws ParseException, IOException {
if (delegate instanceof IContentHandler) {
((IContentHandler) delegate).endObject();
if (delegate instanceof GeometryHandler) {
if (properties != null) {
//this is a regular property
values.add(((IContentHandler<Geometry>)delegate).getValue());
}
else {
//its the default geometry
geometry = ((IContentHandler<Geometry>)delegate).getValue();
}
delegate = NULL;
}
else if (delegate instanceof CRSHandler) {
crs = ((CRSHandler)delegate).getValue();
delegate = UNINITIALIZED;
}
return true;
}
else if (delegate == UNINITIALIZED) {
delegate = NULL;
return true;
}
else if (properties != null) {
if (builder == null) {
//no builder specified, build on the fly
builder = createBuilder();
}
for (int i = 0; i < properties.size(); i++) {
String att = properties.get(i);
Object val = values.get(i);
if (val instanceof String) {
val = attio.parse(att, (String)val);
}
builder.set(att, val );
}
properties = null;
values = null;
return true;
}
else {
feature = buildFeature();
id = null;
geometry = null;
properties = null;
values = null;
return true;
}
}
@Override
public boolean primitive(Object value) throws ParseException, IOException {
if ("".equals(id)) {
id = value.toString();
return true;
}
else if (values != null && delegate == NULL) {
//use the attribute parser
values.add(value);
return true;
}
return super.primitive(value);
}
@Override
public SimpleFeature getValue() {
return feature;
}
public void init() {
feature = null;
}
SimpleFeatureBuilder createBuilder() {
SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
typeBuilder.setName("feature");
typeBuilder.setNamespaceURI("http://geotools.org");
if (crs != null) {
typeBuilder.setCRS(crs);
}
for (int i = 0; i < properties.size(); i++) {
String prop = properties.get(i);
Object valu = values.get(i);
typeBuilder.add(prop, valu != null ? valu.getClass() : Object.class);
}
if (geometry != null) {
typeBuilder.add("geometry", geometry != null ? geometry.getClass() : Geometry.class);
typeBuilder.setDefaultGeometry("geometry");
}
return new SimpleFeatureBuilder(typeBuilder.buildFeatureType());
}
SimpleFeature buildFeature() {
SimpleFeatureType featureType = builder.getFeatureType();
if (geometry != null) {
builder.set(featureType.getGeometryDescriptor().getLocalName(), geometry);
}
return builder.buildFeature(id);
}
// "{" +
// " 'type': 'Feature'," +
// " 'geometry': {" +
// " 'type': 'Point'," +
// " 'coordinates': [" + val + "," + val + "]" +
// " }, " +
// "' properties': {" +
// " 'int': 1," +
// " 'double': " + (double)val + "," +
// " 'string': '" + toString(val) + "'" +
// " }," +
// " 'id':'widgets." + val + "'" +
// "}";
}