V1_0.java [src/java/m/wqm/nutappmgtscores] Revision: cdaf7e395ccc063ea3848164e6a18c0e090681d0  Date: Sat Jun 13 20:25:38 MDT 2015
package m.wqm.nutappmgtscores;

/**
 *
 * @author RUMPAL SIDHU
 */
import csip.ModelDataService;
import static csip.ModelDataService.EXEC_OK;
import csip.utils.JSONUtils;
import csip.utils.Dates;
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.Calendar;
import java.util.Map;
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 java.util.Date;
import java.util.concurrent.TimeUnit;

@Name("WQM-16")
@Description("Nutrient Application Management Scores")
@Path("m/nutappmgtscores/1.0")

public class V1_0 extends ModelDataService {

    //SQL params here for quick modification
    private final String USER = "postgres";
    private final String PASS = "postgresql";
    private final String SERVER = "localhost:5432/postgres";
    private final String JDBC_TYPE = "jdbc:postgresql://";
    private final String CLASS_NAME = "org.postgresql.Driver";

    ArrayList<m.wqm.nutappmgtscores.Input> input = new ArrayList<>(); //Store input
    ArrayList<m.wqm.nutappmgtscores.Result> result = new ArrayList<>(); //Store result

    @Override
    // reading the inputs from the json file into input object and placing it in the arraylist
    protected void preProcess() throws Exception {

        int AoAId = getIntParam("aoa_id", 0);
        String p_soil_test_result = getStringParam("p_soil_test_result", "err");
        ArrayList<Crop> cropList = new ArrayList<>();
        
        //System.out.println("AoAId = " + AoAId);
        //System.out.println("p_soil_test_result = " + p_soil_test_result);

        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);
            boolean lmod = JSONUtils.getBooleanParam(mgtCropId, "from_lmod", false);
            String cropPlantDate = JSONUtils.getStringParam(mgtCropId, "crop_plant_date", "err");
            //Date crop_plant_date = Dates.parse(crop_plant_date_string);
            double cropYield = JSONUtils.getDoubleParam(mgtCropId, "crop_yield", 0);
            String cropYieldUnits = JSONUtils.getStringParam(mgtCropId, "crop_yield_units", "err");

            //System.out.println("cropId = " + cropId);
            //System.out.println("lmod = " + lmod);
            //System.out.println("cropPlantDate = " + cropPlantDate);
           // System.out.println("cropYield = " + cropYield);
            //System.out.println("cropYieldUnits = " + cropYieldUnits);
            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);

                //tem.out.println("nutrient_application_date = " + nutrient_application_date);
               // System.out.println("incorporated = " + incorporated);
                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);
                    //System.out.println("nutrient_applied = " + nutrient_applied);
                    //System.out.println("application_rate = " + application_rate);
                    
                    nutrientAppliedList.add(new NutrientApplied(nutrient_applied, application_rate));
                }
                nutrientApplicationList.add(new Nutrient(nutrient_application_date, incorporated, nutrientAppliedList));
            }
            cropList.add(new Crop(cropId, lmod, cropPlantDate, cropYield, cropYieldUnits, nutrientApplicationList));
        }
        input.add(new m.wqm.nutappmgtscores.Input(AoAId, cropList, p_soil_test_result));
        //tem.out.println(input.size());
       // System.out.println("Input = " + input.get(0));
    }

    @Override
    protected String process() throws Exception {

        Connection conn = null;
        Statement statement = null;
        String query;
        ResultSet resultSet = null;

        try {
            Class.forName(CLASS_NAME);
            conn = DriverManager.getConnection(JDBC_TYPE + SERVER, USER, PASS);
            //System.out.println("Closed = " + conn.isClosed());
            conn.setAutoCommit(false);

            statement = conn.createStatement();

            for (m.wqm.nutappmgtscores.Input ip : input) {
                //System.out.println("In for 1");
                
                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) {
                    //System.out.println("Crop loop");
                    ArrayList<Nutrient> nutrientApplicationList = crop.getNutrientApplicationList();

                    //#If request payload crop is an LMOD vegetation, then convert it to a wqm_crop using the link table
                    if (crop.getLmod()) {
                        query = "SELECT wqm_crop_id FROM wqm_lmod_crop_link WHERE lmod_crop_id=" + crop.getMgtCropId() + ";";
                        resultSet = statement.executeQuery(query);
                        while (resultSet.next()) {
                            this_crop_id = resultSet.getInt("wqm_crop_id");
                        }
                    } else {
                        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";
                    }

                   // System.out.println("crop id" + this_crop_id);
                   // System.out.println("crop type" + crop_type);
                  //  System.out.println("app type" + app_type);
                    //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()) {
                    //    System.out.println("nutrientApplicationList is empty");
                        
                        //#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

                      //  System.out.println("nutrientApplicationList is not empty!!!");
                        
                        double nrate = 0.0;
                        double prate = 0.0;

                        for (Nutrient nutrient : nutrientApplicationList) {
                      //      System.out.println("In nutrientApplicationList for loop!!!");
                            
                            ArrayList<NutrientApplied> nutrientAppliedList = nutrient.getNutrientAppliedList();
                            for (NutrientApplied nApplied : nutrientAppliedList) {
                          //      System.out.println("nApplied = " + nApplied.getNutrientApplied());
                                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);
                      //  System.out.println(app_day_diff);

                        ArrayList<NutrientApplied> nutrientAppliedList = nutrient.getNutrientAppliedList();
                        for (NutrientApplied nApplied : nutrientAppliedList) {
                       //     System.out.println("In for nApplied");
                            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;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                  //      System.out.println("out of nApplied");
                    }
                    for (Nutrient nutrient : nutrientApplicationList) {
                  //      System.out.println("final for loop");
                        //#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");

                            }

                        }

                    }
          //          System.out.println("Out of final loop");
                }
           //     System.out.println("Out");
                //#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);
            }
         //   System.out.println("out of for");
            conn.close();
       //     System.out.println("closed = " + conn.isClosed());
        } catch (SQLException se) {
      //      System.out.println(se.getCause());
       //     System.out.println(se.getStackTrace());
            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);
    }
}