V1_0.java [src/java/m/wqm/NutrientSLP] Revision: 605ab0b57daf97c9c29f6d38dd93486800cbc4fd  Date: Mon Nov 09 14:25:17 MST 2015
package m.wqm.NutrientSLP;

import csip.ModelDataService;
import csip.ServiceException;
import java.util.ArrayList;
import javax.ws.rs.Path;
import oms3.annotations.Description;
import oms3.annotations.Name;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import csip.utils.JSONUtils;
import java.util.Map;
import org.codehaus.jettison.json.JSONException;

/**
 *
 * @ Srinivas
 * @author Rumpal Sidhu
 */
@Name("WQM-05: Nutrient Soil Leaching Potential (NutrientSLP)")
@Description("This service computes nutrient soil leaching potential for soil components in an area of analysis, and then computes nutrient soil leaching potential representing the area of analysis (AoA). The service primarily will consume data from the WQM-02 WQMSoilAttributes service to compute nutrient soil leaching potentials used later by the WQM-13 service to compute threshold treatment level scores.")
@Path("m/nutrient_slp/1.0")

public class V1_0 extends ModelDataService {

    private final String[] nslpList = new String[]{"LOW", "MODERATE", "MODERATELY HIGH", "HIGH"};
    //Request
    private int aoaId;
    private ArrayList<V1_0.SoilComponent> soilComponentList;
    //Result
    private String aoaNslp;
    private String error_msg;

    @Override
    protected void preProcess() throws Exception {
        soilComponentList = new ArrayList<>();
        this.error_msg = "";
        try {
            aoaId = getIntParam("AoAId");
            JSONArray groups = getJSONArrayParam("soilcomponents");
            for (int i = 0; i < groups.length(); i++) {
                Map<String, JSONObject> group = JSONUtils.preprocess(groups.getJSONArray(i));
                V1_0.SoilComponent input = new V1_0.SoilComponent(
                        JSONUtils.getStringParam(group, "cokey", "err"),
                        JSONUtils.getDoubleParam(group, "aoa_comp_area", 0),
                        JSONUtils.getStringParam(group, "aoa_comp_hsg", "err"),
                        JSONUtils.getStringParam(group, "aoa_comp_taxorder", "err"),
                        JSONUtils.getDoubleParam(group, "aoa_comp_kfact", 0),
                        JSONUtils.getDoubleParam(group, "aoa_comp_slope", 0),
                        JSONUtils.getDoubleParam(group, "aoa_comp_coarse_frag", 0),
                        JSONUtils.getBooleanParam(group, "aoa_comp_drained", false),
                        JSONUtils.getStringParam(group, "aoa_comp_wtbl", "err"),
                        JSONUtils.getBooleanParam(group, "aoa_comp_hwt_lt_24", false));
                soilComponentList.add(input);
            }
        } catch (ServiceException | JSONException ex) {
            this.error_msg += "  " + ex.getMessage() + ". ";
        }
    }

    @Override
    protected String process() throws Exception {
        try {
            if (this.error_msg.isEmpty()) {
                this.computeNSLP();
            }
            if (this.error_msg.isEmpty()) {
                this.computeAoaNSLP();
            }
        } catch (Exception ex) {
            LOG.info(ex.getMessage());
            this.error_msg += ex.getMessage();
        }
        return (this.error_msg.isEmpty() ? EXEC_OK : this.error_msg);
    }

    @Override
    protected void postProcess() throws Exception {
        putResult("aoa_id", aoaId, "Area of analysis identifier");
        putResult("aoa_nslp", aoaNslp, "Soil leaching potential of the area of analysis");
        JSONArray resultArr = new JSONArray();
        for (V1_0.SoilComponent sc : soilComponentList) {
            JSONArray array = new JSONArray();
            array.put(JSONUtils.dataDesc("cokey", sc.getCokey(), "Soil component key"));
            array.put(JSONUtils.dataDesc("comp_nslp", sc.getNslp(), "Soil leaching potential of the soil component"));
            resultArr.put(JSONUtils.dataDesc("soil_component", array, "Soil Component"));
        }
        putResult("soil_components", resultArr, "List of Soil Components");
    }

    private void computeNSLP() {
        int comp_nslp_number = -2;
        for (V1_0.SoilComponent ip : soilComponentList) {
            if (ip.getTaxorder().equals("Histosols")) {
                comp_nslp_number = 3;
            } else if ((ip.getWtbl().equals("Apparent") && !ip.isDrained() ) || ip.isHwt_lt_24()) {
                comp_nslp_number = 3;
            } else {
                switch (ip.getHsg()) {
                    case "A":
                        comp_nslp_number = this.computeNSLPHsgA(ip);
                        break;
                    case "B":
                        comp_nslp_number = this.computeNSLPHsgB(ip);
                        break;
                    case "C":
                        comp_nslp_number = this.computeNSLPHsgC(ip);
                        break;
                    case "D":
                        comp_nslp_number = this.computeNSLPHsgD(ip);
                        break;
                    case "A/D":
                        if (ip.isDrained()) {
                            comp_nslp_number = this.computeNSLPHsgA(ip);
                        } else {
                            comp_nslp_number = this.computeNSLPHsgD(ip);
                        }
                        break;
                    case "B/D":
                        if (ip.isDrained()) {
                            comp_nslp_number = this.computeNSLPHsgB(ip);
                        } else {
                            comp_nslp_number = this.computeNSLPHsgD(ip);
                        }
                        break;
                    case "C/D":
                        if (ip.isDrained()) {
                            comp_nslp_number = this.computeNSLPHsgC(ip);
                        } else {
                            comp_nslp_number = this.computeNSLPHsgD(ip);
                        }
                        break;
                }
            }
            if (comp_nslp_number != -1 && comp_nslp_number != -2) {
                ip.setNslpNumber(comp_nslp_number);
                ip.setNslp(nslpList[comp_nslp_number]);
            } else {
                error_msg = "Error.";
            }
        }
    }

    private int computeNSLPHsgA(V1_0.SoilComponent ip) {
        int nslpNumber = -1;
        if (ip.getSlope() > 12) {
            if (ip.getCoarseFrag() > 10) {
                nslpNumber = 3;
            } else {
                nslpNumber = 2;
            }
        } else if (ip.getSlope() <= 12) {
            nslpNumber = 3;
        }
        return nslpNumber;
    }

    private int computeNSLPHsgB(V1_0.SoilComponent ip) {
        int nslpNumber = -1;
        if ((ip.getSlope() <= 12 && ip.getKfact() >= 0.24) || (ip.getSlope() > 12)) {
            if (ip.getCoarseFrag() > 10 && ip.getCoarseFrag() <= 30) {
                nslpNumber = 2;
            } else if (ip.getCoarseFrag() > 30) {
                nslpNumber = 3;
            } else {
                nslpNumber = 1;
            }
        } else if (ip.getSlope() >= 3 && ip.getSlope() <= 12 && ip.getKfact() < 0.24) {
            if (ip.getCoarseFrag() > 10) {
                nslpNumber = 3;
            } else {
                nslpNumber = 2;
            }
        } else if (ip.getSlope() < 3 && ip.getKfact() < 0.24) {
            nslpNumber = 3;
        }
        return nslpNumber;
    }

    private int computeNSLPHsgC(V1_0.SoilComponent ip) {
        int nslpNumber;
        if (ip.getCoarseFrag() > 30) {
            nslpNumber = 3;
        } else if (ip.getCoarseFrag() > 10 && ip.getCoarseFrag() <= 30) {
            nslpNumber = 2;
        } else {
            nslpNumber = 1;
        }
        return nslpNumber;
    }

    private int computeNSLPHsgD(V1_0.SoilComponent ip) {
        int nslpNumber;
        if (ip.getCoarseFrag() > 30) {
            nslpNumber = 2;
        } else if (ip.getCoarseFrag() > 10 && ip.getCoarseFrag() <= 30) {
            nslpNumber = 1;
        } else {
            nslpNumber = 0;
        }
        return nslpNumber;
    }

    //Compute weighted average nutrient soil leaching potential for the AoA
    private void computeAoaNSLP() {
        double cumNslpProduct = 0;
        double aoaArea = 0;

        for (V1_0.SoilComponent sc : soilComponentList) {
            cumNslpProduct += (sc.getNslpNumber() * sc.getArea());
            aoaArea += sc.getArea();
        }
        double aoaNslpFract = cumNslpProduct / aoaArea;
        if (aoaNslpFract <= 0.50) {
            aoaNslp = "LOW";
        } else if (aoaNslpFract > 0.50 && aoaNslpFract <= 1.50) {
            aoaNslp = "MODERATE";
        } else if (aoaNslpFract > 1.50 && aoaNslpFract <= 2.50) {
            aoaNslp = "MODERATELY HIGH";
        } else {
            aoaNslp = "HIGH";
        }
    }

    public class SoilComponent {

        private String cokey;
        private double area;
        private String hsg;
        private String taxorder;
        private double kfact;
        private double slope;
        private double coarseFrag;
        private boolean drained;
        private String wtbl;
        private boolean hwt_lt_24;

        private int nslpNumber;
        private String nslp;

        public SoilComponent(String cokey, double area, String hsg, String taxorder,
                double kfact, double slope, double coarseFrag, boolean drained,
                String wtbl, boolean hwt_lt_24) {
            this.cokey = cokey;
            this.area = area;
            this.hsg = hsg;
            this.taxorder = taxorder;
            this.kfact = kfact;
            this.slope = slope;
            this.coarseFrag = coarseFrag;
            this.drained = drained;
            this.wtbl = wtbl;
            this.hwt_lt_24 = hwt_lt_24;
        }

        //Getter Methods
        public String getCokey() {
            return this.cokey;
        }

        public double getArea() {
            return this.area;
        }

        public String getHsg() {
            return this.hsg;
        }

        public String getTaxorder() {
            return this.taxorder;
        }

        public double getKfact() {
            return this.kfact;
        }

        public double getSlope() {
            return this.slope;
        }

        public double getCoarseFrag() {
            return this.coarseFrag;
        }

        public boolean isDrained() {
            return this.drained;
        }

        public String getWtbl() {
            return this.wtbl;
        }

        public boolean isHwt_lt_24() {
            return this.hwt_lt_24;
        }

        public int getNslpNumber() {
            return this.nslpNumber;
        }

        public String getNslp() {
            return this.nslp;
        }

        //Setter Methods
        public void setNslpNumber(int number) {
            this.nslpNumber = number;
        }

        public void setNslp(String value) {
            this.nslp = value;
        }

    }

}