SOILS_DATA.java [src/soils/db] 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.db;
import csip.api.server.ServiceException;
import gisobjects.GISObject;
import gisobjects.GISObjectException;
import gisobjects.db.GISEngine;
import static java.lang.Double.NaN;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import soils.Component;
import soils.Fragments;
import soils.Horizon;
import soils.MapUnit;
import soils.db.tables.TableComponent;
import soils.db.tables.TableFragments;
import soils.db.tables.TableHorizon;
import soils.db.tables.TableHorizonCalculations;
import soils.db.tables.TableMapUnit;
import soils.exceptions.SDMException;
import soils.exceptions.WEPPException;
import soils.exceptions.WEPSException;
import soils.utils.EvalResult;
import soils.utils.SoilUtils;
/**
*
* @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
*/
public interface SOILS_DATA extends AutoCloseable {
/* This value, DEFAULT_GEOG_SRID, should be used for converting intersection
* polygon results, and area calculations from an SQL statement to the appropriate
* Coordinate Reference System (CRS) default for all csip services,
* which is WGS-84 -> SRID: 4326
*/
public static final String DEFAULT_GEOG_SRID = "4326";
static String BAD_KFFACT_LAYERS = "No kffact could be located or generated for this component.";
static String BAD_SAND_LAYERS = "No suitable sand layer could be found or generated for this component.";
// The functions below fill in database records without any kind of filtering.
public HashMap<String, MapUnit> findAllByShape(GISObject shape, boolean returnIntersectionShape) throws SDMException, GISObjectException;
public boolean findCoCropYieldsByCropNameOrUnit(HashMap<String, MapUnit> mapUnits, ArrayList<String> cropNames, ArrayList<String> yldUnits) throws ServiceException;
public boolean findMuCropYieldsByCropNameOrUnit(HashMap<String, MapUnit> mapUnits, ArrayList<String> cropNames, ArrayList<String> yldUnits) throws ServiceException;
public ArrayList<String> findAreaSymbolsByCounty(String countyWKT) throws ServiceException;
public ArrayList<String> findAreaSymbolsByState(String stateAbbrev) throws ServiceException;
public boolean findAllComonthData(LinkedHashMap<String, MapUnit> map_units) throws ServiceException;
public boolean findAllTextureData(HashMap<String, MapUnit> mapUnits) throws ServiceException;
public boolean findCoCropYldForMukeyList(HashMap<String, MapUnit> mapUnits) throws ServiceException;
/*
public HashMap<String, MapUnit> findAllMapUnitComponentHorizonFragmentRecordsByShape(GISObject shape);
public boolean findAllMapUnitComponentHorizonFragmentRecordsByMukey(MapUnit mapUnit);
public MapUnit findAllMapUnitComponentHorizonFragmentRecordsByCokey(Component component);
*/
// The functions below apply filtering logic to finding records in the database.
public boolean findComponentSoilMoisture(HashMap<String, MapUnit> mapUnits) throws ServiceException;
public boolean findComponentsForMapUnit(MapUnit mapUnit) throws ServiceException;
public MapUnit findComponentsForMukey(String mukey) throws ServiceException;
public boolean findComponentsForMukeyList(HashMap<String, MapUnit> mapUnits, boolean computeLightleWeesieSlope) throws ServiceException;
public Boolean findComponentsByMukey(MapUnit mapUnit) throws ServiceException;
public Boolean findComponentsHorizonsFragsByMukey(MapUnit mapUnit, boolean computeLightleWeesieSlope, String filter) throws ServiceException;
public boolean findAllBasicNoFilterComponentHorizonFragTextureData(HashMap<String, MapUnit> mapUnits) throws ServiceException;
public boolean findAllBasicComponentHorizonFragTextureData(HashMap<String, MapUnit> mapUnits) throws ServiceException;
public boolean findAllBasicComponentHorizonFragTextureData(HashMap<String, MapUnit> mapUnits, boolean includeNonMajComp) throws ServiceException;
//Orders results by mukey, cokey, horizon depth, and kffact. Returned results meet the following criteria:
//Hydrologic group, hydgrp, must not be null/empty, and Component Percentage of the Map Unit, comppct_r, must not be null/empty
public boolean findComponentsHorizonsFragsForMukeyList(HashMap<String, MapUnit> mapUnits, boolean computeLightleWeesieSlope, String filter) throws ServiceException;
public ArrayList<ComponentsHorizonsFrags> findComponentsHorizonsFragsForMukeyList(ArrayList<String> mukeys, boolean computeLightleWeesieSlope, String filter) throws ServiceException;
public boolean findEcoClassForMukeyList(HashMap<String, MapUnit> mapUnits) throws ServiceException;
public boolean findEcoClassForMukeyList(HashMap<String, MapUnit> mapUnits, String addWhere) throws ServiceException;
public boolean findHorizonsForCokey(MapUnit mapUnit, Component component) throws ServiceException;
public HashMap<String, MapUnit> findMapUnitsForGISObject(GISObject gisObject, boolean computeIntersectionArea, boolean returnIntersectionShape) throws ServiceException, GISObjectException;
public HashMap<String, MapUnit> findMapUnitsForGISObject(GISObject gisObject) throws ServiceException, GISObjectException;
public HashMap<String, MapUnit> findMapUnitsForWKT(String wkt, boolean computeIntersectinArea, boolean returnIntersectionShape) throws ServiceException;
public HashMap<String, MapUnit> findMapUnitsForWKT(String wkt) throws ServiceException;
public boolean findMuCropYldForMukeyList(HashMap<String, MapUnit> mapUnits) throws ServiceException;
public MapUnit findMukeyData(String mukey) throws ServiceException;
public boolean findMukeyData(MapUnit mapUnit) throws ServiceException;
public MapUnit findBasicNoFilterMukeyDataByCokey(Component component) throws ServiceException;
public MapUnit findMukeyDataByCokey(Component component) throws ServiceException;
public MapUnit findMapUnitsByMupolygonKey(String mupolygonkey, GISEngine gisEngine, boolean computeIntersectionArea, boolean returnIntersectionShape) throws ServiceException, GISObjectException;
public HashMap<String, MapUnit> findMukeyDataByAreasymbol(String areaSymbol) throws ServiceException;
public void findMukeyDataAndShapeByAreasymbol(ArrayList<String> areaSymbols, GISEngine gisEngine, HashMap<String, MapUnit> mapUnits) throws ServiceException;
@Deprecated
public boolean findWEPSHorizonsForCokey(MapUnit mapUnit, Component component) throws ServiceException;
public MapUnit findBasicNoFilterDataByCokey(Component component) throws ServiceException;
public MapUnit findWEPPDataByCokey(Component component) throws ServiceException, WEPPException;
public MapUnit findWEPSDataByCokey(Component component, boolean adjustStratified, boolean organicChecks, boolean estimateNulls) throws ServiceException, WEPSException;
///////////////////////////////////////////////////////////////////////////
// Interface member functions
///////////////////////////////
public Connection getConnection();
default public String getMapUnitFieldList() {
TableMapUnit mapUnit = new TableMapUnit();
String tableName = TableMapUnit.TABLE_NAME;
String ret_val = "";
int i = 0;
synchronized (this) {
for (String key : mapUnit.getColumnList()) {
if (i > 0) {
ret_val += ", " + tableName + "." + key;
} else {
ret_val += tableName + "." + key;
}
i++;
}
}
return ret_val;
}
default public String getComponentFieldList() {
TableComponent component = new TableComponent();
String tableName = TableComponent.TABLE_NAME;
String ret_val = "";
int i = 0;
synchronized (this) {
Component.setDefaultUsedColumns(component.getColumnList());
for (String key : component.getColumnList()) {
if (i > 0) {
ret_val += ", " + tableName + "." + key;
} else {
ret_val += tableName + "." + key;
}
i++;
}
}
return ret_val;
}
default public String getHorizonFieldList() {
TableHorizon horizon = new TableHorizon();
String tableName = TableHorizon.TABLE_NAME;
String ret_val = "";
ret_val = horizon.getFullColumnNames(false);
// int i = 0;
// Horizon.setDefaultUsedColumns(horizon.getColumnList());
// for (String key : horizon.getColumnList()) {
// if (i > 0) {
// ret_val += ", " + tableName + "." + key;
// } else {
// ret_val += tableName + "." + key;
// }
// i++;
// }
return ret_val;
}
default public String getFragFieldList() {
TableFragments frag = new TableFragments();
String tableName = TableFragments.TABLE_NAME;
String ret_val = "";
int i = 0;
Fragments.setDefaultUsedColumns(frag.getColumnList());
for (String key : frag.getColumnList()) {
if (i > 0) {
ret_val += ", " + tableName + "." + key;
} else {
ret_val += tableName + "." + key;
}
i++;
}
return ret_val;
}
public boolean isCONUS(double lat, double lon) throws SQLException, ServiceException;
/**
* This default member function is vital for continuity among soils service
* calls. It implements the default behavior desired by NRCS and SME's in the
* soils sciences regarding how to select proper horizon dbResults for wind
* and water erosion models.
*
* Side Effects: This function will set values in the component objects passed
* in with the MapUnit object, or will create new ones if not found in the
* MapUnit object. All Components and Horizons will be altered according to
* the data retrieved from the database in the ResultSet passed in the
* dbResults parameter and according to the logic specified herein.
*
*
* Please note: This function is not written to combine wind and water logic
* all in one-fell-swoop. Thus, it could be made to be a tad more efficient,
* if it is written to be able to do both when the filter param is set to, for
* instance, "both". This could be accomplished by resetting the input
* ResultSet back to its top member and reiterating through again for the next
* filter value, not previously used. This would prevent a calling function
* from forcing a requery of the exact same information. (Might trim off a few
* hundred milliseconds...)
*
* @param dbResults
* @param filterResults
* @param mapUnit
* @param filter
* @param computeLightleWeesieSlope
* @return Returns a boolean signifying success or failure of finding a valid
* component, horizon, frag record meeting the logic requirements for the
* filter specified. Additionally, the input parameter, filterResults,
* contains result data pertaining to the success or failure of finding a
* valid kffact and sandlayer value depending on the filter specified.
* @throws SQLException
* @throws ServiceException
*/
@Deprecated
default boolean filterComponentHorizonFragData(ResultSet dbResults, FilterResults filterResults, MapUnit mapUnit, String filter, boolean computeLightleWeesieSlope) throws SQLException, ServiceException {
boolean ret_val = false;
String lastCokey = "";
double lambda = 0.0;
LinkedHashMap<String, Component> components = mapUnit.components();
filterResults.foundKffact = false;
filterResults.foundSandLayer = false;
while (dbResults.next()) {
Component tComponent;
String cokey = dbResults.getString(TableComponent.COKEY);
if (components.containsKey(cokey)) {
tComponent = components.get(cokey);
} else {
tComponent = new Component();
tComponent.cokey(cokey);
components.put(cokey, tComponent);
}
String chkey = dbResults.getString(TableHorizon.CHKEY_NAME);
Horizon tHorizon;
if (tComponent.horizons.containsKey(chkey)) {
tHorizon = tComponent.horizons.get(chkey);
} else {
tHorizon = new Horizon();
tHorizon.chkey(chkey);
}
tComponent.setUsedColumns(new ArrayList<>(Arrays.asList(TableComponent.COMPPCT_R_NAME, TableComponent.HYDGRP_NAME, TableComponent.SLOPE_R_NAME,
TableComponent.TAXORDER_NAME, TableComponent.MUKEY, TableComponent.COKEY, TableComponent.COMPNAME,
TableComponent.WEI_NAME, TableComponent.SLOPELENUSLE_R, TableComponent.TFACT_NAME, TableComponent.HYDRICRATING)));
tHorizon.setUsedColumns(new ArrayList<>(Arrays.asList(TableHorizon.COKEY, TableHorizon.CHKEY_NAME, TableHorizon.OM_R_NAME,
TableHorizon.HZTHK_R_NAME, TableHorizon.HZDEPT_R_NAME, TableHorizon.HZDEPB_R_NAME, TableHorizon.KWFACT_NAME,
TableHorizon.KFFACT_NAME, TableHorizon.SANDTOTAL_R_NAME, TableHorizon.SILTTOTAL_R, TableHorizon.CLAYTOTAL_R,
TableHorizon.PH1TO1H2O_L, TableHorizon.PH1TO1H2O_R, TableHorizon.PH1TO1H2O_H, TableHorizon.SAR_R, TableHorizon.EC_R,
TableHorizonCalculations.FRAGVOL_R_NAME)));
tComponent.readFromSQL(dbResults);
tHorizon.readFromSQL(dbResults);
double slope_r = tComponent.slope_r();
tComponent.slope_r(slope_r);
tComponent.slopegr15((slope_r > 15));
if (mapUnit.aoaArea() > 0.0) {
tComponent.area_pct((tComponent.comppct_r() / 100.0) * (mapUnit.area() / mapUnit.aoaArea()) * 100.0);
} else {
tComponent.area_pct(EvalResult.getDefaultDouble());
}
if (mapUnit.area() > 0.0) {
tComponent.calculated_area(tComponent.comppct_r() / 100.0 * mapUnit.area());
} else {
tComponent.calculated_area(EvalResult.getDefaultDouble());
}
if (filter.equalsIgnoreCase("WATER")) { // Water Erodibility needed.
String taxorder = tComponent.taxorder();
if (!lastCokey.equalsIgnoreCase(tComponent.cokey())) {
if (!filterResults.foundKffact) {
if (!lastCokey.isEmpty()) {
if (components.containsKey(lastCokey)) {
components.get(lastCokey).setExclude(true, BAD_KFFACT_LAYERS);
}
}
}
lastCokey = tComponent.cokey();
filterResults.foundKffact = false;
}
if (!filterResults.foundKffact) {
if (!computeLightleWeesieSlope) {
lambda = tComponent.slopelenusle_r();
} else {
lambda = SoilUtils.calcLightleWeesieSlopeSlopeLength(slope_r, mapUnit.isPalouse());
}
tHorizon.lsfact(SoilUtils.calcLsFactor(slope_r, lambda));
tComponent.length_r(lambda);
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");
tComponent.calculated_kffact(tHorizon.kffact());
tComponent.calculated_lsfact(tHorizon.lsfact());
tComponent.calculated_claytotal_r(tHorizon.claytotal_r());
ret_val = true;
}
} else {
filterResults.foundKffact = true;
tHorizon.selected(true);
tHorizon.selectedReason("WATER");
tComponent.calculated_kffact(tHorizon.kffact());
tComponent.calculated_lsfact(tHorizon.lsfact());
tComponent.calculated_claytotal_r(tHorizon.claytotal_r());
ret_val = true;
}
} else {
filterResults.foundKffact = true;
tHorizon.selected(true);
tHorizon.selectedReason("WATER");
tComponent.calculated_kffact(tHorizon.kffact());
tComponent.calculated_lsfact(tHorizon.lsfact());
tComponent.calculated_claytotal_r(tHorizon.claytotal_r());
ret_val = true;
}
}
tComponent.horizons.put(chkey, tHorizon);
} else if (filter.equalsIgnoreCase("WIND")) { //Wind Erodability needed
if (!lastCokey.equalsIgnoreCase(tComponent.cokey())) {
if (!filterResults.foundSandLayer) {
if (!lastCokey.isEmpty()) {
if (components.containsKey(lastCokey)) {
components.get(lastCokey).setExclude(true, BAD_SAND_LAYERS);
}
}
}
lastCokey = tComponent.cokey();
filterResults.foundSandLayer = false;
}
if (!filterResults.foundSandLayer) {
if (tComponent.taxorder().equalsIgnoreCase("histosols") || (!tComponent.taxorder().equalsIgnoreCase("histosols") && (tHorizon.hzdepb_r() > 10) && (tHorizon.om_r() > 15))) {
tHorizon.sandtotal_r(50);
}
if (tHorizon.sandtotal_r() >= 0.0) {
tComponent.calculated_sandtotal_r(tHorizon.sandtotal_r());
tHorizon.selected(true);
tHorizon.selectedReason("WIND");
tComponent.calculated_om_r(tHorizon.om_r());
tComponent.calculated_hzdepb_r(tHorizon.hzdepb_r());
tComponent.calculated_claytotal_r(tHorizon.claytotal_r());
filterResults.foundSandLayer = true;
ret_val = true;
}
}
tComponent.horizons.put(chkey, tHorizon);
} else {
throw new ServiceException("Invalid filter specified to component lookup. Not implemented.");
}
}
return ret_val;
}
default boolean filterRusle2ComponentHorizonData(ResultSet dbResults, FilterResults filterResults, MapUnit mapUnit, Component tComponent) throws SQLException, ServiceException {
boolean ret_val = false;
String lastCokey = tComponent.cokey();
double lambda = 0.0;
filterResults.foundKffact = false;
filterResults.foundSandLayer = false;
while (dbResults.next()) {
String cokey = dbResults.getString(TableComponent.COKEY);
if (tComponent.cokey().equals(cokey)) {
String chkey = dbResults.getString(TableHorizon.CHKEY_NAME);
Horizon tHorizon;
if (tComponent.horizons.containsKey(chkey)) {
tHorizon = tComponent.horizons.get(chkey);
} else {
tHorizon = new Horizon();
tHorizon.chkey(chkey);
}
mapUnit.setUsedColumns(new ArrayList<>(Arrays.asList(TableMapUnit.MUKEY, TableMapUnit.MUNAME, TableMapUnit.MUSYM, TableMapUnit.AREA_NAME)));
tComponent.setUsedColumns(new ArrayList<>(Arrays.asList(TableComponent.TAXORDER_NAME, TableComponent.TAXSUBGRP, TableComponent.TFACT_NAME,
TableComponent.COMPNAME, TableComponent.COKEY, TableComponent.SLOPE_R_NAME, TableComponent.SLOPE_L, TableComponent.SLOPE_H,
TableComponent.SLOPELENUSLE_R, TableComponent.SLOPELENUSLE_L, TableComponent.SLOPELENUSLE_H,
TableComponent.MUKEY, TableComponent.HYDGRP_NAME)));
tHorizon.setUsedColumns(new ArrayList<>(Arrays.asList(TableHorizon.CEC7_H, TableHorizon.CEC7_L, TableHorizon.CEC7_R,
TableHorizon.SANDTOTAL_R_NAME, TableHorizon.SILTTOTAL_R, TableHorizon.CLAYTOTAL_R,
TableHorizon.WTHIRDBAR_R, TableHorizon.WTHIRDBAR_L, TableHorizon.WTHIRDBAR_H,
TableHorizon.OM_R_NAME, TableHorizon.OM_L, TableHorizon.OM_H,
TableHorizon.WFIFTEENBAR_R, TableHorizon.WFIFTEENBAR_L, TableHorizon.WFIFTEENBAR_H,
TableHorizon.DBTHIRDBAR_R, TableHorizon.DBTHIRDBAR_L, TableHorizon.DBTHIRDBAR_H,
TableHorizon.PH1TO1H2O_R, TableHorizon.PH1TO1H2O_L, TableHorizon.PH1TO1H2O_H)));
mapUnit.readFromSQL(dbResults);
tComponent.readFromSQL(dbResults);
tHorizon.readFromSQL(dbResults);
tComponent.area_pct(EvalResult.getDefaultDouble());
tComponent.calculated_area(EvalResult.getDefaultDouble());
// Water Erodibility needed.
String taxorder = tComponent.taxorder();
String taxsubgrp = tComponent.taxsubgrp();
if (!lastCokey.equalsIgnoreCase(tComponent.cokey())) {
throw new ServiceException("Invalid component key encountered in results from database.");
}
if (!filterResults.foundKffact) {
tHorizon.kffact(dbResults.getDouble(TableHorizon.KFFACT_NAME));
if (dbResults.wasNull()) {
tHorizon.kffact(dbResults.getDouble(TableHorizon.KWFACT_NAME));
if (dbResults.wasNull()) {
if (taxorder.equalsIgnoreCase("histosols") || (taxsubgrp.contains("Histic"))) {
tHorizon.kffact(0.02);
filterResults.foundKffact = true;
tHorizon.selected(true);
tHorizon.selectedReason("WATER");
tComponent.calculated_kffact(tHorizon.kffact());
tComponent.calculated_sandtotal_r(0.0);
tComponent.calculated_silttotal_r(0.0);
tComponent.calculated_claytotal_r(100.0);
ret_val = true;
}
} else {
if (!EvalResult.testDefaultDouble(tHorizon.sandtotal_r())
&& !EvalResult.testDefaultDouble(tHorizon.silttotal_r())
&& !EvalResult.testDefaultDouble(tHorizon.claytotal_r())) {
filterResults.foundKffact = true;
tHorizon.selected(true);
tHorizon.selectedReason("WATER");
// Recall, from above, we copied KWFACT into the KFFACT location of this
//horizon when we couldn't find a kffact value, so copy to component from
//kffact, even though it was a kwfact value.
tComponent.calculated_kffact(tHorizon.kffact());
tComponent.calculated_sandtotal_r(tHorizon.sandtotal_r());
tComponent.calculated_silttotal_r(tHorizon.silttotal_r());
tComponent.calculated_claytotal_r(tHorizon.claytotal_r());
ret_val = true;
}
}
} else {
if (!EvalResult.testDefaultDouble(tHorizon.sandtotal_r())
&& !EvalResult.testDefaultDouble(tHorizon.silttotal_r())
&& !EvalResult.testDefaultDouble(tHorizon.claytotal_r())) {
filterResults.foundKffact = true;
tHorizon.selected(true);
tHorizon.selectedReason("WATER");
tComponent.calculated_kffact(tHorizon.kffact());
tComponent.calculated_sandtotal_r(tHorizon.sandtotal_r());
tComponent.calculated_silttotal_r(tHorizon.silttotal_r());
tComponent.calculated_claytotal_r(tHorizon.claytotal_r());
ret_val = true;
}
}
}
tComponent.horizons.put(chkey, tHorizon);
} else {
break;
}
}
if (!filterResults.foundKffact) {
tComponent.setExclude(true, BAD_KFFACT_LAYERS);
}
return ret_val;
}
/**
* This function filters ONE single component only. Consequently, the excluded
* flag will not ever be set, by this function, for any component of interest.
*
* @param dbResults
* @param filterResults
* @param mapUnit
* @param tComponent
* @param computeLightleWeesieSlope
* @return
* @throws SQLException
* @throws ServiceException
*/
@Deprecated
default boolean filterWEPSComponentHorizonFragData(ResultSet dbResults, FilterResults filterResults, MapUnit mapUnit, Component tComponent, boolean computeLightleWeesieSlope) throws SQLException, ServiceException {
boolean ret_val = false;
String lastCokey = tComponent.cokey();
double lambda = 0.0;
LinkedHashMap<String, Component> components = mapUnit.components();
filterResults.foundKffact = false;
filterResults.foundSandLayer = false;
while (dbResults.next()) {
String cokey = dbResults.getString(TableComponent.COKEY);
if (tComponent.cokey().equals(cokey)) {
String chkey = dbResults.getString(TableHorizon.CHKEY_NAME);
Horizon tHorizon;
if (tComponent.horizons.containsKey(chkey)) {
tHorizon = tComponent.horizons.get(chkey);
} else {
tHorizon = new Horizon();
tHorizon.chkey(chkey);
}
tComponent.setUsedColumns(new ArrayList<>(Arrays.asList(TableComponent.MUKEY, TableComponent.COKEY, TableComponent.COMPNAME,
TableComponent.COMPPCT_R_NAME, TableComponent.HYDGRP_NAME, TableComponent.SLOPE_R_NAME, TableComponent.SLOPE_L, TableComponent.SLOPE_H,
TableComponent.TAXORDER_NAME, TableComponent.TAXSUBGRP,
TableComponent.WEI_NAME, TableComponent.SLOPELENUSLE_R, TableComponent.SLOPELENUSLE_L, TableComponent.SLOPELENUSLE_H,
TableComponent.TFACT_NAME,
TableComponent.ALBEDODRY_R, TableComponent.ALBEDODRY_L, TableComponent.ALBEDODRY_H
)));
tHorizon.setUsedColumns(new ArrayList<>(Arrays.asList(TableHorizon.COKEY, TableHorizon.CHKEY_NAME, TableHorizon.OM_R_NAME,
TableHorizon.HZDEPT_R_NAME, TableHorizon.HZDEPB_R_NAME, TableHorizon.OM_L, TableHorizon.OM_H,
TableHorizon.HZTHK_R_NAME, TableHorizon.KWFACT_NAME, TableHorizon.KFFACT_NAME,
TableHorizon.CLAYTOTAL_R, TableHorizon.CLAYTOTAL_L, TableHorizon.CLAYTOTAL_H,
TableHorizon.SANDVC_R, TableHorizon.SANDVC_L, TableHorizon.SANDVC_H,
TableHorizon.SANDCO_R, TableHorizon.SANDCO_L, TableHorizon.SANDCO_H,
TableHorizon.CACO3_R, TableHorizon.CACO3_L, TableHorizon.CACO3_H,
TableHorizon.SANDMED_R, TableHorizon.SANDMED_L, TableHorizon.SANDMED_H,
TableHorizon.SANDFINE_R, TableHorizon.SANDFINE_L, TableHorizon.SANDFINE_H,
TableHorizon.SANDVF_R, TableHorizon.SANDVF_L, TableHorizon.SANDVF_H,
TableHorizon.SANDTOTAL_R_NAME, TableHorizon.SANDTOTAL_L, TableHorizon.SANDTOTAL_H,
TableHorizon.SILTTOTAL_R, TableHorizon.SILTTOTAL_L, TableHorizon.SILTTOTAL_H,
TableHorizon.CEC7_R, TableHorizon.CEC7_L, TableHorizon.CEC7_H,
TableHorizon.WTHIRDBAR_R, TableHorizon.WTHIRDBAR_L, TableHorizon.WTHIRDBAR_H,
TableHorizon.WFIFTEENBAR_R, TableHorizon.WFIFTEENBAR_L, TableHorizon.WFIFTEENBAR_H,
TableHorizon.DBTHIRDBAR_R, TableHorizon.DBTHIRDBAR_L, TableHorizon.DBTHIRDBAR_H,
TableHorizon.PH1TO1H2O_R, TableHorizon.PH1TO1H2O_L, TableHorizon.PH1TO1H2O_H,
TableHorizon.ECEC_R, TableHorizon.ECEC_L, TableHorizon.ECEC_H,
TableHorizon.LEP_R, TableHorizon.LEP_L, TableHorizon.LEP_H,
TableHorizon.KSAT_R, TableHorizon.KSAT_R, TableHorizon.KSAT_H
)));
tComponent.readFromSQL(dbResults);
tHorizon.readFromSQL(dbResults);
double slope_r = tComponent.slope_r();
tComponent.slope_r(slope_r);
tComponent.slopegr15((slope_r > 15));
if (mapUnit.aoaArea() > 0.0) {
tComponent.area_pct((tComponent.comppct_r() / 100.0) * (mapUnit.area() / mapUnit.aoaArea()) * 100.0);
} else {
tComponent.area_pct(EvalResult.getDefaultDouble());
}
if (mapUnit.area() > 0.0) {
tComponent.calculated_area(tComponent.comppct_r() / 100.0 * mapUnit.area());
} else {
tComponent.calculated_area(EvalResult.getDefaultDouble());
}
//Wind Erodability filtering
if (!lastCokey.equalsIgnoreCase(tComponent.cokey())) {
throw new ServiceException("Invalid component key encountered in results from database.");
}
if (!filterResults.foundSandLayer) {
if (tComponent.taxorder().equalsIgnoreCase("histosols") || (!tComponent.taxorder().equalsIgnoreCase("histosols") && (tHorizon.hzdepb_r() > 10) && (tHorizon.om_r() > 15))) {
tHorizon.sandtotal_r(50);
}
if (tHorizon.sandtotal_r() >= 0.0) {
tComponent.calculated_sandtotal_r(tHorizon.sandtotal_r());
tHorizon.selected(true);
tHorizon.selectedReason("WIND");
tComponent.calculated_om_r(tHorizon.om_r());
tComponent.calculated_hzdepb_r(tHorizon.hzdepb_r());
filterResults.foundSandLayer = true;
ret_val = true;
}
}
tComponent.horizons.put(chkey, tHorizon);
} else {
break;
}
}
if (!filterResults.foundSandLayer) {
tComponent.setExclude(true, BAD_SAND_LAYERS);
}
return ret_val;
}
/**
* This function filters ONE single component only. Consequently, the excluded
* flag will not ever be set, by this function, for any component of interest.
*
* @param dbResults
* @param filterResults
* @param mapUnit
* @param tComponent
* @param computeLightleWeesieSlope
* @return
* @throws SQLException
* @throws ServiceException
*/
default boolean filterWEPPComponentHorizonFragData(ResultSet dbResults, FilterResults filterResults, MapUnit mapUnit, Component tComponent, boolean computeLightleWeesieSlope) throws SQLException, ServiceException {
boolean ret_val = false;
String lastCokey = tComponent.cokey();
double lambda = 0.0;
LinkedHashMap<String, Component> components = mapUnit.components();
filterResults.foundKffact = false;
filterResults.foundSandLayer = false;
while (dbResults.next()) {
String cokey = dbResults.getString(TableComponent.COKEY);
if (tComponent.cokey().equals(cokey)) {
String chkey = dbResults.getString(TableHorizon.CHKEY_NAME);
Horizon tHorizon;
if (tComponent.horizons.containsKey(chkey)) {
tHorizon = tComponent.horizons.get(chkey);
} else {
tHorizon = new Horizon();
tHorizon.chkey(chkey);
}
tComponent.setUsedColumns(new ArrayList<>(Arrays.asList(TableComponent.MUKEY, TableComponent.COKEY, TableComponent.COMPNAME,
TableComponent.COMPPCT_R_NAME, TableComponent.HYDGRP_NAME, TableComponent.SLOPE_R_NAME, TableComponent.SLOPE_L, TableComponent.SLOPE_H,
TableComponent.TAXORDER_NAME, TableComponent.TAXSUBGRP,
TableComponent.WEI_NAME, TableComponent.SLOPELENUSLE_R, TableComponent.SLOPELENUSLE_L, TableComponent.SLOPELENUSLE_H,
TableComponent.TFACT_NAME,
TableComponent.ALBEDODRY_R, TableComponent.ALBEDODRY_L, TableComponent.ALBEDODRY_H
)));
tHorizon.setUsedColumns(new ArrayList<>(Arrays.asList(TableHorizon.COKEY, TableHorizon.CHKEY_NAME, TableHorizon.OM_R_NAME,
TableHorizon.HZDEPT_R_NAME, TableHorizon.HZDEPB_R_NAME, TableHorizon.OM_L, TableHorizon.OM_H,
TableHorizon.HZTHK_R_NAME, TableHorizon.KWFACT_NAME, TableHorizon.KFFACT_NAME,
TableHorizon.CLAYTOTAL_R, TableHorizon.CLAYTOTAL_L, TableHorizon.CLAYTOTAL_H,
TableHorizon.SANDVC_R, TableHorizon.SANDVC_L, TableHorizon.SANDVC_H,
TableHorizon.SANDCO_R, TableHorizon.SANDCO_L, TableHorizon.SANDCO_H,
TableHorizon.CACO3_R, TableHorizon.CACO3_L, TableHorizon.CACO3_H,
TableHorizon.SANDMED_R, TableHorizon.SANDMED_L, TableHorizon.SANDMED_H,
TableHorizon.SANDFINE_R, TableHorizon.SANDFINE_L, TableHorizon.SANDFINE_H,
TableHorizon.SANDVF_R, TableHorizon.SANDVF_L, TableHorizon.SANDVF_H,
TableHorizon.SANDTOTAL_R_NAME, TableHorizon.SANDTOTAL_L, TableHorizon.SANDTOTAL_H,
TableHorizon.SILTTOTAL_R, TableHorizon.SILTTOTAL_L, TableHorizon.SILTTOTAL_H,
TableHorizon.CEC7_R, TableHorizon.CEC7_L, TableHorizon.CEC7_H,
TableHorizon.WTHIRDBAR_R, TableHorizon.WTHIRDBAR_L, TableHorizon.WTHIRDBAR_H,
TableHorizon.WFIFTEENBAR_R, TableHorizon.WFIFTEENBAR_L, TableHorizon.WFIFTEENBAR_H,
TableHorizon.DBTHIRDBAR_R, TableHorizon.DBTHIRDBAR_L, TableHorizon.DBTHIRDBAR_H,
TableHorizon.PH1TO1H2O_R, TableHorizon.PH1TO1H2O_L, TableHorizon.PH1TO1H2O_H,
TableHorizon.ECEC_R, TableHorizon.ECEC_L, TableHorizon.ECEC_H,
TableHorizon.LEP_R, TableHorizon.LEP_L, TableHorizon.LEP_H,
TableHorizon.KSAT_R, TableHorizon.KSAT_R, TableHorizon.KSAT_H
)));
tComponent.readFromSQL(dbResults);
tHorizon.readFromSQL(dbResults);
double slope_r = tComponent.slope_r();
tComponent.slope_r(slope_r);
tComponent.slopegr15((slope_r > 15));
if (mapUnit.aoaArea() > 0.0) {
tComponent.area_pct((tComponent.comppct_r() / 100.0) * (mapUnit.area() / mapUnit.aoaArea()) * 100.0);
} else {
tComponent.area_pct(EvalResult.getDefaultDouble());
}
if (mapUnit.area() > 0.0) {
tComponent.calculated_area(tComponent.comppct_r() / 100.0 * mapUnit.area());
} else {
tComponent.calculated_area(EvalResult.getDefaultDouble());
}
//Wind Erodability filtering
if (!lastCokey.equalsIgnoreCase(tComponent.cokey())) {
throw new ServiceException("Invalid component key encountered in results from database.");
}
String taxorder = tComponent.taxorder();
if (!lastCokey.equalsIgnoreCase(tComponent.cokey())) {
if (!filterResults.foundKffact) {
if (!lastCokey.isEmpty()) {
if (components.containsKey(lastCokey)) {
components.get(lastCokey).setExclude(true, BAD_KFFACT_LAYERS);
}
}
}
lastCokey = tComponent.cokey();
filterResults.foundKffact = false;
}
if (!filterResults.foundKffact) {
if (!computeLightleWeesieSlope) {
lambda = tComponent.slopelenusle_r();
} else {
lambda = SoilUtils.calcLightleWeesieSlopeSlopeLength(slope_r, mapUnit.isPalouse());
}
tHorizon.lsfact(SoilUtils.calcLsFactor(slope_r, lambda));
tComponent.length_r(lambda);
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");
tComponent.calculated_kffact(tHorizon.kffact());
tComponent.calculated_lsfact(tHorizon.lsfact());
tComponent.calculated_claytotal_r(tHorizon.claytotal_r());
ret_val = true;
}
} else {
filterResults.foundKffact = true;
tHorizon.selected(true);
tHorizon.selectedReason("WATER");
tComponent.calculated_kffact(tHorizon.kffact());
tComponent.calculated_lsfact(tHorizon.lsfact());
tComponent.calculated_claytotal_r(tHorizon.claytotal_r());
ret_val = true;
}
} else {
filterResults.foundKffact = true;
tHorizon.selected(true);
tHorizon.selectedReason("WATER");
tComponent.calculated_kffact(tHorizon.kffact());
tComponent.calculated_lsfact(tHorizon.lsfact());
tComponent.calculated_claytotal_r(tHorizon.claytotal_r());
ret_val = true;
}
}
tComponent.horizons.put(chkey, tHorizon);
} else {
break;
}
}
return ret_val;
}
default boolean noFilterComponentData(ResultSet dbResults, MapUnit mapUnit) throws SQLException, ServiceException {
boolean ret_val = false;
LinkedHashMap<String, Component> components = mapUnit.components();
while (dbResults.next()) {
ret_val = true;
Component tComponent;
String cokey = dbResults.getString(TableComponent.COKEY);
if (components.containsKey(cokey)) {
tComponent = components.get(cokey);
} else {
tComponent = new Component();
tComponent.cokey(cokey);
components.put(cokey, tComponent);
}
tComponent.setUsedColumns(new ArrayList<>(Arrays.asList(TableComponent.COMPPCT_R_NAME, TableComponent.HYDGRP_NAME,
TableComponent.TAXORDER_NAME, TableComponent.MUKEY, TableComponent.COKEY, TableComponent.COMPNAME,
TableComponent.WEI_NAME, TableComponent.TFACT_NAME,
TableComponent.RS_PROD_H, TableComponent.RS_PROD_L, TableComponent.RS_PROD_R,
TableComponent.OTHERPH_NAME, TableComponent.LOCALPHASE_NAME, TableComponent.MAJ_COMP_FLAG)));
tComponent.readFromSQL(dbResults);
if (mapUnit.aoaArea() > 0.0) {
tComponent.area_pct((tComponent.comppct_r() / 100.0) * (mapUnit.area() / mapUnit.aoaArea()) * 100.0);
} else {
tComponent.area_pct(EvalResult.getDefaultDouble());
}
if (mapUnit.area() > 0.0) {
tComponent.calculated_area(tComponent.comppct_r() / 100.0 * mapUnit.area());
} else {
tComponent.calculated_area(EvalResult.getDefaultDouble());
}
}
return ret_val;
}
default boolean noFilterComponentHorizonFragData(ResultSet dbResults, HashMap<String, MapUnit> mapUnits, boolean computeLightleWeesieSlope) throws SQLException, ServiceException {
boolean ret_val = false;
TableComponent tableComponent = new TableComponent();
ArrayList<String> componentColumns = tableComponent.getColumnList();
TableHorizon tableHorizon = new TableHorizon();
ArrayList<String> horizonColumns = tableHorizon.getColumnList();
TableFragments tableFragments = new TableFragments();
ArrayList<String> fragmentColumns = tableFragments.getColumnList();
while (dbResults.next()) {
ret_val = true;
MapUnit tMapUnit;
String mukey = dbResults.getString(TableComponent.MUKEY);
// Setup default used columns for reading in SQL.
// TableComponent tComponent = new TableComponent();
// Component.setDefaultUsedColumns(tComponent.getColumnList());
// TableHorizon tHorizon = new TableHorizon();
// Horizon.setDefaultUsedColumns(tHorizon.getColumnList());
// TableFragments tFragments = new TableFragments();
// Fragments.setDefaultUsedColumns(tFragments.getColumnList());
if (mapUnits.containsKey(mukey)) {
tMapUnit = mapUnits.get(mukey);
readNoFilterComponentHorizonFragData(dbResults, tMapUnit, true, componentColumns, horizonColumns, fragmentColumns);
} else {
throw new ServiceException("Invalid Mukey returned in database result set. Mukey: " + mukey + " was not requested, but was returned.");
}
}
return ret_val;
}
default void readNoFilterComponentHorizonFragData(ResultSet dbResults, MapUnit tMapUnit, boolean computeLightleWeesieSlope,
ArrayList<String> componentColumns, ArrayList<String> horizonColumns, ArrayList<String> fragmentColumns) throws SQLException, ServiceException {
String lastCokey = "";
double lambda = 0.0;
LinkedHashMap<String, Component> components = tMapUnit.components();
Component tComponent;
String cokey = dbResults.getString(TableComponent.COKEY);
if (!cokey.isEmpty()) {
if (components.containsKey(cokey)) {
tComponent = components.get(cokey);
} else {
tComponent = new Component(dbResults);
tComponent.cokey(cokey);
components.put(cokey, tComponent);
if (EvalResult.testDefaultEmptyString(tComponent.taxorder()) || (null == tComponent.taxorder())) {
tComponent.setExclude(true, "Taxorder is missing from this component SDM record");
}
}
tComponent.setUsedColumns(componentColumns);
tComponent.readFromSQL(dbResults);
if (tMapUnit.aoaArea() > 0.0) {
tComponent.area_pct((tComponent.comppct_r() / 100.0) * (tMapUnit.area() / tMapUnit.aoaArea()) * 100.0);
} else {
tComponent.area_pct(EvalResult.getDefaultDouble());
}
if (tMapUnit.area() > 0.0) {
tComponent.calculated_area(tComponent.comppct_r() / 100.0 * tMapUnit.area());
} else {
tComponent.calculated_area(EvalResult.getDefaultDouble());
}
double slope_r = tComponent.slope_r();
tComponent.slope_r(slope_r);
tComponent.slopegr15((slope_r > 15));
if (!computeLightleWeesieSlope) {
lambda = tComponent.slopelenusle_r();
} else {
lambda = SoilUtils.calcLightleWeesieSlopeSlopeLength(slope_r, tMapUnit.isPalouse());
}
tComponent.length_r(lambda);
String chkey = dbResults.getString(TableHorizon.CHKEY_NAME);
Horizon tHorizon = null;
if (!chkey.isEmpty()) {
if (tComponent.horizons.containsKey(chkey)) {
tHorizon = tComponent.horizons.get(chkey);
} else {
tHorizon = new Horizon(dbResults);
tHorizon.chkey(chkey);
tComponent.horizons.put(chkey, tHorizon);
}
tHorizon.setUsedColumns(horizonColumns);
tHorizon.readFromSQL(dbResults);
tHorizon.lsfact(SoilUtils.calcLsFactor(slope_r, lambda));
String chfragskey = dbResults.getString(TableFragments.CHFRAGSKEY);
Fragments tFragments = null;
if ((null != chfragskey) && (!chfragskey.isEmpty())) {
if (tHorizon.fragments.containsKey(chfragskey)) {
tFragments = tHorizon.fragments.get(chfragskey);
} else {
tFragments = new Fragments(dbResults);
tFragments.chfragskey(chfragskey);
tHorizon.fragments.put(chfragskey, tFragments);
}
tFragments.setUsedColumns(fragmentColumns);
tFragments.readFromSQL(dbResults);
}
}
}
}
default boolean noFilterComponentHorizonFragData(ResultSet dbResults, MapUnit mapUnit, boolean computeLightleWeesieSlope) throws SQLException, ServiceException {
boolean ret_val = false;
String lastCokey = "";
double lambda = 0.0;
LinkedHashMap<String, Component> components = mapUnit.components();
while (dbResults.next()) {
ret_val = true;
Component tComponent;
String cokey = dbResults.getString(TableComponent.COKEY);
if (components.containsKey(cokey)) {
tComponent = components.get(cokey);
} else {
tComponent = new Component();
tComponent.cokey(cokey);
components.put(cokey, tComponent);
}
String chkey = dbResults.getString(TableHorizon.CHKEY_NAME);
Horizon tHorizon;
if (tComponent.horizons.containsKey(chkey)) {
tHorizon = tComponent.horizons.get(chkey);
} else {
tHorizon = new Horizon();
tHorizon.chkey(chkey);
}
tComponent.setUsedColumns(new ArrayList<>(Arrays.asList(TableComponent.COMPPCT_R_NAME, TableComponent.HYDGRP_NAME, TableComponent.SLOPE_R_NAME,
TableComponent.TAXORDER_NAME, TableComponent.MUKEY, TableComponent.COKEY, TableComponent.COMPNAME,
TableComponent.WEI_NAME, TableComponent.SLOPELENUSLE_R, TableComponent.TFACT_NAME,
TableComponent.RS_PROD_H, TableComponent.RS_PROD_L, TableComponent.RS_PROD_R,
TableComponent.OTHERPH_NAME, TableComponent.LOCALPHASE_NAME, TableComponent.MAJ_COMP_FLAG)));
tHorizon.setUsedColumns(new ArrayList<>(Arrays.asList(TableHorizon.COKEY, TableHorizon.CHKEY_NAME, TableHorizon.OM_R_NAME,
TableHorizon.HZTHK_R_NAME, TableHorizon.HZDEPT_R_NAME, TableHorizon.HZDEPB_R_NAME, TableHorizon.KWFACT_NAME,
TableHorizon.KFFACT_NAME, TableHorizon.SANDTOTAL_R_NAME, TableHorizon.SILTTOTAL_R, TableHorizon.CLAYTOTAL_R,
TableHorizon.PH1TO1H2O_L, TableHorizon.PH1TO1H2O_R, TableHorizon.PH1TO1H2O_H,
TableHorizonCalculations.FRAGVOL_R_NAME)));
tComponent.readFromSQL(dbResults);
tHorizon.readFromSQL(dbResults);
double slope_r = tComponent.slope_r();
tComponent.slope_r(slope_r);
tComponent.slopegr15((slope_r > 15));
if (mapUnit.aoaArea() > 0.0) {
tComponent.area_pct((tComponent.comppct_r() / 100.0) * (mapUnit.area() / mapUnit.aoaArea()) * 100.0);
} else {
tComponent.area_pct(EvalResult.getDefaultDouble());
}
if (mapUnit.area() > 0.0) {
tComponent.calculated_area(tComponent.comppct_r() / 100.0 * mapUnit.area());
} else {
tComponent.calculated_area(EvalResult.getDefaultDouble());
}
if (!computeLightleWeesieSlope) {
lambda = tComponent.slopelenusle_r();
} else {
lambda = SoilUtils.calcLightleWeesieSlopeSlopeLength(slope_r, mapUnit.isPalouse());
}
tHorizon.lsfact(SoilUtils.calcLsFactor(slope_r, lambda));
tComponent.length_r(lambda);
tComponent.horizons.put(chkey, tHorizon);
}
return ret_val;
}
public boolean validateComponent(int cokey) throws SQLException;
///////////////////////////////
// END Interface Functions
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Public inner classes needed for this class or in other code if desired there.
///////////////////////////////
public class ComponentsHorizonsFrags {
public String mukey;
public String cokey;
public String compname;
public double comppct_r = NaN;
public String hydgrp;
public double slope_r = NaN;
public double slope_length = NaN;
public String taxorder;
public String chkey;
public double om_r = NaN;
public double hzthk_r = NaN;
public boolean hzthk_r_b; //Set to false if hzthk_r was null/empty
public double hzdept_r = NaN;
public double hzdepb_r = NaN;
public double kwfact = NaN;
public boolean kwfact_b; //Set to false if kwfact was null/empty
public double kffact = NaN;
public boolean kffact_b; //Set to false if kffact was null/empty
public double fragvol_r = NaN;
public String chfragskey;
}
public class FilterResults {
public boolean foundKffact = false;
public boolean foundSandLayer = false;
}
}