GeoJSONParser.java [src/m/utils] Revision: default Date:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package m.utils;
import csip.api.server.ServiceException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
/**
*
* @author ktraff
*/
public class GeoJSONParser implements Parser {
enum ShapeType {Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, GeometryCollection};
protected final Logger LOG = Logger.getLogger(getClass().getSimpleName());
JSONArray layersJSON;
IGISDatabase db;
// Used to namespace all database tables during creation/upload.
String prefix;
public GeoJSONParser(JSONArray lyrs, IGISDatabase db, String prefix) {
this.layersJSON = lyrs;
this.db = db;
this.prefix = prefix;
}
/**
* Converts geoJSON layers into its database representation.
* @return
* @throws ServiceException
*/
@Override
public ArrayList<Layer> parse() throws ServiceException {
ArrayList<Layer> lyrs = new ArrayList<Layer>();
try {
for (int i = 0; i < layersJSON.length(); i++) {
lyrs.add(parseLayer(layersJSON.getJSONObject(i), i));
}
} catch (JSONException ex) {
throw new csip.api.server.ServiceException(ex);
}
return lyrs;
}
public Layer parseLayer(JSONObject layerJSON, int layerIdx) throws ServiceException {
Layer lyr;
try {
lyr = db.createLayer(prefix + "_" + db.getSessionID() + "_" + layerIdx, layerJSON);
String type = layerJSON.getString("type");
if (type.equalsIgnoreCase("FeatureCollection")) {
JSONArray fts = layerJSON.getJSONArray("features");
for (int i = 0; i < fts.length(); i++) {
lyr.addFeature(parseFeature(fts.getJSONObject(i), layerJSON, lyr));
}
}
else if (type.equalsIgnoreCase("Feature")) {
lyr.addFeature(parseFeature(layerJSON, layerJSON, lyr));
}
} catch (JSONException ex) {
throw new csip.api.server.ServiceException(ex);
}
return lyr;
}
public Feature parseFeature(JSONObject featureJSON, JSONObject layerJSON, Layer lyr) throws ServiceException {
try {
JSONObject crs = generateCRS(db.getDefaultCRS());
if (hasCRS(featureJSON)) {
crs = featureJSON.getJSONObject("crs");
} else if (hasCRS(layerJSON)) {
crs = layerJSON.getJSONObject("crs");
}
LOG.log(Level.INFO, "Chose CRS for layer " + lyr.toString() + ": " + crs.toString());
featureJSON.put("crs", crs);
return db.uploadFeature(featureJSON, lyr);
} catch (JSONException ex) {
throw new ServiceException(ex);
}
}
/**
* Generates a geoJSON coordinate reference system object.
* @param urn the OGC CRS URN string: http://geojson.org/geojson-spec.html#coordinate-reference-system-objects
* @return
*/
public static JSONObject generateCRS(String urn) throws JSONException {
JSONObject crs = new JSONObject();
JSONObject crsProps = new JSONObject();
crsProps.put("name", urn);
crs.put("type", "name");
crs.put("properties", crsProps);
return crs;
}
public static boolean hasCRS(JSONObject geoJSON) {
return geoJSON.has("crs");
}
public static ShapeType getShape(JSONObject layerJSON) throws JSONException {
ShapeType shapeType = null;
String type = layerJSON.getString("type");
if (type.equalsIgnoreCase("Feature")) {
shapeType = ShapeType.valueOf(layerJSON.getJSONObject("geometry").getString("type"));
}
else if (type.equalsIgnoreCase("FeatureCollection")) {
JSONArray fts = layerJSON.getJSONArray("features");
for (int i = 0; i < fts.length(); i++) {
String featureType = fts.getJSONObject(i).getJSONObject("geometry").getString("type");
if (shapeType == null) {
type = featureType;
}
if (!type.equalsIgnoreCase(featureType)) {
if (isMulti(featureType, type)) {
type = multi(type);
}
else {
return ShapeType.GeometryCollection;
}
}
}
shapeType = ShapeType.valueOf(type);
}
else { // Geometry of some kind.
shapeType = ShapeType.valueOf(type);
}
Logger.getLogger(GeoJSONParser.class.getName()).log(Level.INFO, "Shape type found: " + shapeType);
return shapeType;
}
public static boolean isMulti(String typeOne, String typeTwo) {
if (typeOne.toLowerCase().contains("multi") || typeTwo.toLowerCase().contains("multi")) {
String t1 = typeOne.toLowerCase().replace("multi", "");
String t2 = typeOne.toLowerCase().replace("multi", "");
return t1.equals(t2);
}
return false;
}
public static String multi(String shapeType) {
return "Multi" + shapeType;
}
public static String getSrid(JSONObject layerJSON) {
try {
// Note: according to the geoJSON specification, the "crs" attribute
// must always be in the top-level geojson object.
JSONObject crs = layerJSON.getJSONObject("crs");
return crs.getJSONObject("properties").getString("name");
} catch (JSONException ex) {
Logger.getLogger(GeoJSONParser.class.getName()).log(Level.WARNING, "Couldn't find projection");
return null;
}
}
public static int getSRIDInt(JSONObject json) throws JSONException {
String name = getSrid(json);
if (name == null) {
return 0;
}
return getSRIDInt(name);
}
public static int getSRIDInt(String name) throws JSONException {
String [] parts = name.split(":");
return Integer.parseInt(parts[1]);
}
}