Component.java [src/soils] Revision: default 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.
*/
package soils;
import csip.api.server.ServiceException;
import csip.utils.JSONUtils;
import csip.utils.Validation;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
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.db.SOILS_DATA.BAD_KFFACT_LAYERS;
import static soils.db.SOILS_DATA.BAD_SAND_LAYERS;
import soils.db.SOILS_DATA.FilterResults;
import soils.db.tables.TableCocropyld;
import soils.db.tables.TableCoecoclass;
import soils.db.tables.TableColumn;
import soils.db.tables.TableComponent;
import soils.db.tables.TableComponentCalculations;
import soils.db.tables.TableExcluded;
import soils.exceptions.SDMException;
import soils.exceptions.WEPPException;
import soils.exceptions.WEPP_WEPSException;
import soils.exceptions.WEPSException;
import soils.utils.EvalResult;
import soils.utils.GenericIFCData;
import soils.utils.IFCRanges;
import soils.utils.SoilUtils;
import static soils.utils.SoilUtils.formatIFCArray;
import static soils.utils.SoilUtils.formatIFCValue;
import static soils.utils.SoilUtils.getCationExchangeCapacity;
import static soils.utils.SoilUtils.getRockFrags;
import static soils.utils.SoilUtils.getSoilpH;
import static soils.utils.SoilUtils.metricConversion;
import soils.utils.StratifiedTextures;
/**
*
* @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
*/
public class Component {
private static HashMap<String, Integer> pondRatings = new HashMap<>();
private static HashMap<String, Integer> floodRatings = new HashMap<>();
private static ArrayList<String> floodRatingNames = new ArrayList<>(Arrays.asList("None", "Very Rare", "Rare", "Occaisional", "Frequent", "Very Frequent"));
private static ArrayList<String> pondRatingNames = new ArrayList<>(Arrays.asList("None", "Rare", "Occaisional", "Frequent"));
protected static final StratifiedTextures STRATIFIED_TEXTURES = StratifiedTextures.getInstance();
private static double CM_TO_INCH = 0.393701;
private static final String COMP_PSLP_STRING[] = {"", "VERY LOW", "LOW", "INTERMEDIATE", "HIGH"};
private static final String COMP_PSSRP[] = {"", "LOW", "INTERMEDIATE", "HIGH"};
private static double INCH_TO_CM = 2.54;
private static final int PSLP_HIGH = 4;
private static final int PSLP_INTERMEDIATE = 3;
private static final int PSLP_LOW = 2;
private static final int PSLP_VERY_LOW = 1;
private static final String LONG_NAME = "comp_long_name";
protected static ArrayList<String> componentRequiredInputs = new ArrayList<>();
protected static ArrayList<String> componentUsedColumns = new ArrayList<>();
static {
for (int i = 0; i < floodRatingNames.size(); i++) {
floodRatings.put(floodRatingNames.get(i).toLowerCase(), i);
}
for (int i = 0; i < pondRatingNames.size(); i++) {
pondRatings.put(pondRatingNames.get(i).toLowerCase(), i);
}
}
/**
*
* @param usedColumns
*/
public synchronized static void setDefaultUsedColumns(List<String> usedColumns) {
componentUsedColumns.clear();
if (null != usedColumns) {
componentUsedColumns.addAll(usedColumns);
}
}
public synchronized static void setRequiredInputs(List<String> componentInputs) {
componentRequiredInputs.clear();
if (null != componentInputs) {
componentRequiredInputs.addAll(componentInputs);
componentUsedColumns.addAll(componentInputs);
}
}
public synchronized static ArrayList<String> getDefaultUsedColumns() {
return ((null != componentUsedColumns) ? ((ArrayList<String>) componentUsedColumns.clone()) : null);
}
public synchronized static ArrayList<String> getRequiedInputs() {
return ((null != componentRequiredInputs) ? ((ArrayList<String>) componentRequiredInputs.clone()) : null);
}
////////////////////////////////////////////////////////////////////////////////////
// Default Organic layer data to be used for substituted layer lines in .sol file.
////////////////////////////////////////////////////////////////////////////////////
// Thk : (Use existing layer thickness)
// Sand %: 50
// Clay %: 10
// OM %: 77
// CEC : 40
// rfg %: 0
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// Generic Organic Soil SOL File
protected String genericOrganicSoilSol = "2006.2\n"
+ "wepp organic soil file\n"
+ "1 1\n"
+ "'organic' 'SIL' 2 0.230000 0.750000 3112200 0.00257 3.204 10.28756\n"
+ " 400 50.0 10.0 77.000 40.0 0.0\n"
+ " 1500 13.0 5.0 81.000 45.0 0.0\n"
+ "0 0.000000 0";
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// Generic Organic Soil IFC File
protected String genericOrganicSoilIfc = "Version: 1.0\n"
+ "#\n"
+ "# Soil ID\n"
+ "NA-NA-Organic Soil Mod-100-MUCK-NA-NA-NA\n"
+ "#\n"
+ "# Local Phase\n"
+ "NA\n"
+ "# Soil Order\n"
+ "NA\n"
+ "# Soil Loss Tolerance (tons/acre/year)\n"
+ "3\n"
+ "# Dry soil albedo (fraction)\n"
+ "0.090\n"
+ "# Slope gradient (fraction)\n"
+ "0.000\n"
+ "# Surface fragment cover or surface layer fragments (area fraction)\n"
+ "0.000\n"
+ "#\n"
+ "# Depth to bedrock (mm)\n"
+ "99990\n"
+ "# Depth to root restricting layer (mm)\n"
+ "99990\n"
+ "#\n"
+ "# Number of layers\n"
+ "2\n"
+ "# Layer thickness (mm)\n"
+ "400 1100 \n"
+ "#\n"
+ "# Sand fraction\n"
+ "0.500 0.130 \n"
+ "# Silt fraction\n"
+ "0.400 0.820 \n"
+ "# Clay fraction\n"
+ "0.100 0.050 \n"
+ "# Rock fragments\n"
+ "0.000 0.000 \n"
+ "# Sand fraction very coarse\n"
+ "0.000 0.000 \n"
+ "# Sand fraction coarse\n"
+ "0.020 0.003 \n"
+ "# Sand fraction medium\n"
+ "0.128 0.023 \n"
+ "# Sand fraction fine\n"
+ "0.332 0.065 \n"
+ "# Sand fraction very fine\n"
+ "0.020 0.039 \n"
+ "#\n"
+ "# Bulk Density (1/3 bar)(Mg/m^3)\n"
+ "0.390 0.220 \n"
+ "# Organic matter (kg/kg)\n"
+ "0.7700 0.8100 \n"
+ "# Soil PH (0-14)\n"
+ "5.00 5.00 \n"
+ "# Calcium carbonate equivalent (CaCO3)\n"
+ "0.00 0.00 \n"
+ "# Cation exchange capacity (CEC) (meq/100g)\n"
+ "40.00 45.00 \n"
+ "# Linear extensibility\n"
+ "0.000 0.000 \n"
+ "#\n"
+ "# Aggregate geometric mean diameter (mm)\n"
+ "5.000 5.000 \n"
+ "# Aggregate geometric standard deviation\n"
+ "5.000 5.000 \n"
+ "# Maximum aggregate size (mm)\n"
+ "30.000 30.000 \n"
+ "# Minimum aggregate size (mm)\n"
+ "0.010 0.010 \n"
+ "# Aggregate density (Mg/m^3)\n"
+ "0.700 0.700 \n"
+ "# Aggregate stability (ln(J/m^2))\n"
+ "4.000 4.000 \n"
+ "#\n"
+ "# Crust thickness (mm)\n"
+ "0.010\n"
+ "# Crust density (Mg/m^3)\n"
+ "0.600\n"
+ "# Crust stability (ln(J/m^2))\n"
+ "4.00\n"
+ "# Crust surface fraction (m^2/m^2)\n"
+ "0.00\n"
+ "# Mass of loose material on crust (kg/m^2)\n"
+ "0.00\n"
+ "# Fraction of loose material on crust (m^2/m^2)\n"
+ "0.00\n"
+ "#\n"
+ "# Random roughness (mm)\n"
+ "4.00\n"
+ "# Ridge orientation (deg)\n"
+ "0.00\n"
+ "# Ridge height (mm)\n"
+ "0.00\n"
+ "# Spacing between ridge tops (mm)\n"
+ "10.00\n"
+ "# Ridge width (mm)\n"
+ "10.00\n"
+ "#\n"
+ "# Initial Bulk Density (1/3 bar)(Mg/m^3)\n"
+ "0.390 0.220 \n"
+ "# Initial soil water content (m^3/m^3)\n"
+ "0.379 0.379 \n"
+ "# Saturation soil water content (m^3/m^3)\n"
+ "0.550 0.550 \n"
+ "# Field capacity water content (m^3/m^3)\n"
+ "0.335 0.335 \n"
+ "# Wilting point water content (m^3/m^3)\n"
+ "0.240 0.240 \n"
+ "#\n"
+ "# Soil CB value (exponent to Campbell's SWRC)\n"
+ "6.831 6.831 \n"
+ "# Air entry potential (J/kg)\n"
+ "-4.379 -4.379 \n"
+ "# Saturated hydraulic conductivity (m/s)\n"
+ "5.0E-5 2.5E-5 \n"
+ "#";
////////////////////////////////////////////////////////////////////////////////////
private LinkedHashMap<String, Cocropyld> cropYlds = new LinkedHashMap<>();
private LinkedHashMap<String, Coecoclass> ecoClasses = new LinkedHashMap<>();
private final String[] nslpList = new String[]{"LOW", "MODERATE", "MODERATELY HIGH", "HIGH"};
private final String[] srpList = new String[]{"LOW", "MODERATE", "MODERATELY HIGH", "HIGH"};
private final TableComponent tableComponent = new TableComponent();
private final TableComponentCalculations tableComponentCalculatoins = new TableComponentCalculations();
private final TableExcluded tableExcluded = new TableExcluded();
private int restrict = 0;
private int restrictType = 0;
private double aniso = 0;
private double uksat = 0;
private Horizon surfaceHorizon = null;
private Horizon restrictingHorizon = null;
private boolean isOrganic = false;
public LinkedHashMap<String, Horizon> horizons;
public LinkedHashMap<String, Comonth> comonths;
/**
*
* @throws ServiceException
*/
public Component() throws ServiceException {
horizons = new LinkedHashMap<>();
comonths = new LinkedHashMap<>();
tableComponent.setRequiredColumns(componentRequiredInputs);
tableComponentCalculatoins.setRequiredColumns(componentRequiredInputs);
tableComponent.setUsedColumns(componentUsedColumns);
tableComponentCalculatoins.setUsedColumns(componentUsedColumns);
}
/**
*
* @param dataJSON
* @throws ServiceException
* @throws JSONException
*/
public Component(JSONArray dataJSON) throws ServiceException, JSONException {
if ((null != dataJSON) && (dataJSON.length() > 0)) {
Map<String, JSONObject> componentDataArray = JSONUtils.preprocess(dataJSON);
JSONArray horizonsArray;
tableComponent.setRequiredColumns(componentRequiredInputs);
tableComponentCalculatoins.setRequiredColumns(componentRequiredInputs);
tableComponent.setUsedColumns(componentUsedColumns);
tableComponentCalculatoins.setUsedColumns(componentUsedColumns);
tableComponent.readValuesFromJSON(componentDataArray);
tableComponentCalculatoins.readValuesFromJSON(componentDataArray);
tableComponentCalculatoins.area_pct(tableComponentCalculatoins.area_pct() / 100.0);
horizons = new LinkedHashMap<>();
comonths = new LinkedHashMap<>();
//TODO: Look for all horizon list types, i.e. wind, water, or just horizons here...
setHorizons(JSONUtils.getJSONArrayParam(componentDataArray, "horizons"));
} else {
throw new ServiceException("No component JSON specified. A NULL or empty value was passed to Component()");
}
}
public Component(ResultSet results) throws ServiceException {
tableComponent.setUsedColumns(componentUsedColumns);
tableComponentCalculatoins.setUsedColumns(componentUsedColumns);
tableComponent.setRequiredColumns(componentRequiredInputs);
tableComponentCalculatoins.setRequiredColumns(componentRequiredInputs);
tableComponent.readValuesFromSQL(results);
tableComponentCalculatoins.readValuesFromSQL(results);
horizons = new LinkedHashMap<>();
comonths = new LinkedHashMap<>();
}
public boolean hasTableColumn(String columnName) {
return tableComponent.getColumnList().contains(columnName);
}
public Object getTableColumnValue(String columnName) {
if (hasTableColumn(columnName)) {
return tableComponent.getColumns().get(columnName).getValue();
}
return null;
}
public TableColumn getTableColumn(String columnName) {
if (hasTableColumn(columnName)) {
return tableComponent.getColumns().get(columnName);
}
return null;
}
public TableComponent getTableColumns() {
return tableComponent;
}
public boolean isEqual(Component tComp) throws ServiceException {
boolean ret_val = (tableComponent.isEqual(tComp.getTableComponent())
&& tableComponentCalculatoins.isEqual(tComp.getTableComponentCalculations()));
// If sizes don't match, no need to scan each list, something will not match.
ret_val &= (cropYlds.size() == tComp.cropYlds().size()
&& ecoClasses.size() == tComp.ecoClasses().size()
&& horizons.size() == tComp.horizons().size()
&& comonths.size() == tComp.comonths().size());
for (Cocropyld tcropYld : cropYlds.values()) {
if (ret_val && tComp.cropYlds().containsKey(tcropYld.cocropyldkey())) {
ret_val &= tcropYld.isEqual(tComp.cropYlds().get(tcropYld.cocropyldkey()));
}
}
for (Coecoclass tecoClass : ecoClasses.values()) {
if (ret_val && tComp.ecoClasses().containsKey(String.valueOf(tecoClass.coecoclasskey()))) {
ret_val &= tecoClass.isEqual(tComp.ecoClasses().get(String.valueOf(tecoClass.coecoclasskey())));
}
}
for (Horizon thorizon : horizons.values()) {
if (ret_val && tComp.horizons().containsKey(thorizon.chkey())) {
ret_val &= thorizon.isEqual(tComp.horizons().get(thorizon.chkey()));
}
}
for (Comonth tcomonth : comonths.values()) {
if (ret_val && tComp.comonths.containsKey(tcomonth.comonthkey())) {
ret_val &= tcomonth.isEqual(tComp.comonths.get(tcomonth.comonthkey()));
}
}
return ret_val;
}
public void addComonth(Comonth comonth) {
if (null != comonths) {
if (!comonths.containsKey(comonth.comonthkey())) {
comonths.put(comonth.comonthkey(), comonth);
} else {
// Should we ignore this or throw an exception??
}
}
}
public void adjustForWEPS(MapUnit mapUnit, boolean averageStratified, boolean organicChecks, boolean estimateNulls) throws WEPSException {
try {
getWEPPSurfaceHorizon();
} catch (SDMException ex) {
throw new WEPSException(ex);
}
averageMissingWEPSValues();
if (averageStratified) {
SoilUtils.averageStratifiedLayers(this, STRATIFIED_TEXTURES);
}
adjustWEPSData(mapUnit, estimateNulls); // have to do this before converting units, I think it should be after but this is how WEPS does it
SoilUtils.convertUnits(mapUnit, this);
try {
if (organicChecks) {
checkWEPSOrganicSurface();
}
removeBadWEPSLayers();
} catch (SDMException ex) {
throw new WEPSException(ex);
}
}
// TODO: Examine this logic...does this still make sense for the latest WEPS filtering??
protected void removeBadWEPSLayers() throws SDMException {
Iterator<Horizon> it = horizons.values().iterator();
Horizon h;
boolean bad = false; // delete everything after bad found
if (it.hasNext()) {
it.next(); // skip the first horizon but I don't think the WEPS code is right
while (it.hasNext()) {
h = it.next();
if (bad) {
it.remove();
continue;
}
// stop if layer is identified as rock, peat, etc.
if (h.chkWEPSStopTexture()) {
it.remove();
bad = true;
continue;
}
// stop if both sand and clay are missing or zero
// Should already be removed because of the query
if ((EvalResult.testDefaultDouble(h.claytotal_r()) || h.claytotal_r() == 0.0)
&& (EvalResult.testDefaultDouble(h.sandtotal_r()) || h.sandtotal_r() == 0.0)) {
it.remove();
bad = true;
continue;
}
// stop if layer does not have wet bulk density
if (EvalResult.testDefaultDouble(h.dbthirdbar_r()) || h.dbthirdbar_r() == 0.0) {
it.remove();
bad = true;
}
}
} else {
throw new SDMException("No suitable list of horizons can be found for this component. Cannot continue WEPS model preparations.");
}
}
public void adjustWEPSData(MapUnit mapUnit, boolean estimateNulls) {
double calculatedSiltTotal;
if (compname() == null || compname().length() == 0) {
compname("unknown");
}
// WEPS check comp_pct here but as a string? wait until it becomes a problem
if (taxorder() == null || taxorder().length() == 0) {
taxorder("unkown");
}
if (localphase() == null || localphase().length() == 0) {
localphase("unkown");
}
tfact(SoilUtils.testNumericSoilElement(5, 1, tfact(), -1));
slope_r(SoilUtils.testNumericSoilElement(999, 0, slope_r(), -1));
mapUnit.brockdepmin(SoilUtils.testNumericSoilElement(9999, 0, mapUnit.brockdepmin(), 9999));
calculated_resdeptmin_r(SoilUtils.testNumericSoilElement(9999, 0, calculated_resdeptmin_r(), 9999));
for (Horizon h : horizons.values()) {
h.setWEPSDefaults(estimateNulls);
}
}
protected void setOrganicWEPS() throws SDMException {
if (taxorder().equalsIgnoreCase("Histosols")) {
isOrganic = true;
}
// assuming the first horizon is the top because the sql orders by deptht_r
if (surfaceHorizon.isOrganic()) {
isOrganic = true;
}
}
protected void checkWEPSOrganicSurface() throws SDMException, WEPSException {
double maxOrganicDepth = 100; //mm
int i = 0;
Iterator<Horizon> it = horizons.values().iterator();
Horizon h;
while (it.hasNext()) {
h = it.next();
if (h.isOrganic()) {
if (h.hzdepb_r() <= maxOrganicDepth) {
it.remove(); // save remove
} else if (i == 0) {
throw new WEPSException("The organic surface layer depth exceeded the maximum ignorable depth.\n"
+ "hzdepb_r=" + h.hzdepb_r() + " max organic depth set to " + maxOrganicDepth);
} else {
throw new WEPSException("The soil layer below the ignored organic layer is still organic.");
}
i++;
} else {
break; // We found a mineral layer
}
}
}
/**
* Averages the "_l" and "_h" values of component columns in SDM if the "_r"
* column was missing data, and sets the average as the value normally taken
* from the "_r" suffixed column. This function has questionable validity as
* the "_l" and "_h" suffixed columns in SDM are not meant to be interpreted
* this way necessarily; They represent the lowest and highest values
* encountered during a soil survey for this component at this location, but
* do not mean that these are distributed equally across the location, as the
* "_r" value is supposed to be used for that. This function, therefore, was
* created for WEPS in order to allow the WEPS model to run when the SDM
* database was missing data. Ideally, one should report the missing data, as
* is done in other functions, and have an ARS SME update the database.
*/
protected void averageMissingWEPSValues() {
slope_r(SoilUtils.averageMissingValue(slope_h(), slope_l(), slope_r()));
albedodry_r(SoilUtils.averageMissingValue(albedodry_h(), albedodry_l(), albedodry_r()));
for (Horizon h : horizons.values()) {
h.hzdept_r(SoilUtils.averageMissingValue(h.hzdept_h(), h.hzdept_l(), h.hzdept_r()));
h.hzdepb_r(SoilUtils.averageMissingValue(h.hzdepb_h(), h.hzdepb_l(), h.hzdepb_r()));
h.claytotal_r(SoilUtils.averageMissingValue(h.claytotal_h(), h.claytotal_l(), h.claytotal_r()));
h.sandtotal_r(SoilUtils.averageMissingValue(h.sandtotal_h(), h.sandtotal_l(), h.sandtotal_r())); // may be useless because the query removes null sandtotals
h.silttotal_r(SoilUtils.averageMissingValue(h.silttotal_h(), h.silttotal_l(), h.silttotal_r()));
h.sandvc_r(SoilUtils.averageMissingValue(h.sandvc_h(), h.sandvc_l(), h.sandvc_r(), 0));
h.sandco_r(SoilUtils.averageMissingValue(h.sandco_h(), h.sandco_l(), h.sandco_r(), 0));
h.sandmed_r(SoilUtils.averageMissingValue(h.sandmed_h(), h.sandmed_l(), h.sandmed_r(), 0));
h.sandfine_r(SoilUtils.averageMissingValue(h.sandfine_h(), h.sandfine_l(), h.sandfine_r(), 0));
h.sandvf_r(SoilUtils.averageMissingValue(h.sandvf_h(), h.sandvf_l(), h.sandvf_r()));
h.dbthirdbar_r(SoilUtils.averageMissingValue(h.dbthirdbar_h(), h.dbthirdbar_l(), h.dbthirdbar_r()));
h.wthirdbar_r(SoilUtils.averageMissingValue(h.wthirdbar_h(), h.wthirdbar_l(), h.wthirdbar_r()));
h.wfifteenbar_r(SoilUtils.averageMissingValue(h.wfifteenbar_h(), h.wfifteenbar_l(), h.wfifteenbar_r()));
h.ksat_r(SoilUtils.averageMissingValue(h.ksat_h(), h.ksat_l(), h.ksat_r()));
h.cec7_r(SoilUtils.averageMissingValue(h.cec7_h(), h.cec7_l(), h.cec7_r()));
h.ecec_r(SoilUtils.averageMissingValue(h.ecec_h(), h.ecec_l(), h.ecec_r()));
h.om_r(SoilUtils.averageMissingValue(h.om_h(), h.om_l(), h.om_r()));
h.caco3_r(SoilUtils.averageMissingValue(h.caco3_h(), h.caco3_l(), h.caco3_r()));
h.ph1to1h2o_r(SoilUtils.averageMissingValue(h.ph1to1h2o_h(), h.ph1to1h2o_l(), h.ph1to1h2o_r()));
h.ph01mcacl2_r(SoilUtils.averageMissingValue(h.ph01mcacl2_h(), h.ph01mcacl2_l(), h.ph01mcacl2_r()));
h.lep_r(SoilUtils.averageMissingValue(h.lep_h(), h.lep_l(), h.lep_r()));
}
}
/**
* This function checks to see if this component can be represented by the
* generic organic .sol file. Added the check for "histosol" to prevent
* returning the default organic .sol file for components that have complex
* layers and are not histosols.
*
* @return Returns true if the soil is a histosol, or if the "organic" member
* variable has already been set to true.
* @throws ServiceException
*/
protected boolean isDefaultOrganicSolFileComponent() throws SDMException {
return ((isOrganicSoil() && (0 == taxorder().compareToIgnoreCase("histosols"))) || (allHorizonsOrganic()));
}
public void adjustForWEPP_WEPS(String testModel) throws ServiceException, SDMException, WEPP_WEPSException, WEPPException, WEPSException {
ArrayList<String> skippedHorizons = new ArrayList<>();
boolean skipTheRest = false;
String msgWeppWepsParams;
// Do this for all models???
if (testModel.equalsIgnoreCase("weps")) {
slope_r(SoilUtils.averageMissingValue(slope_h(), slope_l(), slope_r()));
albedodry_r(SoilUtils.averageMissingValue(albedodry_h(), albedodry_l(), albedodry_r()));
}
for (Horizon tHorizon : horizons.values()) {
if (!skipTheRest) {
tHorizon.evaluateMineral();
tHorizon.evaluateForRestrictingHorizon(); // Sets the horizon restricting classification using ARS logic.
if (0 == tHorizon.hzdept_r()) {
if (tHorizon.hzdepb_r() >= 10) {
if (tHorizon.isOrganic()) {
surfaceHorizon(tHorizon);
tHorizon.useGenericHz1Values(true); //TODO: Also set component to use organic .sol file line-4 values...
} else {
if ((msgWeppWepsParams = tHorizon.hasWeppWepsParams(testModel)).isEmpty()) {
// Okay move on and use SDM values for this horizon
surfaceHorizon(tHorizon);
tHorizon.useGenericHz1Values(false);
tHorizon.useGenericHz2Values(false);
} else {
if (tHorizon.isRestricting() && tHorizon.isPermiable()) { // non-cemented restricting
skippedHorizons.add(tHorizon.chkey());
} else {
throw new WEPP_WEPSException("Horizon, " + tHorizon.chkey() + ", does not meet model parameter requirements: " + msgWeppWepsParams);
}
}
}
} else {
if (tHorizon.isOrganic()) {
skippedHorizons.add(tHorizon.chkey());
} else {
if (tHorizon.hasWeppWepsParams(testModel).isEmpty()) {
// Okay move on and use SDM values for this horizon
surfaceHorizon(tHorizon);
tHorizon.useGenericHz1Values(false);
tHorizon.useGenericHz2Values(false);
} else {
skippedHorizons.add(tHorizon.chkey());
}
}
}
} else {
if (tHorizon.hzdepb_r() < 10) {
if (tHorizon.isOrganic()) {
skippedHorizons.add(tHorizon.chkey());
} else {
if (tHorizon.hasWeppWepsParams(testModel).isEmpty()) {
// Okay move on and use SDM values for this horizon
if (null == surfaceHorizon()) {
surfaceHorizon(tHorizon);
}
tHorizon.useGenericHz1Values(false);
tHorizon.useGenericHz2Values(false);
} else {
skippedHorizons.add(tHorizon.chkey());
}
}
} else {
if (tHorizon.isOrganic()) {
if (tHorizon.hzdepb_r() < 40) {
if (null == surfaceHorizon()) {
surfaceHorizon(tHorizon);
}
tHorizon.useGenericHz1Values(true);
} else {
// TODO: What to do if we got all the way here and have not yet assigned a surfaceHorizon value??!
// TODO when writing this new horizon function be sure to toggle hz1 and hz2 together...they are mutually exclusive.
tHorizon.useGenericHz2Values(true);
}
} else {
if (tHorizon.isRestricting() && !tHorizon.isPermiable()) {
restrictingHorizon(tHorizon);
restrictingHorizon = tHorizon;
skipTheRest = true;
// ?? How to do this ?? What does this mean??? Is this the "restricting layer" from which we calculate those values
// stop and populate n+1 line in .sol file or depth to bedrock parameter in .ifc file
} else {
if (tHorizon.isRestricting() && tHorizon.isPermiable()) {
if (tHorizon.hasWeppWepsParams(testModel).isEmpty()) {
// Okay move on and use SDM values for this horizon
if (null == surfaceHorizon()) {
surfaceHorizon(tHorizon);
}
tHorizon.useGenericHz1Values(false);
tHorizon.useGenericHz2Values(false);
} else {
skippedHorizons.add(tHorizon.chkey());
}
} else {
if ((msgWeppWepsParams = tHorizon.hasWeppWepsParams(testModel)).isEmpty()) {
// Okay move on and use SDM values for this horizon
if (null == surfaceHorizon()) {
surfaceHorizon(tHorizon);
}
tHorizon.useGenericHz1Values(false);
tHorizon.useGenericHz2Values(false);
} else {
throw new WEPP_WEPSException("Horizon, " + tHorizon.chkey() + ", does not meet model parameter requirements: " + msgWeppWepsParams);
}
}
}
}
}
}
} else {
skippedHorizons.add(tHorizon.chkey());
}
}
if (null == surfaceHorizon()) {
throw new WEPP_WEPSException("Cannot continue with model parameter development, no surface horizon found that meets model requirements");
}
for (int i = 0; i < skippedHorizons.size(); i++) {
horizons.remove(skippedHorizons.get(i));
}
if (testModel.equalsIgnoreCase("wepp") || !testModel.equalsIgnoreCase("weps")) {
try {
if (!surfaceHorizon.useGenericHz1Values()) {
surfaceHorizon.computeErodibility();
}
} catch (WEPPException ex) {
throw new WEPP_WEPSException(ex);
}
setBedrockData(restrictingHorizon);
}
}
/**
* Adjusts the component and its subsequent member horizons data to meet WEPP
* filtering requirements. Finds the surface horizon, the restricting horizon,
* removes horizons that ARS wants to ignore, sets default horizon values, and
* computes the erodibility values. If any of the WEPP filtering requirements
* cannot be met, this function will throw a ServiceException, with an
* explanation of what is missing.
*
* @throws ServiceException
*/
public void adjustForWEPP() throws WEPPException {
try {
getWEPPSurfaceHorizon();
removeIgnoredHorizons();
getWEPPRestrictingHorizon(); // Also sets all the bedrock data for WEPP...
// Surface horizon needs to be set, but some components may not have a restricting layer, so don't error on that not being set.
if (null != surfaceHorizon) {
// If we're going to just return the generic organic sol file,
// no need to calculate erodibility, or set default values.
if (!isDefaultOrganicSolFileComponent()) {
if (!surfaceHorizon.useGenericHz1Values()) {
// Set all default horizon values needed for WEPP before attempting to compute erodability
for (Horizon tH : horizons.values()) {
tH.setWEPPDefaults();
}
surfaceHorizon.computeErodibility();
}
}
} else {
throw new WEPPException("No suitable surface horizon was found for this component. Cannot continue WEPP model preparations. Please contact your SDM data steward to have this corrected for this component: " + cokey());
}
} catch (SDMException ex) { // Wrap into a WEPP Exception so that services can choose to error-out or list errors but continue for WEPP filtering.
throw new WEPPException(ex);
}
}
/**
* Finds the restricting layer (horizon) for this component by calling the
* setBedRockData() function.
*
* @return Returns the restricting horizon if found, or throws an exception on
* error.
* @throws ServiceException
*/
protected Horizon getWEPPRestrictingHorizon() throws SDMException {
if (null == restrictingHorizon) {
if ((null != horizons) && (horizons.size() > 0)) {
// This function finds the restricting horizon and sets the internal restrictingHorizon variable as well along with WEPP specific bedrock data.
setBedrockData();
}
}
return restrictingHorizon;
}
/**
* Locates a suitable surface layer if one is present for this component. If
* multiple organic layers are stacked it adds them up until the total depth
* reaches the required ARS depth for an organic layer. ARS requires WEPP
* surface horizons to be organic.
*
* @return Returns the surface horizon if found.
* @throws ServiceException if an error is encountered during review of
* horizon data.
*/
protected Horizon getWEPPSurfaceHorizon() throws SDMException {
if (null == surfaceHorizon) {
if ((null != horizons) && (horizons.size() > 0)) {
Horizon nextHorizon = null;
double organicDepthTotal = 0;
ArrayList<Horizon> horizonArray = new ArrayList<>(horizons.values());
for (int i = 0; i < horizonArray.size(); i++) {
Horizon tHorizon = horizonArray.get(i);
boolean mineralHorizon = tHorizon.isMineral();
nextHorizon = (((i + 1) < horizonArray.size()) ? horizonArray.get(i + 1) : null);
if (tHorizon.isOrganic()) {
organicDepthTotal += (tHorizon.hzdepb_r() - tHorizon.hzdept_r());
} else {
//stop adding horizons, we have a non organic one.
nextHorizon = tHorizon;
break;
}
if (organicDepthTotal >= 10) {
// Not really needed but keeps the rest of the filter funcitons happy to set this...
surfaceHorizon = horizonArray.get(0);
surfaceHorizon.setSurface(true);
break;
}
}
if (organicDepthTotal >= 10) {
isOrganic = true;
if (null != nextHorizon) {
if (nextHorizon.isMineral()) {
// Set all horizons above the mineral one to use generic hz1 values from generic organic .sol file.
for (int i = 0; i < horizonArray.size(); i++) {
Horizon tHorizon = horizonArray.get(i);
if (tHorizon == nextHorizon) {
break;
}
tHorizon.useGenericSolParams(true);
}
}
}
} else {
surfaceHorizon = nextHorizon;
if (null != surfaceHorizon) {
surfaceHorizon.setSurface(true);
for (int i = 0; i < horizonArray.size(); i++) {
if (horizonArray.get(i) == surfaceHorizon) {
break;
}
// Remove skipped upper horizons from horizon list
horizons.remove(horizonArray.get(i));
}
}
}
}
}
return surfaceHorizon;
}
/**
* Removes horizons that ARS feels should be ignored for WEPP filtering.
* Horizon is removed entirely from the component's current list of horizons
* if it is deemed "ignored".
*
* @throws ServiceException
*/
public void removeIgnoredHorizons() throws SDMException {
ArrayList<String> badKeys = new ArrayList<>();
for (String hKey : horizons.keySet()) {
Horizon tHorizon = horizons.get(hKey);
if (tHorizon.isIgnored() && ((null != surfaceHorizon) && (tHorizon != surfaceHorizon))) {
badKeys.add(hKey);
}
}
for (int i = 0; i < badKeys.size(); i++) {
horizons.remove(badKeys.get(i));
}
}
public void computeSalinityAndSodicity() {
double totalSalinity = 0.0;
double totalSodicity = 0.0;
double totalDepth = 0.0;
boolean allValuesPresent = true;
for (Horizon tHorizon : horizons.values()) {
if ((!EvalResult.testDefaultDouble(tHorizon.hzdepb_r()))
&& (!EvalResult.testDefaultDouble(tHorizon.hzdept_r()))) {
if (tHorizon.hzdept_r() <= 60.0) {
double thickness = (tHorizon.hzdepb_r() - tHorizon.hzdept_r());
if (EvalResult.testDefaultDouble(tHorizon.ec_r()) || EvalResult.testDefaultDouble(tHorizon.sar_r())) {
allValuesPresent = false;
break; // No point in continuing; cannot calculate weighted averages if missing data...
}
double wAvgSal = thickness * tHorizon.ec_r();
double wAvgSod = thickness * tHorizon.sar_r();
if (tHorizon.hzdepb_r() <= 60.0) {
totalSalinity += wAvgSal;
totalSodicity += wAvgSod;
totalDepth += thickness;
} else {
double diff = 60.0 - tHorizon.hzdept_r();
wAvgSal *= (diff / thickness);
wAvgSod *= (diff / thickness);
totalSalinity += wAvgSal;
totalSodicity += wAvgSod;
totalDepth += diff;
}
}
}
}
if ((totalDepth > 0.0) && (allValuesPresent)) {
calculated_salinity(totalSalinity / totalDepth);
calculated_sodicity(totalSodicity / totalDepth);
}
}
public void computeTillageLayerClayTotal() {
double totalClay = 0.0;
double totalDepth = 0.0;
for (Horizon tHorizon : horizons.values()) {
if ((!EvalResult.testDefaultDouble(tHorizon.hzdepb_r()))
&& (!EvalResult.testDefaultDouble(tHorizon.hzdept_r()))
&& (!EvalResult.testDefaultDouble(tHorizon.claytotal_r()))) {
if (tHorizon.hzdept_r() <= 15.24) {
double thickness = (tHorizon.hzdepb_r() - tHorizon.hzdept_r());
double wAvg = thickness * tHorizon.claytotal_r();
if (tHorizon.hzdepb_r() <= 15.24) {
totalClay += wAvg;
totalDepth += thickness;
} else {
double diff = 15.24 - tHorizon.hzdept_r();
wAvg *= (diff / thickness);
totalClay += wAvg;
totalDepth += diff;
}
}
}
}
if (totalDepth > 0.0) {
calculated_tl_claytotal(totalClay / totalDepth);
}
}
private int computeNSLPHsgA() {
int nslpNumber = 3;
if (slope_r() > 12) {
nslpNumber = 2;
}
return nslpNumber;
}
private int computeNSLPHsgB() {
int nslpNumber = -1;
double slope = slope_r();
double kffact = calculated_kffact();
if ((slope <= 12 && kffact >= 0.24) || (slope > 12)) {
nslpNumber = 1;
} else if ((slope >= 3) && (slope <= 12) && (kffact < 0.24)) {
nslpNumber = 2;
} else if ((slope < 3) && (kffact < 0.24)) {
nslpNumber = 3;
}
return nslpNumber;
}
private int computeNSLPHsgC() {
int nslpNumber = 1;
return nslpNumber;
}
private int computeNSLPHsgD() {
int nslpNumber = 0;
return nslpNumber;
}
private int computeSRPHsgB() {
int srp_number = -1;
if (slope_r() < 4) {
srp_number = 0;
} else if (slope_r() >= 4 && slope_r() <= 6 && calculated_kffact() < 0.32) {
srp_number = 1;
} else if (slope_r() >= 4 && slope_r() <= 6 && calculated_kffact() >= 0.32) {
srp_number = 2;
} else if (slope_r() > 6) {
srp_number = 3;
}
return srp_number;
}
private int computeSRPHsgC() {
int srp_number = -1;
if (slope_r() < 2) {
srp_number = 0;
} else if (slope_r() >= 2 && slope_r() <= 6 && calculated_kffact() < 0.28) {
srp_number = 1;
} else if (slope_r() >= 2 && slope_r() <= 6 && calculated_kffact() >= 0.28) {
srp_number = 2;
} else if (slope_r() > 6) {
srp_number = 3;
}
return srp_number;
}
private int computeSRPHsgD() {
int srp_number = -1;
if (slope_r() < 2 && calculated_kffact() < 0.28) {
srp_number = 0;
} else if (slope_r() < 2 && calculated_kffact() >= 0.28) {
srp_number = 1;
} else if (slope_r() >= 2 && slope_r() <= 4) {
srp_number = 2;
}//NOTE: For the else below: The isDrained should already be checked
// before calling this fucntion therefore no need to use it in the hwt_lt_24 comparison.
else if ((slope_r() > 4) || ((calculated_wtkind().equals("Perched")
|| calculated_wtkind().equals("Apparent")) || this.calculated_hwt_lt_24())) {
srp_number = 3;
}
return srp_number;
}
/**
* Traverses the horizons of this component and looks for the layer that meets
* ARS conditions for being a restricting layer. If one is found, it is
* marked, and the permeable or non-permeable restriction values are set.
*
* @throws ServiceException
*/
public void setBedrockData() throws SDMException {
//char hzChar;
restrict = 0;
restrictType = 0;
aniso = 0;
uksat = 0;
if (null != horizons) {
for (Horizon tHorizon : horizons.values()) {
if (tHorizon.evaluateForRestrictingHorizon()) {
if (tHorizon.isPermiable()) {
restrict = 1;
restrictType = 2;
aniso = 25.000000;
uksat = 3.6;
restrictingHorizon = tHorizon;
restrictingHorizon.setRestricting(true);
} else {
restrict = 1;
restrictType = 2;
aniso = 25.000000;
uksat = 0.0036;
restrictingHorizon = tHorizon;
restrictingHorizon.setRestricting(true);
}
break;
}
}
}
}
public void setBedrockData(Horizon tHorizon) throws SDMException {
//char hzChar;
restrict = 0;
restrictType = 0;
aniso = 0;
uksat = 0;
if (null != tHorizon) {
if (tHorizon.evaluateForRestrictingHorizon()) {
if (tHorizon.isPermiable()) {
restrict = 1;
restrictType = 2;
aniso = 25.000000;
uksat = 3.6;
restrictingHorizon = tHorizon;
restrictingHorizon.setRestricting(true);
} else {
restrict = 1;
restrictType = 2;
aniso = 25.000000;
uksat = 0.0036;
restrictingHorizon = tHorizon;
restrictingHorizon.setRestricting(true);
}
}
}
}
private void setHorizons(JSONArray dataJSON) throws ServiceException, JSONException {
if ((null != dataJSON) && (dataJSON.length() > 0)) {
for (int i = 0; i < dataJSON.length(); i++) {
Horizon horizon = new Horizon(dataJSON.getJSONArray(i));
if (!horizons.containsKey(horizon.chkey())) {
horizons.put(horizon.chkey(), horizon);
} else {
throw new ServiceException("Duplicate component passed to Component.setHorizons() from input JSON. Horizon keys listed by component should be unique.");
}
}
tableComponentCalculatoins.long_name(comp_long_name());
}
}
private JSONArray groupBySelectionType(String type, boolean onlySelectedHorizons) throws JSONException {
JSONArray horizonArray = new JSONArray();
for (String chkey : horizons.keySet()) {
Horizon tHorizon = horizons.get(chkey);
if ((tHorizon.selected() && tHorizon.hasSelectedReason(type) && onlySelectedHorizons) || (!onlySelectedHorizons)) {
horizonArray.put(tHorizon.toJSON());
}
}
return horizonArray;
}
private JSONArray groupBySelectionTypeBasicJSON(String type, boolean onlySelectedHorizons) throws JSONException {
JSONArray horizonArray = new JSONArray();
for (String chkey : horizons.keySet()) {
Horizon tHorizon = horizons.get(chkey);
if ((tHorizon.selected() && tHorizon.hasSelectedReason(type) && onlySelectedHorizons) || (!onlySelectedHorizons)) {
horizonArray.put(tHorizon.toBasicJSON());
}
}
return horizonArray;
}
public final void hydricrating(boolean value) {
tableComponent.hydricrating(value);
}
public final boolean hydricrating() {
return tableComponent.hydricrating();
}
public final void albedodry_h(double value) {
tableComponent.albedodry_h(value);
}
public final double albedodry_h() {
return tableComponent.albedodry_h();
}
public final void albedodry_l(double value) {
tableComponent.albedodry_l(value);
}
public final double albedodry_l() {
return tableComponent.albedodry_l();
}
public final void albedodry_r(double value) {
tableComponent.albedodry_r(value);
}
public final double albedodry_r() {
return tableComponent.albedodry_r();
}
/**
*
* @return
*/
public final double calculated_water_ep() {
return tableComponentCalculatoins.calculated_water_ep();
}
/**
*
* @param water_ep
*/
public final void calculated_water_ep(double water_ep) {
tableComponentCalculatoins.calculated_water_ep(water_ep);
}
/**
*
* @return
*/
public final double calculated_wind_ep() {
return tableComponentCalculatoins.calculated_wind_ep();
}
/**
*
* @param wind_ep
*/
public final void calculated_wind_ep(double wind_ep) {
tableComponentCalculatoins.calculated_wind_ep(wind_ep);
}
/**
*
* @return
*/
public final double area_pct() {
return tableComponentCalculatoins.area_pct();
}
/**
*
* @param area_pct
*/
public final void area_pct(double area_pct) {
tableComponentCalculatoins.area_pct(area_pct);
}
/**
*
* @return
*/
public double calculated_area() {
return tableComponentCalculatoins.area();
}
/**
*
* @param value
*/
public final void drainagecl(String value) {
tableComponent.drainagecl(value);
}
/**
*
* @return
*/
public String drainagecl() {
return tableComponent.drainagecl();
}
/**
*
* @param area
*/
public void calculated_area(double area) {
tableComponentCalculatoins.area(area);
}
public String erocl() {
return tableComponent.erocl();
}
public void erocl(String value) {
tableComponent.erocl(value);
}
/**
*
* @return
*/
public final double calculated_claytotal_r() {
return tableComponentCalculatoins.claytotal_r();
}
public final void calculated_claytotal_r(double value) {
tableComponentCalculatoins.claytotal_r(value);
}
public final double calculated_tl_claytotal() {
return tableComponentCalculatoins.tl_claytotal();
}
public final void calculated_tl_claytotal(double value) {
tableComponentCalculatoins.tl_claytotal(value);
}
public final void calculated_salinity(double value) {
tableComponentCalculatoins.calculated_salinity(value);
}
public final void calculated_sodicity(double value) {
tableComponentCalculatoins.calculated_sodicity(value);
}
public final double calculated_salinity() {
return tableComponentCalculatoins.calculated_salinity();
}
public final double calculated_sodicity() {
return tableComponentCalculatoins.calculated_sodicity();
}
/**
*
* @param calculated_coarse_frag
*/
public final void calculated_coarse_frag(double calculated_coarse_frag) {
tableComponentCalculatoins.calculated_coarse_frag(calculated_coarse_frag);
}
/**
*
* @return
*/
public final double calculated_coarse_frag() {
return tableComponentCalculatoins.calculated_coarse_frag();
}
/**
*
* @param calculated_coarse_frag_vol_total
*/
public final void calculated_coarse_frag_vol_total(double calculated_coarse_frag_vol_total) {
tableComponentCalculatoins.calculated_coarse_frag_vol_total(calculated_coarse_frag_vol_total);
}
/**
*
* @return
*/
public final double calculated_coarse_frag_vol_total() {
return tableComponentCalculatoins.calculated_coarse_frag_vol_total();
}
/**
*
* @param calculated_hwt_lt_24
*/
public final void calculated_hwt_lt_24(boolean calculated_hwt_lt_24) {
tableComponentCalculatoins.calculated_hwt_lt_24(calculated_hwt_lt_24);
}
/**
*
* @param value
*/
public final void calculated_ec(double value) {
tableComponentCalculatoins.calculated_ec(value);
}
/**
*
* @return
*/
public final double calculated_ec() {
return tableComponentCalculatoins.calculated_ec();
}
/**
*
* @param value
*/
public final void calculated_ecec(double value) {
tableComponentCalculatoins.calculated_ecec(value);
}
/**
*
* @return
*/
public final double calculated_ecec() {
return tableComponentCalculatoins.calculated_ecec();
}
/**
*
* @param value
*/
public final void calculated_cec7(double value) {
tableComponentCalculatoins.calculated_cec7(value);
}
/**
*
* @return
*/
public final double calculated_cec7() {
return tableComponentCalculatoins.calculated_cec7();
}
/**
*
* @return
*/
public final boolean calculated_hwt_lt_24() {
return tableComponentCalculatoins.calculated_hwt_lt_24();
}
/**
*
* @param calculated_hzdepb_r
*/
public final void calculated_hzdepb_r(double calculated_hzdepb_r) {
tableComponentCalculatoins.calculated_hzdepb_r(calculated_hzdepb_r);
}
/**
*
* @return
*/
public final double calculated_hzdepb_r() {
return tableComponentCalculatoins.calculated_hzdepb_r();
}
/**
*
* @param kffact
*/
public final void calculated_kffact(double kffact) {
tableComponentCalculatoins.calculated_kffact(kffact);
}
/**
*
* @return
*/
public final double calculated_kffact() {
return tableComponentCalculatoins.calculated_kffact();
}
/**
*
* @param lsfact
*/
public final void calculated_lsfact(double lsfact) {
tableComponentCalculatoins.calculated_lsfact(lsfact);
}
public final double calculated_lsfact() {
return tableComponentCalculatoins.calculated_lsfact();
}
/**
*
* @param nslp
*/
public void calculated_nslp(String nslp) {
tableComponentCalculatoins.calculated_nslp(nslp);
}
/**
*
* @return
*/
public String calculated_nslp() {
return tableComponentCalculatoins.calculated_nslp();
}
/**
*
* @param nslp_number
*/
public void calculated_nslp_number(double nslp_number) {
tableComponentCalculatoins.nslp_number(nslp_number);
}
/**
*
* @return
*/
public double calculated_nslp_number() {
return tableComponentCalculatoins.nslp_number();
}
/**
*
* @param calculated_om_r
*/
public final void calculated_om_r(double calculated_om_r) {
tableComponentCalculatoins.calculated_om_r(calculated_om_r);
}
/**
*
* @return
*/
public final double calculated_om_r() {
return tableComponentCalculatoins.calculated_om_r();
}
/**
* @param calculated_pH
*/
public final void calculated_pH(double calculated_pH) {
tableComponentCalculatoins.calculated_pH(calculated_pH);
}
/**
*
* @return
*/
public final double calculated_pH() {
return tableComponentCalculatoins.calculated_pH();
}
public final void calculated_resdeptmin_r(double value) {
tableComponentCalculatoins.resdeptmin_r(value);
}
public final double calculated_resdeptmin_r() {
return tableComponentCalculatoins.resdeptmin_r();
}
/**
*
* @param calculated_sandtotal_r
*/
public final void calculated_sandtotal_r(double calculated_sandtotal_r) {
tableComponentCalculatoins.calculated_sandtotal_r(calculated_sandtotal_r);
}
/**
*
* @return
*/
public final double calculated_sandtotal_r() {
return tableComponentCalculatoins.calculated_sandtotal_r();
}
/**
*
* @return
*/
public final double calculated_silttotal_r() {
return tableComponentCalculatoins.silttotal_r();
}
public final void calculated_silttotal_r(double value) {
tableComponentCalculatoins.silttotal_r(value);
}
/**
*
* @param srp
*/
public void calculated_srp(String srp) {
tableComponentCalculatoins.calculated_srp(srp);
}
/**
*
* @return
*/
public String calculated_srp() {
return tableComponentCalculatoins.calculated_srp();
}
/**
*
* @param srp_number
*/
public void calculated_srp_number(double srp_number) {
tableComponentCalculatoins.calculated_srp_number(srp_number);
}
/**
*
* @return
*/
public double calculated_srp_number() {
return tableComponentCalculatoins.calculated_srp_number();
}
/**
*
* @param wtbl_top_min
*/
public final void calculated_wtbl_top_min(double wtbl_top_min) {
tableComponentCalculatoins.calculated_wtbl_top_min(wtbl_top_min);
}
/**
*
* @return
*/
public final double calculated_wtbl_top_min() {
return tableComponentCalculatoins.calculated_wtbl_top_min();
}
/**
*
* @param wtkind
*/
public final void calculated_wtkind(String wtkind) {
tableComponentCalculatoins.calculated_wtbl(wtkind);
}
/**
*
* @return
*/
public final String calculated_wtkind() {
return tableComponentCalculatoins.calculated_wtbl();
}
// /**
// *
// * @return
// */
// public final String cokey() {
// return tableComponent.cokey();
// }
//
// /**
// *
// * @param cokey
// */
// public final void cokey(String cokey) {
// tableComponent.cokey(cokey);
// }
public final void cokey(int value) {
Validation.checkCokey(value);
tableComponent.cokey(value);
}
public final void cokey(String value) {
Validation.checkCokey(value);
tableComponent.cokey(Integer.parseInt(value));
}
public final String cokey() {
return Integer.toString(tableComponent.cokey());
}
/**
*
* @return
*/
public final String compkind() {
return tableComponent.compkind();
}
/**
*
* @param compkind
*/
public final void compkind(String compkind) {
tableComponent.compkind(compkind);
}
/**
*
* @return
*/
public final String compname() {
return tableComponent.compname();
}
/**
*
* @param compname
*/
public final void compname(String compname) {
tableComponent.compname(compname);
}
/**
*
* @return
*/
public final double comppct_r() {
return tableComponent.comppct_r();
}
/**
*
* @param comppct_r
*/
public final void comppct_r(double comppct_r) {
tableComponent.comppct_r(comppct_r);
}
// NOTE: HSG is hydgrp
public void computeNSLP() throws ServiceException {
int comp_nslp_number = -2; //Preset to error condition of invalid combinations.
// OLD Logic---
// If Histosols OR ( Apparent and wtbl_top_min <= 76cm )
// if (ip.getTaxorder().isEqual("Histosols") || ((ip.getWtbl().isEqual("Apparent")
// || ip.getWtbl().isEqual("Perched")) && (ip.getWtblTopMin() <= 76))) {
// END OLD Logic
if (taxorder().equals("Histosols") || ((calculated_wtkind().equalsIgnoreCase("Apparent")) && (!EvalResult.testDefaultDouble(calculated_wtbl_top_min())) && (calculated_wtbl_top_min() <= 76))) {
comp_nslp_number = 3;
} else {
// Otherwise we need to look at slope and/or coarse fragmentation for this component's hydrologic group.
switch (hydgrp()) {
case "A":
comp_nslp_number = computeNSLPHsgA();
break;
case "B":
comp_nslp_number = computeNSLPHsgB();
break;
case "C":
comp_nslp_number = computeNSLPHsgC();
break;
case "D":
comp_nslp_number = computeNSLPHsgD();
break;
// Any dual/combined hydrologic group is "HIGH"
case "A/D":
case "B/D":
case "C/D":
comp_nslp_number = 3;
break;
//NOTE: There is no default section here because the comp_nslp_number variable is
// being used to mark specific error conditions. If this switch fails through
// then comp_nslp_number will remain set to -2, which is checked below. This should NEVER happen, but
// the check is here just in case...
}
}
//Check for error conditions, and if none, then set the NSLP number for this component.
if (comp_nslp_number != -1 && comp_nslp_number != -2) { // These represent error conditions in this function.
if ((comp_nslp_number >= 0) && (comp_nslp_number <= 3)) {
//Adjust final number by coarseFrag values logic
if (calculated_coarse_frag() > 30) {
comp_nslp_number += 2;
if (comp_nslp_number > 3) {
comp_nslp_number = 3;
}
} else if (calculated_coarse_frag() > 10) {
comp_nslp_number += 1;
if (comp_nslp_number > 3) {
comp_nslp_number = 3;
}
} // Otherwise just leave it alone, no adjustments are needed.
calculated_nslp_number(comp_nslp_number);
calculated_nslp(nslpList[comp_nslp_number]);
} else {
throw new ServiceException("An invalid Soil Leaching Potential value was calculated: " + comp_nslp_number + ". Cannot continue. ");
}
} else if (comp_nslp_number == -1) { // Failed in the embedded Hsg computational functions
throw new ServiceException("Invalid Hsg calculation for this soil for: " + hydgrp() + ". Cannot continue with NSLP estimation for component key: " + cokey() + ". ");
} else if (comp_nslp_number == -2) { //Failed the above switch statement
throw new ServiceException("Invalid Hsg name for this soil component key: " + cokey()
+ " which is neither Histosols nor (Apparent AND <= 76cm) in Water Table Type. Cannot continue with the NSLP estimations.");
} // No else here because it cannot happen...unless someone edits this code and adds a new "error condition" number to use for
// comp_nslp_number...if you do, then PLEASE add a check for it here and keep to the convention of using a negative integer.
}
public void computePestSARP(boolean isDrained) {
String hydgrp = hydgrp();
switch (hydgrp) {
case "A/D":
case "B/D":
case "C/D":
if (!isDrained) {
hydgrp = "D";
} else {
hydgrp = hydgrp.substring(0, 1);
}
break;
}
psarp_number(2);
if ((hydgrp.equals("C") && calculated_kffact() >= 0.21)
|| (hydgrp.equals("D") && calculated_kffact() >= 0.10)) {
psarp_number(3);
} else if (hydgrp.equals("A")
|| (hydgrp.equals("B") && calculated_kffact() <= 0.10)
|| (hydgrp.equals("C") && calculated_kffact() <= 0.07)
|| (hydgrp.equals("D") && calculated_kffact() <= 0.02)) {
psarp_number(1);
}
if (this.slopegr15()) {
if (psarp_number() < 3) {
psarp_number(psarp_number() + 1);
}
}
}
public void computePestSLP(boolean isDrained) {
boolean aoa_comp_cracksgr24 = false;
if (calculated_hwt_lt_24() && !isDrained) {
pslp_number(PSLP_HIGH);
} else if (((hydgrp().equals("A") || hydgrp().equals("A/D")) && ((calculated_hzdepb_r() * calculated_om_r()) <= (30 * INCH_TO_CM)))
|| ((hydgrp().equals("B") || hydgrp().equals("B/D")) && ((calculated_hzdepb_r() * calculated_om_r()) <= (9 * INCH_TO_CM)) && (calculated_kffact() <= 0.48))
|| ((hydgrp().equals("B") || hydgrp().equals("B/D")) && ((calculated_hzdepb_r() * calculated_om_r()) <= (15 * INCH_TO_CM)) && (calculated_kffact() <= 0.26))) {
pslp_number(PSLP_HIGH);
} else if (((hydgrp().equals("B") || hydgrp().equals("B/D")) && ((calculated_hzdepb_r() * calculated_om_r()) >= (35 * INCH_TO_CM)) && calculated_kffact() >= 0.40)
|| ((hydgrp().equals("B") || hydgrp().equals("B/D")) && ((calculated_hzdepb_r() * calculated_om_r()) >= (45 * INCH_TO_CM)) && calculated_kffact() >= 0.20)
|| ((hydgrp().equals("C") || hydgrp().equals("C/D")) && ((calculated_hzdepb_r() * calculated_om_r()) <= (10 * INCH_TO_CM)) && calculated_kffact() <= 0.28)
|| ((hydgrp().equals("C") || hydgrp().equals("C/D")) && ((calculated_hzdepb_r() * calculated_om_r()) >= (10 * INCH_TO_CM)))) {
if (!aoa_comp_cracksgr24) {
pslp_number(PSLP_LOW);
} else {
pslp_number(PSLP_INTERMEDIATE);
}
} else if (hydgrp().equals("D")) {
if (!aoa_comp_cracksgr24) {
pslp_number(PSLP_VERY_LOW);
} else {
pslp_number(PSLP_LOW);
}
} else if (!aoa_comp_cracksgr24) {
pslp_number(PSLP_INTERMEDIATE);
} else {
pslp_number(PSLP_HIGH);
}
if (pslp_number() < COMP_PSLP_STRING.length) {
pslp(COMP_PSLP_STRING[pslp_number()]);
} else {
pslp(COMP_PSLP_STRING[0]);
}
}
public void computePestSSRP(boolean isDrained) {
switch (hydgrp()) {
case "C":
case "D":
case "C/D":
pssrp_number(3);
break;
case "A":
pssrp_number(1);
break;
case "A/D":
if (isDrained) {
pssrp_number(1);
} else {
pssrp_number(3);
}
break;
case "B":
pssrp_number(2);
break;
case "B/D":
if (isDrained) {
pssrp_number(2);
} else if (!isDrained) {
pssrp_number(3);
}
break;
default:
pssrp_number(0);
}
pssrp(COMP_PSSRP[pssrp_number()]);
}
public void computeSedNutSRP(boolean isDrained) throws ServiceException {
int comp_srp_number = -2;
switch (hydgrp()) {
case "A":
comp_srp_number = 0;
break;
case "B":
comp_srp_number = computeSRPHsgB();
break;
case "C":
comp_srp_number = computeSRPHsgC();
break;
case "D":
if ((calculated_wtkind().equals("Perched")
|| calculated_wtkind().equals("Apparent")) || (calculated_hwt_lt_24() && !isDrained)) {
comp_srp_number = 3;
} else if (slope_r() < 2 && calculated_kffact() < 0.28) {
comp_srp_number = 0;
} else if (slope_r() < 2 && calculated_kffact() >= 0.28) {
comp_srp_number = 1;
} else if (slope_r() >= 2 && slope_r() <= 4) {
comp_srp_number = 2;
} else if (slope_r() > 4) {
comp_srp_number = 3;
}
break;
case "A/D":
if (isDrained) {
comp_srp_number = 0;
} else {
comp_srp_number = computeSRPHsgD();
}
break;
case "B/D":
if (isDrained) {
comp_srp_number = computeSRPHsgB();
} else {
comp_srp_number = computeSRPHsgD();
}
break;
case "C/D":
if (isDrained) {
comp_srp_number = computeSRPHsgC();
} else {
comp_srp_number = computeSRPHsgD();
}
break;
}
if (comp_srp_number != -1 && comp_srp_number != -2) {
calculated_srp_number(comp_srp_number);
calculated_srp(srpList[comp_srp_number]);
} else {
throw new ServiceException("Error in calculating SedNutSRP: Invalid hydgrp value, (" + hydgrp() + "), for this component, " + cokey() + ", found in the database. Please contact your NRCS data steward for assistance in corecting the database.");
}
}
public LinkedHashMap<String, Cocropyld> cropYlds() {
return cropYlds;
}
public Component deepCopy() throws ServiceException {
Component tComponent = new Component();
deepCopy(tComponent);
return tComponent;
}
public synchronized void deepCopy(Component newComponent) {
if (null != newComponent) {
tableComponent.deepCopy(newComponent.tableComponent);
tableComponentCalculatoins.deepCopy(newComponent.tableComponentCalculatoins);
tableExcluded.deepCopy(newComponent.tableExcluded);
LinkedHashMap<String, Horizon> tHorizons = new LinkedHashMap<>();
for (Horizon tHorizon : horizons.values()) {
Horizon newHorizon = tHorizon.deepCopy();
if (null != newHorizon) {
tHorizons.put(newHorizon.chkey(), newHorizon);
}
}
if (tHorizons.size() > 0) {
newComponent.setHorizons(tHorizons);
}
newComponent.restrict(restrict());
newComponent.restrictType(restrictType());
newComponent.aniso(aniso());
newComponent.uksat(uksat());
newComponent.surfaceHorizon(surfaceHorizon());
newComponent.restrictingHorizon(restrictingHorizon());
newComponent.isOrganic(isOrganic());
}
}
public void setHorizons(LinkedHashMap<String, Horizon> tHorizons) {
if ((null != tHorizons) && (tHorizons.size() > 0)) {
horizons.clear();
for (Horizon tHorizon : tHorizons.values()) {
if (!horizons.containsKey(tHorizon.chkey())) {
horizons.put(tHorizon.chkey(), tHorizon);
}
}
}
}
public int restrict() {
return restrict;
}
public int restrictType() {
return restrictType;
}
public double aniso() {
return aniso;
}
public double uksat() {
return uksat;
}
public Horizon surfaceHorizon() {
return surfaceHorizon;
}
public Horizon restrictingHorizon() {
return restrictingHorizon;
}
public boolean isOrganic() {
return isOrganic;
}
public void restrict(int value) {
restrict = value;
}
public void restrictType(int value) {
restrictType = value;
}
public void aniso(double value) {
aniso = value;
}
public void uksat(double value) {
uksat = value;
}
/**
* updateCalculations goes through and updates any table calculations locally
* and at the horizon, texture fragment levels in order to fill in missing
* values.
*/
public void updateCalculations() {
double profile_thk = 0.0;
boolean haveHzDepth = false;
boolean haveOM_R = false;
double comp_product = 0.0;
int counter = 0;
if (horizons.size() > 0) {
double pH = 0.0;
double pH_thickness = 0.0;
if (EvalResult.testDefaultDouble(calculated_coarse_frag_vol_total())) {
calculated_coarse_frag_vol_total(0.0);
}
for (Horizon horizon : horizons.values()) {
double horizonThickness = 0.0;
double horizonProduct = 0.0;
double pH_l = horizon.ph1to1h2o_l();
double pH_r = horizon.ph1to1h2o_r();
double pH_h = horizon.ph1to1h2o_h();
// if (0 == counter) {
// calculated_om_r(horizon.om_r());
// }
counter++;
horizonThickness = horizon.hzthk_r();
if ((!haveOM_R) && (!haveHzDepth) && (horizon.selected())) {
calculated_om_r(horizon.om_r());
calculated_hzdepb_r(horizonThickness);
haveHzDepth = true;
haveOM_R = true;
}
if (EvalResult.testDefaultDouble(pH_r)) {
if (!EvalResult.testDefaultDouble(pH_h) && !EvalResult.testDefaultDouble(pH_l)) {
pH_r = (pH_h + pH_l) / 2.0;
pH_thickness += horizonThickness;
pH += pH_r * horizonThickness;
}//Else ignore this layer in the calculation...don't need to do anything else in this case...
} else {
pH_thickness += horizonThickness;
pH += pH_r * horizonThickness;
}
calculated_coarse_frag_vol_total(calculated_coarse_frag_vol_total() + (EvalResult.testDefaultDouble(horizon.fragvol_r()) ? 0 : horizon.fragvol_r()));
profile_thk += horizonThickness;
horizonProduct = horizonThickness * (EvalResult.testDefaultDouble(horizon.fragvol_r()) ? 0 : horizon.fragvol_r());
comp_product += horizonProduct;
}
if (profile_thk > 0.0) {
calculated_coarse_frag(comp_product / profile_thk);
}
if (pH_thickness > 0.0) {
calculated_pH(pH / pH_thickness);
}
profileDepth(profile_thk);
}
// double totalFragVol = 0.0, calculatedFragVol = 0.0;
// double totalProfileDepth = 0.0;
//
// for (Horizon tHorizon : horizons.values()) {
// totalProfileDepth += tHorizon.hzthk_r();
// //fragvol_r auto fills itself from the underlying fragment records, if it hasn't been set yet.
// //calculatedFragVol += (tHorizon.hzthk_r() / totalProfileDepth) * tHorizon.fragvol_r();
// calculatedFragVol = calculatedFragVol + (tHorizon.hzthk_r() * tHorizon.fragvol_r());
// totalFragVol += tHorizon.fragvol_r();
// }
//
// profileDepth(totalProfileDepth);
//
// if (totalProfileDepth > 0.0) {
// calculated_coarse_frag(calculatedFragVol / totalProfileDepth);
// }
//
// calculated_coarse_frag_vol_total(totalFragVol);
}
public void surfaceHorizon(Horizon value) {
surfaceHorizon = value;
}
public void restrictingHorizon(Horizon value) {
restrictingHorizon = value;
}
public void isOrganic(boolean value) {
isOrganic = value;
}
public LinkedHashMap<String, Coecoclass> ecoClasses() {
return ecoClasses;
}
public void exclude() {
tableExcluded.exclude();
}
public void exclude(boolean value) {
tableExcluded.exclude(value);
}
public void setExcludedReason(String reason) {
exclude();
tableExcluded.setExcludedReason(reason);
}
public boolean applyHorizonFilter(String filter) throws ServiceException {
boolean ret_val = false;
FilterResults filterResults = new FilterResults();
switch (filter.toLowerCase()) {
case "water":
filterResults.foundKffact = false;
for (Horizon tHorizon : horizons.values()) {
if (!filterResults.foundKffact) {
if (EvalResult.testDefaultDouble(tHorizon.kffact())) {
if (EvalResult.testDefaultDouble(tHorizon.kwfact())) {
if (taxorder().equalsIgnoreCase("histosols")) {
tHorizon.kffact(0.02);
filterResults.foundKffact = true;
tHorizon.selected(true);
tHorizon.selectedReason("WATER");
calculated_kffact(tHorizon.kffact());
calculated_lsfact(tHorizon.lsfact());
calculated_claytotal_r(tHorizon.claytotal_r());
ret_val = true;
}
} else {
filterResults.foundKffact = true;
tHorizon.selected(true);
tHorizon.selectedReason("WATER");
calculated_kffact(tHorizon.kffact());
calculated_lsfact(tHorizon.lsfact());
calculated_claytotal_r(tHorizon.claytotal_r());
ret_val = true;
}
} else {
filterResults.foundKffact = true;
tHorizon.selected(true);
tHorizon.selectedReason("WATER");
calculated_kffact(tHorizon.kffact());
calculated_lsfact(tHorizon.lsfact());
calculated_claytotal_r(tHorizon.claytotal_r());
ret_val = true;
}
} else {
break;
}
}
if (!filterResults.foundKffact) {
setExclude(true, BAD_KFFACT_LAYERS);
}
break;
case "wind":
filterResults.foundSandLayer = false;
for (Horizon tHorizon : horizons.values()) {
if (!filterResults.foundSandLayer) {
if (taxorder().equalsIgnoreCase("histosols") || (!taxorder().equalsIgnoreCase("histosols") && (tHorizon.hzdepb_r() > 10) && (tHorizon.om_r() > 15))) {
tHorizon.sandtotal_r(50);
}
if (tHorizon.sandtotal_r() >= 0.0) {
calculated_sandtotal_r(tHorizon.sandtotal_r());
tHorizon.selected(true);
tHorizon.selectedReason("WIND");
calculated_om_r(tHorizon.om_r());
calculated_hzdepb_r(tHorizon.hzdepb_r());
calculated_claytotal_r(tHorizon.claytotal_r());
filterResults.foundSandLayer = true;
ret_val = true;
}
} else {
break;
}
}
if (!filterResults.foundSandLayer) {
setExclude(true, BAD_SAND_LAYERS);
}
break;
default:
throw new ServiceException("Invalid filter specified.");
}
return ret_val;
}
public String getExcludedReason() {
return tableExcluded.getExcludedReason();
}
/**
*
* @param usedList
*/
public void setHorizonOutputColumns(List<String> usedList) {
for (String key : horizons.keySet()) {
horizons.get(key).setOutputColumns(usedList);
}
}
/**
*
* @param usedList
*/
public void setHorizonOutputColumnOrdering(List<String> usedList) {
for (String key : horizons.keySet()) {
horizons.get(key).setOutputColumnOrdering(usedList);
}
}
/**
*
* @param usedList
*/
public void setTextureGroupOutputColumns(List<String> usedList) {
for (Horizon tHorizon : horizons.values()) {
for (TextureGroup tGroup : tHorizon.textureGroups.values()) {
tGroup.setOutputColumns(usedList);
}
}
}
/**
*
* @param usedList
*/
public void setTextureOutputColumns(List<String> usedList) {
for (Horizon tHorizon : horizons.values()) {
for (TextureGroup tGroup : tHorizon.textureGroups.values()) {
for (Texture tTexture : tGroup.textures.values()) {
tTexture.setOutputColumns(usedList);
}
}
}
}
/**
*
* @param usedList
*/
public void setFragmentOutputColumns(List<String> usedList) {
for (Horizon tHorizon : horizons.values()) {
for (Fragments tFragments : tHorizon.fragments.values()) {
tFragments.setOutputColumns(usedList);
}
}
}
/**
*
* @param usedList
*/
public void setFragmentOutputColumnOrdering(List<String> usedList) {
for (Horizon tHorizon : horizons.values()) {
for (Fragments tFragments : tHorizon.fragments.values()) {
tFragments.setOutputColumnOrdering(usedList);
}
}
}
/**
*
* @param usedList
*/
public void setTextureGroupOutputColumnOrdering(List<String> usedList) {
for (Horizon tHorizon : horizons.values()) {
for (TextureGroup tGroup : tHorizon.textureGroups.values()) {
tGroup.setOutputColumnOrdering(usedList);
}
}
}
/**
*
* @param usedList
*/
public void setTextureOutputColumnOrdering(List<String> usedList) {
for (Horizon tHorizon : horizons.values()) {
for (TextureGroup tGroup : tHorizon.textureGroups.values()) {
for (Texture tTexture : tGroup.textures.values()) {
tTexture.setOutputColumnOrdering(usedList);
}
}
}
}
/**
*
* @param usedList
*/
public void setHorizonUsedColumns(List<String> usedList) {
for (String key : horizons.keySet()) {
horizons.get(key).setUsedColumns(usedList);
}
}
/**
*
* @param usedList
*/
public void setOutputColumns(List<String> usedList) {
tableComponent.setOutputColumns(usedList);
tableComponentCalculatoins.setOutputColumns(usedList);
}
/**
*
* @param usedList
*/
public void setOutputColumnOrdering(List<String> usedList) {
tableComponent.setOutputColumnOrdering(usedList);
tableComponentCalculatoins.setOutputColumnOrdering(usedList);
}
//TODO: double-check that this is the same as is done for WEPS
public double getWEPPSurfaceAlbedo() throws WEPPException {
if (null != surfaceHorizon) {
if (albedodry_r() == 0.0 || EvalResult.testDefaultDouble(albedodry_r()) || albedodry_r() < 0 || albedodry_r() > 1) {
albedodry_r(0.6 / (Math.exp(0.4 * surfaceHorizon.om_r() * 100.0)));
}
} else {
throw new WEPPException("Cannot compute WEPP surface albedo. Missing surface horizon layer.");
}
return albedodry_r();
}
public TableComponent getTableComponent() {
return tableComponent;
}
public TableComponentCalculations getTableComponentCalculations() {
return tableComponentCalculatoins;
}
/**
*
* @param usedList
*/
public void setUsedColumns(List<String> usedList) {
tableComponent.setUsedColumns(usedList);
tableComponentCalculatoins.setUsedColumns(usedList);
}
public LinkedHashMap<String, Horizon> horizons() {
return this.horizons;
}
public LinkedHashMap<String, Comonth> comonths() {
return this.comonths;
}
/**
*
* @return
*/
public final String hydgrp() {
return tableComponent.hydgrp();
}
/**
*
* @param hydgrp
*/
public final void hydgrp(String hydgrp) {
tableComponent.hydgrp(hydgrp);
}
public boolean isExcluded() {
return tableExcluded.isExcluded();
}
public boolean allHorizonsOrganic() throws SDMException {
int organicCount = 0;
for (Horizon tHorizon : horizons.values()) {
if (tHorizon.isOrganic()) {
organicCount++;
}
}
if (organicCount == horizons.size()) {
return true;
}
return false;
}
public boolean isOrganicSoil() throws SDMException {
// This may get set to true while searching for the surface horizon in
// the beginning if multiple organic layers were found next to each other
// that all added up to more than 10cm in depth.
if (isOrganic) {
return true;
} else if (null != surfaceHorizon) {
// Is the taxorder of this soil a Histosol?
if (0 == taxorder().compareToIgnoreCase("histosols")) {
return true;
}
// Is the surface Horizon organic and sufficiently deep?
if ((surfaceHorizon.hzdepb_r() - surfaceHorizon.hzdept_r()) > 10) {
if (surfaceHorizon.om_r() >= 15) {
return true;
}
}
// Are all horizons organic? Then soil is organic
int organicCount = 0;
for (Horizon tHorizon : horizons.values()) {
if (tHorizon.isOrganic()) {
organicCount++;
}
}
if (organicCount == horizons.size()) {
return true;
}
}
return false;
}
/**
*
* @return
*/
public final double length_r() {
return tableComponentCalculatoins.length_r();
}
/**
*
* @param length_r
*/
public final void length_r(double length_r) {
tableComponentCalculatoins.length_r(length_r);
}
/**
*
* @return
*/
public final String localphase() {
return tableComponent.localphase();
}
/**
*
* @param localphase
*/
public final void localphase(String localphase) {
tableComponent.localphase(localphase);
}
public String comp_long_name() {
String ret_val = compname() + "_" + mukey() + "_";
Double tPct = comppct_r();
ret_val += tPct.intValue();
if (null != horizons) {
Horizon topH = topSelectedHorizon();
if (null != topH) {
for (TextureGroup tGroup : topH.textureGroups.values()) {
if (tGroup.rvindicator()) {
ret_val += "_" + tGroup.texture();
}
}
}
}
return ret_val;
}
public void merge(Component mergeThisUnit) throws ServiceException {
this.tableComponent.merge(mergeThisUnit.getTableComponent());
this.tableComponentCalculatoins.merge(mergeThisUnit.getTableComponentCalculations());
for (String key : mergeThisUnit.horizons.keySet()) {
if (horizons.containsKey(key)) {
horizons.get(key).merge(mergeThisUnit.horizons.get(key));
}
}
}
public final void mukey(String value) {
Validation.checkMukey(value);
tableComponent.mukey(Integer.parseInt(value));
}
public final void mukey(int value) {
Validation.checkMukey(value);
tableComponent.mukey(value);
}
public final String mukey() {
return Integer.toString(tableComponent.mukey());
}
public final boolean majorComponent() {
return tableComponent.majorComponent();
}
/**
*
* @return
*/
public final String otherph() {
return tableComponent.otherph();
}
/**
*
* @param otherph
*/
public final void otherph(String otherph) {
tableComponent.otherph(otherph);
}
public final double profileDepth() {
return tableComponentCalculatoins.calculated_profile_depth();
}
public final void profileDepth(double value) {
tableComponentCalculatoins.calculated_profile_depth(value);
}
public final int psarp_number() {
return tableComponentCalculatoins.psarp_number();
}
public final void psarp_number(int psarp_number) {
tableComponentCalculatoins.psarp_number(psarp_number);
}
/**
*
* @return
*/
public final String pslp() {
return tableComponentCalculatoins.pslp();
}
/**
*
* @param pslp
*/
public final void pslp(String pslp) {
tableComponentCalculatoins.pslp(pslp);
}
/**
*
* @return
*/
public final int pslp_number() {
return tableComponentCalculatoins.pslp_number();
}
/**
*
* @param pslp_number
*/
public final void pslp_number(int pslp_number) {
tableComponentCalculatoins.pslp_number(pslp_number);
}
/**
*
* @return
*/
public final String pssrp() {
return tableComponentCalculatoins.pssrp();
}
/**
*
* @param pssrp
*/
public final void pssrp(String pssrp) {
tableComponentCalculatoins.pssrp(pssrp);
}
/**
*
* @return
*/
public final int pssrp_number() {
return tableComponentCalculatoins.pssrp_number();
}
/**
*
* @param pssrp_number
*/
public final void pssrp_number(int pssrp_number) {
tableComponentCalculatoins.pssrp_number(pssrp_number);
}
public void readCropYldFromSQL(ResultSet results) throws ServiceException {
String cropYldKey;
try {
cropYldKey = results.getString(TableCocropyld.COCROPYLDKEY);
} catch (SQLException ex) {
throw new ServiceException("Cannot find the cocropyldkey value in the returned database resultset in readCropYldFromSQL(): " + ex.getMessage(), ex);
}
if (null != cropYldKey) {
Cocropyld tCropYld = cropYlds.get(cropYldKey);
if (null == tCropYld) {
tCropYld = new Cocropyld(results);
cropYlds.put(cropYldKey, tCropYld);
} else {
throw new ServiceException("Duplicate cocropyldkey found in results returned from database querey in readCropYldFromSQL(). Results should have unidque cocropyldkey.");
}
}
}
public void readEcoClassFromSQL(ResultSet results) throws ServiceException {
String ecoClassKey;
try {
ecoClassKey = results.getString(TableCoecoclass.COECOCLASSKEY);
} catch (SQLException ex) {
throw new ServiceException("Cannot find the coecoclasskey value in the returned database resultset in readEcoClassFromSQL(): " + ex.getMessage(), ex);
}
if (null != ecoClassKey) {
Coecoclass tEcoClass = ecoClasses.get(ecoClassKey);
if (null == tEcoClass) {
tEcoClass = new Coecoclass(results);
ecoClasses.put(ecoClassKey, tEcoClass);
} else {
throw new ServiceException("Duplicate coecoclasskey found in results returned from database querey in readEcoClassFromSQL(). Results should have unidque coecoclasskeys.");
}
}
}
public void readFromSQL(ResultSet results) throws ServiceException {
tableComponent.readValuesFromSQL(results);
tableComponentCalculatoins.readValuesFromSQL(results);
}
public void setExclude(boolean value, String reason) {
tableExcluded.setExcluded(value, reason);
}
public final void rsprod_h(int value) {
tableComponent.rsprod_h(value);
}
public final int rsprod_h() {
return tableComponent.rsprod_h();
}
public final void rsprod_l(int value) {
tableComponent.rsprod_l(value);
}
public final int rsprod_l() {
return tableComponent.rsprod_l();
}
/**
*
* @return
*/
public final int rsprod_r() {
return tableComponent.rsprod_r();
}
/**
*
* @param rsprod_r
*/
public final void rsprod_r(int rsprod_r) {
tableComponent.rsprod_r(rsprod_r);
}
public final void slope_h(double value) {
tableComponent.slope_h(value);
}
public final double slope_h() {
return tableComponent.slope_h();
}
public final void slope_l(double value) {
tableComponent.slope_l(value);
}
public final double slope_l() {
return tableComponent.slope_l();
}
/**
*
* @return
*/
public final double slope_r() {
return tableComponent.slope_r();
}
/**
*
* @param slope_r
*/
public final void slope_r(double slope_r) {
tableComponent.slope_r(slope_r);
}
/**
*
* @param slopegr15
*/
public void slopegr15(boolean slopegr15) {
tableComponentCalculatoins.calculated_slopegr15(slopegr15);
}
/**
*
* @return
*/
public boolean slopegr15() {
return tableComponentCalculatoins.calculated_slopegr15();
}
public final void slopelenusle_h(double value) {
tableComponent.slopelenusle_h(value);
}
public final double slopelenusle_h() {
return tableComponent.slopelenusle_h();
}
public final void slopelenusle_l(double value) {
tableComponent.slopelenusle_l(value);
}
public final double slopelenusle_l() {
return tableComponent.slopelenusle_l();
}
public final void slopelenusle_r(double value) {
tableComponent.slopelenusle_r(value);
}
public final double slopelenusle_r() {
return tableComponent.slopelenusle_r();
}
/**
*
* @param outArray
* @throws JSONException
*/
public void tableColumnsToJSON(JSONArray outArray) throws JSONException {
tableComponent.toJSON(outArray);
tableComponentCalculatoins.toJSON(outArray);
}
/**
*
* @return
*/
public final String taxorder() {
return tableComponent.taxorder();
}
/**
*
* @param taxorder
*/
public final void taxorder(String taxorder) {
tableComponent.taxorder(taxorder);
}
public final void taxsubgrp(String value) {
tableComponent.taxsubgrp(value);
}
public final String taxsubgrp() {
return tableComponent.taxsubgrp();
}
/**
*
* @return
*/
public final String taxpartsize() {
return tableComponent.taxpartsize();
}
/**
*
* @param taxpartsize
*/
public final void taxpartsize(String taxpartsize) {
tableComponent.taxpartsize(taxpartsize);
}
/**
*
* @return
*/
public final double tfact() {
return tableComponent.tfact();
}
/**
*
* @param tfact
*/
public final void tfact(double tfact) {
tableComponent.tfact(tfact);
}
public void usesGenericIFCorSOLValues(boolean value) {
if (null != surfaceHorizon) {
surfaceHorizon.useGenericHz1Values(value);
surfaceHorizon.useGenericHz2Values(value);
}
if (null != horizons) {
for (Horizon horizon : horizons.values()) {
horizon.useGenericHz1Values(value);
horizon.useGenericHz2Values(value);
}
}
}
public boolean usesGenericIFCorSOLValues() {
if ((null != surfaceHorizon) && (surfaceHorizon.useGenericHz1Values() || surfaceHorizon.useGenericHz2Values())) {
return true;
}
if (null != horizons) {
for (Horizon horizon : horizons.values()) {
if (horizon.useGenericHz1Values() || horizon.useGenericHz2Values()) {
return true;
}
}
}
return false;
}
public String toIfc(double brockdepmin) throws WEPSException {
if (null == surfaceHorizon) {
throw new WEPSException("Cannot build IFC file data. Missing a designated surface horizon.");
}
//Remove the restricting horizon. WEPS doesn't want it in the IFC file.
if (null != restrictingHorizon) {
horizons.remove(restrictingHorizon.chkey());
}
// try {
// if (isOrganicSoil()) {
// return genericOrganicSoilIfc;
// }
// } catch (SDMException ex) {
// throw new WEPSException(ex);
// }
horizons.values().forEach((h) -> {
h.hzthk_r(metricConversion(h.hzthk_r(), SoilUtils.Metric.CM, SoilUtils.Metric.MM));
});
String ifcString = "";
ifcString += formatIFCValue(GenericIFCData.LOCAL_PHASE, ((EvalResult.testDefaultEmptyString(localphase()) || (localphase().isEmpty()) ? "unknown" : localphase()))); // local phase
ifcString += formatIFCValue(GenericIFCData.TAX_ORDER, taxorder()); // tax order
ifcString += formatIFCValue(GenericIFCData.SOIL_LOSS_TOLERANCE, ((!surfaceHorizon.useGenericHz1Values()) ? (int) tfact() : GenericIFCData.soilLossTolerance));
try {
ifcString += formatIFCValue(GenericIFCData.DRY_SOIL_ALBEDO, ((!surfaceHorizon.useGenericHz1Values()) ? getWEPPSurfaceAlbedo() : GenericIFCData.drySoilAlbedo), 3);
} catch (WEPPException ex) {
throw new WEPSException(ex);
}
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.SLOPE_GRADIENT, ((!surfaceHorizon.useGenericHz1Values()) ? slope_r() : GenericIFCData.slopeGradient), 3, false, 1.0);
//ifcString += writeValue(IFCRanges.surfaceList[14].getTitle(), Defaults to "0" in WEPS //SoilCalc.getSurfaceFragmentCover(), 3);
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.SURFACE_FRAGMENT_COVER, ((!surfaceHorizon.useGenericHz1Values()) ? surfaceHorizon.fragvol_r() : GenericIFCData.surfFragCover), 3, false); // WAS: 0.0, 3 );
ifcString += soils.utils.SoilUtils.println("#");
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.DEPTH_TO_BEDROCK, ((!surfaceHorizon.useGenericHz1Values()) ? ((EvalResult.testDefaultDouble(brockdepmin)) ? GenericIFCData.depthToBedrock : brockdepmin) : GenericIFCData.depthToBedrock), 0, false);
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.DEPTH_TO_ROOT_RESTRICTING, ((!surfaceHorizon.useGenericHz1Values()) ? ((EvalResult.testDefaultDouble(calculated_resdeptmin_r())) ? GenericIFCData.depthToRootRestrictingLayer : calculated_resdeptmin_r()) : GenericIFCData.depthToRootRestrictingLayer), 0, false);
ifcString += soils.utils.SoilUtils.println("#");
ifcString += formatIFCValue(GenericIFCData.NUM_LAYERS, horizons.size()); // number of layers
ifcString += formatIFCArray(GenericIFCData.LAYER_THICKNESS, this, 0, (Horizon h) -> h.hzthk_r()); // soil characteristics by layer
ifcString += soils.utils.SoilUtils.println("#");
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.SAND_FRACTION, GenericIFCData.sandFraction, true, restrictingHorizon, 3, horizons, (Horizon h) -> h.sandtotal_r()); // soil fractions
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.SILT_FRACTION, GenericIFCData.siltFraction, false, restrictingHorizon, 3, horizons, (Horizon h) -> h.silttotal_r());
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.CLAY_FRACTION, GenericIFCData.clayFraction, true, restrictingHorizon, 3, horizons, (Horizon h) -> h.claytotal_r());
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.ROCK_FRAGMENTS, GenericIFCData.rockFragments, false, restrictingHorizon, 3, horizons, (Horizon h) -> getRockFrags(h));
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.SAND_FRACTION_VC, GenericIFCData.sandFractionVC, false, restrictingHorizon, 3, horizons, (Horizon h) -> h.sandvc_r());
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.SAND_FRACTION_C, GenericIFCData.sandFractionC, false, restrictingHorizon, 3, horizons, (Horizon h) -> h.sandco_r());
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.SAND_FRACTION_M, GenericIFCData.sandFractionM, false, restrictingHorizon, 3, horizons, (Horizon h) -> h.sandmed_r());
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.SAND_FRACTION_F, GenericIFCData.sandFractionF, false, restrictingHorizon, 3, horizons, (Horizon h) -> h.sandfine_r());
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.SAND_FRACTION_VF, GenericIFCData.sandFractionVF, true, restrictingHorizon, 3, horizons, (Horizon h) -> h.sandvf_r());
ifcString += soils.utils.SoilUtils.println("#");
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.BUILK_DENSITY, GenericIFCData.bulkDensity, true, restrictingHorizon, 3, horizons, (Horizon h) -> h.dbthirdbar_r());
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.ORGANIC_MATTER, GenericIFCData.organicMatter, true, restrictingHorizon, 4, horizons, (Horizon h) -> h.om_r()); // soil chemical properties
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.SOIL_PH, GenericIFCData.soilPh, true, restrictingHorizon, 2, horizons, (Horizon h) -> getSoilpH(h));
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.CACO3, GenericIFCData.CaCO3, true, restrictingHorizon, 2, horizons, (Horizon h) -> h.caco3_r());
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.CATION_EXCHANGE_CAPACITY, GenericIFCData.CEC, true, restrictingHorizon, 2, horizons, (Horizon h) -> getCationExchangeCapacity(h));
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.LINEAR_EXTENSIBILITY, GenericIFCData.linearExtensibility, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getLinearExtensibility(h));
ifcString += soils.utils.SoilUtils.println("#");
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.AGG_GMD, GenericIFCData.aggGMD, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getAggregateMeanDiameter(h)); // aggregate characteristics
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.AGG_GSD, GenericIFCData.aggGSD, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getAggregateStdDeviation(h));
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.MAX_AGG_SIZE, GenericIFCData.maxAggSize, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getMaxAggregateSize(h));
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.MIN_AGG_SIZE, GenericIFCData.minAggSize, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getMinAggregateSize());
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.AGG_DENSITY, GenericIFCData.aggDensity, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getAggregateDensity(h));
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.AGG_STABILITY, GenericIFCData.aggStability, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getAggregateStability(h));
ifcString += soils.utils.SoilUtils.println("#");
ifcString += GenericIFCData.formatIFCValue(IFCRanges.surfaceList[1].getTitle(), GenericIFCData.crustThk, 3, false); //SoilUtils.getCrustThickness(), 3); // crust and surface characteristics
// TODO: Check this crustDensity stuff....SoilUtils just always returns 1.8 regardless of soil properties while the default value is always 0.6...
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.CRUST_DENSITY, ((!surfaceHorizon.useGenericHz1Values()) ? SoilUtils.getCrustDensity(surfaceHorizon) : GenericIFCData.crustDensity), 3, false);
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.CRUST_STABILITY, ((!surfaceHorizon.useGenericHz1Values()) ? SoilUtils.getCrustStability(surfaceHorizon) : GenericIFCData.crustStability), 2, false);
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.CRUST_SURFACE_FRACTION, ((!surfaceHorizon.useGenericHz1Values()) ? SoilUtils.getCrustFraction() : GenericIFCData.crustSurfaceFraction), 2, false);
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.MASS_LOOSE_MAT_CRUST, ((!surfaceHorizon.useGenericHz1Values()) ? SoilUtils.getCrustLooseMaterialMass() : GenericIFCData.massLooseMatCrust), 2, false);
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.FRACTION_LOOSE_MAT_CRUST, ((!surfaceHorizon.useGenericHz1Values()) ? SoilUtils.getCrustLooseMaterialFraction() : GenericIFCData.fractionLooseMatCrust), 2, false);
ifcString += soils.utils.SoilUtils.println("#");
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.RANDOM_ROUGHNESS, ((!surfaceHorizon.useGenericHz1Values()) ? SoilUtils.getRandomRoughness() : GenericIFCData.randomRoughness), 2, false);
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.RIDGE_ORIENTATION, ((!surfaceHorizon.useGenericHz1Values()) ? SoilUtils.getRoughnessOrientation() : GenericIFCData.ridgeOrientation), 2, false);
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.RIDGE_HEIGHT, ((!surfaceHorizon.useGenericHz1Values()) ? SoilUtils.getRoughnessHeight() : GenericIFCData.ridgeHeight), 2, false);
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.RIDGE_TOP_SPACING, ((!surfaceHorizon.useGenericHz1Values()) ? SoilUtils.getRoughnessSpacing() : GenericIFCData.ridgeTopSpacing), 2, false);
ifcString += GenericIFCData.formatIFCValue(GenericIFCData.RIDGE_WIDTH, ((!surfaceHorizon.useGenericHz1Values()) ? SoilUtils.getRoughnessWidth() : GenericIFCData.ridgeWidth), 2, false);
ifcString += soils.utils.SoilUtils.println("#");
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.INIT_BULK_DENSITY, GenericIFCData.initBulkDensity, false, restrictingHorizon, 3, horizons, (Horizon h) -> h.dbthirdbar_r()); // hydrology by layers
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.INIT_SOIL_WATER_CONTENT, GenericIFCData.initSoilWaterContent, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getInitialSWC(h)); // hydrology by layers
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.SAT_SOIL_WATER_CONTENT, GenericIFCData.satSoilWaterContent, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getSaturatedSWC(h));
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.FIELD_CAPACITY_WATER_CONTENT, GenericIFCData.fieldCapWaterContent, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getFieldCapacitySWC(h));
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.WILTING_POINT_WATER_CONTENT, GenericIFCData.wiltingPointWaterContent, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getWiltingPointSWC(h));
ifcString += soils.utils.SoilUtils.println("#");
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.SOIL_CB_VALUE, GenericIFCData.soilCBValue, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getSoilCB(h));
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.AIR_ENTRY_POTENTIAL, GenericIFCData.airEntryPotential, false, restrictingHorizon, 3, horizons, (Horizon h) -> SoilUtils.getAirEntryPotential(h));
ifcString += GenericIFCData.formatIFCArray(GenericIFCData.SAT_HYDRAULIC_CONDUCTIVITY, GenericIFCData.satHydraulicConductivity, false, restrictingHorizon, 10, horizons, (Horizon h) -> SoilUtils.getSaturatedHydraulicConductivity(h));
ifcString += soils.utils.SoilUtils.println("#");
return ifcString;
}
// Sol file description
// Line 1: version control number (95.7) - real (datver)
// Line 2: a) User comment line - character*80, (solcom)
// Line 3: a) number of overland flow elements(OFE's) or channels integer (ntemp)
// b) flag to to use internal hydraulic conductivity adjustments - integer (ksflag)
// 0 - do not use adjustments (conductivity will be held constant)
// 1 - use internal adjustments
// Lines 4 & 5 are repeated for the number of OFE's or channels on Line 3a.
// Line 4: a) soil name for current OFE or channel - character (slid)
// b) soil texture for current OFE or channel - character (texid)
// c) number of soil layers for current OFE or channel - integer (nsl)
// d) albedo of the bare dry surface soil on the current OFE or channel - real (salb)
// e) initial saturation level of the soil profile porosity (m/m) - real (sat)
// f) baseline interrill erodibility parameter (kg*s/m4) - real (ki)
// g) baseline rill erodibility parameter (s/m) - real (kr)
// h) baseline critical shear parameter (N/m2) - real (shcrit)
// i) effective hydraulic conductivity of surface soil (mm/h) - real (avke)
// Line 5: (repeated for the number of soil layers indicated on Line 4c.)
// a) depth from soil surface to bottom of soil layer (mm) - real (solthk)
// b) percentage of sand in the layer (%) - real (sand)
// c) percentage of clay in the layer (%) - real (clay)
// d) percentage of organic matter (volume) in the layer (%) - real (orgmat)
// e) cation exchange capacity in the layer (meq/100 g of soil) - real (cec)
// f) percentage of rock fragments by volume in the layer (%) - real (rfg)
// Line 6: Bedrock restricting layer info (Most of the soils are not going to have any bedrock layer defined so this line ends up being all 0's)
// a) flag to indicate if present
// b) type
// c) anisotropy ratio
// d) ksat
// May want to break this into methods if it grows
public String toSol() throws WEPPException {
if (null == surfaceHorizon) {
throw new WEPPException("Cannot build sol file data. Missing a designated surface horizon.");
}
// try {
// if (isDefaultOrganicSolFileComponent()) {
// return genericOrganicSoilSol;
// }
// } catch (SDMException ex) {
// throw new WEPPException(ex);
// }
String solStr = "";
// Line 1:
solStr = "2006.2\n";
//Line 2:
solStr += "Comments: sol file generated by csip-soils.\n";
//Line 3:
// only one soil is used
// always use hydraulic conductivity adjustments
solStr += "1 1\n";
//Line 4:
// append some soil info here
boolean useGenericHz1Values = surfaceHorizon.useGenericHz1Values();
boolean useGenericHz2Values;
solStr += "'" + compname() + "' ";
try {
solStr += "'" + surfaceHorizon.getRepresentativeTextureName() + "' ";
} catch (SDMException ex) {
throw new WEPPException(ex);
}
solStr += ((null == restrictingHorizon) ? horizons.size() : horizons.size() - 1) + " ";
solStr += String.format("%.6f", ((useGenericHz1Values) ? 0.230000 : getWEPPSurfaceAlbedo())) + " ";
solStr += "0.750000 ";
solStr += String.format("%.6f", ((useGenericHz1Values) ? 3112200 : surfaceHorizon.getInterrill())) + " ";
solStr += String.format("%.6f", ((useGenericHz1Values) ? 0.00257 : surfaceHorizon.getRill())) + " ";
solStr += String.format("%.6f", ((useGenericHz1Values) ? 3.204 : surfaceHorizon.getShear())) + " ";
solStr += String.format("%.6f", ((useGenericHz1Values) ? 10.28756 : surfaceHorizon.getConductivity())) + "\n";
//Line 5:
for (Horizon horizon : horizons.values()) {
if (horizon.isRestricting()) {
break;
}
useGenericHz1Values = horizon.useGenericHz1Values();
useGenericHz2Values = horizon.useGenericHz2Values();
solStr += " " + String.format("%.6f", horizon.hzdepb_r() * 10) + " "; // convert from cm to mm
solStr += String.format("%.6f", ((useGenericHz1Values) ? 50.0 : ((useGenericHz2Values) ? 13.0 : horizon.sandtotal_r()))) + " ";
solStr += String.format("%.6f", ((useGenericHz1Values) ? 10.0 : ((useGenericHz2Values) ? 5.0 : horizon.claytotal_r()))) + " ";
solStr += String.format("%.6f", ((useGenericHz1Values) ? 77.000 : ((useGenericHz2Values) ? 81.0 : horizon.om_r()))) + " ";
solStr += String.format("%.6f", ((useGenericHz1Values) ? 40.0 : ((useGenericHz2Values) ? 45.0 : horizon.cec7_r()))) + " ";
solStr += String.format("%.6f", ((useGenericHz1Values) ? 0.0 : ((useGenericHz2Values) ? 0.0 : horizon.getWEPPRockFragments()) * 100)); // put rock frag here. should be in percent
solStr += "\n";
}
//Line 6:
// add some bedrock data
solStr += restrict + " ";
solStr += restrictType + " ";
solStr += String.format("%.6f", aniso) + " ";
solStr += String.format("%.6f", uksat);
solStr += "\n";
return solStr;
}
/**
*
* @param onlySelectedHorizons
* @return
* @throws JSONException
*/
public JSONArray toJSON(boolean onlySelectedHorizons) throws JSONException {
return toJSON(onlySelectedHorizons, null);
}
/**
*
* @param onlySelectedHorizons
* @param selectedReasons
* @return
* @throws JSONException
*/
public JSONArray toJSON(boolean onlySelectedHorizons, ArrayList<String> selectedReasons) throws JSONException {
JSONArray ret_val = new JSONArray();
JSONArray horizonsArray;
tableExcluded.toJSON(ret_val);
tableComponent.toJSON(ret_val);
tableComponentCalculatoins.long_name(comp_long_name());
//Calculated or interpolated values
tableComponentCalculatoins.toJSON(ret_val);
if (!isExcluded()) {
if ((null != selectedReasons) && !selectedReasons.isEmpty()) {
for (String type : selectedReasons) {
horizonsArray = groupBySelectionType(type, onlySelectedHorizons);
if (horizonsArray.length() > 0) {
ret_val.put(JSONUtils.data(type.toLowerCase() + " horizons", horizonsArray));
}
}
} else {
horizonsArray = groupBySelectionType("ANY", onlySelectedHorizons);
if (horizonsArray.length() > 0) {
ret_val.put(JSONUtils.data("horizons", horizonsArray));
}
}
}
return ret_val;
}
/**
*
* @param onlySelectedHorizons
* @param selectedReasons
* @return
* @throws JSONException
*/
public JSONObject toBasicJSON(boolean onlySelectedHorizons, List<String> selectedReasons) throws JSONException {
JSONObject ret_val = new JSONObject();
JSONArray horizonsArray;
tableExcluded.toBasicJSON(ret_val);
tableComponent.toBasicJSON(ret_val);
tableComponentCalculatoins.long_name(comp_long_name());
//Calculated or interpolated values
tableComponentCalculatoins.toBasicJSON(ret_val);
if (!isExcluded()) {
if ((null != selectedReasons) && !selectedReasons.isEmpty()) {
for (String type : selectedReasons) {
horizonsArray = groupBySelectionTypeBasicJSON(type, onlySelectedHorizons);
if (horizonsArray.length() > 0) {
ret_val.put(type.toLowerCase() + " horizons", horizonsArray);
}
}
} else {
horizonsArray = groupBySelectionTypeBasicJSON("ANY", onlySelectedHorizons);
if (horizonsArray.length() > 0) {
ret_val.put("horizons", horizonsArray);
}
}
}
return ret_val;
}
public Horizon topHorizon() {
Horizon tHorizon = null;
if (null != horizons) {
for (Horizon horizon : horizons.values()) {
if (null != tHorizon) {
if (horizon.hzdept_r() < tHorizon.hzdept_r()) {
tHorizon = horizon;
}
} else {
tHorizon = horizon;
}
}
}
return tHorizon;
}
public Horizon topSelectedHorizon() {
Horizon tHorizon = null;
if (null != horizons) {
for (Horizon horizon : horizons.values()) {
if (null != tHorizon) {
if ((horizon.hzdept_r() < tHorizon.hzdept_r()) && (horizon.selected())) {
tHorizon = horizon;
}
} else {
if (horizon.selected()) {
tHorizon = horizon;
}
}
}
}
return tHorizon;
}
/**
* Finds highest/maximum Flooding rating in the monthly rating values and uses
* that as the general rating for this component. If no ratings are found
* "None" is assumed as the rating value. Also, if any monthly value is
* missing or NULL, then "None" is assume for that month's value during
* comparisons.
*
* @return
* @throws ServiceException
*/
public void maxFloodFreq() throws ServiceException {
int tComonthRate = floodRatings.get("none");
if (null != comonths) {
for (Comonth comonth : comonths.values()) {
if (null != comonth) {
if (floodRatings.containsKey(comonth.flodfreqcl().toLowerCase())) {
int newRating = floodRatings.get(comonth.flodfreqcl().toLowerCase());
if (tComonthRate < newRating) {
tComonthRate = newRating;
}
}
}
}
}
if ((tComonthRate >= 0) && (tComonthRate < floodRatingNames.size())) { //this should always be true, but just in case...
tableComponentCalculatoins.calculated_flod_freq_cl(floodRatingNames.get(tComonthRate));
} else {
tableComponentCalculatoins.calculated_flod_freq_cl("None");
}
}
/**
* Finds highest/maximum Ponding rating in the monthly rating values and uses
* that as the general rating for this component. If no ratings are found
* "None" is assumed as the rating value. Also, if any monthly value is
* missing or NULL, then "None" is assume for that month's value during
* comparisons.
*
* @return
* @throws ServiceException
*/
public void maxPoolFreq() throws ServiceException {
int tComonthRate = pondRatings.get("none");
if (null != comonths) {
for (Comonth comonth : comonths.values()) {
if (null != comonth) {
if (pondRatings.containsKey(comonth.pondfreqcl().toLowerCase())) {
int newRating = pondRatings.get(comonth.pondfreqcl().toLowerCase());
if (tComonthRate < newRating) {
tComonthRate = newRating;
}
}
}
}
}
if ((tComonthRate >= 0) && (tComonthRate < pondRatingNames.size())) { //this should always be true, but just in case...
tableComponentCalculatoins.calculated_pond_freq_cl(pondRatingNames.get(tComonthRate));
} else {
tableComponentCalculatoins.calculated_pond_freq_cl("None");
}
}
/**
*
* @return
*/
public final double wei() {
return tableComponent.wei();
}
/**
*
* @param wei
*/
public final void wei(double wei) {
tableComponent.wei(wei);
}
}