V1_1.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.Collections;
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.1")
@Resource(from = DBResources.class)

public class V1_1 extends ModelDataService {

    private String error_msg;
    private ArrayList<m.wqm.wqm12_rfactor.V1_1.AoA> list;

    @Override
    public void preProcess() throws ServiceException {
        this.error_msg = "";
        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_1.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 {

        if (this.error_msg.isEmpty()) {
            try (Connection conn = resources().getJDBC(WQM_ID);
                    Statement statement = conn.createStatement()) {
                String rFactor;
                GISEngine gisEngine = GISEngineFactory.createGISEngine(conn);
                GISObjectFactory.setFixBadGeometries(true);

                for (m.wqm.wqm12_rfactor.V1_1.AoA list1 : this.list) {
                    ArrayList<String> rfactorList = new ArrayList<>();
                    list1.readShape(gisEngine);
                    
                    ResultSet results = statement.executeQuery(DBQueries.WQM12Query02(list1.getShape().toWKT()));
                    while (results.next()) {
                        rFactor = results.getString("r_factor");

                        if (null != rFactor) {
                            rfactorList.add(rFactor);
                        } else {
                            break;
                        }
                    }

                    if (!this.error_msg.isEmpty()) {
                        break;
                    }

                    if (rfactorList.size() > 0) {
                        list1.setRFactor(rfactorList);
                    }
                }
            } catch (ServiceException | SQLException ex) {
                LOG.log(Level.SEVERE, "SQL problem for WQM-12!", ex);
                throw new ServiceException("SQL problem", ex);
            }
        }
    }

    @Override
    public void postProcess() throws Exception {
        ArrayList<Double> temp;
        try {
            if (this.error_msg.isEmpty()) {
                JSONArray finalArr = new JSONArray();
                for (m.wqm.wqm12_rfactor.V1_1.AoA list1 : this.list) {
                    JSONArray resultArr = new JSONArray();
                    temp = new ArrayList<>();
                    for (int j = 0; j < list1.getRFactor().size(); j++) {
                        temp.add(Double.parseDouble(list1.getRFactor().get(j)));
                    }

                    resultArr.put(JSONUtils.dataDesc("AoAId", list1.getAoAId(), "Area of Analysis Identifier"));

                    if (temp.size() > 0) {
                        Collections.sort(temp);
                        resultArr.put(JSONUtils.dataDesc("RFactor", temp.get(temp.size() - 1), "R Factor"));
                    } else {
                        resultArr.put(JSONUtils.dataDesc("RFactor", "No polygon intersection found", "R Factor"));
                    }
                    if ( list1.getShape().hasChanged() ){
                        resultArr.put(JSONUtils.dataDesc(soils.AoA.CORRECTED_GEOMETRY, list1.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;
    }
// rFactor now coming from map_climates table
//    private String getAndProcessXml(String url) {
//        String ret_val = null;
//
//        try {
//            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//            DocumentBuilder db = dbf.newDocumentBuilder();
//
//            URL Url = new URL(url);
//            URLConnection urlConnection = Url.openConnection();
//            Document document = db.parse(urlConnection.getInputStream());
//            document.getDocumentElement().normalize();
//            Element root = document.getDocumentElement();
//            NodeList nList = document.getElementsByTagName("Flt");
//
//            for (int temp = 0; temp < nList.getLength(); temp++) {
//                Node node = nList.item(temp);
//
//                if (node.getNodeType() == Node.ELEMENT_NODE) {
//                    Element eElement = (Element) node;
//                    String Name = eElement.getElementsByTagName("Name").item(0).getTextContent();
//                    if (Name.equals("R_FACTOR")) {
//                        ret_val = eElement.getElementsByTagName("Data").item(0).getTextContent();
//                    }
//                }
//            }
//        } catch (ParserConfigurationException | IOException | SAXException | DOMException ex) {
//            this.error_msg = "Cannot parse the returned XML: " + ex.getMessage();
//            LOG.log(Level.SEVERE, this.error_msg);
//        }
//
//        return ret_val;
//    }

    static class AoA {

        private final String aoa_id;
        private GISObject shape;
        private final JSONObject aoa_geometry;
        private ArrayList<String> rfactor;

        /**
         *
         * @param aoa_id
         * @param coordinates
         */
        public AoA(String aoa_id, JSONObject aoa_geometry) {
            this.aoa_id = aoa_id;
            rfactor = new ArrayList<>();
            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 ArrayList<String> getRFactor() {
            return rfactor;
        }

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

    }
}