V1_0.java [src/java/d/soils/wwe01_wwesoilparams] Revision: default  Date:
/*
 * $Id$
 *
 * This file is part of the Cloud Services Integration Platform (CSIP),
 * a Model-as-a-Service framework, API, and application suite.
 *
 * 2012-2017, OMSLab, Colorado State University.
 *
 * OMSLab licenses this file to you under the MIT license.
 * See the LICENSE file in the project root for more information.
 */
package d.soils.wwe01_wwesoilparams;

import static adb.DBResources.EROSION_SQLSVR;
import csip.Config;
import csip.ModelDataService;
import csip.api.server.ServiceException;
import csip.SessionLogger;
import csip.annotations.Resource;
import gisobjects.GISObject;
import gisobjects.GISObjectException;
import static gisobjects.GISObjectFactory.createGISObject;
import static gisobjects.GISObjectFactory.setFixBadGeometries;
import static gisobjects.db.GISEngineFactory.createGISEngine;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import javax.ws.rs.*;
import csip.annotations.*;
import java.util.LinkedHashMap;
import java.util.Map;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import static soils.AoA.CORRECTED_GEOMETRY;
import static soils.AoA.EXCLUDED_LIST;
import soils.MapUnit;
import soils.SoilsData; // updated jar
import soils.db.DBResources;
import static soils.db.DBResources.SDM;
import soils.db.SOILS_DATA;
import soils.db.SOILS_DB_Factory;
import soils.db.tables.TableComponent;
import soils.db.tables.TableComponentCalculations;
import soils.db.tables.TableHorizon;
import soils.db.tables.TableHorizonCalculations;
import soils.db.tables.TableMapUnit;
import soils.db.tables.TableMapUnitCalculations;
import static soils.utils.EvalResult.writeDouble;

/**
 * REST Web Service. Front end callable.
 *
 * @author wlloyd, od
 * @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
 */
@Name("WWE-01:  Erosion Soil Parameters (wwesoilparams)")
@Description("Intersects area of analysis (AoA) geometry with NRCS Soil Data Mart (SDM) mapunit geometry, derives a list of distinct soil components  for the AoA, and gets parameters from SDM tables for populating application UI data fields and computing erosion rates and other resource analysis output")
@VersionInfo("1.0")
@Path("d/wwesoilparams/1.0")
@Resource(from = DBResources.class)
public class V1_0 extends ModelDataService {

  GISObject aoa_geometry;
  JSONObject aoa_input_geometry;
  double aoiArea;
  JSONArray outputObj;
  HashMap<String, MapUnit> soils;
  String newWKT = "";
  private JSONArray excludeds;
  private JSONArray results;


    @Override
  protected Map<String, Object> getConfigInfo() {
    return new LinkedHashMap<String, Object>() {
      {
        put("soils.gis.database.source", resources().getResolved("soils.gis.database.source"));
        put(SDM, resources().getResolved(SDM));
        put("wwe.version", "wwe 1.0");
      }
    };
  }


    @Override
    protected void doProcess()  throws ServiceException, GISObjectException, IOException, Exception {
    try (SOILS_DATA soilsDb = SOILS_DB_Factory.createEngine(getClass(), LOG, Config.getString("soils.gis.database.source")); Connection gisDb = resources().getJDBC(EROSION_SQLSVR);) {
      V1_0.AoA aoaObject = new AoA(soilsDb, gisDb, aoa_input_geometry, LOG);
      aoiArea = aoaObject.getArea();
      aoaObject.findSoils();
      results = aoaObject.toJSON();
      excludeds = aoaObject.getExcluded();

      if (aoaObject.hasGeomChanged()) {
        newWKT = aoaObject.shapeWKT();
      }
    }
  }

  @Override
  protected void postProcess() throws Exception {
    results().put("AoA Area", writeDouble(aoiArea, "%.3f"), "acres");
    results().put(SoilsData.MAP_UNIT_LIST, results);
    results().put(EXCLUDED_LIST, excludeds);
    if (!newWKT.isEmpty()) {
      results().put(CORRECTED_GEOMETRY, newWKT, "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.");
    }
  }

  @Override
  protected void preProcess() throws ServiceException {
    aoa_input_geometry = parameter().getParamJSON("aoa_geometry");
    if (null == this.aoa_input_geometry) {
      throw new csip.api.server.ServiceException("No 'AoA' item was found in the JSON input.  Please specify an 'AoA' .");
    }
  }

  private class AoA extends soils.AoA {

    AoA(SOILS_DATA soilsDb, Connection gisDb, JSONObject geometry, SessionLogger LOG) throws GISObjectException, SQLException, JSONException, IOException, ServiceException {
      super(soilsDb, LOG);

      setFixBadGeometries(true);
      shape = createGISObject(geometry, createGISEngine(gisDb));
      area = shape.areaInAcres();

      if (area > 10000.0) {
        throw new ServiceException("Feature specified has an area greater than 10,000 acres.  Area is too large.");
      }
      // Is it only a POINT?  (We don't allow this anymore)
      if (shape.toWKT().toUpperCase().contains("POINT")) {
        throw new ServiceException("Feature specified has a location specified that is a point value, not a polygon.  This version does not allow point locations.");
      }
    }

    public void findSoils() throws SQLException, ServiceException, GISObjectException {
      findIntersectedMapUnitsWithAreas();
      findAllComponentsApplyWindWaterFilters();
    }

    public JSONArray toJSON() throws JSONException, ServiceException {
      JSONArray mapunitData = new JSONArray();

      for (MapUnit mapUnit : map_units.values()) {
        if (!mapUnit.isExcluded()) {

          mapUnit.setOutputColumns(new ArrayList<>(Arrays.asList(TableMapUnit.MUKEY, TableMapUnit.MUNAME,
              TableMapUnit.MUSYM, TableMapUnit.AREASYMBOL_NAME, TableMapUnitCalculations.AREA_NAME
          )));
          mapUnit.setComponentOutputColumns(new ArrayList<>(Arrays.asList(TableComponent.COKEY, TableComponent.COMPNAME,
              TableComponent.COMPPCT_R_NAME, TableComponentCalculations.AREA_PCT_NAME, TableComponentCalculations.COMP_AREA_NAME,
              TableComponent.TFACT_NAME, TableComponent.WEI_NAME,
              TableComponent.SLOPE_R_NAME, TableComponentCalculations.LENGTH_R_NAME,
              TableComponentCalculations.KFFACT_NAME, TableComponentCalculations.SANDTOTAL_R_NAME, TableComponentCalculations.OM_R_NAME
          )));
          mapUnit.setHorizonOutputColumns(new ArrayList<>(Arrays.asList(TableHorizon.CHKEY_NAME, TableHorizon.HZDEPB_R_NAME, TableHorizon.HZDEPT_R_NAME,
              TableHorizon.HZTHK_R_NAME, TableHorizon.KFFACT_NAME, TableHorizon.KWFACT_NAME, TableHorizon.SANDTOTAL_R_NAME,
              TableHorizonCalculations.FRAGVOL_R_NAME, TableHorizonCalculations.LSFACT_NAME, TableHorizon.OM_R_NAME
          )));

          mapunitData.put(mapUnit.toJSON(true, new ArrayList<>(Arrays.asList("WATER", "WIND"))));

        }
      }

      return mapunitData;
    }
  }
}