/*
* 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;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.lang.reflect.Proxy;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import org.geotools.util.Converters;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.vividsolutions.jts.geom.Coordinate;
public class GeoJSONUtil {
/**
* Date format (ISO 8601)
*/
public static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
static {
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
}
//
// io
//
/**
* Converts an object to a {@link Reader} instance.
* <p>
* The <tt>input</tt> parameter may be one of the following types:
* <ul>
* <li>{@link Reader}
* <li>{@link InputStream}
* <li>{@link File}
* <li>{@link String} *
* </ul>
* * A string parameter is considered a file path.
* </p>
*
* @param input The input object.
*
* @return A reader.
* @throws IOException
*/
public static Reader toReader(Object input) throws IOException {
if (input instanceof BufferedReader) {
return (BufferedReader) input;
}
if (input instanceof Reader) {
return new BufferedReader((Reader)input);
}
if (input instanceof InputStream) {
return new BufferedReader(new InputStreamReader((InputStream)input));
}
if (input instanceof File) {
return new BufferedReader(new FileReader((File)input));
}
if (input instanceof String) {
return new StringReader((String)input);
}
throw new IllegalArgumentException("Unable to turn " + input + " into a reader");
}
/**
* Converts an object to {@link Writer} instance.
* <p>
* The <tt>output</tt> parameter may be one of the following types:
* <ul>
* <li>{@link Writer}
* <li>{@link OutputStream}
* <li>{@link File}
* <li>{@link String} *
* </ul>
* * A string parameter is considered a file path.
* </p>
* @param output The output object.
*
* @return A writer.
* @throws IOException
*/
public static Writer toWriter(Object output) throws IOException {
if (output instanceof BufferedWriter) {
return (BufferedWriter) output;
}
if (output instanceof Writer) {
return new BufferedWriter((Writer)output);
}
if (output instanceof OutputStream) {
return new BufferedWriter(new OutputStreamWriter((OutputStream)output));
}
if (output instanceof File) {
return new BufferedWriter(new FileWriter((File)output));
}
if (output instanceof String) {
return new BufferedWriter(new FileWriter((String)output));
}
throw new IllegalArgumentException("Unable to turn " + output + " into a writer");
}
//
// encoding
//
public static StringBuilder string(String string, StringBuilder sb) {
sb.append("\"").append(JSONObject.escape(string)).append("\"");
return sb;
}
public static StringBuilder entry(String key, Object value, StringBuilder sb) {
string(key, sb).append(":");
if (value instanceof Number || value instanceof Boolean || value instanceof Date) {
literal(value, sb);
} else {
String str = Converters.convert(value, String.class);
if(str == null) {
str = value.toString();
}
string(str, sb);
}
return sb;
}
static StringBuilder literal(Object value, StringBuilder sb) {
//handle date as special case special case
if (value instanceof Date) {
return string(DATE_FORMAT.format((Date)value), sb);
}
return sb.append(value);
}
public static StringBuilder array(String key, Object value, StringBuilder sb) {
return string(key, sb).append(":").append(value);
}
public static StringBuilder nul(StringBuilder sb) {
sb.append("null");
return sb;
}
//
// parsing
//
public static <T> T trace(T handler, Class<T> clazz) {
return (T) Proxy.newProxyInstance(handler.getClass().getClassLoader(), new Class[]{clazz},
new TracingHandler(handler));
}
public static boolean addOrdinate(List ordinates, Object value) {
if (ordinates != null) {
ordinates.add(value);
}
return true;
}
public static Coordinate createCoordinate(List ordinates) {
Coordinate c = new Coordinate();
if (ordinates.size() > 0) {
c.x = ((Number)ordinates.get(0)).doubleValue();
}
if (ordinates.size() > 1) {
c.y = ((Number)ordinates.get(1)).doubleValue();
}
if (ordinates.size() > 2) {
c.z = ((Number)ordinates.get(2)).doubleValue();
}
return c;
}
public static Coordinate[] createCoordinates(List coordinates) {
return (Coordinate[]) coordinates.toArray(new Coordinate[coordinates.size()]);
}
public static <T> T parse(IContentHandler<T> handler, Object input, boolean trace) throws IOException {
Reader reader = toReader(input);
if (trace) {
handler = (IContentHandler<T>) Proxy.newProxyInstance( handler.getClass().getClassLoader(),
new Class[]{ IContentHandler.class}, new TracingHandler(handler));
}
JSONParser parser = new JSONParser();
try {
parser.parse(reader, handler);
return handler.getValue();
}
catch (ParseException e) {
throw (IOException) new IOException().initCause(e);
}
}
public static void encode(String json, Object output) throws IOException {
Writer w = toWriter(output);
w.write(json);
w.flush();
}
public static void encode(Map<String,Object> obj, Object output) throws IOException {
Writer w = toWriter(output);
JSONObject.writeJSONString(obj, w);
w.flush();
}
}