V1_0.java [src/java/org/rti/rivertrak] 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 org.rti.rivertrak;
import csip.Config;
import csip.api.server.Executable;
import csip.ModelDataService;
import csip.api.server.ServiceException;
import csip.annotations.Category;
import csip.annotations.Description;
import csip.annotations.Documentation;
import csip.annotations.Name;
import csip.annotations.Resource;
import static csip.annotations.ResourceType.*;
import csip.annotations.State;
import csip.annotations.VersionInfo;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.logging.Level;
import javax.ws.rs.Path;
import org.apache.commons.io.FileUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.codehaus.jettison.json.JSONObject;
import static org.rti.rivertrak.V1_0.*;
/**
* Rivertrak model.
*
* @author Olaf David, Michael Thieman
*/
@Name("Rivertrak")
@Description("Dynamic Flood Inundation, real-time floodplain mapping system.")
@Documentation("https://www.rivertrak.com/system")
@State(State.STABLE)
@VersionInfo("$Id$")
@Category("Hydrology")
@Category("Flood forecasting")
@Path("m/rivertrak/3.2")
@Resource(file = "/bin/OpTableAppLight.exe", id = RIVERTRAK, wine = true, type = EXECUTABLE)
@Resource(file = "/bin/OpTableAppLight_Mar2019.exe", id = RIVERTRAK_MAR19, wine = true, type = EXECUTABLE)
@Resource(file = "/config/RiverTrak_Dimensions.csv", id = CONFIG_DIM)
@Resource(file = "/config/RiverTrak_Units.csv", id = CONFIG_UNITS)
@Resource(file = "/config/RiverTrak_DataTypes.csv", id = CONFIG_DATATYPES)
@Resource(file = "/config/RiverTrak_Properties.csv", id = CONFIG_PROPERTIES)
@Resource(file = "OpTableAppLight.log TimeSeries/* ", type = OUTPUT)
public class V1_0 extends ModelDataService {
static VelocityEngine velocity = new VelocityEngine();
public static final String RIVERTRAK = "rivertrak";
public static final String RIVERTRAK_MAR19 = "rivertrak_Mar19";
static final String RIVERTRAK_CFG = "rivertrak.cfg";
static final String CONFIG_DIM = "dim";
static final String CONFIG_UNITS = "units";
static final String CONFIG_DATATYPES = "datatypes";
static final String CONFIG_PROPERTIES = "properties";
static final String RIVERTRAK_CONF_VM = "org/rti/rivertrak/config.vm";
static final String FORMKEY_TSINPUT = "ts_input";
static final String METAKEY_MODELNAME = "model_name";
static final String PARAMKEY_OPTABLE = "OpTable";
static final String PARAMKEY_RUNSTARTDATE = "RunStartDate";
static final String PARAMKEY_RUNENDDATE = "RunEndDate";
static final String PARAMKEY_STATESWRITEMODE = "StatesWriteMode";
// config properties
static final String DRIVE = Config.getString("win.drive", "Z:");
// payload
int enableDebug;
int debugLevel;
int statusLevel;
int warningLevel;
int refreshCount;
String opTable = "Models.optable";
private static class JSONKeys implements Iterable<String> {
JSONObject json;
JSONKeys(JSONObject json) {
this.json = json;
}
@Override
public Iterator<String> iterator() {
return json.keys();
}
}
@Override
protected void doProcess() throws Exception {
parameter().require(PARAMKEY_OPTABLE)
.require(PARAMKEY_RUNSTARTDATE)
.require(PARAMKEY_RUNENDDATE)
.require(PARAMKEY_STATESWRITEMODE);
// formdata().require(FORMKEY_TSINPUT);
// config settings with defaults
enableDebug = parameter().getInt("EnableDebug", 0);
debugLevel = parameter().getInt("DebugLevel", 1);
statusLevel = parameter().getInt("StatusLevel", 1);
warningLevel = parameter().getInt("WarningLevel", 1);
refreshCount = parameter().getInt("RefreshCount", 10);
workspace().getFile("States").mkdirs();
if (!workspace().getFile("TimeSeries").exists()) {
throw new ServiceException("No Time series data.");
}
File modelFolder = workspace().getFile("Models");
if (!modelFolder.exists()) {
modelFolder.mkdirs();
}
try {
// assume an embedded JSONObject for optable
JSONObject j = parameter().getJSON(PARAMKEY_OPTABLE);
for (String modelName : new JSONKeys(j)) {
// append to opTable
FileUtils.write(new File(modelFolder, opTable), modelName + "\n", true);
try (PrintWriter w = new PrintWriter(new File(modelFolder, modelName))) {
JSONObject modelDefs = j.getJSONObject(modelName);
for (String section : new JSONKeys(modelDefs)) {
w.println("#" + section);
JSONObject kv = modelDefs.getJSONObject(section);
for (String key : new JSONKeys(kv)) {
w.println(key + "=" + kv.get(key).toString());
}
}
}
}
} catch (ServiceException E) {
// carry on
opTable = parameter().getString(PARAMKEY_OPTABLE);
}
File opTableFile = new File(modelFolder, opTable);
if (!opTableFile.exists()) {
throw new ServiceException("OpTable file not found: " + opTable);
}
String modelName = RIVERTRAK;
if (metainfo().hasName(METAKEY_MODELNAME)) {
modelName = metainfo().getString(METAKEY_MODELNAME);
}
Executable rt = resources().getExe(modelName);
rt.addArguments("-Config", createConfig(),
"-RunStartDate", parameter().getString(PARAMKEY_RUNSTARTDATE),
"-RunEndDate", parameter().getString(PARAMKEY_RUNENDDATE),
"-StatesWriteMode", parameter().getString(PARAMKEY_STATESWRITEMODE, "WRITE")
);
int ret = rt.exec();
if (ret != 0) {
throw new ServiceException("Error running Rivertrak: " + ret);
}
}
/// public properties for Velocity access
public String getWorkspace() {
return toWin(workspace().getDir());
}
public String getDrive() {
return DRIVE;
}
public int getEnableDebug() {
return enableDebug;
}
public int getDebugLevel() {
return debugLevel;
}
public String getOpTable() {
return opTable;
}
public int getStatusLevel() {
return statusLevel;
}
public int getWarningLevel() {
return warningLevel;
}
public int getRefreshCount() {
return refreshCount;
}
public String getConfigDimensions() throws ServiceException {
return toWin(resources().getFile(CONFIG_DIM));
}
public String getConfigUnits() throws ServiceException {
return toWin(resources().getFile(CONFIG_UNITS));
}
public String getConfigDatatypes() throws ServiceException {
return toWin(resources().getFile(CONFIG_DATATYPES));
}
public String getConfigProperties() throws ServiceException {
return toWin(resources().getFile(CONFIG_PROPERTIES));
}
private static String toWin(File f) {
return f.toString().replace('/', '\\');
}
private String createConfig() throws IOException {
VelocityContext context = new VelocityContext();
context.put("service", this);
FileWriter w = new FileWriter(workspace().getFile(RIVERTRAK_CFG));
velocity.getTemplate(RIVERTRAK_CONF_VM, "utf-8").merge(context, w);
w.close();
if (LOG.isLoggable(Level.INFO)) {
LOG.info("Created: " + RIVERTRAK_CFG);
LOG.info("\n" + FileUtils.readFileToString(workspace().getFile(RIVERTRAK_CFG)));
}
return RIVERTRAK_CFG;
}
public static void onContextInit() {
velocity.setProperty("file.resource.loader.class",
ClasspathResourceLoader.class.getName());
velocity.init();
}
}