V1_0.java [src/java/d/soils/wwe04_weppsoilinput] 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.wwe04_weppsoilinput;

import csip.Config;
import csip.ModelDataService;
import csip.annotations.Description;
import csip.annotations.Name;
import csip.annotations.Resource;
import csip.api.server.ServiceException;
import csip.utils.Validation;
import d.dataNodes.WEPPData;
import d.util.SolWriter;
import d.util.Utils;
import java.io.File;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.ws.rs.Path;
import soils.Component;
import soils.Horizon;
import soils.MapUnit;
import static soils.db.DBResources.SDM;
import soils.db.SOILS_DATA;
import soils.db.SOILS_DB_Factory;
import soils.utils.EvalResult;

/**
 *
 * @author Brad
 * @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
 */
@Name("WWE-04:  WEPP Soil Input XML (weppsoilinput)")
@Description("Gets data from the NRCS Soil Data Mart and generates a soil component sol input file for the WEPP model")
@Path("d/weppsoilinput/1.0")
@Resource(from = soils.db.DBResources.class)
public class V1_0 extends ModelDataService {

  static final String KEY_COKEY = "cokey";
  static final String STREAM_FILE = "stream_file";

  protected boolean streamFile = false;
  protected Component comp = null;
  protected MapUnit mapUnit = null;
  protected String fileOut = "";
  protected File solFile = null;

  @Override
  protected void preProcess() throws Exception {
    String cokey = parameter().getString(KEY_COKEY);
    streamFile = parameter().getBoolean(STREAM_FILE, false);

    Validation.checkCokey(cokey);

    comp = new Component();
    comp.cokey(cokey);
    mapUnit = new MapUnit(comp);
  }

  @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("fpp.version", "wwe-04 1.0");
      }
    };
  }

  @Override
  protected void doProcess() throws ServiceException, Exception {

    //  Get the filtered SOILS data for the cokey provided.
    try (SOILS_DATA soilsDb = SOILS_DB_Factory.createEngine(getClass(), LOG, Config.getString("soils.gis.database.source"))) {
      if (soilsDb.validateComponent(Integer.parseInt(comp.cokey()))) {
        //  This function, also, by default fills in all of the MapUnit data from the cokey reference.
        if (!soilsDb.findWEPSHorizonsForCokey(mapUnit, comp)) {
          //found no results for this cokey...throw exception??  Figure out what is missing??
        }
      } else {
        throw new ServiceException("The cokey value provided does not exist in the SDM database.  Cannot continue.");
      }
    }

    if (comp.isExcluded()) {
      throw new ServiceException("Component: " + comp.compname() + " has been excluded. Reason: " + comp.getExcludedReason());
    }

    Horizon surfaceHorizon = Utils.getSurfaceHorizon(comp);
    defaultHorizonValues(comp, surfaceHorizon);

    WEPPData data = new WEPPData();
    data.computeErodibility(surfaceHorizon);
    data.setBedrockData(comp);

    SolWriter writer = new SolWriter();

    solFile = ((streamFile) ? null : (workspace().getFile(comp.compname() + ".sol")));
    fileOut = writer.writeSolEx(comp, solFile, 1, data, !streamFile);
  }

  protected void postProcess() throws Exception {
    if (!streamFile && solFile.exists()) {
      results().put(solFile);
    } else {
      if (!streamFile) {
        throw new ServiceException("File " + solFile.getName() + " could not be created.");
      } else {
        if ((null != fileOut) && (!fileOut.isEmpty()) && (fileOut.length() > 0)) {
          results().put(comp.compname(), fileOut);
        } else {
          throw new ServiceException("Resulting sol file was empty, cannot proceed");
        }
      }
    }
  }

  private void defaultHorizonValues(Component comp, Horizon surfaceH) throws ServiceException {
    for (Horizon h : comp.horizons.values()) {
      if (EvalResult.testDefaultDouble(h.cec7_r()) || h.cec7_r() == 0) {
        //Find out when it is okay to move on if a horizon has no CEC nor ECEC value:  There are some cases where that is okay.
        //  For now, just be sure that it isn't the surface horizon that is missing all data.
        if (((EvalResult.testDefaultDouble(h.ecec_r()) || h.ecec_r() == 0)) && (h == surfaceH)) {
          throw new ServiceException("Cannot procede building sol file:  No CEC nor ECEC value available for this horizon, " + h.chkey() + ".");
        } else {
          h.cec7_r(h.ecec_r());
        }
      }

      if (EvalResult.testDefaultDouble(h.claytotal_r())) {
        h.claytotal_r(0.0);
      }
    }
  }
}