V1_0.java [src/java/m/crp/topthree] 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-2019, 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 m.crp.topthree;

import crp.utils.DBResources;
import static crp.utils.DBResources.LOCAL_SQLSERVER;
import crp.utils.SoilResult;
import crp.utils.WWESoilParams;
import csip.Config;
import csip.ModelDataService;
import csip.PayloadParameter;
import csip.PayloadResults;
import csip.ServiceException;
import csip.annotations.Description;
import csip.annotations.Name;
import csip.annotations.Polling;
import csip.annotations.Resource;
import csip.utils.JSONUtils;
import gisobjects.GISObject;
import gisobjects.GISObjectFactory;
import gisobjects.db.GISEngine;
import gisobjects.db.GISEngineFactory;
import java.sql.Connection;
import java.util.ArrayList;
import javax.ws.rs.Path;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;

/**
 *
 * @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
 */
@Name("CRP Top Three")
@Description("This service provides the cokey values of the top three soils found for the location specified.")
@Path("m/topthree/1.0")
@Polling(first = 2000, next = 1000)
@Resource(from = DBResources.class)

public class V1_0 extends ModelDataService {

  public static final String SCENARIO_ID = "scenario_id";
  public static final String SCENARIO_GEOMETRY = "scenario_geometry";
  public static final String BUFFER_SIZE = "buffer_size";
  public static final String SHOW_DEBUG_OUTPUT = "show_debug_output";

  protected static final int SLEEP_TIMER = 1000; //milliseconds to sleep while polling async model calls
  protected static final int INITIAL_POLL_WAIT_TIMER = 1000; //milliseconds to sleep while polling async model calls
  protected static final int GET_CALL_WAIT = 150; // milliseconds to sleep between internal get requests in loop of testing status of all calls at once.

  protected JSONObject scenario_geometry;
  protected String scenario_id;
  protected double bufferSize = 200.0;
  protected double aoa_area = 0.0;
  protected GISObject aoa_geometry;
  protected boolean debugOutput = false;
  protected GISEngine gEngine;

  protected String soilsURI = "http://csip.engr.colostate.edu:8083/csip-soils/d/wwesoilparams/2.1";

  protected ArrayList<SoilResult> topThreeComponents;

  @Override
  protected void preProcess() throws Exception {
    PayloadParameter params = parameter();

    soilsURI = Config.getString("crp.soils", soilsURI);

    if (params.has(SCENARIO_ID)) {
      scenario_id = params.getString(SCENARIO_ID);
    } else {
      throw new ServiceException("A required input 'scenario_id' was missing.  Please specify a scenario_id value.");
    }

    if (params.has(BUFFER_SIZE)) {
      bufferSize = params.getDouble(BUFFER_SIZE);
    }

    if (params.has(SHOW_DEBUG_OUTPUT)) {
      debugOutput = params.getBoolean(SHOW_DEBUG_OUTPUT);
    }

    if (params.has(SCENARIO_GEOMETRY)) {
      scenario_geometry = params.getParamJSON(SCENARIO_GEOMETRY);

      try (Connection connection = resources().getJDBC(LOCAL_SQLSERVER);) {
        gEngine = GISEngineFactory.createGISEngine(connection);
        aoa_geometry = GISObjectFactory.createGISObject(scenario_geometry, gEngine);

        if ((aoa_geometry.getType() == GISObject.GISObjectType.point) || (aoa_geometry.getGeometry().getNumPoints() < 4)) {

          GISObject newGeometry = aoa_geometry.buffer(bufferSize);
          aoa_geometry = newGeometry;
        } else if ((aoa_geometry.getType() != GISObject.GISObjectType.polygon) && ((aoa_geometry.getType() != GISObject.GISObjectType.multipolygon))) {
          throw new ServiceException("The input geometry must be a Polygon, Multipolygon, or Point.");
        }
        aoa_area = aoa_geometry.areaInAcres();
      }

    } else {
      throw new ServiceException("A required input " + SCENARIO_GEOMETRY + " was missing.  Please specify a scenario_geometry value.");
    }

  }

  @Override
  protected void doProcess() throws Exception {

    //  Get all soils information for this AoI.
    WWESoilParams wweCall = new WWESoilParams(metainfo().toString(), aoa_geometry.toJSON(), soilsURI, null);
    wweCall.call();
    topThreeComponents = wweCall.getTopThree();

  }

  @Override
  protected void postProcess() throws Exception {
    PayloadResults results = results();
    JSONArray soilsResult = new JSONArray();

    results.put(SCENARIO_ID, scenario_id);
    results.put("aoa_area", aoa_area);
    results.put("aoa_geometry", aoa_geometry.toJSON());

    for (SoilResult soilResult : topThreeComponents) {
      JSONArray soilData = new JSONArray();
      soilData.put(JSONUtils.data("soilPtr", soilResult.cokey, "A non-connotative string of characters used to uniquely identify a record in the Component table"));
      soilData.put(JSONUtils.data("soilName", soilResult.soilName, "Name assigned to a component based on its range of properties"));
      soilData.put(JSONUtils.data("area_pct", soilResult.area_pct, "The percentage of the component of the mapunit intersection with the CRP Offer Area", "Percent"));
      soilData.put(JSONUtils.data("area", soilResult.area, "Soil Component Area (Acres) in the CRP Offer area", "Acres"));

      if (debugOutput) {
        soilData.put(JSONUtils.data("mukey", soilResult.mukey,"A non-connotative string of characters used to uniquely identify a record in the Mapunit table"));
        soilData.put(JSONUtils.dataUnitDesc("slope_r", soilResult.slope_r,"Percent", "Slope RV: The difference in elevation between two points, expressed as a percentage of the distance between those points. (SSM)"));
        soilData.put(JSONUtils.dataUnitDesc("length", soilResult.length, "Feet", "Calculated slope length"));
        soilData.put(JSONUtils.data("soilLongName", soilResult.soilLongName, "A long name assigned to a component based on its range of properties and other factors"));
      }

      soilsResult.put(soilData);
    }
    results.put("top_3_soils", soilsResult);
  }
}