/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2011, 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.data.couchdb.client; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Scanner; import java.util.regex.Pattern; import org.geotools.feature.NameImpl; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.geojson.GeoJSONUtil; import org.geotools.geojson.geom.GeometryJSON; import org.geotools.geometry.jts.Geometries; import org.json.simple.JSONObject; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.feature.type.Name; import org.opengis.geometry.BoundingBox; import org.opengis.referencing.crs.CoordinateReferenceSystem; /** * Everyone loves some utilities. * @author Ian Schneider (OpenGeo) */ public final class CouchDBUtils { private CouchDBUtils() { } /** * @todo this was spiked from GeoJSONUtil to allow adding the 'featureClass' property. * I suppose another way to do this would be to wrap the geojson in another object * and rewrite the spatial views, etc. * @todo GeoJSONUtil could be made more efficient and flexible by using Appendable */ public static String writeJSON(SimpleFeature feature, String featureClass, GeometryJSON gjson) { SimpleFeatureType featureType = feature.getFeatureType(); StringBuilder sb = new StringBuilder(); sb.append("{"); //type GeoJSONUtil.entry("type", "Feature", sb); sb.append(','); GeoJSONUtil.entry("featureClass", featureClass, sb); sb.append(','); //crs @todo /* if (encodeFeatureCRS) { CoordinateReferenceSystem crs = feature.getFeatureType().getCoordinateReferenceSystem(); if (crs != null) { try { string("crs", sb).append(":"); sb.append(FeatureJSON.this.toString(crs)).append(","); } catch (IOException e) { throw new RuntimeException(e); } } } */ //bounding box @todo /* if (encodeFeatureBounds) { BoundingBox bbox = feature.getBounds(); string("bbox", sb).append(":"); sb.append(gjson.toString(bbox)).append(","); } */ //geometry if (feature.getDefaultGeometry() != null) { GeoJSONUtil.string("geometry", sb).append(":").append(gjson.toString((Geometry) feature.getDefaultGeometry())); sb.append(","); } //properties int gindex = featureType.getGeometryDescriptor() != null ? featureType.indexOf(featureType.getGeometryDescriptor().getLocalName()) : -1; GeoJSONUtil.string("properties", sb).append(":").append("{"); boolean attributesWritten = false; for (int i = 0; i < featureType.getAttributeCount(); i++) { AttributeDescriptor ad = featureType.getDescriptor(i); // skip the default geometry, it's already encoded if (i == gindex) { continue; } Object value = feature.getAttribute(i); if (value == null) { //skip continue; } attributesWritten = true; // handle special types separately, everything else as a string or literal if (value instanceof Envelope) { GeoJSONUtil.array(ad.getLocalName(), gjson.toString((Envelope) value), sb); } else if (value instanceof BoundingBox) { GeoJSONUtil.array(ad.getLocalName(), gjson.toString((BoundingBox) value), sb); } else if (value instanceof Geometry) { GeoJSONUtil.string(ad.getLocalName(), sb).append(":").append(gjson.toString((Geometry) value)); } else { GeoJSONUtil.entry(ad.getLocalName(), value, sb); } sb.append(","); } if (attributesWritten) { sb.setLength(sb.length() - 1); } sb.append("},"); //id GeoJSONUtil.entry("id", feature.getID(), sb); sb.append("}"); return sb.toString(); } public static SimpleFeatureType createFeatureType(JSONObject obj, String name) throws IOException { return createFeatureType(obj,new NameImpl(name)); } public static SimpleFeatureType createFeatureType(JSONObject obj, Name name) throws IOException { JSONObject props = (JSONObject) obj.get("properties"); JSONObject geom = (JSONObject) obj.get("geometry"); SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName(name); for (Object k : props.keySet()) { builder.add(k.toString(), String.class); } String geomType = geom.get("type").toString(); Class clazz = Geometries.getForName(geomType).getBinding(); if (clazz == null) { throw new IOException("Unable to parse geometry type from " + geomType); } builder.add("geometry", clazz, (CoordinateReferenceSystem) null); // @todo find type from name? return builder.buildFeatureType(); } public static String stripComments(String json) { Pattern pat = Pattern.compile("/\\*(?:.)*?\\*/", Pattern.MULTILINE | Pattern.DOTALL); return pat.matcher(json).replaceAll(""); } public static String read(File f) throws FileNotFoundException { String text = null; Scanner s = new Scanner(f); try { text = s.useDelimiter("\\Z").next(); } finally { s.close(); } if (f.getName().endsWith(".json")) { // strip comments text = stripComments(text); } return text; } }