Displaying differences for changeset
 
display as  

src/java/m/wqm/nutappmgtscores/Crop.java

@@ -3,35 +3,270 @@
 /**
  *
  * @author RUMPAL SIDHU
+ * @author Shaun Case
  */
+import csip.utils.Dates;
+import csip.utils.JSONUtils;
+
 import java.util.Date;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.GregorianCalendar;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONObject;
 
 public class Crop {
 
+    //  Inner Classes
+    class NutrientApplication {
+    
+        class Nutrient {
+            private String error_msg = "";
+            private String nutrientApplied;
+            private double applicationRate;
+
+            public Nutrient(String nutrientApplied, double applicationRate) {
+                this.nutrientApplied = nutrientApplied;
+                this.applicationRate = applicationRate;
+                
+                if ( !nutrientApplied.equals("Nitrogen") && !nutrientApplied.equals("Phosphorus") ) {
+                    this.error_msg += "Invalid input data.  Bad nutrient name";
+                } 
+            }
+
+            //Get Methods
+            public String getNutrientApplied() {
+                return this.nutrientApplied;
+            }
+
+            public double getApplicationRate() {
+                return this.applicationRate;
+            }
+            
+            public String getErrorMsg(){
+                return this.error_msg;
+            }      
+
+            public Boolean validate(){
+                return (this.error_msg.isEmpty());
+            }
+       }
+
+        private String error_msg = "";
+        private String applicationDate;
+        private boolean incorporated;
+        private ArrayList<Crop.NutrientApplication.Nutrient> nutrientList;
+        private int appMethodScore = 0; 
+        private int[] nutrientTimingScores = new int[2];
+
+        public NutrientApplication(String applicationDate, String incorporated, JSONArray applications) {
+            this.applicationDate = applicationDate;
+            nutrientTimingScores[N_APP_TIMING_SCORE] = nutrientTimingScores[P_APP_TIMING_SCORE] = -1;
+           
+            if ( ( !"true".equalsIgnoreCase(incorporated) ) && ( !"false".equalsIgnoreCase(incorporated) ) ) {
+                this.error_msg += "Invalid incorporation value for nutrient application " + applicationDate;
+            }
+            else{
+                this.incorporated = Boolean.parseBoolean(incorporated);               
+                nutrientList = new ArrayList<>();
+             
+                try{
+                    for (int k = 0; k < applications.length(); k++) {
+                        Map<String, JSONObject> nutrient = JSONUtils.preprocess(applications.getJSONArray(k));              
+                        nutrientList.add(new Crop.NutrientApplication.Nutrient(JSONUtils.getStringParam(nutrient, "nutrient_applied", "err"), JSONUtils.getDoubleParam(nutrient, "application_rate", 0)));
+                    }                 
+                }
+                catch(Exception ex){
+                    this.error_msg += "Cannot process applied nutrient list.  " + ex.getMessage();
+                }                   
+            }
+       }
+
+        //Get Methods
+        public Date getApplicationDate() throws Exception {
+            String[] parse = this.applicationDate.split("-");
+            //Some say should set to use UTC first...do we wanna do that?
+            Calendar date = new GregorianCalendar(Integer.parseInt(parse[0]),
+                    Integer.parseInt(parse[1]) - 1, Integer.parseInt(parse[2]));
+            return date.getTime();
+        }
+
+        public boolean isIncorporated() {
+            return this.incorporated;
+        }
+
+        public ArrayList getNutrientList() {
+            return this.nutrientList;
+        }
+       
+        public String getErrorMsg(){
+            for (Crop.NutrientApplication.Nutrient nutrient : this.nutrientList ){
+                this.error_msg += nutrient.getErrorMsg();
+            }
+            return this.error_msg;
+        }    
+        
+        public Boolean validate(){            
+            for( Crop.NutrientApplication.Nutrient nutrient : nutrientList )
+                if ( !nutrient.validate() )
+                    this.error_msg += "; " + nutrient.getErrorMsg();
+
+            return (this.error_msg.isEmpty());
+        } 
+        
+        public int[] getNutrientTimingScores( Boolean split ){
+            if ( ( nutrientTimingScores[N_APP_TIMING_SCORE] < 0 ) || ( nutrientTimingScores[P_APP_TIMING_SCORE] < 0 ) ){
+                int tempNScore = 100;
+                int tempPScore = 100;
+                ResultSet resultSet;
+                
+                for ( Crop.NutrientApplication.Nutrient nutrient : nutrientList ){
+                    int app_timing_score;
+                            
+                    try{
+                        long app_day_diff = Dates.diffInMillis( getCropPlantDate(), getApplicationDate() );
+                        app_day_diff = TimeUnit.MILLISECONDS.toDays(app_day_diff);
+
+                        String query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='";
+
+                        query += nutrient.getNutrientApplied() + "' ";
+                        query += "AND app_mgt_kind='Timing' AND app_mgt_factor='" + (split? "split":"nosplit") + "'AND days_fr_plant_1 <= " + app_day_diff + "AND days_fr_plant_2 > " + app_day_diff + ";";
+                        
+                        resultSet = statement.executeQuery(query);
+                        if ( !resultSet.first() ) {
+                            app_timing_score = -1;
+                        }
+                        else {
+                            app_timing_score = resultSet.getInt("app_mgt_score");
+                        }
+                        
+                        switch (nutrient.getNutrientApplied())
+                        {
+                            case "Nitrogen":
+                                if ( app_timing_score < tempNScore )
+                                    tempNScore = app_timing_score;                                
+                                break;
+                                
+                            case "Phosphorus":
+                                if ( app_timing_score < tempPScore )
+                                    tempPScore = app_timing_score;                                
+                                break;
+                                
+                            default:
+                                this.error_msg += "Invalid nutrient name specified";
+                        }                        
+                    }
+                    catch (Exception ex){
+                        this.error_msg += "Cannot calculate nutrient application timing scores: " + ex.getMessage();
+                    }       
+                    
+                    if ( this.error_msg.isEmpty() ){
+                        nutrientTimingScores[N_APP_TIMING_SCORE] = tempNScore;
+                        nutrientTimingScores[P_APP_TIMING_SCORE] = tempPScore;
+                    }                        
+                }                                
+            }
+            
+            return nutrientTimingScores;
+        }
+        
+        public Boolean allNutrientsIncorporated(){
+            return this.incorporated;
+        }
+   }
+    
+    
+    //  Begin Crop Class
+    public static final int N_APP_RATE_SCORE = 0;
+    public static final int P_APP_RATE_SCORE = 1;
+    public static final int N_APP_TIMING_SCORE = 0;
+    public static final int P_APP_TIMING_SCORE = 1;
+    
     private int mgtCropId;
     private String cropPlantDate;
+    private Date plantDate;
     private double cropYield;
     private String cropYieldUnits;
-    private ArrayList<Nutrient> nutrientApplicationList;
-
+    private ArrayList<Crop.NutrientApplication> nutrientApplicationList;
+    private m.wqm.nutappmgtscores.Result calc_result;
+    private Statement statement;
+    private String cropType = "";
+    private String error_msg = "";
+    private Boolean multipleNutrientApplication = false;
+    private int n_app_timing_score = 100;
+    private int p_app_timing_score = 100;
+    private int app_method_score = 0;
+    private int[] appRateScore = new int[2];
+    private int[] appNutrientTimingScore = new int[2];
+    private String pSoilTestResult = "None";
+  
     public Crop(int mgtCropId,String cropPlantDate, double cropYield,
-            String cropYieldUnits, ArrayList<Nutrient> nutrientApplicationList) {
+                String cropYieldUnits, JSONArray applicationList, String pSoilTestResult, Statement statement){
         this.mgtCropId = mgtCropId;
         this.cropPlantDate = cropPlantDate;
         this.cropYield = cropYield;
         this.cropYieldUnits = cropYieldUnits;
-        this.nutrientApplicationList = nutrientApplicationList;
+        this.statement = statement;
+        this.pSoilTestResult = pSoilTestResult;
+     
+        nutrientApplicationList = new ArrayList<>();
+        
+        try{
+            plantDate = getCropPlantDate();
+            for (int j = 0; j < applicationList.length(); j++) {
+                Map<String, JSONObject> application = JSONUtils.preprocess(applicationList.getJSONArray(j));
+                nutrientApplicationList.add(new Crop.NutrientApplication(JSONUtils.getStringParam(application, "nutrient_application_date", "err"), JSONUtils.getStringParam(application, "incorporated", ""), JSONUtils.getJSONArrayParam(application, "application")));              
+            }            
+        }
+        catch( Exception ex){
+           error_msg += "Cannot process list of applied nutrients.  " + ex.getMessage(); 
+        }
+
+        multipleNutrientApplication = (nutrientApplicationList.size() > 1);           
+        this.appRateScore[N_APP_RATE_SCORE] = this.appRateScore[P_APP_RATE_SCORE] = -1;
+        this.appNutrientTimingScore[N_APP_TIMING_SCORE] = this.appNutrientTimingScore[P_APP_TIMING_SCORE] = -1;
     }
 
-    //Getter methods
+    //Get methods
     public int getMgtCropId() {
         return this.mgtCropId;
     }
 
-    public Date getCropPlantDate() throws Exception {
+    public String getErrorMsg(){
+        for ( Crop.NutrientApplication nutrientApplied: this.nutrientApplicationList ){
+            error_msg += nutrientApplied.getErrorMsg();
+        }
+        return error_msg;
+    }
+    
+    public String getCropType(){
+        if ( (cropType.isEmpty()) && (error_msg.isEmpty()) ){
+            ResultSet resultSet;                   
+            String query = "SELECT wqm_crop_type FROM wqm_crops WHERE wqm_crop_id=" + mgtCropId + " AND wqm_crop_units='" + cropYieldUnits + "';";
+            try{
+                resultSet = statement.executeQuery(query);
+                if (!resultSet.first()){
+                    error_msg += "That crop, " + mgtCropId + ", and crop yield units, "+ cropYieldUnits + ", was not found in the database";
+                }
+                else{                        
+                    cropType = resultSet.getString("wqm_crop_type");   
+                }
+            }
+            catch( Exception ex ) {
+                error_msg += ex.getMessage();
+            }
+        }
+        return cropType;
+    }
+    public final Date getCropPlantDate() throws Exception {
         String[] parse = this.cropPlantDate.split("-");
         Calendar date = new GregorianCalendar(Integer.parseInt(parse[0]),
                 Integer.parseInt(parse[1]) - 1, Integer.parseInt(parse[2]));
@@ -49,4 +284,186 @@
     public ArrayList getNutrientApplicationList() {
         return this.nutrientApplicationList;
     }
+    
+    public int[] getNutrientApplicationRateScores(){
+        if ( ( appRateScore[N_APP_RATE_SCORE] <0 ) || ( appRateScore[P_APP_RATE_SCORE] <0 ) ) {
+            try{
+                if ( nutrientApplicationList.isEmpty() ){
+                    ResultSet resultSet;                   
+
+                    appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0;            
+                    String queryNitrogen = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='Nitrogen' AND app_mgt_kind='Rate' AND app_mgt_factor='none';";
+                    String queryPhosporous = "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='" + pSoilTestResult + "';";
+
+                    resultSet = statement.executeQuery(queryNitrogen);
+                    if ( resultSet.first() )
+                        appRateScore[N_APP_RATE_SCORE] = resultSet.getInt("app_mgt_score");
+
+                    resultSet = statement.executeQuery(queryPhosporous);
+                    if ( resultSet.first() )
+                        appRateScore[P_APP_RATE_SCORE] = resultSet.getInt("app_mgt_score");  
+                }
+                else{
+                    ResultSet resultSet;
+                    String query;
+                    
+                    double nrate = 0.0;
+                    double prate = 0.0;
+
+                    double wqm_crop_pct_dmat = 0.0;
+                    double wqm_pct_nitrogen = 0.0;
+                    double wqm_pct_phosphorus = 0.0;
+                    double wqm_crop_yield = 0.0;
+                                        
+                    int ncrop_app_rate_score = 0;
+                    int pcrop_app_rate_score = 0;                       
+                    
+                    for (Crop.NutrientApplication nutrient : nutrientApplicationList) {
+                        ArrayList<Crop.NutrientApplication.Nutrient> nutrientAppliedList = nutrient.getNutrientList();
+                        for (Crop.NutrientApplication.Nutrient nApplied : nutrientAppliedList) {
+                            switch(nApplied.getNutrientApplied()){  //Note:  This switch requires JDK 1.7 or above
+                                case "Nitrogen":
+                                    nrate = nrate + nApplied.getApplicationRate();
+                                    break;
+                                case "Phosphorus":
+                                    prate = prate + nApplied.getApplicationRate();
+                                    break;                                                                                                 
+                            }
+                        }
+                    }
+                    
+                    query = "SELECT wqm_crop_pct_dmat, wqm_pct_nitrogen, wqm_pct_phosphorus, wqm_crop_yield FROM wqm_crops WHERE wqm_crop_id=" + mgtCropId + ";";
+                    resultSet = statement.executeQuery(query);
+                    if (resultSet.first()) {
+                        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");
+                        wqm_crop_yield = resultSet.getDouble("wqm_crop_yield");
+                        
+                        //  Added wqm_crop_yield to the calc per bug #462839
+                        double n_growout = cropYield * wqm_crop_yield * wqm_crop_pct_dmat * wqm_pct_nitrogen;
+                        double p_growout = cropYield * wqm_crop_yield * wqm_crop_pct_dmat * wqm_pct_phosphorus;
+
+                        double n_remove_ratio = nrate / n_growout;
+                        double p_remove_ratio = prate / p_growout;      
+
+                        query = "SELECT app_mgt_score FROM wqm_nutrient_application_mgt_scores WHERE nutrient='" + "Nitrogen" + "' AND app_mgt_kind='" + "Rate" + "' AND app_mgt_factor=";
+
+                        switch( cropType ){
+                            case "Small Grain":  //Note the case conflicts here...
+                                query += "'small grain'";
+                                break;
+
+                            default:  
+                                query += "'none'";
+                        }   
+                        query += " AND remove_ratio_1 <= " + n_remove_ratio + "AND remove_ratio_2 > " + n_remove_ratio + ";";
+                        
+                        resultSet = statement.executeQuery(query);
+                        if (resultSet.first()) {
+                            ncrop_app_rate_score = resultSet.getInt("app_mgt_score");
+                        }
+                        else{
+                            appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0;
+                        }
+                            
+                        pcrop_app_rate_score = -1;
+                        //#Compute P application management rate scores based on removal ratio and soil test result
+                        switch (pSoilTestResult){
+                            case "High":
+                               if (p_remove_ratio >= 1.2) {
+                                    pcrop_app_rate_score = 0;
+                                }
+                                break;
+                            case "Medium": case "Low":
+                                if (p_remove_ratio >= 1.6) {
+                                    pcrop_app_rate_score = 0;
+                                }
+                                break;
+                            case "None":
+                                if (p_remove_ratio >= 1.2) {
+                                    pcrop_app_rate_score = 0;
+                                }
+                                break;                                                                                                                                                                                     
+                        }
+
+                        if ( pcrop_app_rate_score == -1 ){
+                            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='" + pSoilTestResult +"' AND remove_ratio_1 <= " + p_remove_ratio + " AND remove_ratio_2 > " + p_remove_ratio + ";";
+                            resultSet = statement.executeQuery(query);
+                            if (resultSet.first()) {
+                                 pcrop_app_rate_score = resultSet.getInt("app_mgt_score");
+                             }                                   
+                        }
+
+                        if (pcrop_app_rate_score != -1){
+                        //#Update N and P application management rate scores for the AoA
+                        appRateScore[N_APP_RATE_SCORE] = ncrop_app_rate_score;
+                        appRateScore[P_APP_RATE_SCORE] = pcrop_app_rate_score;                                                                                                
+                        }
+                        else{//We have a problem...no validity in any following computations if we proceed since the last query failed to find any data.  What would you like to do?
+                            appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0;
+                        }                                                                                                                                                                                                                                                                                                                                                                              
+                    }
+                    else{ //We have a problem...no validity in any following computations if we proceed.  What would you like to do?
+                        appRateScore[N_APP_RATE_SCORE] = appRateScore[P_APP_RATE_SCORE] = 0;
+                    }                                                       
+                }
+            }
+            catch (Exception ex) {
+                error_msg += ex.getMessage();
+            }                   
+        }
+       
+        return this.appRateScore;
+    }
+    
+    public int[] getNutrientApplicationTimingScores(){
+        if ( ( appNutrientTimingScore[N_APP_TIMING_SCORE]  <0 ) || ( appNutrientTimingScore[P_APP_TIMING_SCORE]  <0 ) ) {
+            int tempNScore = 100;
+            int tempPScore = 100;
+            
+            for ( Crop.NutrientApplication nutrientApplication : this.nutrientApplicationList ){
+                //  Call each application compare its results to the last and adjust main score if necessary.
+                int[] tempAppTimingScores = nutrientApplication.getNutrientTimingScores( this.multipleNutrientApplication );
+                
+                if ( tempAppTimingScores[N_APP_TIMING_SCORE] < tempNScore )
+                    tempNScore = tempAppTimingScores[N_APP_TIMING_SCORE];
+                
+                if ( tempAppTimingScores[P_APP_TIMING_SCORE] < tempPScore )
+                    tempPScore = tempAppTimingScores[P_APP_TIMING_SCORE];                               
+            }
+            
+            appNutrientTimingScore[P_APP_TIMING_SCORE] = tempPScore;
+            appNutrientTimingScore[N_APP_TIMING_SCORE] = tempNScore;
+        }
+                
+        return this.appNutrientTimingScore;                        
+    }
+            
+    public Boolean allNutrientsIncorporated(){
+        Boolean ret_val = true;
+        for( Crop.NutrientApplication nutrientApplication : this.nutrientApplicationList ){
+            if ( !nutrientApplication.allNutrientsIncorporated() ){
+                ret_val = false;
+                break;
+            }
+        }
+        
+        return ret_val;
+    }
+    
+    public String processCropData(){
+        String ret_val = "";
+        
+        return ret_val;
+    }
+    
+    public Boolean validate(){          
+        for( Crop.NutrientApplication tNutrientApplication : nutrientApplicationList )
+            if ( !tNutrientApplication.validate() )
+                error_msg += "; " + tNutrientApplication.getErrorMsg();                
+
+        
+        return ( error_msg.isEmpty() );
+    }
 }

src/java/m/wqm/nutappmgtscores/V1_0.java

@@ -3,7 +3,10 @@
 /**
  *
  * @author RUMPAL SIDHU
+ * @author Shaun Case
+ * 
  */
+ 
 import csip.ModelDataService;
 import csip.utils.JSONUtils;
 import csip.utils.Dates;
@@ -43,325 +46,143 @@
     private ArrayList<Input> input;
     //Response
     private ArrayList<Result> result;
-
+    
+    //private class variables for this service
+    private int AoAId = 0;
+    private String p_soil_test_result = "err";
+    private ArrayList<Crop> cropList;   
+    private String error_msg = "";
+    private Connection conn = null;
+    private Statement statement = null;    
+    
     @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));
+        try{
+            Class.forName(CLASS_NAME);            
+            conn = DriverManager.getConnection(CONNECTION, USER, PASS);
+            statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
+        }
+        catch(ClassNotFoundException | SQLException ex) {
+            if (ex instanceof SQLException) {
+                LOG.info("Did not open database for WQM-16!");
+                LOG.info(ex.getMessage());      
+                error_msg = "Could not open database for WQM-16!  " + ex.getMessage();
+            }
+            else{
+                error_msg = "Could not instantiate postgres database object: " + ex.getMessage();
+            }                                            
+        }
 
-            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));
+        if (error_msg.isEmpty()){
+            AoAId = getIntParam("aoa_id", 0);
+            p_soil_test_result = getStringParam("p_soil_test_result", "err");
+            cropList = new ArrayList<>();
+
+            JSONArray cropIds = getJSONArrayParam("cropIds");
+            for (int i = 0; i < cropIds.length(); i++) {
+                Map<String, JSONObject> mgtCropId = JSONUtils.preprocess(cropIds.getJSONArray(i));
+                cropList.add( new Crop(JSONUtils.getIntParam(mgtCropId, "mgt_crop_id", 0), JSONUtils.getStringParam(mgtCropId, "crop_plant_date", "err"), 
+                            JSONUtils.getDoubleParam(mgtCropId, "crop_yield", 0), JSONUtils.getStringParam(mgtCropId, "crop_yield_units", "err"), 
+                            JSONUtils.getJSONArrayParam(mgtCropId, "applicationList"), p_soil_test_result, statement));
+            }            
+            
+            ValidateInput();
         }
-        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;
+    protected String process() throws Exception {        
+        String ret_val = EXEC_OK;
+        int n_app_timing_score = 100;
+        int p_app_timing_score = 100;
+        int app_method_score = -1;
+        int n_app_rate_score = 0;
+        int p_app_rate_score = 0;
+        int this_crop_id = 0;
         String query;
         ResultSet resultSet;
+        
+        if ( !error_msg.isEmpty()){
+            ret_val = error_msg;
+        }
+        else{
+            result = new ArrayList<>();
 
-        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();
+            try {
                 for (Crop crop : cropList) {
-                    ArrayList<Nutrient> nutrientApplicationList = crop.getNutrientApplicationList();
-                    this_crop_id = crop.getMgtCropId();
+                    
+                    String crop_type = crop.getCropType();
+//////TODO:  Remember to check for errors from the classes....   ///////                    
+                    if ( !crop_type.isEmpty() ){                                               
+                         //#Update N and P application management rate scores for each crop
+                        int[] app_rate_scores = crop.getNutrientApplicationRateScores();
+                        if ( !(error_msg = crop.getErrorMsg()).isEmpty() )
+                            break;
+                        
+                        //Cummulative sum of N and P application management scores over all crops for the AoA
+                        n_app_rate_score += app_rate_scores[Crop.N_APP_RATE_SCORE];
+                        p_app_rate_score += app_rate_scores[Crop.P_APP_RATE_SCORE];
+                                                
+                        
+                        //#Compute N and P application timing scores for the crop and update timing scores for the AoA
+                        int [] app_time_scores = crop.getNutrientApplicationTimingScores();
+                        if ( !(error_msg = crop.getErrorMsg()).isEmpty() )
+                            break;                        
 
-                    //#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");
+                        //  There is a problem with the logic of the specification here...It does not take into account the actual timing of applications when
+                        //  there are mulitple crops and multiple years invovled....these final values are probably not correct.  The "-1" below is placed here
+                        //  in an attempt to fix the missing database values problem that also exists with this logic at the nutrient level.
+                        if (( app_time_scores[Crop.N_APP_TIMING_SCORE] < n_app_timing_score ) || (n_app_timing_score == -1))
+                            n_app_timing_score = app_time_scores[Crop.N_APP_TIMING_SCORE];
+                        
+                        if (( app_time_scores[Crop.P_APP_TIMING_SCORE] < p_app_timing_score ) || (p_app_timing_score == -1))
+                            p_app_timing_score = app_time_scores[Crop.P_APP_TIMING_SCORE];
+                        
+                        //#If any nutrient application for any crop is not incorporated, the method score for the AoA is zero
+                        if ( !crop.allNutrientsIncorporated() ){
+                            app_method_score = 0;
+                        }                          
+                        if ( !(error_msg = crop.getErrorMsg()).isEmpty() )
+                            break;                        
                     }
-
-                    //#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");
-                            }
-                        }
+                    else{
+                        ret_val = error_msg = "Cannot get crop_type. " + crop.getErrorMsg();
                     }
                 }
+                
+                //  If all crops' nutrients were incorporated this value will still be -1
+                if ( app_method_score == -1 ){
+                    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);
+                    if ( resultSet.first() ){
+                        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);
+                m.wqm.nutappmgtscores.Result result1 = new m.wqm.nutappmgtscores.Result(AoAId, 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());
+                    ret_val += se.getMessage();                    
+                }catch (Exception ex ){
+                    ret_val += ex.getMessage();
+            } finally {
+                if (statement != null) {
+                    statement.close();
+                }
+                if (conn != null) {
+                    conn.close();
+                }
             }
-            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;
+        }       
+        return (error_msg.isEmpty()? EXEC_OK:error_msg);
     }
 
     @Override
@@ -383,4 +204,12 @@
         }
         putResult("Result", resultArr);
     }
+    
+    private boolean ValidateInput(){
+        for( Crop tCrop : cropList )
+            if ( !tCrop.validate() )
+                error_msg += "; " + tCrop.getErrorMsg();
+      
+      return (error_msg.isEmpty());    
+    }
 }

web/META-INF/csip-conf.json

@@ -1,5 +1,5 @@
 { 
   "csip.archive.enabled"  : false,
   "csip.logging.enabled"  : false,
-  "wqm.version" : "$version: 0.1.38 369b033f4373 2015-08-11 $"
+  "wqm.version" : "$version: 0.1.39 01ac35d4e4cd 2015-08-11 $"
 }