V1_2.java [src/java/m/wqm/wqm12_rfactor] Revision:   Date:
/*
 * 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.
 */
/**
 *
 * @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
 */
package m.wqm.wqm12_rfactor;


import csip.ModelDataService;
import csip.api.server.ServiceException;
import csip.annotations.Resource;
import csip.utils.JSONUtils;
import gisobjects.GISObject;
import gisobjects.GISObjectException;
import gisobjects.GISObjectFactory;
import gisobjects.db.GISEngine;
import gisobjects.db.GISEngineFactory;
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.Map;
import java.util.logging.Level;
import javax.ws.rs.Path;
import csip.annotations.Description;
import csip.annotations.Name;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import wqm.utils.DBQueries;
import wqm.utils.DBResources;
import static wqm.utils.DBResources.WQM_ID;

/**
 *
 * @author Sandeep
 * @author Shaun Case
 */
@Name("WQM-12: Climate R Factor for an Area of Analysis (AoARFactor)")
@Description("This service intersects an area of analysis (AoA) with the "
        + "Revised Universal Soil Loss Equation (RUSLE2) climate R Factor layer "
        + "and computes an R Factor representing the AoA.")
@Path("m/wqm/rfactor/1.2")
@Resource(from = DBResources.class)

public class V1_2 extends ModelDataService {

    private ArrayList<m.wqm.wqm12_rfactor.V1_2.AoA> list;

    @Override
    public void preProcess() throws ServiceException {
        String points;
        JSONObject shape;
        JSONArray aoaArr;
        String aoaId;
        JSONArray polygon, coordinates;

        try {
            this.list = new ArrayList<>();

            aoaArr = parameter().getJSONArray("aoas");

            for (int i = 0; i < aoaArr.length(); i++) {
                //Map individual JSONObject & extract values
                Map<String, JSONObject> thisAoA = JSONUtils.preprocess(aoaArr.getJSONArray(i));
                aoaId = JSONUtils.getStringParam(thisAoA, "aoa_id", "unknown");
                shape = getJSONObject(aoaArr.getJSONArray(i), "aoa_geometry");
                this.list.add(new V1_2.AoA(aoaId, shape));
            }
        } catch (ServiceException | JSONException ex) {
            LOG.log(Level.SEVERE, "Error in processing the request JSON for WQM-12", ex);
            throw new ServiceException("Error in processing the request JSON.", ex);
        }
    }

    @Override
    public void doProcess() throws ServiceException, GISObjectException, JSONException, IOException {
        try (Connection conn = resources().getJDBC(WQM_ID);
                Statement statement = conn.createStatement()) {

            GISEngine gisEngine = GISEngineFactory.createGISEngine(conn);
            GISObjectFactory.setFixBadGeometries(true);

            for (m.wqm.wqm12_rfactor.V1_2.AoA aoi : this.list) {
                String rFactor = "NONE";
                aoi.readShape(gisEngine);

                ResultSet results = statement.executeQuery(DBQueries.WQM12Query02(aoi.getShape().toWKT()));
                if (results.next()) {
                    rFactor = results.getString("r_factor");

                    if (null == rFactor) {
                        throw new ServiceException("Returned r_factor column was empty.");
                    }

                } else {
                    results.close();
                    //Find nearest neighbor record and use it.
                    results = statement.executeQuery(DBQueries.WQM12Query03(aoi.getShape().getCentroid()));
                    if (results.next()) {
                        rFactor = results.getString("r_factor");

                        if (null == rFactor) {
                            throw new ServiceException("Returned r_factor column was empty.");
                        }
                    } else {
                        throw new ServiceException("No r_factor was found for that AoI,(" + aoi.getAoAId() + "), and a nearest neighbor search was also empty.");
                    }
                }
                aoi.setRFactor(rFactor);
            }
        } catch (ServiceException | SQLException ex) {
            LOG.log(Level.SEVERE, "SQL problem for WQM-12!", ex);
            throw new ServiceException("SQL problem: " + ex.getMessage(), ex);
        }
    }

    @Override
    public void postProcess() throws Exception {
        ArrayList<Double> temp;
        try {
            JSONArray finalArr = new JSONArray();
            for (m.wqm.wqm12_rfactor.V1_2.AoA aoi : this.list) {
                JSONArray resultArr = new JSONArray();

                resultArr.put(JSONUtils.dataDesc("AoAId", aoi.getAoAId(), "Area of Analysis Identifier"));
                resultArr.put(JSONUtils.dataDesc("RFactor", aoi.getRFactor(), "R Factor"));

                if (aoi.getShape().hasChanged()) {
                    resultArr.put(JSONUtils.dataDesc(soils.AoA.CORRECTED_GEOMETRY, aoi.getShape().toWKT(), "If this section is present, the input geometry was invalid.  This service attempted to correct it, and was successful in creating a new geometry that could be utilized.  Please check this corrected geometry to be sure it represents what you originally intended.  If it does, please contact the source of your original geometry to have it corrected.  You may use this WKT to do so."));
                }

                finalArr.put(resultArr);
            }
            results().put("", finalArr);

        } catch (NumberFormatException | JSONException ex) {
            LOG.log(Level.SEVERE, "Error in processing the response JSON for WQM-12!", ex);
            throw new ServiceException("Error in processing the response JSON.", ex);
        }
    }

    private JSONObject getJSONObject(JSONArray array, String name) throws JSONException {
        JSONObject ret_val = null;

        for (int i = 0; i < array.length(); i++) {
            if (array.getJSONObject(i).getString("name").equals(name)) {
                ret_val = array.getJSONObject(i);
                break;
            }
        }

        return ret_val;
    }

    static class AoA {

        private final String aoa_id;
        private GISObject shape;
        private final JSONObject aoa_geometry;
        private String rfactor;

        /**
         *
         * @param aoa_id
         * @param coordinates
         */
        public AoA(String aoa_id, JSONObject aoa_geometry) {
            this.aoa_id = aoa_id;
            this.aoa_geometry = aoa_geometry;
        }

        public void readShape(GISEngine gisEngine) throws JSONException, IOException, GISObjectException {
            shape = GISObjectFactory.createGISObject(aoa_geometry, gisEngine);
        }

        public GISObject getShape() {
            return shape;
        }

        /**
         *
         * @return
         */
        public String getAoAId() {
            return aoa_id;
        }

        /**
         *
         * @return
         */
        public String getRFactor() {
            return rfactor;
        }

        /**
         *
         * @param rf
         */
        public void setRFactor(String rfactor) {
            this.rfactor = rfactor;
        }

    }
}