de.bund.bfr.knime.fsklab.deprecatednodes/src-1_7_2/de/bund/bfr/knime/fsklab/CombinedFskPortObject.java
/*
***************************************************************************************************
* Copyright (c) 2015 Federal Institute for Risk Assessment (BfR), Germany
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If
* not, see <http://www.gnu.org/licenses/>.
*
* Contributors: Department Biological Safety - BfR
*************************************************************************************************
*/
package de.bund.bfr.knime.fsklab;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.border.Border;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.emfjson.jackson.module.EMFModule;
import org.knime.core.node.CanceledExecutionException;
import org.knime.core.node.ExecutionMonitor;
import org.knime.core.node.InvalidSettingsException;
import org.knime.core.node.NodeLogger;
import org.knime.core.node.port.PortObjectSpec;
import org.knime.core.node.port.PortObjectZipInputStream;
import org.knime.core.node.port.PortObjectZipOutputStream;
import org.knime.core.node.port.PortType;
import org.knime.core.node.port.PortTypeRegistry;
import org.knime.core.util.FileUtil;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import de.bund.bfr.knime.fsklab.nodes.common.ui.FLabel;
import de.bund.bfr.knime.fsklab.nodes.common.ui.FPanel;
import de.bund.bfr.knime.fsklab.nodes.common.ui.ScriptPanel;
import de.bund.bfr.knime.fsklab.nodes.common.ui.UIUtils;
import de.bund.bfr.knime.fsklab.rakip.RakipModule;
import de.bund.bfr.knime.fsklab.rakip.RakipUtil;
import de.bund.bfr.metadata.swagger.ConsumptionModel;
import de.bund.bfr.metadata.swagger.DataModel;
import de.bund.bfr.metadata.swagger.DoseResponseModel;
import de.bund.bfr.metadata.swagger.ExposureModel;
import de.bund.bfr.metadata.swagger.GenericModel;
import de.bund.bfr.metadata.swagger.HealthModel;
import de.bund.bfr.metadata.swagger.Model;
import de.bund.bfr.metadata.swagger.OtherModel;
import de.bund.bfr.metadata.swagger.Parameter;
import de.bund.bfr.metadata.swagger.PredictiveModel;
import de.bund.bfr.metadata.swagger.ProcessModel;
import de.bund.bfr.metadata.swagger.QraModel;
import de.bund.bfr.metadata.swagger.RiskModel;
import de.bund.bfr.metadata.swagger.ToxicologicalModel;
import metadata.SwaggerUtil;
/**
* A port object for an combined FSK model port providing two FSK Models.
*
* @author Ahmad Swaid, BfR, Berlin.
*/
public class CombinedFskPortObject extends FskPortObject {
private static NodeLogger LOGGER = NodeLogger.getLogger(CombinedFskPortObject.class);
final FskPortObject firstFskPortObject;
public FskPortObject getFirstFskPortObject() {
return firstFskPortObject;
}
public FskPortObject getSecondFskPortObject() {
return secondFskPortObject;
}
final FskPortObject secondFskPortObject;
List<JoinRelation> joinerRelation;
public List<JoinRelation> getJoinerRelation() {
return joinerRelation;
}
public void setJoinerRelation(List<JoinRelation> joinerRelation) {
this.joinerRelation = joinerRelation;
}
public static final PortType TYPE = PortTypeRegistry.getInstance().getPortType(FskPortObject.class);
public static final PortType TYPE_OPTIONAL = PortTypeRegistry.getInstance().getPortType(FskPortObject.class, true);
public static final String[] RESOURCE_EXTENSIONS = new String[] { "txt", "RData", "csv" };
private static int numOfInstances = 0;
private static Random ran = new Random();
public CombinedFskPortObject(final String model, final String param, final String viz, final Model modelMetadata,
final Path workspace, final List<String> packages, final String workingDirectory, final String plot,
final FskPortObject firstFskPortObject, final FskPortObject secondFskPortObject) throws IOException {
super(model, viz, modelMetadata, workspace, packages, workingDirectory, plot, "", "");
this.firstFskPortObject = firstFskPortObject;
this.secondFskPortObject = secondFskPortObject;
objectNum = numOfInstances;
numOfInstances += 1;
}
public CombinedFskPortObject(final String workingDirectory, final List<String> packages,
final FskPortObject firstFskPortObject, final FskPortObject secondFskPortObject) throws IOException {
super(workingDirectory, "", packages);
this.firstFskPortObject = firstFskPortObject;
this.secondFskPortObject = secondFskPortObject;
objectNum = numOfInstances;
numOfInstances += 1;
}
public CombinedFskPortObject(final String model, final String viz, final Model modelMetadata,
final String workingDirectory, final List<String> packages, final FskPortObject firstFskPortObject,
final FskPortObject secondFskPortObject) throws IOException {
super(workingDirectory, "", packages);
this.model = model;
this.viz = viz;
this.firstFskPortObject = firstFskPortObject;
this.secondFskPortObject = secondFskPortObject;
this.modelMetadata = modelMetadata;
objectNum = numOfInstances;
numOfInstances += 1;
}
@Override
public FskPortObjectSpec getSpec() {
return FskPortObjectSpec.INSTANCE;
}
@Override
public String getSummary() {
return "Combined FSK Object";
}
/**
* Serializer used to save this port object.
*
* @return a {@link CombinedFskPortObject}.
*/
public static final class Serializer extends PortObjectSerializer<CombinedFskPortObject> {
private static final String COMBINED = "COMBINED";
private static final String MODEL = "model.R";
private static final String VIZ = "viz.R";
private static final String META_DATA = "metaData";
private static final String CFG_GENERAL_INFORMATION = "generalInformation";
private static final String JOINED_GENERAL_INFORMATION = "joinedGeneralInformation";
private static final String JOINED_SIMULATION = "joinedsimulation";
private static final String JOINED_WORKSPACE = "joinedworkspace";
private static final String JOINED_VIZ = "joinedviz.R";
private static final String WORKSPACE = "workspace";
private static final String SIMULATION = "simulation";
private static final String SIMULATION_INDEX = "xSimulationIndex";
private static final String WORKING_DIRECTORY = "workingDirectory";
private static final String PLOT = "plot";
private static final String README = "readme";
private static final String SPREADSHEET = "spreadsheet";
private static final String JOINER_RELATION = "joinrelation";
private static final String LIBRARY_LIST = "library.list";
private static final String BREAK = "break";
/** Object mapper for 1.0.2 metadata. */
private static final ObjectMapper MAPPER102;
/** Object mapper for 1.0.3 metadata. */
private static final ObjectMapper MAPPER103;
/** Object mapper for 1.0.4 metadata. */
private static final ObjectMapper MAPPER104;
public static Map<String, Class<? extends Model>> modelClasses;
static {
try {
// ObjectMapper defaults to use a JsonFactory that automatically closes
// the stream. When further entries are added to the archive the stream
// is closed and fails. The AUTO_CLOSE_TARGET needs to be disabled.
JsonFactory jsonFactory = new JsonFactory();
jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
jsonFactory.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false);
MAPPER102 = new ObjectMapper(jsonFactory);
MAPPER102.registerModule(new RakipModule());
MAPPER103 = new ObjectMapper(jsonFactory);
MAPPER103.registerModule(new EMFModule());
MAPPER104 = new ObjectMapper(jsonFactory);
MAPPER104.registerModule(new ThreeTenModule());
modelClasses = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
modelClasses.put("genericModel", GenericModel.class);
modelClasses.put("dataModel", DataModel.class);
modelClasses.put("predictiveModel", PredictiveModel.class);
modelClasses.put("otherModel", OtherModel.class);
modelClasses.put("exposureModel", ExposureModel.class);
modelClasses.put("toxicologicalModel", ToxicologicalModel.class);
modelClasses.put("doseResponseModel", DoseResponseModel.class);
modelClasses.put("processModel", ProcessModel.class);
modelClasses.put("consumptionModel", ConsumptionModel.class);
modelClasses.put("healthModel", HealthModel.class);
modelClasses.put("riskModel", RiskModel.class);
modelClasses.put("qraModel", QraModel.class);
} catch (Throwable throwable) {
LOGGER.error("Failure during static initialization", throwable);
throw throwable;
}
}
@Override
public void savePortObject(final CombinedFskPortObject portObject, final PortObjectZipOutputStream out,
final ExecutionMonitor exec) throws IOException, CanceledExecutionException {
saveFSKPortObject(portObject, out, exec);
out.close();
}
public void saveFSKPortObject(FskPortObject portObject, final PortObjectZipOutputStream out,
final ExecutionMonitor exec) throws IOException {
// First FSK Object
// model entry (file with model script)
if (portObject instanceof CombinedFskPortObject) {
// write tag value to check the type of the fsk port object when read it back
int level = ran.nextInt();
out.putNextEntry(new ZipEntry(COMBINED + level));
IOUtils.write(COMBINED + level, out, "UTF-8");
out.closeEntry();
CombinedFskPortObject joinedPortObject = (CombinedFskPortObject) portObject;
if (joinedPortObject.joinerRelation == null) {
joinedPortObject.joinerRelation = new ArrayList<>();
}
writeEObjectList(JOINER_RELATION + level, joinedPortObject.joinerRelation, out);
// workspace entry
if (portObject.workspace != null) {
out.putNextEntry(new ZipEntry(JOINED_WORKSPACE + level));
Files.copy(portObject.workspace, out);
out.closeEntry();
}
// Save simulations
if (!portObject.simulations.isEmpty()) {
out.putNextEntry(new ZipEntry(JOINED_SIMULATION + level));
try {
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(portObject.simulations);
} catch (IOException exception) {
exception.printStackTrace();
}
out.closeEntry();
}
// Write Joined Object Meta data: model type and metadata
out.putNextEntry(new ZipEntry("modelType" + level));
IOUtils.write(portObject.modelMetadata.getModelType(), out, "UTF-8");
out.closeEntry();
out.putNextEntry(new ZipEntry("swagger" + level));
MAPPER104.writeValue(out, portObject.modelMetadata);
out.closeEntry();
// joined viz entry (file with visualization script)
out.putNextEntry(new ZipEntry(JOINED_VIZ + level));
IOUtils.write(portObject.viz, out, "UTF-8");
out.closeEntry();
saveFSKPortObject(joinedPortObject.getFirstFskPortObject(), out, exec);
saveFSKPortObject(joinedPortObject.getSecondFskPortObject(), out, exec);
} else {
// model entry (file with model script)
int level = ran.nextInt();
out.putNextEntry(new ZipEntry(MODEL + level));
IOUtils.write(portObject.model, out, "UTF-8");
out.closeEntry();
// viz entry (file with visualization script)
out.putNextEntry(new ZipEntry(VIZ + level));
IOUtils.write(portObject.viz, out, "UTF-8");
out.closeEntry();
// model type and metadata
out.putNextEntry(new ZipEntry("modelType" + level));
IOUtils.write(portObject.modelMetadata.getModelType(), out, "UTF-8");
out.closeEntry();
out.putNextEntry(new ZipEntry("swagger" + level));
MAPPER104.writeValue(out, portObject.modelMetadata);
out.closeEntry();
// workspace entry
if (portObject.workspace != null) {
out.putNextEntry(new ZipEntry(WORKSPACE + level));
Files.copy(portObject.workspace, out);
out.closeEntry();
}
// libraries
if (!portObject.packages.isEmpty()) {
out.putNextEntry(new ZipEntry(LIBRARY_LIST + level));
IOUtils.writeLines(portObject.packages, "\n", out, StandardCharsets.UTF_8);
out.closeEntry();
}
// Save working directory
if (StringUtils.isNotEmpty(portObject.getWorkingDirectory())) {
out.putNextEntry(new ZipEntry(WORKING_DIRECTORY + level));
IOUtils.write(portObject.getWorkingDirectory(), out, "UTF-8");
out.closeEntry();
}
// Save plot
if (StringUtils.isNotEmpty(portObject.getPlot())) {
out.putNextEntry(new ZipEntry(PLOT + level));
IOUtils.write(portObject.getPlot(), out, "UTF-8");
out.closeEntry();
}
// Save README
if (StringUtils.isNotEmpty(portObject.getReadme())) {
out.putNextEntry(new ZipEntry(README + level));
IOUtils.write(portObject.getReadme(), out, "UTF-8");
out.closeEntry();
}
// Save spreadsheet
if (StringUtils.isNotEmpty(portObject.getSpreadsheet())) {
out.putNextEntry(new ZipEntry(SPREADSHEET + level));
IOUtils.write(portObject.getSpreadsheet(), out, "UTF-8");
out.closeEntry();
}
// Save simulations
if (!portObject.simulations.isEmpty()) {
out.putNextEntry(new ZipEntry(SIMULATION + level));
try {
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(portObject.simulations);
} catch (IOException exception) {
exception.printStackTrace();
}
out.closeEntry();
}
// Save selected simulation index
out.putNextEntry(new ZipEntry(SIMULATION_INDEX + level));
try {
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(portObject.selectedSimulationIndex);
out.closeEntry();
out.putNextEntry(new ZipEntry(BREAK + level));
IOUtils.write("", out, "UTF-8");
out.closeEntry();
} catch (IOException exception) {
exception.printStackTrace();
}
}
}
@SuppressWarnings("unchecked")
public FskPortObject loadFSKPortObject(PortObjectZipInputStream in, PortObjectSpec spec, ExecutionMonitor exec)
throws IOException, CanceledExecutionException {
String modelScript = "";
String visualizationScript = "";
Path workspacePath = FileUtil.createTempFile("workspace", ".r").toPath();
List<String> packages = new ArrayList<>();
Model modelMetadata = null;
String workingDirectory = ""; // Empty string if not set
String plot = ""; // Empty string if not set
String readme = ""; // Empty string if not set
String spreadsheet = ""; // Empty string if not set
List<FskSimulation> simulations = new ArrayList<>();
int selectedSimulationIndex = 0;
List<JoinRelation> joinerRelation = new ArrayList<>();
ZipEntry entry;
while ((entry = in.getNextEntry()) != null) {
String entryName = entry.getName();
// check if the entry contains combined FSK object
if (entryName.startsWith(COMBINED)) {
String level = entryName.substring(COMBINED.length(), entryName.length());
// read relations
// jump one step since we know it has relation in the next part
entry = in.getNextEntry();
entryName = entry.getName();
if (entryName.startsWith(JOINER_RELATION + level)) {
try {
joinerRelation = ((List<JoinRelation>) readEObjectList(in, JoinRelation.class));
} catch (InvalidSettingsException e) {
e.printStackTrace();
}
}
entry = in.getNextEntry();
entryName = entry.getName();
if (entryName.startsWith(JOINED_WORKSPACE + level)) {
Files.copy(in, workspacePath, StandardCopyOption.REPLACE_EXISTING);
entry = in.getNextEntry();
entryName = entry.getName();
if (entryName.startsWith(JOINED_SIMULATION + level)) {
try {
ObjectInputStream ois = new ObjectInputStream(in);
simulations = ((List<FskSimulation>) ois.readObject());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} else if (entryName.startsWith(JOINED_SIMULATION + level)) {
try {
ObjectInputStream ois = new ObjectInputStream(in);
simulations = ((List<FskSimulation>) ois.readObject());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
entry = in.getNextEntry();
entryName = entry.getName();
if (entryName.equals("modelType"+ level)) {
// deserialize new models
String modelClass = IOUtils.toString(in, "UTF-8");
in.getNextEntry();
modelMetadata = MAPPER104.readValue(in, modelClasses.get(modelClass));
}
else if (entryName.startsWith(JOINED_GENERAL_INFORMATION + level)) {
metadata.GeneralInformation deprecatedInformation = readEObject(in,
metadata.GeneralInformation.class);
in.getNextEntry();
metadata.Scope deprecatedScope = readEObject(in, metadata.Scope.class);
in.getNextEntry();
metadata.DataBackground deprecatedBackground = readEObject(in, metadata.DataBackground.class);
in.getNextEntry();
metadata.ModelMath deprecatedMath = readEObject(in, metadata.ModelMath.class);
// Read 1.0.3 metadata
GenericModel gm = new GenericModel();
gm.setModelType("genericModel");
gm.setGeneralInformation(SwaggerUtil.convert(deprecatedInformation));
gm.setScope(SwaggerUtil.convert(deprecatedScope));
gm.setDataBackground(SwaggerUtil.convert(deprecatedBackground));
gm.setModelMath(SwaggerUtil.convert(deprecatedMath));
modelMetadata = gm;
}
entry = in.getNextEntry();
entryName = entry.getName();
if (entryName.startsWith(JOINED_VIZ + level)) {
visualizationScript = IOUtils.toString(in, "UTF-8");
}
// read first FSKObject
FskPortObject firstFSKObject = loadFSKPortObject(in, spec, exec);
// read second FSKObject
FskPortObject secondFSKObject = loadFSKPortObject(in, spec, exec);
// build combined object out of the previous objects
final CombinedFskPortObject portObj = new CombinedFskPortObject(modelScript, visualizationScript,
modelMetadata, FileUtil.createTempDir("combined").getAbsolutePath(), new ArrayList<>(),
firstFSKObject, secondFSKObject);
portObj.workspace = workspacePath;
if (!joinerRelation.isEmpty()) {
portObj.setJoinerRelation(joinerRelation);
}
if (!simulations.isEmpty()) {
portObj.simulations.addAll(simulations);
}
return portObj;
} else {
if (entryName.startsWith(MODEL)) {
modelScript = IOUtils.toString(in, "UTF-8");
} else if (entryName.startsWith(VIZ)) {
visualizationScript = IOUtils.toString(in, "UTF-8");
}
if (entryName.startsWith("modelType")) {
// deserialize new models
String modelClass = IOUtils.toString(in, "UTF-8");
in.getNextEntry();
modelMetadata = MAPPER104.readValue(in, modelClasses.get(modelClass));
}
// If found old deprecated metadata, restore it and convert it to new EMF
// metadata
else if (entryName.startsWith(META_DATA)) {
final String metaDataAsString = IOUtils.toString(in, "UTF-8");
ObjectMapper mapper = new ObjectMapper().registerModule(new RakipModule());
de.bund.bfr.knime.fsklab.rakip.GenericModel deprecatedModel = mapper.readValue(metaDataAsString,
de.bund.bfr.knime.fsklab.rakip.GenericModel.class);
GenericModel gm = new GenericModel();
gm.setModelType("genericModel");
gm.setGeneralInformation(RakipUtil.convert(deprecatedModel.generalInformation));
gm.setScope(RakipUtil.convert(deprecatedModel.scope));
gm.setDataBackground(RakipUtil.convert(deprecatedModel.dataBackground));
gm.setModelMath(RakipUtil.convert(deprecatedModel.modelMath));
}
else if (entryName.startsWith(CFG_GENERAL_INFORMATION)) {
metadata.GeneralInformation deprecatedInformation = readEObject(in,
metadata.GeneralInformation.class);
in.getNextEntry();
metadata.Scope deprecatedScope = readEObject(in, metadata.Scope.class);
in.getNextEntry();
metadata.DataBackground deprecatedBackground = readEObject(in, metadata.DataBackground.class);
in.getNextEntry();
metadata.ModelMath deprecatedMath = readEObject(in, metadata.ModelMath.class);
in.getNextEntry();
GenericModel gm = new GenericModel();
gm.setModelType("genericModel");
gm.setGeneralInformation(SwaggerUtil.convert(deprecatedInformation));
gm.setScope(SwaggerUtil.convert(deprecatedScope));
gm.setDataBackground(SwaggerUtil.convert(deprecatedBackground));
gm.setModelMath(SwaggerUtil.convert(deprecatedMath));
modelMetadata = gm;
} else if (entryName.startsWith(WORKSPACE)) {
Files.copy(in, workspacePath, StandardCopyOption.REPLACE_EXISTING);
} else if (entryName.startsWith(LIBRARY_LIST)) {
packages = IOUtils.readLines(in, "UTF-8");
} else if (entryName.startsWith(WORKING_DIRECTORY)) {
workingDirectory = IOUtils.toString(in, "UTF-8");
} else if (entryName.startsWith(PLOT)) {
plot = IOUtils.toString(in, "UTF-8");
} else if (entryName.startsWith(README)) {
readme = IOUtils.toString(in, "UTF-8");
} else if (entryName.startsWith(SPREADSHEET)) {
spreadsheet = IOUtils.toString(in, "UTF-8");
} else if (entryName.startsWith(SIMULATION)) {
try {
ObjectInputStream ois = new ObjectInputStream(in);
simulations = ((List<FskSimulation>) ois.readObject());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
else if (entryName.startsWith(SIMULATION_INDEX)) {
ObjectInputStream ois = new ObjectInputStream(in);
try {
selectedSimulationIndex = ((Integer) ois.readObject()).intValue();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else if (entryName.startsWith(BREAK)) {
break;
}
}
}
final FskPortObject portObj = new FskPortObject(modelScript, visualizationScript, modelMetadata,
workspacePath, packages, workingDirectory, plot, readme, spreadsheet);
if (!simulations.isEmpty()) {
portObj.simulations.addAll(simulations);
}
portObj.selectedSimulationIndex = selectedSimulationIndex;
return portObj;
}
@Override
public CombinedFskPortObject loadPortObject(PortObjectZipInputStream in, PortObjectSpec spec,
ExecutionMonitor exec) throws IOException, CanceledExecutionException {
CombinedFskPortObject portObj = (CombinedFskPortObject) loadFSKPortObject(in, spec, exec);
in.close();
return portObj;
}
private <T> T readEObject(PortObjectZipInputStream zipStream, Class<T> valueType) throws IOException {
String jsonStr = IOUtils.toString(zipStream, "UTF-8");
ObjectMapper mapper = EMFModule.setupDefaultMapper();
return mapper.readValue(jsonStr, valueType);
}
private static <T> T getEObjectFromJson(String jsonStr, Class<T> valueType)
throws InvalidSettingsException, JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = EMFModule.setupDefaultMapper();
return mapper.readValue(jsonStr, valueType);
}
@SuppressWarnings("unchecked")
private <T> List<T> readEObjectList(PortObjectZipInputStream zipStream, Class<T> valueType)
throws IOException, InvalidSettingsException {
List<JoinRelation> joinerRelation = new ArrayList<>();
String jsonStr = IOUtils.toString(zipStream, "UTF-8");
if (jsonStr != null) {
JsonReader jsonReader = Json.createReader(new StringReader(jsonStr));
JsonArray relationJsonArray = jsonReader.readArray();
jsonReader.close();
for (JsonValue element : relationJsonArray) {
JsonObject sourceTargetRelation = ((JsonObject) element);
JoinRelation jR = new JoinRelation();
if (sourceTargetRelation.containsKey("command")) {
jR.setCommand(sourceTargetRelation.getString("command"));
}
if (sourceTargetRelation.containsKey("sourceParam")) {
jR.setSourceParam(getEObjectFromJson(sourceTargetRelation.get("sourceParam").toString(),
Parameter.class));
}
if (sourceTargetRelation.containsKey("targetParam")) {
jR.setTargetParam(getEObjectFromJson(sourceTargetRelation.get("targetParam").toString(),
Parameter.class));
}
joinerRelation.add(jR);
}
}
return (List<T>) joinerRelation;
}
private static <T extends List> void writeEObjectList(String entryName, T value, PortObjectZipOutputStream out)
throws IOException {
out.putNextEntry(new ZipEntry(entryName));
String jsonStr = "[";
for (Object o : value) {
JoinRelation jR = ((JoinRelation) o);
String repre = jR.getJsonReresentaion();
jsonStr += repre + ",";
}
if (jsonStr.length() > 1) {
jsonStr = jsonStr.substring(0, jsonStr.length() - 1) + "]";
} else {
jsonStr += "]";
}
IOUtils.write(jsonStr, out, "UTF-8");
out.closeEntry();
}
}
class CommandScript {
String id;
String script;
public CommandScript(String id, String script) {
this.id = id;
this.script = script;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getScript() {
return script;
}
public void setScript(String script) {
this.script = script;
}
public String toString() {
return id;
}
}
public void buildScriptNodes(DefaultMutableTreeNode top, FskPortObject currentPortObject, boolean modelScriptFlag) {
if (currentPortObject instanceof CombinedFskPortObject) {
DefaultMutableTreeNode anotherJoinedModel = new DefaultMutableTreeNode("joined");
buildScriptNodes(anotherJoinedModel, ((CombinedFskPortObject) currentPortObject).getFirstFskPortObject(),
modelScriptFlag);
if (modelScriptFlag) {
StringBuilder script = new StringBuilder();
String language = "";
if (((CombinedFskPortObject) currentPortObject).getJoinerRelation() != null
&& ((CombinedFskPortObject) currentPortObject).getJoinerRelation().size() > 0) {
((CombinedFskPortObject) currentPortObject).getJoinerRelation().stream().forEach(connection -> {
script.append(connection.getTargetParam().getId() + " <- " + connection.getCommand() + "\n");
});
language = ((CombinedFskPortObject) currentPortObject).getJoinerRelation().get(0)
.getLanguage_written_in();
}
anotherJoinedModel.add(new DefaultMutableTreeNode(new CommandScript(
"Joining Model Script" + (language != null ? "( " + language + " )" : ""), script.toString())));
}
buildScriptNodes(anotherJoinedModel, ((CombinedFskPortObject) currentPortObject).getSecondFskPortObject(),
modelScriptFlag);
top.add(anotherJoinedModel);
} else {
DefaultMutableTreeNode childModel = new DefaultMutableTreeNode(currentPortObject);
top.add(childModel);
}
}
/** {Override} */
@Override
public JComponent[] getViews() {
JPanel modelScriptPanel = new ScriptPanel("Model script", false);
DefaultMutableTreeNode top = new DefaultMutableTreeNode("Model Scripts");
buildScriptNodes(top, this, true);
JTree modelTree = new JTree(top);
modelTree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) modelTree.getLastSelectedPathComponent();
if (node == null)
return;
Object script = node.getUserObject();
if (node.isLeaf()) {
if (script instanceof FskPortObject) {
FskPortObject selectedFSK = (FskPortObject) script;
((ScriptPanel) modelScriptPanel).setText(selectedFSK.model);
} else {
((ScriptPanel) modelScriptPanel).setText(((CommandScript) script).getScript());
}
}
}
});
modelTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
modelTree.setVisible(true);
((ScriptPanel) modelScriptPanel).setScriptTree(modelTree);
JPanel vizScriptPanel = new ScriptPanel("Visualization script", false);
DefaultMutableTreeNode visTop = new DefaultMutableTreeNode("Visualization Scripts");
buildScriptNodes(visTop, this, false);
JTree visTree = new JTree(visTop);
visTree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) visTree.getLastSelectedPathComponent();
if (node == null)
return;
Object script = node.getUserObject();
if (node.isLeaf()) {
FskPortObject selectedFSK = (FskPortObject) script;
((ScriptPanel) vizScriptPanel).setText(selectedFSK.viz);
}
}
});
visTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
visTree.setVisible(true);
((ScriptPanel) vizScriptPanel).setScriptTree(visTree);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String jsonString = gson.toJson(modelMetadata);
final JScrollPane metaDataPane = new JScrollPane(new JTextArea(jsonString));
metaDataPane.setName("Meta data");
final JPanel librariesPanel = UIUtils.createLibrariesPanel(packages);
JPanel simulationsPanel = new SimulationsPanel();
// Readme
JTextArea readmeArea = new JTextArea("");
readmeArea.setEnabled(false);
JPanel readmePanel = new ScriptPanel("README", false);
DefaultMutableTreeNode readmetop = new DefaultMutableTreeNode("Readme");
buildScriptNodes(readmetop, this, false);
JTree readmeTree = new JTree(readmetop);
readmeTree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) readmeTree.getLastSelectedPathComponent();
if (node == null)
return;
Object script = node.getUserObject();
if (node.isLeaf()) {
FskPortObject selectedFSK = (FskPortObject) script;
((ScriptPanel) readmePanel).setText(selectedFSK.getReadme());
}
}
});
readmeTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
readmeTree.setVisible(true);
((ScriptPanel) readmePanel).setScriptTree(readmeTree);
return new JComponent[] { modelScriptPanel, vizScriptPanel, metaDataPane, librariesPanel, simulationsPanel,
readmePanel };
}
private class SimulationsPanel extends FPanel {
private static final long serialVersionUID = -4887698302872695689L;
private final FormPanel formPanel;
private Map<Object, Icon> icons = new HashMap<Object, Icon>();
private final String SELETCTED_SIMULATION_STR = "selected";
public SimulationsPanel() {
// Panel to show parameters (show initially the simulation 0)
formPanel = new FormPanel(simulations.get(selectedSimulationIndex).getParameters());
icons.put(selectedSimulationIndex, UIUtils.getResourceImageIcon("selectedsimulation.png"));
createUI();
}
private void createUI() {
FPanel simulationPanel = new FPanel();
simulationPanel.setLayout(new BorderLayout());
JScrollPane parametersPane = new JScrollPane(
UIUtils.createTitledPanel(UIUtils.createNorthPanel(formPanel), "Parameters"));
parametersPane.setBorder(null);
simulationPanel.add(parametersPane, BorderLayout.WEST);
// Panel to show preview of generated script out of parameters
String previewScript = buildParameterScript(simulations.get(selectedSimulationIndex));
ScriptPanel scriptPanel = new ScriptPanel("Preview", previewScript, false, true);
simulationPanel.add(UIUtils.createTitledPanel(scriptPanel, "Preview script"), BorderLayout.CENTER);
// Panel to select simulation
FskSimulation[] simulationsArray = simulations.toArray(new FskSimulation[simulations.size()]);
JComboBox<FskSimulation> simulationList = new JComboBox<FskSimulation>(simulationsArray);
simulationList.setRenderer(new IconListRenderer(icons, simulationsArray));
simulationList.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Get selected simulation
if (simulationList.getSelectedIndex() != -1) {
FskSimulation selectedSimulation = (FskSimulation) simulationList.getSelectedItem();
// Update parameters
formPanel.setValues(selectedSimulation.getParameters());
// Update previewPanel
String previewScript = buildParameterScript(selectedSimulation);
scriptPanel.setText(previewScript);
}
}
});
simulationList.setSelectedIndex(selectedSimulationIndex);
JPanel selectionPanel = new JPanel();
selectionPanel.setBackground(Color.WHITE);
selectionPanel.add(simulationList);
// selectionPanel.add(new
// JLabel(simulationsArray[selectedSimulationIndex].getName()+" is the selected
// simulation to be used by the FSK Runner to run the model"));
JPanel simulationSelection = UIUtils
.createCenterPanel(UIUtils.createHorizontalPanel(new JLabel("Simulation:"), selectionPanel));
// Build simulations panel
setLayout(new BorderLayout());
setName("Simulations");
add(simulationSelection, BorderLayout.NORTH);
add(simulationPanel, BorderLayout.CENTER);
}
class IconListRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 1L;
private Map<Object, Icon> icons = null;
private FskSimulation[] simulationsArray;
private String selectedSimulationName;
public IconListRenderer(Map<Object, Icon> icons, FskSimulation[] simulationsArray) {
this.icons = icons;
this.simulationsArray = simulationsArray;
this.selectedSimulationName = simulationsArray[selectedSimulationIndex].getName();
}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected,
cellHasFocus);
// Get icon to use for the list item value
Icon icon = icons.get(value);
if (index == selectedSimulationIndex
|| (index == -1 && value.toString().trim().equals(selectedSimulationName.trim()))) {
icon = icons.get(selectedSimulationIndex);
}
// Set icon to display for value
label.setIcon(icon);
return label;
}
}
class FormPanel extends FPanel {
private static final long serialVersionUID = 4324891441984883445L;
private final JTextField[] fields;
FormPanel(LinkedHashMap<String, String> parameters) {
fields = new JTextField[parameters.size()];
for (int i = 0; i < parameters.size(); i++) {
fields[i] = new JTextField();
}
createUI(parameters);
}
private void createUI(LinkedHashMap<String, String> parameters) {
// Create labels
List<FLabel> labels = parameters.keySet().stream().map(FLabel::new).collect(Collectors.toList());
// Create field panels
List<JPanel> fieldPanels = new ArrayList<>(parameters.size());
int i = 0;
for (String value : parameters.values()) {
JPanel panel = createFieldPanel(fields[i], value);
fieldPanels.add(panel);
i++;
}
int n = labels.size();
FPanel leftPanel = new FPanel();
leftPanel.setLayout(new GridLayout(n, 1, 5, 5));
labels.forEach(leftPanel::add);
FPanel rightPanel = new FPanel();
rightPanel.setLayout(new GridLayout(n, 1, 5, 5));
fieldPanels.forEach(rightPanel::add);
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
add(leftPanel, BorderLayout.WEST);
add(rightPanel, BorderLayout.CENTER);
}
public void setValues(LinkedHashMap<String, String> parameters) {
int i = 0;
for (String value : parameters.values()) {
fields[i].setText(value);
i++;
}
}
private JPanel createFieldPanel(JTextField field, String value) {
field.setColumns(30);
field.setBackground(UIUtils.WHITE);
field.setText(value);
field.setHorizontalAlignment(JTextField.RIGHT);
field.setEditable(false);
field.setBorder(null);
JButton copyButton = UIUtils.createCopyButton();
copyButton.setVisible(false);
field.addFocusListener(new FieldListener(copyButton));
copyButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(new StringSelection(field.getText()), null);
}
});
JPanel fieldPanel = new JPanel(new BorderLayout());
fieldPanel.setBackground(UIUtils.WHITE);
fieldPanel.add(field, BorderLayout.CENTER);
fieldPanel.add(copyButton, BorderLayout.EAST);
Border matteBorder = BorderFactory.createMatteBorder(1, 1, 1, 1, UIUtils.BLUE);
Border emptyBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5);
Border compoundBorder = BorderFactory.createCompoundBorder(matteBorder, emptyBorder);
fieldPanel.setBorder(compoundBorder);
fieldPanel.setPreferredSize(new Dimension(100, 20));
return fieldPanel;
}
private class FieldListener implements FocusListener {
private final JButton button;
public FieldListener(JButton button) {
this.button = button;
}
@Override
public void focusGained(FocusEvent arg0) {
button.setVisible(true);
}
@Override
public void focusLost(FocusEvent arg0) {
button.setVisible(false);
}
}
}
}
/** Builds string with R parameters script out. */
private static String buildParameterScript(FskSimulation simulation) {
String paramScript = "";
for (Map.Entry<String, String> entry : simulation.getParameters().entrySet()) {
String parameterName = entry.getKey();
String parameterValue = entry.getValue();
paramScript += parameterName + " <- " + parameterValue + "\n";
}
return paramScript;
}
}