V1_0.java [src/java/m/wqm/nutappmgtscores] Revision: d4e5c230d855e631706b46dd08625538a324d934 Date: Thu Aug 13 16:01:47 MDT 2015
package m.wqm.nutappmgtscores;
/**
*
* @author RUMPAL SIDHU
* @author Shaun Case
*
*/
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 = "wqm";
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;
//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 {
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();
}
}
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();
}
}
@Override
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 {
for (Crop crop : cropList) {
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;
// 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;
}
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(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();
}
}
}
return (error_msg.isEmpty()? EXEC_OK:error_msg);
}
@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);
}
private boolean ValidateInput(){
for( Crop tCrop : cropList )
if ( !tCrop.validate() )
error_msg += "; " + tCrop.getErrorMsg();
return (error_msg.isEmpty());
}
}