GISObjectFactory.java [src/gisobjects] Revision: default Date:
/*
* $Id$
*
* This file is part of the Cloud Services Integration Platform (CSIP),
* a Model-as-a-Service framework, API, and application suite.
*
* 2012-2017, OMSLab, Colorado State University.
*
* OMSLab licenses this file to you under the MIT license.
* See the LICENSE file in the project root for more information.
*/
package gisobjects;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKBReader;
import com.vividsolutions.jts.io.WKTReader;
import static gisobjects.GISObject.DEFAULT_ASSUMED_SRID;
import static gisobjects.GISObject.INPUT_PRECISION;
import gisobjects.db.GISEngine;
import gisobjects.vector.GIS_FeatureCollection;
import gisobjects.vector.GIS_Geometry;
import gisobjects.vector.GIS_GeometryCollection;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.geotools.feature.FeatureCollection;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geojson.geom.GeometryJSON;
import org.opengis.feature.Feature;
import org.opengis.feature.simple.SimpleFeature;
/**
*
* @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
*/
public class GISObjectFactory {
public static double defaultPrecision = INPUT_PRECISION;
private static boolean fixBadGeometries = true;
// private static GeometryFactory geoFactory = new GeometryFactory(new PrecisionModel(Math.pow(10,
// ((defaultPrecision != INPUT_PRECISION) ? defaultPrecision : INPUT_PRECISION))), DEFAULT_ASSUMED_SRID);
private static GISObject createGISObject(byte[] WKB, int SRID) throws GISObjectException {
GISObject ret_val;
GeometryFactory geoFactory = new GeometryFactory(new PrecisionModel(Math.pow(10, ((defaultPrecision != INPUT_PRECISION) ? defaultPrecision : INPUT_PRECISION))), SRID);
WKBReader wkbReader = new WKBReader(geoFactory);
Geometry geometry;
try {
geometry = wkbReader.read(WKB);
} catch (ParseException ex) {
throw new GISObjectException("Error parsing WKB into a geometry object: ", ex);
}
ret_val = createGISObject(geometry);
return ret_val;
}
private static GISObject createGISObject(String WKT, int SRID) throws GISObjectException {
GISObject ret_val;
GeometryFactory geoFactory = new GeometryFactory(new PrecisionModel(Math.pow(10, ((defaultPrecision != INPUT_PRECISION) ? defaultPrecision : INPUT_PRECISION))), SRID);
WKTReader wktReader = new WKTReader(geoFactory);
Geometry geometry;
try {
geometry = wktReader.read(WKT);
} catch (ParseException ex) {
throw new GISObjectException("Error parsing WKT into a geometry object: ", ex);
}
ret_val = createGISObject(geometry);
return ret_val;
}
private static GISObject createGISObject(Geometry geometry) throws GISObjectException {
GISObject ret_val = null;
if (geometry.isValid()) {
ret_val = getGISGeometryByType(geometry, null);
} else {
if (fixBadGeometries && (geometry.getGeometryType().equals("Polygon") || geometry.getGeometryType().equals("MultiPolygon") || geometry.getGeometryType().equals("GeometryCollection"))) {
Geometry newGeometry = geometry.buffer(0);
if (newGeometry.isValid()) {
ret_val = getGISGeometryByType(newGeometry, null);
ret_val.hasChanged(true);
} else {
throw new GISObjectException("Invalid geometry passed to createGISObject.");
}
} else {
throw new GISObjectException("Invalid geometry passed to createGISObject.");
}
}
return ret_val;
}
private static GISObject createGISObject(JSONObject shape) throws JSONException, IOException, GISObjectException {
return createGISObject(shape, null, DEFAULT_ASSUMED_SRID);
}
protected static GISObject getGISGeometryByType(Geometry tGeometry, GISEngine engine) throws GISObjectException {
GISObject ret_val = null;
if (null != tGeometry) {
switch (tGeometry.getGeometryType()) {
case "GeometryCollection":
ret_val = new GIS_GeometryCollection(tGeometry, engine);
break;
// Thus far, it appears that we can join all of these into one single type...may need to break them out later.
case "Point":
case "MultiPoint":
case "LineString":
case "MultiLineString":
case "Polygon":
case "MultiPolygon":
ret_val = new GIS_Geometry(tGeometry, engine);
break;
default:
throw new GISObjectException("Invalid geometry type passed to getGISObjectByType.");
}
} else {
throw new GISObjectException("NULL geometry value passed to getGISObjectByType. Cannot create a GISObject.");
}
return ret_val;
}
public static GISObject createGISObjectWKB(String WKB, GISEngine engine) throws GISObjectException {
return createGISObjectWKB(WKB, engine, DEFAULT_ASSUMED_SRID);
}
public static GISObject createGISObjectWKB(String WKB, GISEngine engine, int SRID) throws GISObjectException {
return createGISObject(WKBReader.hexToBytes(WKB), engine, SRID);
}
public static GISObject createGISObject(byte[] WKB, GISEngine engine) throws GISObjectException {
return createGISObject(WKB, engine, DEFAULT_ASSUMED_SRID);
}
public static GISObject createGISObject(byte[] WKB, GISEngine engine, int SRID) throws GISObjectException {
GISObject ret_val = createGISObject(WKB, SRID);
if (null != ret_val) {
ret_val.setGISEngine(engine);
}
return ret_val;
}
public static GISObject createGISObject(String WKT, GISEngine engine) throws GISObjectException {
return createGISObject(WKT, engine, DEFAULT_ASSUMED_SRID);
}
public static GISObject createGISObject(String WKT, GISEngine engine, int SRID) throws GISObjectException {
GISObject ret_val = createGISObject(WKT, SRID);
if (null != ret_val) {
ret_val.setGISEngine(engine);
}
return ret_val;
}
public static GISObject createGISObject(Geometry geometry, GISEngine engine) throws GISObjectException {
GISObject ret_val;
ret_val = createGISObject(geometry);
ret_val.setGISEngine(engine);
return ret_val;
}
public static GISObject createGISObject(JSONObject shape, GISEngine tEngine) throws JSONException, IOException, GISObjectException {
GISObject ret_val = createGISObject(shape, tEngine, DEFAULT_ASSUMED_SRID);
return ret_val;
}
public static GISObject createGISObject(JSONObject shape, GISEngine tEngine, int defaultSRID) throws JSONException, IOException, GISObjectException {
GISObject ret_val = null; //Default value if parsing falls-through below.
if ((null != shape) && (shape.has("type"))) {
String geoJSONType = shape.optString("type");
if (geoJSONType.length() > 0) {
switch (geoJSONType) {
case "FeatureCollection": {
FeatureJSON featureJSON = new FeatureJSON();
FeatureCollection inputFeatures = featureJSON.readFeatureCollection(shape.toString());
ret_val = new GIS_FeatureCollection(inputFeatures, tEngine, fixBadGeometries, defaultSRID);
}
break;
case "Feature": {
// Create a Feature GISObject here...(same as basic Geometry type, but with "properties")
FeatureJSON featureJSON = new FeatureJSON();
Feature tFeature = featureJSON.readFeature(shape.toString());
//GeometryFactory geoFactory = new GeometryFactory(new PrecisionModel(Math.pow(10, INPUT_PRECISION)), defaultSRID);
GeometryFactory geoFactory = new GeometryFactory(new PrecisionModel(Math.pow(10,
((defaultPrecision != INPUT_PRECISION) ? defaultPrecision : INPUT_PRECISION))), defaultSRID);
Geometry tGeometry = geoFactory.createGeometry((Geometry) ((SimpleFeature) tFeature).getAttribute("geometry"));
if (tGeometry.isValid()) {
ret_val = getGISGeometryByType(tGeometry, tEngine);
} else if (fixBadGeometries) {
ret_val = createGISObject(tEngine.makeValid(tGeometry.toString()), tEngine);
if ((null == ret_val) || !ret_val.isValid()) {
throw new GISObjectException("Invalid geometry specified for this feature.");
} else {
ret_val.hasChanged(true);
}
} else {
throw new GISObjectException("Invalid geometry specified for this feature.");
}
//TODO: Iterate over the properties here and place into the GISObject returned; (Maybe...) Will need a GIS_Feature class at that time.
// For now, we do not make use of the "Properties" to pass information in our JSON input packages for csip,
// however, in the future, this may become necessary. Currently, each property that we wish to know for each "Feature"
// is specified separately within the JSON input array at the same level as each "Feature".
}
break;
case "GeometryCollection":
case "Polygon":
case "MultiPolygon":
case "Point":
case "MultiPoint":
case "LineString":
case "MultiLineString": {
//GeometryFactory geoFactory = new GeometryFactory(new PrecisionModel(Math.pow(10, INPUT_PRECISION)), defaultSRID);
GeometryJSON geoJSON = new GeometryJSON();
Geometry newGeometry = geoJSON.read(new ByteArrayInputStream(shape.toString().getBytes()));
Geometry tGeometry;
GeometryFactory geoFactory = new GeometryFactory(new PrecisionModel(Math.pow(10,
((defaultPrecision != INPUT_PRECISION) ? defaultPrecision : INPUT_PRECISION))), defaultSRID);
tGeometry = geoFactory.createGeometry(newGeometry);
if (tGeometry.isValid()) {
ret_val = getGISGeometryByType(tGeometry, tEngine);
} else if (fixBadGeometries) {
ret_val = createGISObject(tEngine.makeValid(tGeometry.toString()), tEngine);
if ((null == ret_val) || !ret_val.isValid()) {
ret_val = createGISObject(ret_val.getGeometry().convexHull());
if (!ret_val.isValid()) {
throw new GISObjectException("Invalid geometry specified for this feature.");
} else {
ret_val.hasChanged(true);
}
}
} else {
throw new GISObjectException("Invalid geometry specified for this feature.");
}
}
break;
default:
throw new GISObjectException("Invalid GeoJSON type value specified. Cannot parse into a GISObject.");
}
}
}
if (null == ret_val) {
throw new GISObjectException("Invalid JSONObject passed to createGISObject. Cannot create a GISObject.");
}
ret_val.setGISEngine(tEngine);
return ret_val;
}
//public void setGISObjectEngine(GISEngine engine) {
// engine = engine;
//}
public static void setFixBadGeometries(boolean fixBadGeometries) {
GISObjectFactory.fixBadGeometries = fixBadGeometries;
}
}