V1_21.java [src/java/d/soils] Revision: 1e3f2b36363f0eeca9f70d1b10adc5e6aaf69e99 Date: Tue Nov 06 16:10:17 MST 2018
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package d.soils;
import c.GIS_DB;
import c.SqlGIS;
import com.vividsolutions.jts.geom.Geometry;
import java.util.Collection;
import java.util.logging.Level;
import csip.ServiceException;
import java.io.IOException;
import javax.ws.rs.*;
import org.apache.commons.io.IOUtils;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import csip.ModelDataService;
import csip.annotations.*;
import csip.annotations.Resource;
import static csip.annotations.ResourceType.JDBC;
import static csip.annotations.State.RELEASED;
import csip.utils.JSONUtils;
import java.sql.SQLException;
import java.util.Map;
import org.codehaus.jettison.json.JSONException;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geojson.geom.GeometryJSON;
import org.opengis.feature.Feature;
import org.opengis.feature.simple.SimpleFeature;
import static d.soils.V1_21.DB;
/**
* REST Web Service. Front end callable.
*
* @author wlloyd, od
*/
@Name("Soils")
@Description("IET soils")
@VersionInfo("1.2")
@State(RELEASED)
@Path("d/soils/1.2")
@Resource(type = JDBC, file = "${conservation_resources.db}", id = DB)
public class V1_21 extends ModelDataService {
JSONArray outputObj;
JSONObject aoa_input_geometry;
Geometry aoa_geometry;
static final String DB = "csip.erosion.sqlsvr";
@Override
protected void preProcess() throws ServiceException {
Map<String, JSONObject> inputParams = getParamMap();
aoa_input_geometry = inputParams.get("AoI");
if (null == aoa_input_geometry) {
throw new ServiceException("No 'AoI' item was found in the JSON input. Please specify an 'AoI' .");
}
}
@Override
protected void doProcess() throws Exception {
GIS_DB db = new SqlGIS(getResourceJDBC(DB));
try {
LOG.log(Level.INFO, "phacil soils input obj dump");
outputObj = new JSONArray(getParam().toString());
Collection<JSONObject> coll = getParamMap().values();
for (JSONObject jsonobj : coll) {
LOG.log(Level.INFO, "json obj=" + jsonobj.toString());
JSONObject aoiobj = jsonobj.optJSONObject("value");
JSONArray features = aoiobj.optJSONArray("features");
if (LOG.isLoggable(Level.INFO)) {
LOG.log(Level.INFO, "****THE FEATURES IS");
LOG.log(Level.INFO, "features=" + features.toString());
}
// get polygon translation
String sPolygon = geometryToText(aoiobj);
LOG.log(Level.INFO, "features obj=" + features.toString());
for (int i = 0; i < features.length(); i++) {
JSONObject poly = features.getJSONObject(i);
LOG.log(Level.INFO, "poly obj #" + i + poly.toString());
JSONObject geometry = poly.optJSONObject("geometry");
LOG.log(Level.INFO, "geometry obj=" + geometry.toString());
JSONArray coords = geometry.optJSONArray("coordinates");
LOG.log(Level.INFO, "coords obj=" + coords.toString());
JSONArray aCoord = new JSONArray();
for (int j = 0; j < coords.length(); j++) {
JSONArray shape = coords.getJSONArray(j);
LOG.log(Level.INFO, "shape obj=" + shape.toString());
JSONArray aPoly = new JSONArray();
String newPolygon = "POLYGON((";
double firstLong = 0.0;
for (int k = 0; k < shape.length(); k++) {
JSONArray point = shape.getJSONArray(k);
if (firstLong == 0) {
firstLong = point.getDouble(0);
}
if (LOG.isLoggable(Level.INFO)) {
LOG.log(Level.INFO, "point obj=" + point.toString());
LOG.log(Level.INFO, "point 0 value=" + point.getDouble(0));
LOG.log(Level.INFO, "point 1 value=" + point.getDouble(1));
}
if (k > 0) {
newPolygon += ",";
}
newPolygon += point.getDouble(0) + " " + point.getDouble(1);
}
newPolygon += "))";
if (LOG.isLoggable(Level.INFO)) {
LOG.log(Level.INFO, "Polygon of interest=" + newPolygon);
LOG.log(Level.INFO, "Query Rusle2 Soils coverage");
}
// if we were able to get a polygon from the GeometryToText call, use it instead
// otherwise use what was generated above...
if ((sPolygon != null) && (sPolygon.length() > 0)) {
newPolygon = sPolygon;
}
Collection<GIS_DB.Soil> soils = db.findSoilsForPolygonWithSand(newPolygon, firstLong);
for (GIS_DB.Soil soilObj : soils) {
LOG.log(Level.INFO, "\n\n\n\n\n\n\n\n\nSAND TOTAL VALUE=" + soilObj.sandtotalR);
// String sSoil = "R2 SOIL INTERSECTION: cokey:" + soilObj.coKey;
// sSoil += ", mukey:" + soilObj.muKey;
// sSoil += " ,cofips:" + soilObj.coFips;
// sSoil += " ,compname:" + soilObj.compName;
// sSoil += " ,kffact:" + soilObj.kffact;
// sSoil += " ,tfact:" + soilObj.tfact + " " + soilObj.tfactUnits;
// sSoil += " ,muname:" + soilObj.muName;
// sSoil += " ,musym:" + soilObj.muSym;
// sSoil += " ,perwater:" + soilObj.perWater + " " + soilObj.perWaterUnits;
// sSoil += " ,perwind:" + soilObj.perWind + " " + soilObj.perWindUnits;
// sSoil += " ,r2name:" + soilObj.r2Name;
// sSoil += " ,r2path:" + soilObj.r2Path;
// sSoil += " ,lengthR:" + soilObj.lengthR + " " + soilObj.lengthRUnits;
// sSoil += " ,slopeR:" + soilObj.slopeR + " " + soilObj.slopeRUnits;
// sSoil += " ,sandtotalR:" + soilObj.sandtotalR + " " + soilObj.sandtotalRUnits;
// sSoil += " ,%AOI:" + soilObj.percentAoi;
// sSoil += " ,sizeaoi:" + soilObj.sizeAoi + " " + soilObj.sizeAoiUnits;
//LOG.log(Level.INFO, sSoil);
JSONArray aSoil = new JSONArray();
aSoil.put(JSONUtils.data("ssurgo_cokey", soilObj.coKey));
aSoil.put(JSONUtils.data("ssurgo_mukey", soilObj.muKey));
aSoil.put(JSONUtils.data("ssurgo_areasymbol", soilObj.coFips));
aSoil.put(JSONUtils.data("ssurgo_compname", soilObj.compName));
aSoil.put(JSONUtils.data("ssurgo_kffact", soilObj.kffact));
aSoil.put(JSONUtils.data("ssurgo_tfact", soilObj.tfact, soilObj.tfactUnits));
aSoil.put(JSONUtils.data("ssurgo_muname", soilObj.muName));
aSoil.put(JSONUtils.data("ssurgo_musym", soilObj.muSym));
aSoil.put(JSONUtils.data("per_water", soilObj.perWater, soilObj.perWaterUnits));
aSoil.put(JSONUtils.data("per_wind", soilObj.perWind, soilObj.perWindUnits));
aSoil.put(JSONUtils.data("r2_r2name", soilObj.r2Name));
aSoil.put(JSONUtils.data("r2_r2path", soilObj.r2Path));
aSoil.put(JSONUtils.data("length_r", soilObj.lengthR, soilObj.lengthRUnits));
aSoil.put(JSONUtils.data("ssurgo_slopeR", soilObj.slopeR, soilObj.slopeRUnits));
aSoil.put(JSONUtils.data("ssurgo_sandtotalR", soilObj.sandtotalR, soilObj.sandtotalRUnits));
aSoil.put(JSONUtils.data("percent_of_aoi", soilObj.percentAoi, soilObj.percentAoiUnits));
aSoil.put(JSONUtils.data("acres_in_aoi", soilObj.sizeAoi, soilObj.sizeAoiUnits));
aPoly.put(aSoil);
}
LOG.log(Level.INFO, "Query WEPS Soils coverage");
Collection<GIS_DB.Soil> soilsW = db.findSoilsForPolygonWeps(newPolygon, firstLong);
for (GIS_DB.Soil soilObj : soilsW) {
// String sSoil = "WEPS SOIL INTERSECTION: cokey:" + soilObj.coKey;
// sSoil += ", mukey:" + soilObj.muKey;
// sSoil += " ,cofips:" + soilObj.coFips;
// sSoil += " ,compname:" + soilObj.compName;
// sSoil += " ,kffact:" + soilObj.kffact;
// sSoil += " ,tfact:" + soilObj.tfact + " " + soilObj.tfactUnits;
// sSoil += " ,muname:" + soilObj.muName;
// sSoil += " ,musym:" + soilObj.muSym;
// sSoil += " ,perwater:" + soilObj.perWater + " " + soilObj.perWaterUnits;
// sSoil += " ,perwind:" + soilObj.perWind + " " + soilObj.perWindUnits;
// sSoil += " ,wepsname:" + soilObj.wepsName;
// sSoil += " ,wepspath:" + soilObj.wepsPath;
// sSoil += " ,lengthR:" + soilObj.lengthR + " " + soilObj.lengthRUnits;
// sSoil += " ,slopeR:" + soilObj.slopeR + " " + soilObj.slopeRUnits;
// sSoil += " ,%AOI:" + soilObj.percentAoi;
// sSoil += " ,sizeaoi:" + soilObj.sizeAoi + " " + soilObj.sizeAoiUnits;
//LOG.log(Level.INFO, sSoil);
JSONArray aSoil = new JSONArray();
aSoil.put(JSONUtils.data("ssurgo_cokey", soilObj.coKey));
aSoil.put(JSONUtils.data("ssurgo_mukey", soilObj.muKey));
aSoil.put(JSONUtils.data("ssurgo_areasymbol", soilObj.coFips));
aSoil.put(JSONUtils.data("ssurgo_compname", soilObj.compName));
aSoil.put(JSONUtils.data("ssurgo_kffact", soilObj.kffact));
aSoil.put(JSONUtils.data("ssurgo_tfact", soilObj.tfact, soilObj.tfactUnits));
aSoil.put(JSONUtils.data("ssurgo_muname", soilObj.muName));
aSoil.put(JSONUtils.data("ssurgo_musym", soilObj.muSym));
aSoil.put(JSONUtils.data("per_water", soilObj.perWater, soilObj.perWaterUnits));
aSoil.put(JSONUtils.data("per_wind", soilObj.perWind, soilObj.perWindUnits));
aSoil.put(JSONUtils.data("weps_name", soilObj.wepsName));
aSoil.put(JSONUtils.data("weps_path", soilObj.wepsPath));
aSoil.put(JSONUtils.data("length_r", soilObj.lengthR, soilObj.lengthRUnits));
aSoil.put(JSONUtils.data("ssurgo_slopeR", soilObj.slopeR, soilObj.slopeRUnits));
// aSoil.put(JSONUtils.data("ssurgo_sandtotalR", soilObj.sandtotalR, soilObj.sandtotalRUnits));
aSoil.put(JSONUtils.data("percent_of_aoi", soilObj.percentAoi, soilObj.percentAoiUnits));
aSoil.put(JSONUtils.data("acres_in_aoi", soilObj.sizeAoi, soilObj.sizeAoiUnits));
// Check if soil is already in aPoly - if so add weps path/name otherwise append
addWepsSoil(aPoly, aSoil, soilObj);
}
aCoord.put(aPoly);
}
outputObj.put(aCoord);
// aCoord is now returned with putResults
}
}
} catch (JSONException | SQLException jse) {
throw new ServiceException("Error executing soil serivce ", jse);
} finally {
db.close();
}
}
@Override
protected void postProcess() throws Exception {
for (int i = 0; i < outputObj.length(); i++) {
putResult(outputObj.get(i));
}
}
private void addWepsSoil(JSONArray aPolygon, JSONArray wepsSoil, GIS_DB.Soil soilObj) throws JSONException {
String wepsCokey = JSONUtils.getValueByKey(wepsSoil, "ssurgo_cokey");
String wepsaoi = JSONUtils.getValueByKey(wepsSoil, "acres_in_aoi");
for (int i = 0; i < aPolygon.length(); i++) {
JSONArray aSoil = aPolygon.getJSONArray(i);
String cokey = JSONUtils.getValueByKey(aSoil, "ssurgo_cokey");
String aoi = JSONUtils.getValueByKey(aSoil, "acres_in_aoi");
if ((cokey.equals(wepsCokey)) && (aoi.equals(wepsaoi))) {
// append weps attrs to existing soil
aSoil.put(JSONUtils.data("weps_name", soilObj.wepsName));
aSoil.put(JSONUtils.data("weps_path", soilObj.wepsPath));
return;
}
}
// add new WEPS soil results because its not there
aPolygon.put(wepsSoil);
}
private String geometryToText(JSONObject features) throws JSONException {
GeometryJSON geoJSON = new GeometryJSON();
try {
if (features.has("features")) {
FeatureJSON featureJSON = new FeatureJSON();
FeatureCollection inputFeatures = featureJSON.readFeatureCollection(features.toString());
FeatureIterator tFeatures = inputFeatures.features();
while (tFeatures.hasNext()) {
Feature tFeature = tFeatures.next();
String polygon = ((SimpleFeature) tFeature).getDefaultGeometry().toString();
if ((polygon != null) && (polygon.length() > 0)) {
return polygon;
}
aoa_geometry = (Geometry) ((SimpleFeature) tFeature).getAttribute("geometry");
// Do something with this particular feature here...OR just grab the first one if only one was specified.
// This particular code assumes only one was specified, but can easily be altered to send more than one
// and do something with each....
}
} else {
if (LOG.isLoggable(Level.INFO)) {
LOG.log(Level.INFO, "***NO FEATURES!!!");
LOG.log(Level.INFO, "THE AOA_INPUT_GEOMETRY=" + features.toString());
}
if (features.has("type")) { //Try to uncover if this is a "Feature" or a geometry object
if (features.getString("type").equalsIgnoreCase("feature")) {
FeatureJSON featureJSON = new FeatureJSON();
Feature tFeature = featureJSON.readFeature(features.toString());
String polygon = ((SimpleFeature) tFeature).getAttribute("geometry").toString();
aoa_geometry = (Geometry) ((SimpleFeature) tFeature).getAttribute("geometry");
if (LOG.isLoggable(Level.INFO)) {
// Here we could pull out the Feature's properies as well...
LOG.log(Level.INFO, "This Feature''s Id is: {0}", ((SimpleFeature) tFeature).getID());
LOG.log(Level.INFO, "This Feature''s name is: {0}", ((SimpleFeature) tFeature).getAttribute("name"));
//NOTE: For some reason, property values that are arrays (as in the example JSON), don't get read, so watch out for this!
LOG.log(Level.INFO, "This Feature''s adjustment factor is: {0}", ((SimpleFeature) tFeature).getAttribute("AdjustmentFactor"));
}
return polygon;
} else { //Try to read the GeoJSON geometry object
LOG.log(Level.INFO, "***TRY TO READ AS INPUT STREAM!");
aoa_geometry = geoJSON.read(IOUtils.toInputStream(features.toString()));
return aoa_geometry.toString();
}
} else {
LOG.log(Level.INFO, "***GEOJSON is unparsable!!!");
throw new JSONException("Unable to parse GEOJSON");
}
}
// TODO: Add your code here to do something with the geometry(ies) you read in.
// For instance: See code lines below: (NOTE: The .toText() funciton of "Geometry" returns WKT..)
// Log the WKT of the input.
LOG.log(Level.INFO, "***Last aoa_geometry value recieved was: {0}", aoa_geometry.toText());
throw new JSONException("Unable to parse GEOJSON");
} catch (IOException ioe) {
LOG.log(Level.SEVERE, "$$$$$$$$$io exception converting geometry to text=" + ioe.toString());
} catch (JSONException jse) {
LOG.log(Level.SEVERE, "***************************************JSON EXCEPTION converting geometry to text=" + jse.toString());
throw new JSONException("Unable to parse GEOJSON for soils service request");
}
return "";
}
}