LMODWeppData.java [src/java/m/wepp] Revision: Date:
package m.wepp;
import csip.Config;
import csip.api.client.ModelDataServiceCall;
import csip.SessionLogger;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import java.io.ByteArrayInputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.GregorianCalendar;
import java.util.logging.Level;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
/**
* This class manages the individual WEPP parameters.
*
* @author jrf
*/
public class LMODWeppData {
List<TillageRec> tillages;
List<VegetationRec> vegs;
List<ResidueRec> residues;
List<IrrigationRec> irrigations;
List<ContourRec> contours;
JSONArray woodyvegs;
JSONObject vegBlobsCRLMOD;
JSONObject opBlobsCRLMOD;
JSONObject resBlobsCRLMOD;
WEPSTags lastProcess;
JSONObject debugData;
SessionLogger LOG;
boolean crlmod31_format;
String weppOpParamSetName;
String weppResParamSetName;
String weppCropParamSetName;
String cropsURL;
String operationsURL;
String residueURL;
String dataversion;
static boolean lmodCache = Config.getBoolean("lmod.cache", false);
/**
* This is constructed once for each management rotation and holds all the
* WEPP data used in that management.
*
* @param debugData JSON data that can overwrite crop database parameters.
* @param log CSIP logging pointer
*/
LMODWeppData(JSONObject debugData, SessionLogger log, String cropsURL, String operationsURL, String residueURL, String version) {
this.LOG = log;
this.cropsURL = cropsURL;
this.operationsURL = operationsURL;
this.residueURL = residueURL;
this.dataversion = version;
lastProcess = new WEPSTags();
tillages = new ArrayList<>();
vegs = new ArrayList<>();
residues = new ArrayList<>();
irrigations = new ArrayList<>();
contours = new ArrayList<>();
woodyvegs = new JSONArray();
vegBlobsCRLMOD = new JSONObject();
opBlobsCRLMOD = new JSONObject();
resBlobsCRLMOD = new JSONObject();
this.debugData = debugData;
crlmod31_format = true;
if (cropsURL.endsWith("/2.0") || cropsURL.endsWith("/3.0") || cropsURL.endsWith("/4.0")) {
crlmod31_format = false;
}
if (crlmod31_format) {
weppOpParamSetName = "weppOpFile";
weppResParamSetName = "weppResFile";
weppCropParamSetName = "weppCropFile";
} else {
weppOpParamSetName = "weppOpParamSet";
weppResParamSetName = "weppResParamSet";
weppCropParamSetName = "weppCropParamSet";
}
}
/**
* These are from the WEPS portion of an operation
*
*/
private static class WEPSTags {
float fuel;
float stir;
};
/**
* WEPP parameters for contouring
*/
private static class ContourRec {
String weppkey;
float slope;
float height;
float length;
float spacing;
/**
* Converts data into a string that is used in management.
*
* @return contour string for .rot file
*/
public String toDBString() {
String rec = weppkey + " 1\n";
rec = rec + "Contour " + weppkey + "\n";
rec = rec + "comment...\ncomment...\ncomment...\n";
rec = rec + String.format("%f %f %f %f\n", slope, height, length, spacing);
return rec;
}
/**
* Constructs a contour record with parameters.
*
* @param key contour key name
* @param slp slope of contour
* @param hgt height of contour
* @param len length of contour
* @param sp spacing of contours
*/
ContourRec(String key, float slp, float hgt, float len, float sp) {
weppkey = key;
slope = slp;
height = hgt;
length = len;
spacing = sp;
}
};
/**
* WEPP parameters for residues.
*
*/
private static class ResidueRec {
String cropKey;
float amount;
boolean isAddOp;
String weppkey;
int type;
/**
* Construct generic residue
*
* @param ty true if add residue, false for remove
*/
ResidueRec(boolean ty) {
isAddOp = ty;
if (isAddOp == true) {
amount = (float) 250.0; // add is in pounds
} else {
amount = (float) 1.0; // remove is a fraction
}
}
/**
* Construct specific residue
*
* @param ty true if add residue, false for remove
* @param key key to assign to this residue
* @param ckey crop/veg key used by the residue
* @param amt amount added or removed. Add is kg, remove is fraction.
*/
ResidueRec(boolean ty, String key, String ckey, float amt) {
isAddOp = ty;
weppkey = key;
cropKey = ckey;
amount = amt;
}
/**
* Formats the residue record as a string to use in management file.
*
* @return string representation of residue record.
*/
public String toDBString() {
String rec = weppkey + " 1\n";
rec = rec + "Residue " + weppkey + "\n";
rec = rec + "comment...\ncomment...\ncomment...\n";
if (isAddOp) {
rec = rec + "1\n";
double kgamt = (amount * 1.12085) / 10000;
rec = rec + String.format("0 %f %s\n", kgamt, cropKey);
} else {
// amount is fraction 0-1
rec = rec + "2\n";
rec = rec + String.format("0 %f\n", amount);
}
return rec;
}
};
/**
* WEPP parameters for irrigation.
*
*/
private static class IrrigationRec {
String weppkey;
String name;
int type; // fixed-stationary(1) or depletion-stationary(0)
float rate;
float mindepth;
float maxdepth;
float depth;
float ratio;
float maxratio;
float nozzle;
int startDate, endDate;
/**
* Convert the data into a string that can be written to the management
* file.
*
* @return string to include in management file
*/
public String toDBString() {
String rec = weppkey + " 1\n";
float ratemsec = (float) ((rate / 3600) / 1000.0);
rec = rec + " Irrigation " + weppkey + "\n";
rec = rec + name + "\n";
rec = rec + "comment..\ncomment...\n";
if (type == 0) { // depletion
rec = rec + "1 1 1\n";
rec = rec + "0 0 0\n";
rec = rec + String.format("%f %f # mindepth maxdepth\n", mindepth / 1000.0, maxdepth / 1000.0);
rec = rec + String.format(" %f %f %f %f %d %d\n", ratemsec, ratio, maxratio, nozzle, startDate, endDate);
} else {
rec = rec + "1\n";
rec = rec + String.format("%f %f %f # rate depth nozzle\n", ratemsec, depth, nozzle);
}
return rec;
}
/**
* Construct an irrigation record starting from a specific date to the end
* of the year.
*
* @param date starting date
*/
IrrigationRec(String date) {
String mdate[] = date.split("-");
int yr = Integer.parseInt(mdate[0]);
int mon = Integer.parseInt(mdate[1]) - 1;
int day = Integer.parseInt(mdate[2]);
GregorianCalendar gc = new GregorianCalendar();
gc.set(GregorianCalendar.DAY_OF_MONTH, day);
gc.set(GregorianCalendar.MONTH, mon);
gc.set(GregorianCalendar.YEAR, 2001);
startDate = gc.get(GregorianCalendar.DAY_OF_YEAR);
endDate = 365;
}
/**
* Construct an irrigation record with all parameters.
*
* @param ty type of irrigation
* @param rt rate
* @param mndepth minimum depth
* @param mxdepth maximum depth
* @param dep depth
* @param rat rate
* @param mrat maximum ratio
* @param noz nozzle energy
* @param date date of irrigation
*/
IrrigationRec(int ty, float rt, float mndepth, float mxdepth, float dep, float rat, float mrat, float noz, String date) {
type = ty;
rate = rt;
mindepth = mndepth;
maxdepth = mxdepth;
depth = dep;
ratio = rat;
maxratio = mrat;
nozzle = noz;
startDate = 1;
endDate = 365;
}
/**
* Get irrigation parameters from JSON test in database operations record.
*
* @param nirr XML node of irrigation data
* @return true if parsed ok
*/
public boolean parseIrrigation(Node nirr) {
NodeList parms = nirr.getChildNodes();
for (int k = 0; k < parms.getLength(); k++) {
Node n = parms.item(k);
if (n.getNodeType() == Node.ELEMENT_NODE) {
String elem = n.getNodeName();
String value = n.getTextContent();
switch (elem) {
case "name":
name = value;
break;
case "type":
List<String> irrCodes = Arrays.asList(new String[]{
"depletion-stationary", "fixed-stationary"
});
type = irrCodes.indexOf(value.toLowerCase());
break;
case "rate":
rate = Float.parseFloat(value);
break;
case "mindepth":
mindepth = Float.parseFloat(value);
break;
case "maxdepth":
maxdepth = Float.parseFloat(value);
break;
case "depth":
depth = Float.parseFloat(value);
break;
case "ratio":
ratio = Float.parseFloat(value);
break;
case "maxratio":
maxratio = Float.parseFloat(value);
break;
case "nozzle":
nozzle = Float.parseFloat(value);
break;
default:
break;
}
}
}
if ((weppkey == null) || (weppkey.isEmpty())) {
String key;
if (name.length() > 6) {
key = name.substring(0, 6);
} else {
key = name;
}
key = key.toUpperCase();
key = key.trim();
String uniqueId = Integer.toUnsignedString(name.hashCode());
key += "_" + uniqueId.substring(0, Math.min(5, uniqueId.length()));
key = key.replace(' ', '_');
key = key.replace(',', '_');
weppkey = key;
}
return true;
}
/**
* Generate a key based on the name. Used to identify records.
*
* @param idx index
*/
void adjustKey(int idx) {
String key;
if (name.length() > 6) {
key = name.substring(0, 6);
} else {
key = name;
}
key = key.toUpperCase();
key = key.trim();
int random = name.hashCode() + idx;
String uniqueId = Integer.toUnsignedString(random);
key += "_" + uniqueId.substring(0, Math.min(5, uniqueId.length()));
key = key.replace(' ', '_');
key = key.replace(',', '_');
weppkey = key;
}
};
/**
* WEPP parameters for tillage
*/
private class TillageRec {
float mfo1, mfo2, rho, rint, rmfo1, rmfo2, rro, surdis, tdmean;
int numof, pcode, cltpos;
float rfrag, rnfrag;
String weppkey;
String path, name, comment;
float weps_rfrag, weps_rnfrag;
/**
* Creates a string formatted to the what the WEPP management file needs.
*
* @return string of formatted tillage operation
*/
public String toDBString() {
String rec = weppkey + " 1\n";
rec = rec + name + "\n";
//if (comment.length() > 80) {
//rec = rec + comment.substring(0,80) + "...\n";
//} else {
//rec = rec + comment + "\n";
//}
if (name.length() > 65) {
rec = rec + "comment: " + name.substring(0, 65) + "\n";
} else {
rec = rec + "comment: " + name + "\n";
}
rec = rec + "(from WEPP LMOD service)\n";
rec = rec + "comment...\n";
rec = rec + "1 #landuse\n";
rec = rec + String.format("%f %f %d\n%d", mfo1, mfo2, numof, pcode);
if (pcode == 3) {
rec = rec + String.format(" %d", cltpos);
}
rec = rec + String.format("\n%f %f %f %f %f %f %f %f %f\n", rho, rint, rmfo1, rmfo2, rro, surdis, tdmean, rfrag, rnfrag);
return rec;
}
/**
* Gets the XML parameters from a database record and saves them in this
* class.
*
* @param ntill XML node with tillage parameters
* @return true if parameters read ok
*/
public boolean parseTillage(Node ntill, String opName, int tillSeq) {
NodeList parms = ntill.getChildNodes();
for (int k = 0; k < parms.getLength(); k++) {
Node n = parms.item(k);
if (n.getNodeType() == Node.ELEMENT_NODE) {
String elem = n.getNodeName();
String value = n.getTextContent();
switch (elem) {
case "path":
path = value;
break;
case "name":
name = value;
break;
case "comment":
comment = value;
if (comment.length() > 240) {
comment = comment.substring(0, 240);
}
break;
case "mfo1":
mfo1 = Float.parseFloat(value);
break;
case "mfo2":
mfo2 = Float.parseFloat(value);
break;
case "numof":
numof = Integer.parseInt(value);
break;
case "pcode":
List<String> implementCodes = Arrays.asList(
"pcodeMissing", "planter", "drill", "cultivator", "other"
);
pcode = implementCodes.indexOf(value.toLowerCase());
break;
case "cltpos":
List<String> cltCodes = Arrays.asList("front mounted", "rear mounted");
cltpos = cltCodes.indexOf(value.toLowerCase());
break;
case "rho":
rho = Float.parseFloat(value);
break;
case "rint":
rint = Float.parseFloat(value);
break;
case "rmfo1":
rmfo1 = Float.parseFloat(value);
break;
case "rmfo2":
rmfo2 = Float.parseFloat(value);
break;
case "rro":
rro = Float.parseFloat(value);
break;
case "surdis":
surdis = Float.parseFloat(value);
break;
case "tdmean":
tdmean = Float.parseFloat(value);
break;
case "rfrag":
rfrag = Float.parseFloat(value);
break;
case "rnfrag":
rnfrag = Float.parseFloat(value);
break;
case "weppkey":
weppkey = value;
break;
default:
break;
}
}
}
if ((weppkey == null) || (weppkey.isEmpty())) {
String key;
if (opName.length() > 6) {
key = opName.substring(0, 6);
} else {
key = opName;
}
key = key.toUpperCase();
key = key.trim();
String uniqueId = Integer.toUnsignedString(opName.hashCode() + tillSeq);
if (uniqueId.length() <= 6) {
key += "_" + uniqueId;
} else {
//key += "_" + uniqueId.substring(0, Math.min(5, uniqueId.length()));
key += "_" + uniqueId.substring(uniqueId.length() - 6);
}
key = key.replace(' ', '_');
key = key.replace(',', '_');
LOG.info(key + "*" + uniqueId);
weppkey = key;
} else {
weppkey = weppkey.replace(' ', '_');
weppkey = weppkey.replace(',', '_');
}
return true;
}
};
/**
* WEPP parameters for crops.
*/
private class VegetationRec implements Cloneable {
String path, name, comment;
String weppkey;
int iplant, mfocod, spriod;
String crunit;
float bb, bbb, beinp, btemp, cf, crit, critvm, cuthgt, decfct, diam, dlai, dropfc;
float extnct, fact, flivmx, gddmax, hi, hmax, oratea, orater, otemp, pltol;
float pltsp, rdmax, rsr, rtmmax, tmpmax, tmpmin, xmxlai, yld, rcc, rowWidth, bbAdjust;
// these are from WEPS
String weps_hyldunits;
float weps_tgtyield, weps_grf;
int weps_hyldflag, weps_cbaflag, weps_idc;
float weps_hmx, weps_rdmx, weps_topt, weps_hyconfact, weps_stemdia, weps_hyldwater;
// other
float targetYield, defaultYield;
int sens;
boolean hasHarvest;
boolean rcc_mod;
/**
* Construct an empty vegetation record
*/
VegetationRec() {
targetYield = -999;
weps_hyconfact = 0;
hasHarvest = false;
rcc = 0;
rowWidth = 0;
bbAdjust = 1;
weps_tgtyield = 0;
defaultYield = 0;
sens = 0;
rcc_mod = false;
}
public VegetationRec attachYield(float val) {
float tempYieldDry = val / weps_hyconfact;
float ty = tempYieldDry * (float) (1.0 - (weps_hyldwater / 100.0));
if (targetYield <= 0) {
targetYield = ty;
if (weps_tgtyield > 0) {
defaultYield = weps_tgtyield / weps_hyconfact;
defaultYield = defaultYield * (float) (1.0 - (weps_hyldwater / 100.0));
} else {
defaultYield = targetYield;
}
LOG.info("First yield: " + weppkey);
} else {
// yield already set, check if this is a different yield
// this is the same crop with a different yield, need to create a new
// record.
LOG.info("Second yield: " + weppkey);
try {
VegetationRec vr = (VegetationRec) this.clone();
vr.targetYield = ty;
vr.weppkey = vr.weppkey + "_" + String.valueOf((int) val);
LOG.info("New Record added: " + vr.weppkey);
return vr;
} catch (Exception e) {
LOG.info("Error: Could not duplicate veg record " + weppkey);
}
}
return null;
}
/**
* Get WEPP key associated with this crop record.
*
* @return key as a string
*/
public String getWEPPKey() {
return weppkey;
}
/**
* Check if this crop is considered a perennial.
*
* @return true if the crop is a perennial
*/
boolean isPerennial() {
// type 7 is ambiguous for wepp - Bi-annuals or Perennials with Tuber Dormancy
// default type 7 to an annual
if ((weps_idc == 3) || (weps_idc == 6) || (weps_idc == 8) || (weps_idc == 10) || (weps_idc == 11) || (weps_idc == 12) || (weps_idc == 9)) {
return true;
}
return false;
}
/**
* Formats the vegetation record for the WEPP .rot file.
*
* @return formatted string of parameters.
*/
public String toDBString() {
int doCalibrate = 0;
double adjhi = hi;
// check for WEPS below ground mass used for yield
if (weps_hyldflag == 5) {
adjhi = hi * (-1.0);
}
// hasHarvest - some crops are not harvested so should not be calibrated
if ((weps_cbaflag > 0) && (hasHarvest)) {
if (weps_hyconfact > 0) {
doCalibrate = 1;
}
}
String rec = String.format("%s 1 %d %f %f\n", weppkey, doCalibrate, targetYield, defaultYield);
rec = rec + name + "\n";
if (comment.length() > 80) {
rec = rec + comment.substring(0, 80) + "...\n";
} else {
rec = rec + comment + "\n";
}
rec = rec + "(from WEPP LMOD service)\n";
rec = rec + "comment...\n";
rec = rec + "1\n";
rec = rec + crunit + "\n";
float bbFinal = bb * bbAdjust;
rec = rec + String.format("%f %f %f %f %f %f %f %f %f %f\n", bbFinal, bbb, beinp, btemp, cf, crit, critvm, cuthgt, decfct, diam);
rec = rec + String.format("%f %f %f %f %f %f %f %f\n", dlai, dropfc, extnct, fact, flivmx, gddmax, adjhi, hmax);
rec = rec + String.format("%d\n", mfocod);
rec = rec + String.format("%f %f %f %f %f %f %f %f %d %f\n", oratea, orater, otemp, pltol, pltsp, rdmax, rsr, rtmmax, spriod, tmpmax);
rec = rec + String.format("%f %f %f %f\n", tmpmin, xmxlai, yld, rcc);
return rec;
}
/**
* Parses the database XML for a crop record for the WEPS section. These are
* WEPS parameters that are used by the WEPP interface and service code but
* not directly by the WEPP model.
*
* @param n XML node to parse
* @return true
*/
private boolean parseVegWepsTags(Node n) {
NodeList nl2 = n.getChildNodes();
for (int j = 0; j < nl2.getLength(); j++) {
if (nl2.item(j).getNodeType() == Node.ELEMENT_NODE) {
Node chld = nl2.item(j);
String elem = chld.getNodeName();
String value = chld.getTextContent();
switch (elem) {
case "hyldunits":
weps_hyldunits = value;
break;
case "tgtyield":
weps_tgtyield = Float.parseFloat(value);
break;
case "grf":
weps_grf = Float.parseFloat(value);
break;
case "hyldflag":
weps_hyldflag = Integer.parseInt(value);
break;
case "hmx":
weps_hmx = Float.parseFloat(value);
break;
case "rdmx":
weps_rdmx = Float.parseFloat(value);
break;
case "topt":
weps_topt = Float.parseFloat(value);
break;
case "cbaflag":
weps_cbaflag = Integer.parseInt(value);
break;
case "hyconfact":
try {
weps_hyconfact = Float.parseFloat(value);
} catch (Exception e) {
weps_hyconfact = -999;
}
break;
case "stemdia":
weps_stemdia = Float.parseFloat(value);
break;
case "hyldwater":
weps_hyldwater = Float.parseFloat(value);
break;
case "idc":
// perennial crops are codes 3,6,7,8
weps_idc = Integer.parseInt(value);
break;
default:
break;
}
}
}
return true;
}
/**
* parse the XML from a crop database record into WEPP parameters.
*
* @param nveg XML crop node
* @return true
*/
public boolean parseVeg(Node nveg) {
NodeList parms = nveg.getChildNodes();
for (int k = 0; k < parms.getLength(); k++) {
Node n = parms.item(k);
if (n.getNodeType() == Node.ELEMENT_NODE) {
String elem = n.getNodeName();
String value = n.getTextContent();
switch (elem) {
case "wepstags":
parseVegWepsTags(n);
break;
case "path":
path = value;
break;
case "name":
name = value;
break;
case "comments":
comment = value;
if (comment.length() > 240) {
comment = comment.substring(0, 240);
}
break;
case "weppkey":
weppkey = value;
break;
case "iplant":
iplant = 1; // always use cropland which is 1
break;
case "crunit":
crunit = value;
break;
case "bb":
bb = Float.parseFloat(value);
break;
case "bbb":
bbb = Float.parseFloat(value);
break;
case "beinp":
beinp = Float.parseFloat(value);
break;
case "btemp":
btemp = Float.parseFloat(value);
break;
case "cf":
cf = Float.parseFloat(value);
break;
case "crit":
crit = Float.parseFloat(value);
break;
case "critvm":
critvm = Float.parseFloat(value);
break;
case "cuthgt":
cuthgt = Float.parseFloat(value);
break;
case "decfct":
decfct = Float.parseFloat(value);
break;
case "diam":
diam = Float.parseFloat(value);
break;
case "dlai":
dlai = Float.parseFloat(value);
break;
case "dropfc":
dropfc = Float.parseFloat(value);
break;
case "extnct":
extnct = Float.parseFloat(value);
break;
case "fact":
fact = Float.parseFloat(value);
break;
case "flivmx":
flivmx = Float.parseFloat(value);
break;
case "gddmax":
gddmax = Float.parseFloat(value);
break;
case "hi":
hi = Float.parseFloat(value);
break;
case "hmax":
hmax = Float.parseFloat(value);
break;
case "mfocod":
List<String> mfoCodes = Arrays.asList(new String[]{
"???", "fragile", "non-fragile"
});
mfocod = mfoCodes.indexOf(value.toLowerCase());
break;
case "oratea":
oratea = Float.parseFloat(value);
break;
case "orater":
orater = Float.parseFloat(value);
break;
case "otemp":
otemp = Float.parseFloat(value);
break;
case "pltol":
pltol = Float.parseFloat(value);
break;
case "pltsp":
pltsp = Float.parseFloat(value);
break;
case "rdmax":
rdmax = Float.parseFloat(value);
break;
case "rsr":
rsr = Float.parseFloat(value);
break;
case "rtmmax":
rtmmax = Float.parseFloat(value);
break;
case "spriod":
spriod = Integer.parseInt(value);
break;
case "tmpmax":
tmpmax = Float.parseFloat(value);
break;
case "tmpmin":
tmpmin = Float.parseFloat(value);
break;
case "xmxlai":
xmxlai = Float.parseFloat(value);
break;
case "yld":
yld = Float.parseFloat(value);
break;
case "rcc":
rcc = Float.parseFloat(value);
break;
case "hyldunits":
weps_hyldunits = value;
break;
case "tgtyield":
weps_tgtyield = Float.parseFloat(value);
break;
case "hyldflag":
weps_hyldflag = Integer.parseInt(value);
break;
case "cbaflag":
weps_cbaflag = Integer.parseInt(value);
break;
case "hyconfact":
try {
weps_hyconfact = Float.parseFloat(value);
} catch (Exception e) {
weps_hyconfact = -999;
}
break;
case "hyldwater":
weps_hyldwater = Float.parseFloat(value);
break;
case "idc":
// perennial crops are codes 3,6,7,8
weps_idc = Integer.parseInt(value);
break;
case "sene":
// senesence day for perennial
sens = Integer.parseInt(value);
break;
}
}
}
if ((weppkey == null) || (weppkey == "")) {
String key;
if (name.length() > 6) {
key = name.substring(0, 6);
} else {
key = name;
}
key = key.toUpperCase();
key = key.trim();
String uniqueId = Integer.toUnsignedString(name.hashCode());
key += "_" + uniqueId.substring(0, Math.min(5, uniqueId.length()));
key = key.replace(' ', '_');
key = key.replace(',', '_');
weppkey = key;
} else {
weppkey = weppkey.replace(' ', '_');
weppkey = weppkey.replace(',', '_');
}
return true;
}
}
/**
* Create a WEPP formatted string for a .rot file of the vegetation records.
*
* @return string of vegetation records
*/
public String printVegs() {
String allVegs = "";
if (!vegs.isEmpty()) {
for (VegetationRec vr : vegs) {
String rec = vr.toDBString();
allVegs = allVegs + rec + "\n\n";
}
}
return allVegs;
}
/**
* For a given vegetation record update the release canopy cover (rcc)
* parameter to the value passed which overwrites the value in the crop
* database.
*
* @param key vegetation rcc to update
* @param amount new value for rcc
*/
public void updateVegsRCC(String key, double amount) {
if (!vegs.isEmpty()) {
for (VegetationRec vr : vegs) {
if (vr.getWEPPKey().equals(key)) {
if (vr.rcc_mod == false) {
vr.rcc = (float) amount;
}
return;
}
}
}
}
public void updateVegsRowWidth(String key, double amount) {
if (!vegs.isEmpty()) {
for (VegetationRec vr : vegs) {
if (vr.getWEPPKey().equals(key)) {
vr.rowWidth = (float) amount;
return;
}
}
}
}
public void updateVegsCanopyCoverCoef(String key, double amount) {
if (!vegs.isEmpty()) {
for (VegetationRec vr : vegs) {
if (vr.getWEPPKey().equals(key)) {
vr.bbAdjust = (float) amount;
return;
}
}
}
}
/**
* Generate a list of those crops need to be calibrated.
*
* @return list of vegetation keys and names to calibrate.
*/
public String getVegsToCal() {
String calVegs = "";
if (!vegs.isEmpty()) {
for (VegetationRec vr : vegs) {
if ((vr.weps_cbaflag > 0) && (vr.hasHarvest)) {
//calVegs = calVegs + vr.weppkey + " " + vr.targetYield + "\n";
calVegs = calVegs + vr.weppkey + "\t" + vr.name + "\n";
}
}
}
return calVegs;
}
/**
* Get a string representing if the crop was calibrated.
*
* @param key vegetation key
* @return yes or no if the crop is calibrated
*/
public String getVegCalibStatus(String key) {
String rc = "?";
if (!vegs.isEmpty()) {
for (VegetationRec vr : vegs) {
if (vr.weppkey.equals(key)) {
if (vr.weps_cbaflag == 0) {
rc = "No";
} else {
rc = "Yes";
}
}
}
}
return rc;
}
/**
* Get a string representing all of the operation section in the .rot file for
* this management.
*
* @return string of operations to output to .rot file
*/
public String printOps() {
String allOps = "";
if (!tillages.isEmpty()) {
for (TillageRec tr : tillages) {
String rec = tr.toDBString();
allOps = allOps + rec + "\n\n";
}
}
return allOps;
}
/**
* Get a string representation of the irrigation section in the .rot file for
* this management.
*
* @param ty type of irrigation to output
* @return string of irrigations matching the type
*/
public String printIrrs(int ty) {
String allIrrs = "";
if (!irrigations.isEmpty()) {
for (IrrigationRec ir : irrigations) {
if (ir.type == ty) {
String rec = ir.toDBString();
allIrrs = allIrrs + rec + "\n\n";
}
}
}
return allIrrs;
}
/**
* Get the number of irrigation processes of a certain type for this
* management.
*
* @param ty type of irrigation
* @return number of irrigation records matching the type
*/
public int getIrrCount(int ty) {
int count = 0;
if (!irrigations.isEmpty()) {
for (IrrigationRec ir : irrigations) {
if (ir.type == ty) {
count++;
}
}
}
return count;
}
/**
* Get a string of all the residues to output in the .rot file
*
* @return string of residue records.
*/
public String printResidues() {
String allRes = "";
if (!residues.isEmpty()) {
for (ResidueRec vr : residues) {
String rec = vr.toDBString();
allRes = allRes + rec + "\n";
}
}
return allRes;
}
/**
* Get a string of all the contours to output in the .rot file.
*
* @return string of contour records
*/
public String printContours() {
String allCont = "";
if (!contours.isEmpty()) {
for (ContourRec cr : contours) {
String rec = cr.toDBString();
allCont = allCont + rec + "\n";
}
}
return allCont;
}
/**
* Parse the WEPS section of the operation record. This contains two
* parameters.
*
* @param nweps XML node to start with
* @return true
*/
boolean parseWepsTags(Node nweps) {
NodeList nl2 = nweps.getChildNodes();
for (int j = 0; j < nl2.getLength(); j++) {
if (nl2.item(j).getNodeType() == Node.ELEMENT_NODE) {
Node chld = nl2.item(j);
String pname = chld.getNodeName();
String value = chld.getTextContent();
if (pname.equals("oenergyarea")) {
lastProcess.fuel = Float.parseFloat(value);
} else if (pname.equals("ostir")) {
lastProcess.stir = Float.parseFloat(value);
}
}
}
return true;
}
/**
* Parse residue removal parameters from XML.
*
* @param nres XML node to start with.
*
* @return array with flat and standing removal amounts.
*/
double[] parseResRemoval(Node nres) {
double[] amounts = new double[2];
double standamount = 0.0;
double flatamount = 0.0;
NodeList nl2 = nres.getChildNodes();
for (int j = 0; j < nl2.getLength(); j++) {
if (nl2.item(j).getNodeType() == Node.ELEMENT_NODE) {
Node chld = nl2.item(j);
String pname = chld.getNodeName();
String value = chld.getTextContent();
if (pname.equals("standamount")) {
standamount = Float.parseFloat(value);
}
if (pname.equals("flatamount")) {
flatamount = Float.parseFloat(value);
}
}
}
amounts[0] = standamount;
amounts[1] = flatamount;
return amounts;
}
/**
* Gets a value from an XML tag.
*
* @param nres Starting XML mode
* @param tag tag to search for
* @return value attached to tag
*/
double parseAmount(Node nres, String tag) {
double amount = -999;
NodeList nl2 = nres.getChildNodes();
for (int j = 0; j < nl2.getLength(); j++) {
if (nl2.item(j).getNodeType() == Node.ELEMENT_NODE) {
Node chld = nl2.item(j);
String pname = chld.getNodeName();
String value = chld.getTextContent();
if (pname.equals(tag)) {
amount = Float.parseFloat(value);
}
}
}
return amount;
}
/**
* Sets up a base residue record, adds it to list.
*
* @param nres XML node to start parsing.
* @param isadd true if this is an add residue process.
*
* @return true
*/
boolean parseResidue(Node nres, boolean isadd) {
NodeList nl2 = nres.getChildNodes();
ResidueRec r = new ResidueRec(isadd);
r.amount = (float) 1.0;
for (int j = 0; j < nl2.getLength(); j++) {
if (nl2.item(j).getNodeType() == Node.ELEMENT_NODE) {
Node chld = nl2.item(j);
String pname = chld.getNodeName();
String value = chld.getTextContent();
if (pname.equals("name")) {
// need to translate this, default for now, will be replaced with actual later
r.cropKey = "Corn";
} else if (pname.equals("flatamount")) {
r.amount = Float.parseFloat(value);
}
}
}
// Nothing to do because the information is real parms are specified
// in the other tables.
Integer sz = residues.size() + 1;
String key = "RES_" + Integer.toString(sz);
r.weppkey = key;
r.isAddOp = isadd;
addResidue(r);
return true;
}
/**
* Get the key of the last residue in the list.
*
* @return key of last residue or null if none.
*/
String getLastResidue() {
String name = null;
if (residues != null && !residues.isEmpty()) {
name = residues.get(residues.size() - 1).weppkey;
}
return name;
}
/**
* Decodes the vegetation XML into something WEPP can understand.
*
* @param vegBlob string of XML data
* @return key of vegetation record added
*
* @throws IOException if any
* @throws SAXException if any
* @throws ParserConfigurationException if any
*/
public String getVegs(String vegBlob) throws IOException, SAXException, ParserConfigurationException {
String vkey = null;
if ((vegBlob != null) && (vegBlob != "")) {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
InputStream inputStream = new ByteArrayInputStream(vegBlob.getBytes(Charset.forName("UTF-8")));
Document doc = dBuilder.parse(inputStream);
doc.getDocumentElement().normalize();
NodeList nl = doc.getElementsByTagName("weppcrop");
for (int i = 0; i < nl.getLength(); i++) {
Node n = nl.item(i);
String elem = n.getNodeName();
if (elem.equals("weppcrop")) {
VegetationRec v = new VegetationRec();
v.parseVeg(n);
addCrop(v);
vkey = v.weppkey;
applyTempDatabase();
}
}
}
return vkey;
}
/**
* This builds a list of WEPP detail records that need to be included to
* support this LMOD operation.
*
* @param opBlob string of operation XML date
* @param date date of operation
* @return list of WEPP process and parameters
*
* @throws IOException if any
* @throws SAXException if any
* @throws ParserConfigurationException if any
*/
public List<String> getProcesses(String opBlob, String opName, String date) throws IOException, SAXException, ParserConfigurationException {
List<String> processes = new ArrayList<>();
if ((opBlob != null) && (opBlob != "")) {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
InputStream inputStream = new ByteArrayInputStream(opBlob.getBytes(Charset.forName("UTF-8")));
Document doc = dBuilder.parse(inputStream);
doc.getDocumentElement().normalize();
NodeList nl = doc.getElementsByTagName("process");
Node n;
String elem;
String value;
int tillSeq = 0;
for (int i = 0; i < nl.getLength(); i++) {
n = nl.item(i);
elem = n.getNodeName();
if (elem.equals("process")) {
NodeList n2 = n.getChildNodes();
for (int j = 0; j < n2.getLength(); j++) {
n = n2.item(j);
if (n.getNodeType() == Node.ELEMENT_NODE) {
elem = n.getNodeName();
if (elem.equals("tillage")) {
TillageRec tr = new TillageRec();
tr.parseTillage(n, opName, tillSeq);
tillSeq = tillSeq + 1;
addTillage(tr);
processes.add(elem + "|" + tr.weppkey);
} else if (elem.equals("add-residue")) {
parseResidue(n, true);
processes.add(elem);
} else if (elem.equals("remove-residue")) {
double[] lost = parseResRemoval(n);
if ((lost[0] > 0.0) && (lost[1] > 0.0)) {
// this may need to be restricted to removing flat residue if this is a perennial
parseResidue(n, false);
// need to do burning instead
processes.add("burning" + "|" + Double.toString(lost[0]) + "|" + Double.toString(lost[1]));
} else {
// do regular remove of flat residue
parseResidue(n, false);
processes.add(elem + "|" + Double.toString(lost[1]));
}
} else if (elem.equals("plant")) {
double amount = parseAmount(n, "rcc");
if (amount < 0.0) {
amount = 0.0;
}
double rowWidth = parseAmount(n, "rowWidth");
if (rowWidth < 0.0) {
rowWidth = -1.0;
}
double canopyAdjust = parseAmount(n, "canopyCoverAdjust");
if (canopyAdjust < 0.0) {
canopyAdjust = 1.0;
}
processes.add(elem + "|" + Double.toString(amount) + "|" + Double.toString(rowWidth) + "|" + Double.toString(canopyAdjust));
} else if (elem.equals("harvest")) {
// notthing to do
processes.add(elem);
} else if (elem.equals("kill-crop")) {
// nothing to do
processes.add(elem);
/*
} else if (elem.equals("burning")) {
double []lost = parseBurning(n);
processes.add(elem + "|" + Double.toString(lost[0]) + "|" + Double.toString(lost[1]));
*/
} else if( elem.equals( "kill-annual-crop" ) ) {
// nothing to do
processes.add( elem );
} else if (elem.equals("flatten-residue")) {
double amount = parseAmount(n, "amount");
if (amount < 0.0) {
amount = 0.0;
}
processes.add(elem + "|" + Double.toString(amount));
} else if (elem.equals("silage")) {
// nothing to do
processes.add(elem);
} else if (elem.equals("initialplant")) {
//nothing to do
processes.add(elem);
} else if (elem.equals("remove-live") || elem.equals("remove-live-not-yield")) {
double amount = parseAmount(n, "amount");
if (amount > 0.0) {
processes.add(elem + "|" + Double.toString(amount));
} else {
processes.add(elem + "|");
}
} else if (elem.equals("remove-live-leave") || elem.equals("remove-live-leave-not-yield")) {
double amount = parseAmount(n, "amount");
if (amount > 0.0) {
processes.add(elem + "|" + Double.toString(amount));
} else {
processes.add(elem + "|");
}
} else if (elem.equals("irrigation")) {
IrrigationRec ir = new IrrigationRec(date);
ir.parseIrrigation(n);
addIrrigation(ir);
if (ir.type == 0) {
processes.add(elem + "|" + ir.weppkey);
} else {
processes.add("fixed-" + elem + "|" + ir.weppkey);
}
} else if (elem.equals("irrigation-stop")) {
// nothing to do
stopIrrigation(date);
processes.add(elem);
} else if (elem.equals("next-day")) {
processes.add(elem);
}
}
}
}
}
nl = doc.getElementsByTagName("ostir");
if (nl.getLength() > 0) {
n = nl.item(0);
if (n.getNodeType() == Node.ELEMENT_NODE) {
value = n.getTextContent();
lastProcess.stir = Float.parseFloat(value);
}
}
nl = doc.getElementsByTagName("oenergyarea");
if (nl.getLength() > 0) {
n = nl.item(0);
if (n.getNodeType() == Node.ELEMENT_NODE) {
value = n.getTextContent();
lastProcess.fuel = Float.parseFloat(value);
}
}
nl = doc.getElementsByTagName("wepstags");
for (int i = 0; i < nl.getLength(); i++) {
n = nl.item(i);
elem = n.getNodeName();
if (elem.equals("wepstags")) {
parseWepsTags(n);
}
}
}
return processes;
}
/**
* Add a tillage record to the list if it does not exist.
*
* @param t tillage record to add
*/
private void addTillage(TillageRec t) {
for (TillageRec tr : tillages) {
if (t.weppkey.equals(tr.weppkey)) {
return;
}
}
// need to add
tillages.add(t);
}
/**
* Adds an irrigation. Will change the key to make it unique if it is already
* in the list.
*
* @param irr Irrigation record to add
*/
private void addIrrigation(IrrigationRec irr) {
boolean tryAgain = true;
int idx = 1;
while (tryAgain == true) {
boolean present = false;
for (IrrigationRec ir : irrigations) {
if (irr.weppkey.equals(ir.weppkey)) {
// same key, need to change
irr.adjustKey(idx++);
present = true;
}
}
if (present == false) {
tryAgain = false;
}
}
// need to add
irrigations.add(irr);
}
/**
* Add a stop date to the last irrigation record.
*
* @param date stop date
*/
private void stopIrrigation(String date) {
// this applies to the last irrigation added
int last = irrigations.size() - 1;
if (last >= 0) {
IrrigationRec ir = irrigations.get(last);
// date to Julian
String mdate[] = date.split("-");
int yr = Integer.parseInt(mdate[0]);
int mon = Integer.parseInt(mdate[1]) - 1;
int day = Integer.parseInt(mdate[2]);
GregorianCalendar gc = new GregorianCalendar();
gc.set(GregorianCalendar.DAY_OF_MONTH, day);
gc.set(GregorianCalendar.MONTH, mon);
gc.set(GregorianCalendar.YEAR, 2001);
ir.endDate = gc.get(GregorianCalendar.DAY_OF_YEAR);
}
}
/**
* Add a crop to the list if it does not already exist.
*
* @param v vegetation record to add.
*/
private void addCrop(VegetationRec v) {
for (VegetationRec vr : vegs) {
if (v.weppkey.equals(vr.weppkey)) {
return;
}
}
// need to add
vegs.add(v);
}
/**
* Set yield for the specific crop. The conversion factor saves the units in
* kg/m^2.
*
* @param key vegetation key yield to update
* @param val new yield in user units.
*/
public String attachYield(String key, float val) {
// char[] exts = new char[]{
// 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
// };
for (VegetationRec vr : vegs) {
if (key.equals(vr.weppkey)) {
if (vr.weps_hyconfact > 0) {
VegetationRec temp = vr.attachYield(val);
if (temp != null) {
// this indicates a new record was created because it is
// the same crop with a different yield so add to list
// make sure it is not already present.
if (getVegName(temp.weppkey).equals("")) {
// does not exist, add it
vegs.add(temp);
return temp.weppkey;
} else {
return temp.weppkey;
}
/* This logic was to test when the same crop with the same yield is
// used in multiple places in the management schedule which would
// probably require a different calibration factor. This
// is commented out now because it could lead to a lot of
// different crop records that may cause other problems.
int tries = 1;
String iniKey = temp.weppkey;
while (tries < exts.length) {
if (getVegName(temp.weppkey).equals("")) {
// does not exist, add it
vegs.add(temp);
return temp.weppkey;
} else {
// already exists, change key to be unique
temp.weppkey = iniKey + exts[tries];
tries = tries + 1;
}
}
*/
}
}
return null;
}
}
return null;
}
/**
* Add a residue record to the list if it does not exist.
*
* @param v Residue record to add
*/
private void addResidue(ResidueRec v) {
for (ResidueRec vr : residues) {
if (v.weppkey.equals(vr.weppkey)) {
return;
}
}
// need to add
residues.add(v);
}
/**
* Create a new residue record and add it to the list.
*
* @param ty type, add or remove
* @param ckey vegetation key
* @param amt amount to add or remove
* @return key of new residue record.
*/
public String addResidueRec(boolean ty, String ckey, float amt) {
Integer sz = residues.size() + 1;
String key = "RES_" + Integer.toString(sz);
ResidueRec rr = new ResidueRec(ty, key, ckey, amt);
addResidue(rr);
return key;
}
/**
* Adds a remove residue record if it does not exist. If there is already an
* existing record it will use that.
*
* @param ty type (remove=false)
* @param ckey vegetation key with this residue
* @param amt amount of residue to add.
* @return new residue key added
*/
public String addResidueRecRem(boolean ty, String ckey, float amt) {
for (ResidueRec vr : residues) {
// seems like crop key should also be compared?
if ((vr.isAddOp == false) && (vr.amount == amt)) {
return vr.weppkey;
}
}
// not found, add record
String key = addResidueRec(ty, ckey, amt);
return key;
}
/**
* Add a contour record to the list. There would only be one contour record
* per management.
*
* @param slp slope of contour in %
* @param len length of contour
* @return key of new contour record
*/
public String addContour(float slp, float len) {
String key = "CONT1";
float spacing = (float) 0.97537;
float hgt = (float) 0.03048;
float grade = (float) (slp / 100.0);
ContourRec cr = new ContourRec(key, grade, hgt, len, spacing);
contours.add(cr);
return key;
}
/**
* Update a vegetation record whether it has a harvest or not.
*
* @param key vegetation key to update
* @param state true if has a harvest, or false
*/
public void setVegHarvest(String key, boolean state) {
for (VegetationRec vr : vegs) {
if (vr.weppkey.equals(key)) {
vr.hasHarvest = state;
}
}
}
/**
* Get the user yield units string from a vegetation.
*
* @param key vegetation key to look at
* @return yield units.
*/
public String getVegYieldUnits(String key) {
String rstr = "";
for (VegetationRec vr : vegs) {
if (vr.weppkey.equals(key)) {
rstr = vr.weps_hyldunits;
}
}
return rstr;
}
/**
* Get the yield moisture from a vegetation.
*
* @param key vegetation key to look at.
* @return moisture content for yields
*/
public float getVegYieldMoisture(String key) {
float val = 0;
for (VegetationRec vr : vegs) {
if (vr.weppkey.equals(key)) {
val = vr.weps_hyldwater;
}
}
return val;
}
/**
* Get the conversion factor to convert from kg/m^2 of yield to the user
* defined units.
*
* @param key vegetation key to look at.
* @return yield conversion factor
*/
public float getVegYieldConvFactor(String key) {
float val = 0;
for (VegetationRec vr : vegs) {
if (vr.weppkey.equals(key)) {
val = vr.weps_hyconfact;
}
}
return val;
}
/**
* Get the target yield for a vegetation.
*
* @param key vegetation key to look at.
* @return target yield
*/
public float getVegTargetYield(String key) {
float val = 0;
for (VegetationRec vr : vegs) {
if (vr.weppkey.equals(key)) {
val = vr.targetYield;
}
}
return val;
}
/**
* Get the full vegetation name.
*
* @param key vegetation key to look at
* @return full name of vegetation
*/
public String getVegName(String key) {
String rstr = "";
for (VegetationRec vr : vegs) {
if (vr.weppkey.equals(key)) {
rstr = vr.name;
}
}
return rstr;
}
/**
* Get the vegetation key give the full name.
*
* @param name full name to look for
* @return key associated with the name
*/
public String getVegKey(String name) {
for (VegetationRec vr : vegs) {
if (vr.name.equals(name)) {
return vr.weppkey;
}
}
return null;
}
/**
* Get the tillage depth parameter for a specific tillage key.
*
* @param key tillage key to search for
* @return tillage depth parameter, 0 if not found
*/
public float getTillDepth(String key) {
for (TillageRec tr : tillages) {
if (tr.weppkey.equals(key)) {
return tr.tdmean;
}
}
return 0;
}
/**
* Get the row width for a specific tillage key.
*
* @param key tillage key to search for
* @return tillage ridge interval parameter, 0 if not found
*/
public float getTillRowWidth(String key) {
for (TillageRec tr : tillages) {
if (tr.weppkey.equals(key)) {
return tr.rint;
}
}
return 0;
}
/**
* Check if particular vegetation is a perennial.
*
* @param key vegetation to check
* @return true if record is a perennial
*/
public boolean isPerennial(String key) {
for (VegetationRec vr : vegs) {
if (vr.weppkey.equals(key)) {
return vr.isPerennial();
}
}
return false;
}
/**
* Get senescence day if vegetation is a perennial.
*
* @param key vegetation to check
* @return true if record is a perennial
*/
public int getSenescenceDay(String key) {
for (VegetationRec vr : vegs) {
if (vr.weppkey.equals(key)) {
return vr.sens;
}
}
return 0;
}
public JSONObject getWoodyVeg(String name, File woodyFile) throws Exception {
// if the file has not been loaded, read it now
if (woodyvegs.length() == 0) {
try {
// read in the JSON data for woody vegs
String ifile = woodyFile.getAbsolutePath();
byte[] data = Files.readAllBytes(Paths.get(ifile));
String woodydata = new String(data, Charset.defaultCharset());
JSONObject st = new JSONObject(woodydata);
woodyvegs = st.getJSONArray("woodyinicond");
} catch (Exception e) {
LOG.warning("Error: Could not get woody JSON file" + woodyFile.getName());
return null;
}
}
for (int i = 0; i < woodyvegs.length(); i++) {
JSONObject veg = woodyvegs.optJSONObject(i);
if (veg.getString("name").equals(name)) {
// found it
JSONObject wr = new JSONObject();
wr.put("cancov", veg.getDouble("cancov"));
wr.put("inrcov", veg.getDouble("inrcov"));
wr.put("rilcov", veg.getDouble("rilcov"));
wr.put("usrril", veg.getDouble("usrril"));
wr.put("usrintr", veg.getDouble("usrintr"));
return wr;
}
}
// did not find it, return null object
return null;
}
/**
* Get number of vegetation records.
*
* @return veg count
*/
public int getVegCount() {
return vegs.size();
}
/**
* Get number of residue records.
*
* @return residue count
*/
public int getResCount() {
return residues.size();
}
/**
* Get number of contour records.
*
* @return contour count
*/
public int getContCount() {
return contours.size();
}
/**
* Get number of irrigation records
*
* @return irrigation count
*/
public int getIrrCount() {
return irrigations.size();
}
/**
* Get STIR value of last process.
*
* @return STIR
*/
public float getLastSTIR() {
return lastProcess.stir;
}
/**
* Get fuel value of last process.
*
* @return fuel
*/
public float getLastFuel() {
return lastProcess.fuel;
}
/**
* Use the debug JSON to modify any vegetation records. This is done after all
* the vegetation records have been built.
*
* This would allow the default vegetation database records to be modified.
*/
public void applyTempDatabase() {
VegetationRec vegRec;
if (debugData == null) {
return;
}
if (debugData.length() == 0) {
return;
}
try {
JSONArray crps = debugData.getJSONArray("crops");
for (int i = 0; i < crps.length(); i++) {
JSONObject cropObj = crps.getJSONObject(i);
String cname = cropObj.getString("name");
vegRec = null;
if (!vegs.isEmpty()) {
for (VegetationRec vr : vegs) {
if (vr.name.equals(cname)) {
vegRec = vr;
}
}
if (vegRec != null) {
for (int j = 0; j < cropObj.names().length(); j++) {
String ckey = cropObj.names().getString(j);
switch (ckey) {
case "name":
break;
case "bb":
vegRec.bb = (float) cropObj.getDouble("bb");
break;
case "hi":
vegRec.hi = (float) cropObj.getDouble("hi");
break;
case "fact":
vegRec.fact = (float) cropObj.getDouble("fact");
break;
case "cuthgt":
vegRec.cuthgt = (float) cropObj.getDouble("cuthgt");
break;
case "rdmax":
vegRec.rdmax = (float) cropObj.getDouble("rdmax");
break;
case "rtmmax":
vegRec.rtmmax = (float) cropObj.getDouble("rtmmax");
break;
case "pltol":
vegRec.pltol = (float) cropObj.getDouble("pltol");
break;
case "pltsp":
vegRec.pltsp = (float) cropObj.getDouble("pltsp");
break;
case "tmpmax":
vegRec.tmpmax = (float) cropObj.getDouble("tmpmax");
break;
case "hmax":
vegRec.hmax = (float) cropObj.getDouble("hmax");
break;
case "rsr":
vegRec.rsr = (float) cropObj.getDouble("rsr");
break;
case "otemp":
vegRec.otemp = (float) cropObj.getDouble("otemp");
break;
case "mfocod":
vegRec.mfocod = (int) cropObj.getInt("mfocod");
break;
case "rcc":
vegRec.rcc = (float) cropObj.getDouble("rcc");
vegRec.rcc_mod = true;
break;
case "beinp":
vegRec.beinp = (float) cropObj.getDouble("beinp");
break;
case "orater":
vegRec.orater = (float) cropObj.getDouble("orater");
break;
case "diam":
vegRec.diam = (float) cropObj.getDouble("diam");
break;
case "dlai":
vegRec.dlai = (float) cropObj.getDouble("dlai");
break;
case "bbb":
vegRec.bbb = (float) cropObj.getDouble("bbb");
break;
case "cf":
vegRec.cf = (float) cropObj.getDouble("cf");
break;
case "oratea":
vegRec.oratea = (float) cropObj.getDouble("oratea");
break;
case "xmxlai":
vegRec.xmxlai = (float) cropObj.getDouble("xmxlai");
break;
case "btemp":
vegRec.btemp = (float) cropObj.getDouble("btemp");
break;
case "gddmax":
vegRec.gddmax = (float) cropObj.getDouble("gddmax");
break;
case "flivmx":
vegRec.flivmx = (float) cropObj.getDouble("flivmx");
break;
case "dropfc":
vegRec.dropfc = (float) cropObj.getDouble("dropfc");
break;
case "crit":
vegRec.crit = (float) cropObj.getDouble("crit");
break;
case "extnct":
vegRec.extnct = (float) cropObj.getDouble("extnct");
break;
case "spriod":
vegRec.spriod = (int) cropObj.getInt("spriod");
break;
case "decfct":
vegRec.decfct = (float) cropObj.getDouble("decfct");
break;
case "tmpmin":
vegRec.tmpmin = (float) cropObj.getDouble("tmpmin");
break;
case "hyldunits":
vegRec.weps_hyldunits = cropObj.getString("hyldunits");
break;
case "cbaflag":
vegRec.weps_cbaflag = (int) cropObj.getInt("cbaflag");
break;
case "hyldwater":
vegRec.weps_hyldwater = (float) cropObj.getDouble("hyldwater");
break;
case "idc":
vegRec.weps_idc = (int) cropObj.getInt("idc");
break;
case "tgtyield":
vegRec.weps_tgtyield = (float) cropObj.getDouble("tgtyield");
break;
case "hyldflag":
vegRec.weps_hyldflag = (int) cropObj.getInt("hyldflag");
break;
case "sene":
vegRec.sens = (int) cropObj.getInt("sene");
break;
}
}
}
}
}
} catch (Exception e) {
LOG.log(Level.WARNING, "Ignore: problem with debug syntax -- ignore data settings", e);
}
}
/**
* Get the detail WEPP vegetation data from a CSIP service.
*
* @param names list of vegetation names to fetch
*/
public void getVegBlobsCRLMOD(List<String> names) {
try {
ModelDataServiceCall r;
// needed for testing to use alternate data
if(cropsURL.indexOf( "purdue" ) > -1 ) {
r = new ModelDataServiceCall()
.put("limit", names.size())
.put("native_formats", "true")
.put("name", names)
.put("dtype","vegetations")
.put("ver", dataversion)
.url(cropsURL)
.withDefaultLogger()
.call();
} else {
r = new ModelDataServiceCall()
.put("limit", names.size())
.put("native_formats", "true")
.put("name", names)
.url(cropsURL)
.withDefaultLogger()
.withCache(lmodCache)
.call();
}
if (r.serviceFinished()) {
vegBlobsCRLMOD = r.getJSONObject(r.getNames().get(0));
} else {
LOG.log(Level.WARNING, "LMOD Crop Service failed.");
}
} catch (Exception ex) {
LOG.log(Level.WARNING, "Ignored Error: could not get crops CRLMOD", ex);
}
}
/**
* Get the detail WEPP operation data from a CSIP service.
*
* @param names list of operation names to fetch
*/
public void getOpBlobsCRLMOD(List<String> names) {
try {
ModelDataServiceCall r;
// needed for testing to use alternate data
if(operationsURL.indexOf( "purdue" ) > -1 ) {
r = new ModelDataServiceCall()
.put("limit", names.size())
.put("native_formats", "true")
.put("name", names)
.put("dtype","operations")
.put("ver", dataversion)
.url(operationsURL)
.withDefaultLogger()
.call();
} else {
r = new ModelDataServiceCall()
.put("limit", names.size())
.put("native_formats", "true")
.put("name", names)
.url(operationsURL)
.withDefaultLogger()
.withCache(lmodCache)
.call();
}
if (r.serviceFinished()) {
opBlobsCRLMOD = r.getJSONObject(r.getNames().get(0));
} else {
LOG.log(Level.WARNING, "LMOD operations Service failed.");
}
} catch (Exception ex) {
LOG.log(Level.WARNING, "Ignored Error: could not get operations CRLMOD", ex);
}
}
/**
* Get the WEPP residue data from a CSIP service.
*
* @param names list of residue names to fetch
*/
public void getResBlobsCRLMOD(List<String> names) {
try {
ModelDataServiceCall r;
// needed for testing to use alternate data
if(residueURL.indexOf( "purdue" ) > -1 ) {
r = new ModelDataServiceCall()
.put("limit", names.size())
.put("native_formats", "true")
.put("name", names)
.put("dtype","residues")
.put("ver", dataversion)
.url(residueURL)
.withDefaultLogger()
.call();
} else {
r = new ModelDataServiceCall()
.put("limit", names.size())
.put("native_formats", "true")
.put("name", names)
.url(residueURL)
.withDefaultLogger()
.withCache(lmodCache)
.call();
}
if (r.serviceFinished()) {
resBlobsCRLMOD = r.getJSONObject(r.getNames().get(0));
} else {
LOG.log(Level.WARNING, "LMOD Residue Service failed.");
}
} catch (Exception ex) {
LOG.log(Level.WARNING, "Ignored Error: could not get CRLMOD Residues", ex);
}
}
/**
* From the residue data read from CSIP get a specific JSON subset matching
* the passed in name.
*
* @param name residue name to extract from JSON object.
*
* @return residue data as a string
*/
public String getResBlob(String name) {
String blob = "";
try {
JSONArray mans = resBlobsCRLMOD.getJSONArray("residues");
for (int i = 0; i < mans.length(); i++) {
JSONObject theOp = mans.getJSONObject(i);
if (theOp.getString("name").equals(name)) {
blob = theOp.getString(weppResParamSetName);
//LOG.info("Got residue blob: " + name);
}
}
} catch (Exception e) {
LOG.log(Level.WARNING, "Ignored:", e);
}
return blob;
}
/**
* From the vegetation data read from CSIP get a specific JSON subset matching
* the passed in name.
*
* @param name vegetation name to extract from JSON object
*
* @return vegetation data as a string
*/
public String getVegBlob(String name) {
String blob = "";
try {
JSONArray mans = vegBlobsCRLMOD.getJSONArray("crops");
for (int i = 0; i < mans.length(); i++) {
JSONObject theOp = mans.getJSONObject(i);
if (theOp.getString("name").equals(name)) {
blob = theOp.getString(weppCropParamSetName);
//LOG.info("Got veg blob: " + name);
}
}
} catch (Exception e) {
LOG.log(Level.WARNING, "Ignored:", e);
}
//vegBlobsCRLMOD
if (blob.equals("")) {
LOG.info("Failed to get VEG: " + name + "\n");
}
return blob;
}
/**
* From the operation data read from CSIP get a specific JSON subset matching
* the passed in name.
*
* @param name operation name to extract from JSON object
*
* @return operation data as a string
*/
public String getOpBlob(String name) {
String blob = "";
String tempName;
try {
JSONArray mans = opBlobsCRLMOD.getJSONArray("operations");
//LOG.info("Looking at ops: " + String.valueOf(mans.length()) + "\n");
for (int i = 0; i < mans.length(); i++) {
JSONObject theOp = mans.getJSONObject(i);
//LOG.info("DUMP: " + theOp.getString("name"));
tempName = theOp.getString("name").trim();
if (tempName.equals(name)) {
blob = theOp.getString(weppOpParamSetName);
if (blob.startsWith("No matching")) {
blob = "";
break;
}
} else {
//LOG.info("Miss OP: >" + name + "< " + theOp.getString("name"));
}
}
} catch (Exception e) {
LOG.log(Level.WARNING, "Ignored:", e);
}
if (blob.equals("")) {
LOG.severe("Failed to get operation data: >" + name + "<\n");
}
return blob;
}
}