V1_0.java [src/java/m/wqm/scpestslp] Revision: 473ac8e3d12827ec383e0f35e31fe62abe96be3a Date: Fri May 27 10:24:41 MDT 2016
/*
* 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.wqm.scpestslp;
import csip.ModelDataService;
import csip.ServiceException;
import csip.utils.JSONUtils;
import java.util.ArrayList;
import java.util.Map;
import java.util.logging.Level;
import javax.ws.rs.Path;
import oms3.annotations.Description;
import oms3.annotations.Name;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
/**
*
* @author Srinivas
* @author Rumpal Sidhu
* @author Shaun Case
*/
@Name("WQM-07: Pesticide Soil Leaching Potential (PesticideSLP)")
@Description("This service computes pesticide soil leaching potential "
+ "for soil components in an area of analysis, and then computes "
+ "pesticide soil leaching potential representing the area of analysis. "
+ "The service primarily will consume data from the WQM-2 WQMSoilAttributes "
+ "service to compute soil pesticide leaching potential used later by "
+ "the WQM-13 service to compute threshold treatment level scores.")
@Path("m/pesticide_slp/1.0")
public class V1_0 extends ModelDataService {
private static final int VERY_LOW = 1;
private static final int LOW = 2;
private static final int INTERMEDIATE = 3;
private static final int HIGH = 4;
private final String comp_pslp_string[] = {"", "VERY LOW", "LOW", "INTERMEDIATE", "HIGH"};
private int comp_pslp_number;
private String aoa_pslp;
private ArrayList<AoA> aoAs;
private String error_msg;
// request payload
// Store all of the input data by AoA
private Input inputData;
// response payload
// Storeage the results
private Result result;
@Override
// reading the inputs from the json file into input object and placing it in the arraylist
protected void preProcess() throws Exception {
comp_pslp_number = 0;
aoa_pslp = "";
error_msg = "";
result = null;
aoAs = new ArrayList<>();
inputData = new Input(aoAs);
if (inputData.getError()) {
throw new ServiceException(inputData.getErrorMsg());
}
}
@Override
protected void doProcess() throws Exception {
if (error_msg.isEmpty()) {
for (AoA aoA : aoAs) {
if (!aoA.process()) {
error_msg += aoA.getErrorMsg();
break;
}
}
if (error_msg.isEmpty()) {
result = new Result(aoAs);
}
}
}
@Override
//writing the results back to JSON
protected void postProcess() throws Exception {
if (null != result) {
result.putResults();
}
}
class AoA {
private ArrayList<SoilComponent> soilComponents;
private final int AoAId;
private String error_msg;
private double cum_pslp_product;
private double aoa_area;
private String aoa_pslp;
AoA(int AoAId, JSONArray components) throws ServiceException {
this.cum_pslp_product = 0;
this.aoa_area = 0;
this.AoAId = AoAId;
this.error_msg = "";
this.aoa_pslp = "NONE";
this.soilComponents = new ArrayList<>();
if (AoAId == -1) {
this.error_msg = " Invalid AoA Identifier. ";
} else {
try {
if ((null != components) && (components.length() > 0)) {
for (int j = 0; j < components.length(); j++) {
Map<String, JSONObject> cokey = JSONUtils.preprocess(components.getJSONArray(j));
SoilComponent tSC = new SoilComponent(AoAId, JSONUtils.getStringParam(cokey, "cokey", "err"),
JSONUtils.getStringParam(cokey, "compname", " "), JSONUtils.getDoubleParam(cokey, "aoa_comp_area", 0.0),
JSONUtils.getStringParam(cokey, "aoa_comp_hsg", "err"), JSONUtils.getDoubleParam(cokey, "aoa_comp_kfact", 0.0),
JSONUtils.getDoubleParam(cokey, "aoa_comp_om", 0.0), JSONUtils.getIntParam(cokey, "aoa_comp_hzdepth", 0),
JSONUtils.getBooleanParam(cokey, "aoa_comp_cracksgr24", false), JSONUtils.getBooleanParam(cokey, "aoa_comp_hwt_lt_24", false)
);
if (!tSC.getError()) {
if (!soilComponents.add(tSC)) {
//Shouldn't ever happen, but just in case...
error_msg += "Internal error, could not add this component to the list.";
break;
}
} else {
//Most likely an input validation error here, caught by the subclass
error_msg += tSC.getErrorMsg();
break;
}
}// End for loop of components for this AoA
} else {
//This component was empty or the JSON failed to create an item.
error_msg += " This AoA's component is empty or missing, cannot proceed.";
}
} catch (Exception ex) {
error_msg += " " + ex.getMessage();
LOG.log(Level.SEVERE, "Error in processing the request JSON for WQM-7!", ex);
throw new ServiceException("Error in processing the request JSON.", ex);
}
}
}
public Boolean process() {
Boolean ret_val = true;
for (SoilComponent component : soilComponents) {
if (!component.process()) {
error_msg += " " + component.getErrorMsg();
break;
}
cum_pslp_product += (component.getCompPslpNumber() * component.getAoaCompArea());
aoa_area += component.getAoaCompArea();
}
if (error_msg.isEmpty()) {
double aoa_pslp_fract = (cum_pslp_product / aoa_area);
if (aoa_pslp_fract <= 1.50) {
aoa_pslp = "VERY LOW";
} else if (aoa_pslp_fract > 1.50 && aoa_pslp_fract <= 2.50) {
aoa_pslp = "LOW";
} else if (aoa_pslp_fract > 2.50 && aoa_pslp_fract <= 3.50) {
aoa_pslp = "INTERMEDIATE";
} else {
aoa_pslp = "HIGH";
}
}
return ret_val;
}
public JSONArray putResults() throws ServiceException {
JSONArray AoAData;
JSONArray components;
AoAData = new JSONArray();
try {
AoAData.put(JSONUtils.dataDesc("AoAId", AoAId, "Area of Analysis Identifier"));
AoAData.put(JSONUtils.dataDesc("aoa_pslp", aoa_pslp, "Pesticide soil leaching potential representing the AoA"));
components = new JSONArray();
for (SoilComponent component : soilComponents) {
components.put(component.putResults());
if (component.getError()) {
error_msg += " " + component.getErrorMsg();
break;
}
}
AoAData.put(JSONUtils.dataDesc("componentlist", components, "List of soil components"));
} catch (JSONException ex) {
error_msg += " " + ex.getMessage();
LOG.log(Level.SEVERE, "Error in processing the response JSON for WQM-7!", ex);
throw new ServiceException("Error in processing the response JSON.", ex);
}
return AoAData;
}
public Boolean getError() {
return (!error_msg.isEmpty());
}
public String getErrorMsg() {
return error_msg;
}
public String getAoAPslp() {
return aoa_pslp;
}
public int getAoAId() {
return AoAId;
}
class SoilComponent {
private final int AoAId;
private final String cokey;
private final String compname;
private String comp_pslp;
private int comp_pslp_number;
private final double aoa_comp_area;
private final String aoa_comp_hsg;
private final double aoa_comp_kfact;
private final double aoa_comp_om;
private final int aoa_comp_hzdepth;
private final boolean aoa_comp_cracksgr24;
private final boolean aoa_comp_hwt_lt_24;
private String error_msg;
SoilComponent(int AoAId, String cokey, String compname, double aoa_comp_area, String aoa_comp_hsg, double aoa_comp_kfact, double aoa_comp_om, int aoa_comp_hzdepth, boolean aoa_comp_cracksgr24, boolean aoa_comp_hwt_lt_24) {
this.AoAId = AoAId;
this.cokey = cokey;
this.compname = compname;
this.aoa_comp_area = aoa_comp_area;
this.aoa_comp_hsg = aoa_comp_hsg;
this.aoa_comp_kfact = aoa_comp_kfact;
this.aoa_comp_om = aoa_comp_om;
this.aoa_comp_hzdepth = aoa_comp_hzdepth;
this.aoa_comp_cracksgr24 = aoa_comp_cracksgr24;
this.aoa_comp_hwt_lt_24 = aoa_comp_hwt_lt_24;
this.error_msg = "";
this.comp_pslp = "";
this.comp_pslp_number = 0;
if (cokey.equals("err") || aoa_comp_hsg.equals("err") || (AoAId == -1)) {
error_msg += " Invalid input data for this soil component.";
}
}
public int getAoAId() {
return AoAId;
}
public String getCokey() {
return cokey;
}
public String getCompname() {
return compname;
}
public String getCompPslp() {
return comp_pslp;
}
;
public int getCompPslpNumber() {
return comp_pslp_number;
}
public double getAoaCompArea() {
return aoa_comp_area;
}
public Boolean getError() {
return (!error_msg.isEmpty());
}
public String getErrorMsg() {
return (error_msg);
}
public boolean process() {
boolean ret_val = true;
if (aoa_comp_hwt_lt_24) {
comp_pslp_number = HIGH;
} else if (((aoa_comp_hsg.equals("A") || aoa_comp_hsg.equals("A/D")) && ((aoa_comp_hzdepth * aoa_comp_om) <= 30))
|| ((aoa_comp_hsg.equals("B") || aoa_comp_hsg.equals("B/D")) && ((aoa_comp_hzdepth * aoa_comp_om) <= 9) && (aoa_comp_kfact <= 0.48))
|| ((aoa_comp_hsg.equals("B") || aoa_comp_hsg.equals("B/D")) && ((aoa_comp_hzdepth * aoa_comp_om) <= 15) && (aoa_comp_kfact <= 0.26))) {
comp_pslp_number = HIGH;
} else if (((aoa_comp_hsg.equals("B") || aoa_comp_hsg.equals("B/D")) && ((aoa_comp_hzdepth * aoa_comp_om) >= 35) && aoa_comp_kfact >= 0.40)
|| ((aoa_comp_hsg.equals("B") || aoa_comp_hsg.equals("B/D")) && ((aoa_comp_hzdepth * aoa_comp_om) >= 45) && aoa_comp_kfact >= 0.20)
|| ((aoa_comp_hsg.equals("C") || aoa_comp_hsg.equals("C/D")) && ((aoa_comp_hzdepth * aoa_comp_om) <= 10) && aoa_comp_kfact <= 0.28)
|| ((aoa_comp_hsg.equals("C") || aoa_comp_hsg.equals("C/D")) && ((aoa_comp_hzdepth * aoa_comp_om) >= 10))) {
if (!aoa_comp_cracksgr24) {
comp_pslp_number = LOW;
} else {
comp_pslp_number = INTERMEDIATE;
}
} else if (aoa_comp_hsg.equals("D")) {
if (!aoa_comp_cracksgr24) {
comp_pslp_number = VERY_LOW;
} else {
comp_pslp_number = LOW;
}
} else if (!aoa_comp_cracksgr24) {
comp_pslp_number = INTERMEDIATE;
} else {
comp_pslp_number = HIGH;
}
comp_pslp = comp_pslp_string[comp_pslp_number];
return ret_val;
}
public JSONArray putResults() throws ServiceException {
JSONArray componentData;
componentData = new JSONArray();
try {
componentData.put(JSONUtils.dataDesc("cokey", cokey, "Soil component key"));
componentData.put(JSONUtils.dataDesc("compname", compname, "Soil component name"));
componentData.put(JSONUtils.dataDesc("comp_pslp", comp_pslp, "Pesticide soil leaching potential representing the soil component"));
} catch (JSONException ex) {
error_msg += " " + ex.getMessage();
LOG.log(Level.SEVERE, "Error in processing the response JSON for WQM-7!", ex);
throw new ServiceException("Error in processing the response JSON.", ex);
}
return componentData;
}
}
}
public class Input {
private String error_msg;
private JSONArray AoAList;
Input(ArrayList<AoA> aoAs) throws ServiceException {
error_msg = "";
try {
AoAList = getJSONArrayParam("AoAList");
if (null != AoAList) {
for (int i = 0; i < AoAList.length(); i++) {
Map<String, JSONObject> componentGroup = JSONUtils.preprocess(AoAList.getJSONArray(i));
int AoAId = JSONUtils.getIntParam(componentGroup, "AoAId", -1);
if (AoAId != -1) {
JSONArray components = JSONUtils.getJSONArrayParam(componentGroup, "componentlist");
AoA aoA = new AoA(AoAId, components);
if (aoA.getError()) {
error_msg += " " + aoA.getErrorMsg();
break;
} else {
aoAs.add(aoA);
}
} else {
error_msg += " The AoAId is not valid or is missing, cannot proceed";
break;
}
}// End for loop of AoA's
} else {
error_msg += " There were no AoA's found in the input payload. Cannot proceed.";
}
} catch (ServiceException | JSONException ex) {
error_msg += " " + ex.getMessage();
LOG.log(Level.SEVERE, "Error in processing the request JSON for WQM-7!", ex);
throw new ServiceException("Error in processing the request JSON.", ex);
}
}
public String getErrorMsg() {
return error_msg;
}
public Boolean getError() {
return (!error_msg.isEmpty());
}
}
public class Result {
JSONArray AoAList;
Result(ArrayList<AoA> aoAs) throws Exception {
if (!aoAs.isEmpty()) {
AoAList = new JSONArray();
for (AoA aoA : aoAs) {
AoAList.put(aoA.putResults());
if (aoA.getError()) {
AoAList.put(JSONUtils.dataDesc("Error:", aoA.getErrorMsg(), "Error message returned while trying to build result output"));
break;
}
}
} else {
AoAList = null;
}
}
public void putResults() {
if (null != AoAList) {
putResult("AoAList", AoAList);
}
}
}
}