V1_0.java [src/java/m/wqm/wqsr] Revision: ed954c4ca150533c1922906456ae2c6329c5a307  Date: Thu May 26 13:54:54 MDT 2016
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package m.wqm.wqsr;

import GISObjects.GISEngineFactory;
import GISObjects.GISObject;
import GISObjects.GISObjectException;
import GISObjects.GISObjectFactory;
import csip.ModelDataService;
import csip.ServiceException;
import csip.annotations.Resource;
import static csip.annotations.ResourceType.JDBC;
import csip.utils.JSONUtils;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.ws.rs.Path;
import oms3.annotations.Description;
import oms3.annotations.Name;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import wqm.utils.DBResources;
import static wqm.utils.DBResources.WQM_ID;

/**
 * WQM-01: Water Quality Sensitivity Rating (WQSR)
 *
 * @author Sandeep, od, rumpal
 */
@Name("WQM-01: Water Quality Sensitivity Rating (WQSR)")
@Description("This service intersects area of analysis (AoA) geometry with the NRCS Water Quality "
        + "Sensitivity Rating (WQSR) spatial layer and computes a sensitivity rating and treatment "
        + "level required for mitigating nutrient and pesticide loss potentials and hazards.")
@Path("m/wqm/wqsr/1.0")
@Resource(from = DBResources.class)
@Resource(type = JDBC, file = "${mssql-ssurgo.db}", id = "mssql", env = {
    "removeAbandoned=false", "defaultReadOnly=true", "defaultAutoCommit=false",
    "jdbcInterceptors=org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
    + "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;"
    + "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"
})
public class V1_0 extends ModelDataService {

    private List<m.wqm.wqsr.V1_0.AoA> list;

    @Override
    public void preProcess() throws ServiceException {
        list = new ArrayList<>();
        try {
            JSONArray aoaArr = getJSONArrayParam("aoas");
            for (int i = 0; i < aoaArr.length(); i++) {
                //Map individual JSONObject & extract values
                Map<String, JSONObject> thisAoA = JSONUtils.preprocess(aoaArr.getJSONArray(i));

                String aoaId = JSONUtils.getStringParam(thisAoA, "aoa_id", "unknown");
                JSONObject aoaGeometry = JSONUtils.getJSONObjectParam(thisAoA, "aoa_geometry");

                GISObject aoa_geometry;
                try (Connection connection = getResourceJDBC("mssql");) {
                    //  Sets the GIS Engine of the GISObjects to the DBMS specified in
                    //the creation of the “connection” variable.  MsSQL in this case
                    GISObjectFactory.setGISObjectEngine(GISEngineFactory.createGISEngine(connection));
                    aoa_geometry = GISObjectFactory.createGISObject(aoaGeometry);
                    System.out.println("aoa_geometry = " + aoa_geometry.getGeometry());
                    connection.close();
                } catch (ServiceException | JSONException | SQLException | IOException | GISObjectException ex) {
                    LOG.log(Level.SEVERE, "WQM-1: Error in processing the aoa geometry.", ex);
                    throw new ServiceException("Error in processing the aoa geometry", ex);
                }

                list.add(new m.wqm.wqsr.V1_0.AoA(aoaId, aoa_geometry));
            }
        } catch (JSONException ex) {
            LOG.log(Level.SEVERE, "Error in processing the request JSON for WQM-1!", ex);
            throw new ServiceException("Error in processing the request JSON.", ex);
        }
    }

    @Override
    public void doProcess() throws ServiceException, SQLException {

        try (Connection tempCon = getResourceJDBC(WQM_ID);
                Statement stmt = tempCon.createStatement()) {

            for (m.wqm.wqsr.V1_0.AoA aoa : list) {
                double aoaBaseArea = 0.0;
                double aoaSensitiveArea = 0.0;
                double aoaCriticalArea = 0.0;

                //Query to select the area,rating and treatment level
                // which given coordinates intersects wqsr_area geometry
                try (ResultSet results = stmt.executeQuery("SELECT shape_area, wqs_rating "
                        + "FROM wqm_huc12.wqsr_area WHERE geom.STIntersects(geometry::STGeomFromText('"
                        + aoa.getAoaGeometry().getGeometry() + "', 0)) = 1 AND geom.STIsValid() = 1 "
                        + "AND geometry::STGeomFromText('" + aoa.getAoaGeometry().getGeometry() + "', 0).STIsValid() = 1;")) {
                    while (results.next()) {
                        String wqsRating = results.getString("wqs_rating");
                        double shape_area = results.getDouble("shape_area");
                        if (wqsRating.equalsIgnoreCase("base")) {
                            aoaBaseArea += shape_area;
                        } else if (wqsRating.equalsIgnoreCase("sensitive")) {
                            aoaSensitiveArea += shape_area;
                        } else if (wqsRating.equalsIgnoreCase("critical")) {
                            aoaCriticalArea += shape_area;
                        }
                    }
                }

                if ((aoaBaseArea >= aoaSensitiveArea) && (aoaBaseArea >= aoaCriticalArea)) {
                    aoa.setWQSRating("Base");
                    aoa.setTreatmentLevel("I");
                } else if ((aoaSensitiveArea >= aoaBaseArea) && (aoaSensitiveArea >= aoaCriticalArea)) {
                    aoa.setWQSRating("Sensitive");
                    aoa.setTreatmentLevel("II");
                } else {
                    aoa.setWQSRating("Critical");
                    aoa.setTreatmentLevel("III");
                }
            }
        } catch (SQLException ex) {
            LOG.log(Level.SEVERE, "SQLException for WQM-1!", ex);
            throw new ServiceException("SQL problem.", ex);
        }

    }

    @Override
    public void postProcess() throws ServiceException {
        try {
            JSONArray finalArr = new JSONArray();
            for (m.wqm.wqsr.V1_0.AoA aoa : list) {
                JSONArray resultArr = new JSONArray();
                resultArr.put(JSONUtils.dataDesc("AoAId", aoa.getAoAId(), "Area of Analysis Identifier"));
                resultArr.put(JSONUtils.dataDesc("wqs_Rating", aoa.getWQSRating(), "WQS Rating"));
                resultArr.put(JSONUtils.dataDesc("wqs_treatment_level", aoa.getTreatmentLevel(), "WQS Treatment Level"));
                finalArr.put(resultArr);
            }
            putResult("", finalArr);
        } catch (JSONException ex) {
            LOG.log(Level.SEVERE, "Error in processing the response JSON for WQM-1!", ex);
            throw new ServiceException("Error in processing the response JSON.", ex);
        }
    }

    static class AoA {

        String aoa_id;
        GISObject aoaGeometry;
        String wqsRating;
        String treatmentLevel;

        public AoA(String aoa_id, GISObject geometry) {
            this.aoa_id = aoa_id;
            this.aoaGeometry = geometry;
        }

        public String getAoAId() {
            return this.aoa_id;
        }

        public String getWQSRating() {
            return this.wqsRating;
        }

        public String getTreatmentLevel() {
            return this.treatmentLevel;
        }

        public GISObject getAoaGeometry() {
            return this.aoaGeometry;
        }

        public void setWQSRating(String wqs) {
            this.wqsRating = wqs;
        }

        public void setTreatmentLevel(String level) {
            this.treatmentLevel = level;
        }
    }

}