V1_0.java [src/java/d/bamert_01/edit_soils_properties] Revision: 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 d.bamert_01.edit_soils_properties;
import com.jayway.jsonpath.ReadContext;
import csip.Config;
import csip.ModelDataService;
import csip.ServiceException;
import csip.SessionLogger;
import csip.annotations.Description;
import csip.annotations.Name;
import csip.annotations.Resource;
import csip.annotations.VersionInfo;
import csip.utils.JSONUtils;
import csip.utils.Parallel;
import csip.utils.Parallel.Run;
import static db.DBResources.GIS_DB;
import edit.EditConnection;
import edit.EditQueries;
import gisobjects.GISObject;
import static gisobjects.GISObject.DEFAULT_ASSUMED_SRID;
import gisobjects.GISObjectException;
import gisobjects.GISObjectFactory;
import gisobjects.db.GISEngine;
import gisobjects.db.GISEngineFactory;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.ws.rs.Path;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import soils.Coecoclass;
import soils.Component;
import soils.MapUnit;
import soils.SoilsData;
import static soils.db.DBResources.PROVIDER_TYPE;
import soils.db.SOILS_DATA;
import soils.db.SOILS_DB_Factory;
import soils.db.tables.TableCoecoclass;
import soils.db.tables.TableCoecoclassCalculations;
import soils.db.tables.TableComponent;
import soils.db.tables.TableComponentCalculations;
import soils.db.tables.TableHorizon;
import soils.db.tables.TableHorizonCalculations;
import soils.db.tables.TableMapUnit;
import soils.db.tables.TableMapUnitCalculations;
import soils.db.tables.TableTextureGroup;
/**
*
* @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
*/
@Name("BAMERT-01: Get Soil Map Unit and Component Properties")
@Description("Get and return a payload of Soil Data Mart (SDM) soil properties "
+ "and Ecosystem Dynamics Interpretative Tool (EDIT) ecological site properties.")
@VersionInfo("1.0")
@Path("d/edit_soils_properties/1.0")
@Resource(from = soils.db.DBResources.class)
@Resource(from = db.DBResources.class)
public class V1_0 extends ModelDataService {
static final String AOA_GEOMETRY = "aoa_geometry";
JSONObject aoa_geometry;
AoA aoa;
@Override
protected void preProcess() throws Exception {
aoa_geometry = parameter().getParamJSON(AOA_GEOMETRY);
}
@Override
protected void doProcess() throws Exception {
try (GISEngine gisEngine = GISEngineFactory.createGISEngine(resources().getJDBC(GIS_DB));
SOILS_DATA soilsDb = SOILS_DB_Factory.createEngine(V1_0.class, LOG, Config.getString("soils.gis.database.source"));) {
GISObject aoaGeometry = GISObjectFactory.createGISObject(aoa_geometry, gisEngine);
aoa = new AoA(soilsDb, aoaGeometry, LOG);
aoa.findSoils();
}
}
@Override
protected void postProcess() throws Exception {
results().put("aoa_acres", aoa.getArea());
results().put("mapunits", aoa.toJSON());
}
public class AoA extends soils.AoA {
private SortedMap<Double, Component> componentOrderList = new TreeMap<>(Collections.reverseOrder());
public static final String BUFFER_SIZE_KEY = "buffer_size";
static final double MINIMUM_PERCENTAGE_2 = 20.0;
static final int ALLOWED_SRID = DEFAULT_ASSUMED_SRID;
static final double DEFAULT_WEI = 134.0;
static final double DEFAULT_POINT_BUFFER_SIZE = 113.5; // 133.5m buffer = 10 acres.
protected String mupolygonkey = ""; // This is held over from the original, in case we want to search by mupolygon in the future.
protected GISEngine gisEngine = null;
protected double bufferSize = DEFAULT_POINT_BUFFER_SIZE;
/**
*
* @param soilsDb
* @param aoa_geometry
* @param Log
* @throws GISObjectException
* @throws SQLException
* @throws JSONException
* @throws IOException
* @throws ServiceException
*/
public AoA(SOILS_DATA soilsDb, GISObject aoa_geometry, SessionLogger Log) throws GISObjectException, SQLException, JSONException, IOException, ServiceException {
super(soilsDb, aoa_geometry, Log);
if (ALLOWED_SRID != getSRID()) {
throw new ServiceException("This service, currently, only supports an input CRS of WGS-84 (4326 SRID). You requested service for a geometry that was SRID: " + getSRID());
}
shape.makeValid(GISObject.UsePurpose.all_purposes, GISObject.GISType.all_types);
if (shape.getGeometry().getGeometryType() == "Point") {
shape = shape.buffer(bufferSize);
}
area = shape.areaInAcres();
if (area > 10000.0) {
throw new ServiceException("Feature specified has an area greater than 10,000 acres. Area is too large.");
}
}
/**
*
* @throws SQLException
* @throws ServiceException
* @throws GISObjectException
*/
public void findSoils() throws SQLException, ServiceException, GISObjectException, Exception {
if (null != shape) {
findIntersectedMapUnitsWithAreasAndShapes();
} else {
throw new ServiceException("No AoI location was speified. Please specify an AoI location as a geometry.");
}
if (soilsDb.findAllBasicComponentHorizonFragTextureData(map_units, true)) {
soilsDb.findEcoClassForMukeyList(map_units,
" ((ecoclassid LIKE 'R%' AND ecoclasstypename='NRCS Rangeland Site') "
+ " OR (ecoclassid LIKE 'F%' AND ecoclasstypename='NRCS Forestland Site'))"
);
getEDITEcoclassNames();
}
}
private void queryEdit(Coecoclass coEcoClass, EditConnection editConn) throws Exception {
String ecId = coEcoClass.ecoclassid();
String edit_es_name = EditQueries.getEcoClassNameFor(editConn.fetchEcoClassList(ecId), ecId);
if ((null != edit_es_name) && (!edit_es_name.isEmpty())) {
coEcoClass.ecoclassname(edit_es_name);
coEcoClass.setEDITPath("https://edit.jornada.nmsu.edu/catalogs/esd/" + ecId.substring(1, 5) + "/" + ecId);
}
}
private void getEDITEcoclassNames() throws ServiceException, Exception {
if (null != map_units) {
ArrayList<Run> runs = new ArrayList<>();
EditConnection editConn = new EditConnection(LOG);
for (MapUnit mapUnit : map_units.values()) {
for (Component component : mapUnit.components().values()) {
for (Coecoclass coEcoClass : component.ecoClasses().values()) {
String ecId = coEcoClass.ecoclassid();
if (ecId.length() == 11 && ((ecId.charAt(0) == 'R' || ecId.charAt(0) == 'F'))) {
runs.add(() -> queryEdit(coEcoClass, editConn));
}
}
}
}
if (runs.size() > 0) {
Parallel.run(runs);
}
} else {
throw new ServiceException("Cannot find ecoclass names from EDIT with an empty mapunit list.");
}
}
/**
*
* @return
*/
public final int getSRID() {
return shape.getGeometry().getSRID();
}
/**
*
* @return @throws JSONException
*/
public JSONArray toJSON() throws JSONException, ServiceException, IOException {
JSONArray mapunitData = new JSONArray();
for (MapUnit mapUnit : map_units.values()) {
if (!mapUnit.isExcluded()) {
JSONArray mapUnitArray = new JSONArray();
ArrayList<GISObject> intersections = mapUnit.getIntersectionPolygons();
mapUnit.setOutputColumnOrdering(new ArrayList<>(Arrays.asList(
TableMapUnit.AREASYMBOL_NAME, TableMapUnit.AREA_NAME, TableMapUnit.MUKEY, TableMapUnit.MUNAME,
TableMapUnit.MUSYM, TableMapUnit.MUACRES, TableMapUnitCalculations.AREA_NAME, TableMapUnitCalculations.AREA_PCT
)));
mapUnit.mapUnitJSON(mapUnitArray);
JSONArray intersectionArray = new JSONArray();
for (GISObject intersect : intersections) {
intersectionArray.put(intersect.toJSON());
}
mapUnitArray.put(JSONUtils.data("mapunit_intersections", intersectionArray));
JSONArray componentArray = new JSONArray();
for (Component component : mapUnit.components().values()) {
if (!component.isExcluded()) {
JSONArray componentObject;
component.setOutputColumnOrdering(new ArrayList<>(Arrays.asList(
TableComponent.COKEY, TableComponent.COMPNAME, TableComponent.COMPPCT_R_NAME,
TableComponent.MAJ_COMP_FLAG, TableComponentCalculations.AREA_PCT_NAME, TableComponentCalculations.COMP_AREA_NAME
)));
component.setHorizonOutputColumnOrdering(new ArrayList<>(Arrays.asList(TableHorizon.CHKEY_NAME, TableHorizonCalculations.DEPT_R_IN,
TableHorizonCalculations.DEPB_R_IN)));
component.setTextureGroupOutputColumnOrdering(new ArrayList<>(Arrays.asList(TableTextureGroup.DESCRIPTION)));
componentObject = component.toJSON(false);
JSONArray ecoClassArray = new JSONArray();
for (Coecoclass ecoClass : component.ecoClasses().values()) {
ecoClass.setOutputColumns(new ArrayList<>(Arrays.asList(TableCoecoclass.ECOCLASSID,
TableCoecoclass.ECOCLASSNAME, TableCoecoclassCalculations.ES_EDIT_URL)));
ecoClassArray.put(ecoClass.toJSON());
}
componentObject.put(JSONUtils.data("EcoClassList", ecoClassArray));
componentArray.put(componentObject);
}
}
if (componentArray.length() > 0) {
mapUnitArray.put(JSONUtils.data(SoilsData.MAPUNIT_COMPONENT_LIST_NAME, componentArray));
mapunitData.put(mapUnitArray);
}
}
}
return mapunitData;
}
}
}