V1_0.java [src/java/m/wqm/nutappmgtscores] Revision: a3d12e5ce267e5f39f948a7006ceddb3c1af4a70  Date: Fri Aug 07 08:31:59 MDT 2015
package m.wqm.nutappmgtscores;

/**
 *
 * @author RUMPAL SIDHU
 */
import csip.ModelDataService;
import csip.utils.JSONUtils;
import csip.utils.Dates;
import csip.annotations.Polling;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Map;
import javax.ws.rs.Path;
import oms3.annotations.Name;
import oms3.annotations.Description;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import java.util.concurrent.TimeUnit;

@Name("WQM-16")
@Description("Nutrient Application Management Scores")
@Path("m/nutappmgtscores/1.0")
@Polling(first = 10000, next = 2000)

public class V1_0 extends ModelDataService {

    //SQL params here for quick modification
    private final String USER = "postgres";
    private final String PASS = "admin";
    private final String HOST = "localhost";
    private final String PORT = "5432";
    private final String DBNAME = "postgres";
    private final String JDBC_TYPE = "jdbc:postgresql://";
    private final String CONNECTION = JDBC_TYPE + HOST + ":" + PORT + "/" + DBNAME;
    private final String CLASS_NAME = "org.postgresql.Driver";

    //Request
    private ArrayList<Input> input;
    //Response
    private ArrayList<Result> result;

    @Override
    protected void preProcess() throws Exception {
        input = new ArrayList<>();
        int AoAId = getIntParam("aoa_id", 0);
        String p_soil_test_result = getStringParam("p_soil_test_result", "err");
        ArrayList<Crop> cropList = new ArrayList<>();
        JSONArray cropIds = getJSONArrayParam("cropIds");
        for (int i = 0; i < cropIds.length(); i++) {
            Map<String, JSONObject> mgtCropId = JSONUtils.preprocess(cropIds.getJSONArray(i));

            int cropId = JSONUtils.getIntParam(mgtCropId, "mgt_crop_id", 0);
            String cropPlantDate = JSONUtils.getStringParam(mgtCropId, "crop_plant_date", "err");
            double cropYield = JSONUtils.getDoubleParam(mgtCropId, "crop_yield", 0);
            String cropYieldUnits = JSONUtils.getStringParam(mgtCropId, "crop_yield_units", "err");
            ArrayList<Nutrient> nutrientApplicationList = new ArrayList<>();
            JSONArray applicationList = JSONUtils.getJSONArrayParam(mgtCropId, "applicationList");
            for (int j = 0; j < applicationList.length(); j++) {
                Map<String, JSONObject> application = JSONUtils.preprocess(applicationList.getJSONArray(j));
                String nutrient_application_date = JSONUtils.getStringParam(application, "nutrient_application_date", "err");
                boolean incorporated = JSONUtils.getBooleanParam(application, "incorporated", false);
                ArrayList<NutrientApplied> nutrientAppliedList = new ArrayList<>();
                JSONArray applicate = JSONUtils.getJSONArrayParam(application, "application");
                for (int k = 0; k < applicate.length(); k++) {
                    Map<String, JSONObject> a = JSONUtils.preprocess(applicate.getJSONArray(k));
                    String nutrient_applied = JSONUtils.getStringParam(a, "nutrient_applied", "err");
                    double application_rate = JSONUtils.getDoubleParam(a, "application_rate", 0);
                    nutrientAppliedList.add(new NutrientApplied(nutrient_applied, application_rate));
                }
                nutrientApplicationList.add(new Nutrient(nutrient_application_date, incorporated, nutrientAppliedList));
            }
            cropList.add(new Crop(cropId, cropPlantDate, cropYield, cropYieldUnits, nutrientApplicationList));
        }
        input.add(new m.wqm.nutappmgtscores.Input(AoAId, cropList, p_soil_test_result));
    }

    @Override
    protected String process() throws Exception {
        result = new ArrayList<>();
        Connection conn = null;
        Statement statement = null;
        String query;
        ResultSet resultSet;

        try {
            Class.forName(CLASS_NAME);
            conn = DriverManager.getConnection(CONNECTION, USER, PASS);
            conn.setAutoCommit(false);
            statement = conn.createStatement();
            for (Input ip : input) {
                int n_app_timing_score = 100;
                int p_app_timing_score = 100;
                int app_method_score = 0;
                int n_app_rate_score = 0;
                int p_app_rate_score = 0;
                int this_crop_id = 0;
                ArrayList<Crop> cropList = ip.getCropList();
                for (Crop crop : cropList) {
                    ArrayList<Nutrient> nutrientApplicationList = crop.getNutrientApplicationList();
                    this_crop_id = crop.getMgtCropId();

                    //#Determine crop type of the crop
                    query = "SELECT wqm_crop_type FROM wqm_crops WHERE wqm_crop_id=" + this_crop_id + ";";
                    resultSet = statement.executeQuery(query);
                    String crop_type = "err";
                    while (resultSet.next()) {
                        crop_type = resultSet.getString("wqm_crop_type");
                    }

                    //#Determine whether split nutrient applications or not
                    int app_count = 0;
                    String app_type;
                    //For each nutrient_application_date in the crop period
                    //for (Nutrient i : nutrientApplication) {
                    //    app_count = app_count + 1;
                    //}
                    app_count = nutrientApplicationList.size();
                    if (app_count == 1) {
                        app_type = "nosplit";
                    } else {
                        app_type = "split";
                    }
                    //If no nutrient_application_date (no nutrient applications for the crop)
                    int ncrop_app_rate_score = 0;
                    int pcrop_app_rate_score = 0;
                    if (nutrientApplicationList.isEmpty()) {
                        //#Compute score for not fertilizing.
                        query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "None" + "';";
                        resultSet = statement.executeQuery(query);
                        while (resultSet.next()) {
                            n_app_rate_score = resultSet.getInt("app_mgt_score");
                        }
                        switch (ip.getPSoilTestResult()) {
                            case "High": {
                                query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "None" + "' AND soil_test_result='" + "High" + "';";
                                resultSet = statement.executeQuery(query);
                                while (resultSet.next()) {
                                    p_app_rate_score = resultSet.getInt("app_mgt_score");
                                }
                                break;
                            }
                            case "Medium": {
                                query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "None" + "' AND soil_test_result='" + "Medium" + "';";
                                resultSet = statement.executeQuery(query);
                                while (resultSet.next()) {
                                    p_app_rate_score = resultSet.getInt("app_mgt_score");
                                }
                                break;
                            }
                            case "None": {
                                query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "None" + "' AND soil_test_result='" + "None" + "';";
                                resultSet = statement.executeQuery(query);
                                while (resultSet.next()) {
                                    p_app_rate_score = resultSet.getInt("app_mgt_score");
                                }
                            }
                        }
                    } else { //Else #Compute N and P removal ratios
                        double nrate = 0.0;
                        double prate = 0.0;
                        for (Nutrient nutrient : nutrientApplicationList) {
                            ArrayList<NutrientApplied> nutrientAppliedList = nutrient.getNutrientAppliedList();
                            for (NutrientApplied nApplied : nutrientAppliedList) {
                                if (nApplied.getNutrientApplied().equals("Nitrogen")) {
                                    nrate = nrate + nApplied.getApplicationRate();
                                } else {
                                    prate = prate + nApplied.getApplicationRate();
                                }
                            }
                        }
                        double wqm_crop_pct_dmat = 0.0;
                        double wqm_pct_nitrogen = 0.0;
                        double wqm_pct_phosphorus = 0.0;
                        query = "SELECT wqm_crop_pct_dmat, wqm_pct_nitrogen, wqm_pct_phosphorus FROM wqm_crops WHERE wqm_crop_id=" + this_crop_id + ";";
                        resultSet = statement.executeQuery(query);
                        while (resultSet.next()) {
                            wqm_crop_pct_dmat = resultSet.getDouble("wqm_crop_pct_dmat");
                            wqm_pct_nitrogen = resultSet.getDouble("wqm_pct_nitrogen");
                            wqm_pct_phosphorus = resultSet.getDouble("wqm_pct_phosphorus");
                        }

                        double n_growout = crop.getCropYield() * wqm_crop_pct_dmat * wqm_pct_nitrogen;
                        double p_growout = crop.getCropYield() * wqm_crop_pct_dmat * wqm_pct_phosphorus;

                        double n_remove_ratio = nrate / n_growout;
                        double p_remove_ratio = prate / p_growout;

                        //#Compute N application management rate score based on removal ratio and whether small grain or not
                        if (crop_type.equals("small grain")) {
                            query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "small grain" + "' AND remove_ratio_1 <= " + n_remove_ratio + "AND remove_ratio_2 > " + n_remove_ratio + ";";
                            resultSet = statement.executeQuery(query);
                            while (resultSet.next()) {
                                ncrop_app_rate_score = resultSet.getInt("app_mgt_score");
                            }
                        } else {
                            query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "other" + "' AND remove_ratio_1 <= " + n_remove_ratio + "AND remove_ratio_2 > " + n_remove_ratio + ";";
                            resultSet = statement.executeQuery(query);
                            while (resultSet.next()) {
                                ncrop_app_rate_score = resultSet.getInt("app_mgt_score");
                            }
                        }

                        //#Compute P application management rate scores based on removal ratio and soil test result
                        switch (ip.getPSoilTestResult()) {
                            case "High": {
                                if (p_remove_ratio >= 1.2) {
                                    pcrop_app_rate_score = 0;
                                } else {
                                    query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "app" + "' AND soil_test_result'=" + "High" + "'AND remove_ratio_1 <= " + p_remove_ratio + "AND remove_ratio_2 > " + p_remove_ratio + ";";
                                    resultSet = statement.executeQuery(query);
                                    while (resultSet.next()) {
                                        pcrop_app_rate_score = resultSet.getInt("app_mgt_score");
                                    }
                                }
                                break;
                            }
                            case "Medium": {
                                if (p_remove_ratio >= 1.6) {
                                    pcrop_app_rate_score = 0;
                                } else {
                                    query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "app" + "' AND soil_test_result'=" + "Medium" + "'AND remove_ratio_1 <= " + p_remove_ratio + "AND remove_ratio_2 > " + p_remove_ratio + ";";
                                    resultSet = statement.executeQuery(query);
                                    while (resultSet.next()) {
                                        pcrop_app_rate_score = resultSet.getInt("app_mgt_score");
                                    }
                                }
                                break;
                            }
                            case "Low": {
                                if (p_remove_ratio >= 1.6) {
                                    pcrop_app_rate_score = 0;
                                } else {
                                    query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "app" + "' AND soil_test_result'=" + "Low" + "'AND remove_ratio_1 <= " + p_remove_ratio + "AND remove_ratio_2 > " + p_remove_ratio + ";";
                                    resultSet = statement.executeQuery(query);
                                    while (resultSet.next()) {
                                        pcrop_app_rate_score = resultSet.getInt("app_mgt_score");
                                    }
                                }
                                break;
                            }
                            case "None": {
                                if (p_remove_ratio >= 1.2) {
                                    pcrop_app_rate_score = 0;
                                } else {
                                    query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor='" + "app" + "' AND soil_test_result'=" + "None" + "'AND remove_ratio_1 <= " + p_remove_ratio + "AND remove_ratio_2 > " + p_remove_ratio + ";";
                                    resultSet = statement.executeQuery(query);
                                    while (resultSet.next()) {
                                        pcrop_app_rate_score = resultSet.getInt("app_mgt_score");
                                    }
                                }
                                break;
                            }
                        }
                        //#Update N and P application management rate scores for the AoA
                        n_app_rate_score = n_app_rate_score + ncrop_app_rate_score;
                        p_app_rate_score = p_app_rate_score + pcrop_app_rate_score;
                    }
                    //#Compute N and P application timing scores for the crop and update timin scores for the AoA
                    int ncrop_app_timing_score = 0;
                    int pcrop_app_timing_score = 0;
                    for (Nutrient nutrient : nutrientApplicationList) {
                        long app_day_diff = Dates.diffInMillis(crop.getCropPlantDate(), nutrient.getApplicationDate());
                        app_day_diff = TimeUnit.MICROSECONDS.convert(app_day_diff, TimeUnit.DAYS);
                        ArrayList<NutrientApplied> nutrientAppliedList = nutrient.getNutrientAppliedList();
                        for (NutrientApplied nApplied : nutrientAppliedList) {
                            switch (nApplied.getNutrientApplied()) {
                                case "Nitrogen": {
                                    if (app_type.equals("split")) {
                                        query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Timing" + "' AND app_mgt_factor='" + "split" + "'AND days_fr_plant_1 <= " + app_day_diff + "AND days_fr_plant_2 > " + app_day_diff + ";";
                                        resultSet = statement.executeQuery(query);
                                        while (resultSet.next()) {
                                            ncrop_app_timing_score = resultSet.getInt("app_mgt_score");
                                            //Doubt
                                            if (resultSet.wasNull()) {
                                                n_app_timing_score = 0;
                                            } else if (ncrop_app_timing_score < n_app_timing_score) {
                                                n_app_timing_score = ncrop_app_timing_score;
                                            }
                                        }

                                    } else {
                                        query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Timing" + "' AND app_mgt_factor='" + "nosplit" + "'AND days_fr_plant_1 <= " + app_day_diff + "AND days_fr_plant_2 > " + app_day_diff + ";";
                                        resultSet = statement.executeQuery(query);
                                        while (resultSet.next()) {
                                            ncrop_app_timing_score = resultSet.getInt("app_mgt_score");
                                            //Doubt
                                            if (resultSet.wasNull()) {
                                                n_app_timing_score = 0;
                                            } else if (ncrop_app_timing_score < n_app_timing_score) {
                                                n_app_timing_score = ncrop_app_timing_score;
                                            }
                                        }
                                    }
                                    break;
                                }
                                case "Phosphorus": {
                                    if (app_type.equals("split")) {
                                        query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Timing" + "' AND app_mgt_factor='" + "split" + "'AND days_fr_plant_1 <= " + app_day_diff + "AND days_fr_plant_2 > " + app_day_diff + ";";
                                        resultSet = statement.executeQuery(query);
                                        while (resultSet.next()) {
                                            pcrop_app_timing_score = resultSet.getInt("app_mgt_score");
                                            //Doubt
                                            if (resultSet.wasNull()) {
                                                p_app_timing_score = 0;
                                            } else if (pcrop_app_timing_score < p_app_timing_score) {
                                                p_app_timing_score = ncrop_app_timing_score;
                                            }
                                        }
                                    } else {
                                        query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Phosphorus" + "' AND app_mgt_kind='" + "Timing" + "' AND app_mgt_factor='" + "nosplit" + "'AND days_fr_plant_1 <= " + app_day_diff + "AND days_fr_plant_2 > " + app_day_diff + ";";
                                        resultSet = statement.executeQuery(query);
                                        while (resultSet.next()) {
                                            pcrop_app_timing_score = resultSet.getInt("app_mgt_score");
                                            //Doubt
                                            if (resultSet.wasNull()) {
                                                p_app_timing_score = 0;
                                            } else if (pcrop_app_timing_score < p_app_timing_score) {
                                                p_app_timing_score = pcrop_app_timing_score;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    for (Nutrient nutrient : nutrientApplicationList) {
                        //#If any nutrient application for any crop is not incorporated, the method score for the AoA is zero
                        if (!nutrient.isIncorporated()) {
                            app_method_score = 0;
                            break;
                        } else if (nutrient.isIncorporated()) { //#If all nutrient applications for all crops are incorporated, the method score for incorporation applies to the AoA
                            query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE app_mgt_kind='" + "Method" + "' AND app_mgt_factor='" + "incorporate" + "';";
                            resultSet = statement.executeQuery(query);
                            while (resultSet.next()) {
                                app_method_score = resultSet.getInt("app_mgt_score");
                            }
                        }
                    }
                }
                //#Compute application management scores for nitrogen in groundwater, nitrogen in surface water, and phosphorus in surface water
                int nleach_app_mgt_score = n_app_rate_score + n_app_timing_score + app_method_score;
                int nsurf_app_mgt_score = n_app_rate_score + n_app_timing_score + app_method_score;
                int psurf_app_mgt_score = p_app_rate_score + p_app_timing_score + app_method_score;
                m.wqm.nutappmgtscores.Result result1 = new m.wqm.nutappmgtscores.Result(ip.getAoAId(), nleach_app_mgt_score, nsurf_app_mgt_score, psurf_app_mgt_score, n_app_rate_score, n_app_timing_score, p_app_rate_score, p_app_timing_score, app_method_score);
                result.add(result1);
            }
            conn.close();
        } catch (SQLException se) {
            LOG.info("Did not open database for WQM-16!");
            LOG.info(se.getMessage());
        } finally {
            if (statement != null) {
                statement.close();
            }
            if (conn != null) {
                conn.close();
            }
        }
        return EXEC_OK;
    }

    @Override
    //writing the results back to JSON
    protected void postProcess() throws Exception {
        JSONArray resultArr = new JSONArray();
        for (m.wqm.nutappmgtscores.Result rs1 : result) {
            JSONArray tmpArr = new JSONArray();
            tmpArr.put(JSONUtils.dataDesc("AoAId", rs1.getAoAId(), "Area of Analysis Identifier"));
            tmpArr.put(JSONUtils.dataDesc("nleach_app_mgt_score", rs1.getNleachAppMgtScore(), "Nitrogen Application Management Score for Mitigating Leaching Loss Potential"));
            tmpArr.put(JSONUtils.dataDesc("nsurf_app_mgt_score", rs1.getNsurfAppMgtScore(), "Nitrogen Application Management Score for Mitigating Surface Runoff Loss Potential"));
            tmpArr.put(JSONUtils.dataDesc("psurf_app_mgt_score", rs1.getPsurfAppMgtScore(), "Phosphorus Application Management Score for Mitigating Surface Runoff Loss Potential"));
            tmpArr.put(JSONUtils.dataDesc("n_app_rate_score", rs1.getnAppRateScore(), "Nitrogen Application Rate Mitigation Score"));
            tmpArr.put(JSONUtils.dataDesc("n_app_timing_score", rs1.getnAppTimingScore(), "Nitrogen Application Timing Mitigation Score"));
            tmpArr.put(JSONUtils.dataDesc("p_app_rate_score", rs1.getpAppRateScore(), "Phosphorus Application Rate Mitigation Score"));
            tmpArr.put(JSONUtils.dataDesc("p_app_timing_score", rs1.getpAppTimingScore(), "Phosphorus Application Timing Mitigation Score"));
            tmpArr.put(JSONUtils.dataDesc("app_method_score", rs1.getAppMethodScore(), "Nutrient Application Method Mitigation Score"));
            resultArr.put(JSONUtils.dataDesc("Nutrition Application Summary", tmpArr, "Nutrition Application Summary"));
        }
        putResult("Result", resultArr);
    }
}