de.bund.bfr.knime.fsklab.deprecatednodes/src-1_7_2/de/bund/bfr/knime/fsklab/nodes/v1_7_2/reader/ReaderNodeModel.java
/*
***************************************************************************************************
* Copyright (c) 2017 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.nodes.v1_7_2.reader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import javax.swing.tree.TreeNode;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.emfjson.jackson.module.EMFModule;
import org.jlibsedml.ChangeAttribute;
import org.jlibsedml.Libsedml;
import org.jlibsedml.SEDMLTags;
import org.jlibsedml.SedML;
import org.knime.core.node.ExecutionContext;
import org.knime.core.node.InvalidSettingsException;
import org.knime.core.node.NoInternalsModel;
import org.knime.core.node.NodeSettingsRO;
import org.knime.core.node.NodeSettingsWO;
import org.knime.core.node.port.PortObject;
import org.knime.core.node.port.PortObjectSpec;
import org.knime.core.node.port.PortType;
import org.knime.core.node.util.CheckUtils;
import org.knime.core.node.workflow.NodeContext;
import org.knime.core.node.workflow.WorkflowContext;
import org.knime.core.node.workflow.WorkflowManager;
import org.knime.core.util.FileUtil;
import org.sbml.jsbml.Annotation;
import org.sbml.jsbml.JSBML;
import org.sbml.jsbml.ListOf;
import org.sbml.jsbml.SBMLDocument;
import org.sbml.jsbml.ext.comp.CompModelPlugin;
import org.sbml.jsbml.ext.comp.CompSBasePlugin;
import org.sbml.jsbml.ext.comp.Submodel;
import org.sbml.jsbml.xml.XMLAttributes;
import org.sbml.jsbml.xml.XMLNode;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule;
import de.bund.bfr.fskml.FSKML;
import de.bund.bfr.fskml.FskMetaDataObject;
import de.bund.bfr.fskml.FskMetaDataObject.ResourceType;
import de.bund.bfr.fskml.RScript;
import de.bund.bfr.knime.fsklab.CombinedFskPortObject;
import de.bund.bfr.knime.fsklab.FskPortObject;
import de.bund.bfr.knime.fsklab.FskPortObjectSpec;
import de.bund.bfr.knime.fsklab.FskSimulation;
import de.bund.bfr.knime.fsklab.JoinRelation;
import de.bund.bfr.knime.fsklab.nodes.v1_7_2.joiner.JoinerNodeModel;
import de.bund.bfr.knime.fsklab.nodes.v1_7_2.writer.WriterNodeModel;
import de.bund.bfr.knime.fsklab.rakip.RakipUtil;
import de.bund.bfr.metadata.swagger.GenericModel;
import de.bund.bfr.metadata.swagger.Model;
import de.bund.bfr.metadata.swagger.Parameter;
import de.unirostock.sems.cbarchive.ArchiveEntry;
import de.unirostock.sems.cbarchive.CombineArchive;
import de.unirostock.sems.cbarchive.meta.MetaDataObject;
import metadata.EmfMetadataModule;
import metadata.SwaggerUtil;
public class ReaderNodeModel extends NoInternalsModel {
private static final PortType[] IN_TYPES = {};
private static final PortType[] OUT_TYPES = {FskPortObject.TYPE};
private static final ObjectMapper MAPPER103;
private static final ObjectMapper MAPPER104;
static {
MAPPER103 = EMFModule.setupDefaultMapper();
MAPPER103.registerModule(new ThreeTenModule());
JsonFactory jsonFactory = new JsonFactory();
jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
jsonFactory.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false);
MAPPER104 = new ObjectMapper(jsonFactory).registerModule(new ThreeTenModule())
.registerModule(new EMFModule()).registerModule(new EmfMetadataModule());
MAPPER104.setSerializationInclusion(Include.NON_NULL);
}
private final ReaderNodeSettings nodeSettings = new ReaderNodeSettings();
public ReaderNodeModel() {
super(IN_TYPES, OUT_TYPES);
}
@Override
protected void saveSettingsTo(NodeSettingsWO settings) {
nodeSettings.save(settings);
}
@Override
protected void loadValidatedSettingsFrom(NodeSettingsRO settings)
throws InvalidSettingsException {
nodeSettings.load(settings);
}
@Override
protected void validateSettings(NodeSettingsRO settings) throws InvalidSettingsException {
CheckUtils.checkDestinationFile(settings.getString("filename"), true);
}
@Override
protected void reset() {
NodeContext nodeContext = NodeContext.getContext();
WorkflowManager wfm = nodeContext.getWorkflowManager();
WorkflowContext workflowContext = wfm.getContext();
/*
* find and delete only the working directory folder related to current reader node in the mean
* that, we are not deleting folders which are representing the working directory of other
* reader nodes which maybe exist in the same workflow
*/
try {
Files.walk(workflowContext.getCurrentLocation().toPath())
.filter(path -> path.toString()
.contains(nodeContext.getNodeContainer().getNameWithID().toString()
.replaceAll("\\W", "").replace(" ", "") + "_" + "workingDirectory"))
.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(file -> {
try {
file.delete();
}catch(Exception ex) {
ex.printStackTrace();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected PortObjectSpec[] configure(PortObjectSpec[] inSpecs) throws InvalidSettingsException {
return new PortObjectSpec[] {FskPortObjectSpec.INSTANCE};
}
@Override
protected PortObject[] execute(PortObject[] inObjects, ExecutionContext exec) throws Exception {
URL url = FileUtil.toURL(nodeSettings.filePath);
Path localPath = FileUtil.resolveToPath(url);
FskPortObject inObject;
if (localPath != null) {
inObject = readArchive(localPath.toFile());
}
// if path is an external URL the archive is downloaded to a temporary file
else {
File temporaryFile = FileUtil.createTempFile("model", "fskx");
temporaryFile.delete();
try (InputStream inStream = FileUtil.openStreamWithTimeout(new URL(nodeSettings.filePath),10000);
OutputStream outStream = new FileOutputStream(temporaryFile)) {
IOUtils.copy(inStream, outStream);
}
inObject = readArchive(temporaryFile);
temporaryFile.delete();
}
return new PortObject[] {inObject};
}
private FskPortObject readArchive(File in) throws Exception {
FskPortObject fskObj = null;
try (final CombineArchive archive = new CombineArchive(in)) {
// Get the directories inside the archive without duplication
// The directories are sorted to have the related directories (Joiner One) after each other
TreeSet<String> entries = archive.getEntries().parallelStream().map(ArchiveEntry::getFilePath)
.map(fullPath -> fullPath.substring(0, fullPath.lastIndexOf("/") + 1))
.filter(path -> StringUtils.countMatches(path, "/") > 2 && !path.endsWith("simulations/"))
.collect(Collectors.toCollection(TreeSet::new));
// Get the number of SBML files available in this archive
// to be used as tag of joining if they are more than one.
URI sbmlUri = FSKML.getURIS(1, 0, 12).get("sbml");
// If only one SBML entry then no joining, just normal FSK object
List<String> listOfPaths =
archive.getNumEntriesWithFormat(sbmlUri) > 1 ? new ArrayList<>(entries)
: Arrays.asList("/");
NodeContext nodeContext = NodeContext.getContext();
WorkflowManager wfm = nodeContext.getWorkflowManager();
WorkflowContext workflowContext = wfm.getContext();
File currentWorkingDirectory = new File(workflowContext.getCurrentLocation(),
nodeContext.getNodeContainer().getNameWithID().toString().replaceAll("\\W", "").replace(" ",
"") + "_" + "workingDirectory" );
fskObj = readFskPortObject(archive, listOfPaths, 0, currentWorkingDirectory);
}
return fskObj;
}
private FskPortObject getEmbedSecondFSKObject(CombinedFskPortObject comFskObj) {
FskPortObject embedFSKObject = comFskObj.getSecondFskPortObject();
if (embedFSKObject instanceof CombinedFskPortObject) {
embedFSKObject = getEmbedSecondFSKObject((CombinedFskPortObject) embedFSKObject);
}
return embedFSKObject;
}
private FskPortObject readFskPortObject(CombineArchive archive, List<String> ListOfPaths,
int readLevel, File currentWorkingDirectory) throws Exception {
Map<String, URI> URIS = FSKML.getURIS(1, 0, 12);
// each sub Model has it's own working directory to avoid resource conflict.
// get current node's and workflow's context
// get the location of the current Workflow to create the working directory in it and use the
// name with current reader node id for the prefix of the working directory name
if (!currentWorkingDirectory.exists()) {
currentWorkingDirectory.mkdir();
}
final Path workingDirectory = currentWorkingDirectory.toPath();
Model model = new Model();
// more one than one element means this model is joined one
if (ListOfPaths != null && ListOfPaths.size() > 1) {
String firstelement = ListOfPaths.get(ListOfPaths.size() % 2);
// classify the pathes into two groups, each belongs to sub model
List<String> firstGroup = ListOfPaths.stream().filter(line -> line.startsWith(firstelement))
.collect(Collectors.toList());
List<String> secondGroup = ListOfPaths.stream().filter(line -> !firstGroup.contains(line))
.collect(Collectors.toList());
if (secondGroup.size() == 2) {
secondGroup.remove(0);
}
// invoke this mothod recursively to get the sub model using the corresponding path group
FskPortObject firstFskPortObject = readFskPortObject(archive, firstGroup, ++readLevel,new File(currentWorkingDirectory,"sub"+readLevel));
FskPortObject secondFskPortObject = readFskPortObject(archive, secondGroup, ++readLevel,new File(currentWorkingDirectory,"sub"+readLevel));
String tempString = firstelement.substring(0, firstelement.length() - 2);
String parentPath = tempString.substring(0, tempString.lastIndexOf('/'));
// Gets metadata
{
// Create temporary file with metadata
Path temp = Files.createTempFile("metadata", ".json");
List<ArchiveEntry> jsonEntries = archive.getEntriesWithFormat(URIS.get("json"));
for (ArchiveEntry jsonEntry : jsonEntries) {
String path = jsonEntry.getEntityPath();
if (path.startsWith(parentPath)
&& (StringUtils.countMatches(path,
"/") == (StringUtils.countMatches(parentPath, "/") + 1))
&& path.endsWith("metaData.json")) {
jsonEntry.extractFile(temp.toFile());
// Loads metadata from temporary file
JsonNode modelNode = MAPPER103.readTree(temp.toFile());
if(modelNode.has("modelType")) {
Class<? extends Model> modelClass = FskPortObject.Serializer.modelClasses.get(modelNode.get("modelType").asText());
model = MAPPER103.readValue(temp.toFile(), modelClass);
}
else if(modelNode.get("version") != null) {
GenericModel gm = new GenericModel();
gm.setModelType("genericModel");
gm.setGeneralInformation(SwaggerUtil.convert(MAPPER103.treeToValue(modelNode.get("generalInformation"), metadata.GeneralInformation.class)));
gm.setScope(SwaggerUtil.convert(MAPPER103.treeToValue(modelNode.get("scope"), metadata.Scope.class)));
gm.setDataBackground(SwaggerUtil.convert(MAPPER103.treeToValue(modelNode.get("dataBackground"), metadata.DataBackground.class)));
gm.setModelMath(SwaggerUtil.convert(MAPPER103.treeToValue(modelNode.get("modelMath"), metadata.ModelMath.class)));
model = gm;
}
// generalInformation =
// mapper.treeToValue(modelNode.get("generalInformation"), GeneralInformation.class);
// scope = mapper.treeToValue(modelNode.get("scope"), Scope.class);
// dataBackground =
// mapper.treeToValue(modelNode.get("dataBackground"), DataBackground.class);
// modelMath = mapper.treeToValue(modelNode.get("modelMath"), ModelMath.class);
}
}
Files.delete(temp); // Deletes temporary file
}
String firstModelId = "";
// get Joiner Relations
List<JoinRelation> joinerRelation = new ArrayList<>();
{
SBMLDocument parentSBMLDoc = null;
List<ArchiveEntry> sbmlEntries = archive.getEntriesWithFormat(URIS.get("sbml"));
for (ArchiveEntry sbmlEntry : sbmlEntries) {
String path = sbmlEntry.getEntityPath();
if (path.startsWith(parentPath) && (StringUtils.countMatches(path,
"/") == (StringUtils.countMatches(parentPath, "/") + 1))) {
Path parentFile = Files.createTempFile("Model", ".sbml");
sbmlEntry.extractFile(parentFile.toFile());
try {
parentSBMLDoc = JSBML.readSBMLFromFile(parentFile.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
Files.delete(parentFile); // Deletes temporary file
}
}
if (parentSBMLDoc != null) {
ListOf<org.sbml.jsbml.Parameter> params = parentSBMLDoc.getModel().getListOfParameters();
CompModelPlugin subModels =
(CompModelPlugin) parentSBMLDoc.getModel().getExtension("comp");
List<Submodel> listOfSubModels = subModels.getListOfSubmodels();
if (listOfSubModels.size() > 0) {
firstModelId = listOfSubModels.get(0).getModelRef();
}
// String s = subModels.getReplacedBy().getIdRef();
for (org.sbml.jsbml.Parameter param : params) {
JoinRelation jR = new JoinRelation();
List<Parameter> coll =
SwaggerUtil.getParameter(secondFskPortObject.modelMetadata).stream().filter(cp -> {
String paramId = cp.getId();
String compareTo = param.getId();
if (paramId.replaceAll(JoinerNodeModel.suffix, "")
.equals(compareTo.replaceAll(JoinerNodeModel.suffix, ""))) {
cp.setId(param.getId());
return true;
} else {
return false;
}
}).collect(Collectors.toList());
if (coll.size() == 0) {
continue;
}
Parameter targetParam = coll.get(0);
jR.setTargetParam(targetParam);
CompSBasePlugin a = (CompSBasePlugin) param.getExtension("comp");
String replacmentLement = a.getReplacedBy().getIdRef();
Parameter sourceParam =
SwaggerUtil.getParameter(firstFskPortObject.modelMetadata).stream().filter(cp -> {
String paramId = cp.getId();
if (paramId.replaceAll(JoinerNodeModel.suffix, "")
.equals(replacmentLement.replaceAll(JoinerNodeModel.suffix, ""))) {
cp.setId(a.getReplacedBy().getIdRef());
return true;
} else {
return false;
}
}).filter(cp -> cp.getId().equals(replacmentLement))
.collect(Collectors.toList()).get(0);
jR.setSourceParam(sourceParam);
Annotation annotation = param.getAnnotation();
if (annotation != null) {
XMLNode nonRDFAnnotation = annotation.getNonRDFannotation();
if (nonRDFAnnotation != null) {
Enumeration<TreeNode> childEnum = nonRDFAnnotation.children();
while (childEnum.hasMoreElements()) {
XMLNode child = (XMLNode) childEnum.nextElement();
XMLAttributes atts = child.getAttributes();
String commandValue = atts.getValue(WriterNodeModel.METADATA_COMMAND_VALUE);
if (commandValue != null && !commandValue.equals("")) {
jR.setCommand(commandValue);
}
}
}
}
joinerRelation.add(jR);
}
}
}
// Get simulations for combined FSKObject
List<FskSimulation> simulations = new ArrayList<>();
List<ArchiveEntry> sedmlEntries = archive.getEntriesWithFormat(URIS.get("sedml"));
for (ArchiveEntry simEntry : sedmlEntries) {
String path = simEntry.getEntityPath();
if (path.startsWith(parentPath) && (StringUtils.countMatches(path,
"/") == (StringUtils.countMatches(parentPath, "/") + 1))) {
File simulationsFile = FileUtil.createTempFile("sim", ".sedml");
simEntry.extractFile(simulationsFile);
// Loads simulations from temporary file
SedML sedml = Libsedml.readDocument(simulationsFile).getSedMLModel();
simulations.addAll(loadSimulations(sedml));
}
}
CombinedFskPortObject topfskObj;
String currentModelID = SwaggerUtil.getModelName(firstFskPortObject.modelMetadata).replaceAll("\\W", "");
if (currentModelID.equals(firstModelId)) {
topfskObj = new CombinedFskPortObject("", "", model, workingDirectory.toString(), new ArrayList<>(), firstFskPortObject,
secondFskPortObject);
} else {
// topfskObj = new CombinedFskPortObject("", "", generalInformation, scope, dataBackground,
// modelMath, workingDirectory.toString(), new ArrayList<>(), secondFskPortObject,
// firstFskPortObject);
topfskObj = new CombinedFskPortObject("", "", model, workingDirectory.toString(), new ArrayList<>(), secondFskPortObject,
firstFskPortObject);
}
topfskObj.viz = getEmbedSecondFSKObject(topfskObj).viz;
topfskObj.simulations.addAll(simulations);
topfskObj.setJoinerRelation(joinerRelation);
return topfskObj;
} else {
String modelScript = "";
String visualizationScript = "";
File workspace = null; // null if missing
String pathToResource = ListOfPaths.get(0);
String spreadsheetPath = "";
List<FskSimulation> simulations = new ArrayList<>();
String readme = "";
for (final ArchiveEntry entry : archive.getEntriesWithFormat(URIS.get("r"))) {
String path = entry.getEntityPath();
if (path.indexOf(pathToResource) == 0) {
List<MetaDataObject> descriptions = entry.getDescriptions();
if (descriptions.size() > 0) {
final FskMetaDataObject fmdo = new FskMetaDataObject(descriptions.get(0));
final ResourceType resourceType = fmdo.getResourceType();
if (resourceType.equals(ResourceType.modelScript)) {
modelScript = loadTextEntry(entry);
} else if (resourceType.equals(ResourceType.visualizationScript)) {
visualizationScript = loadTextEntry(entry);
} else if (resourceType.equals(ResourceType.workspace)) {
workspace = FileUtil.createTempFile("workspace", ".r");
entry.extractFile(workspace);
}
}
}
}
// Gets resources
Set<ArchiveEntry> resourceEntries = new HashSet<>();
// Take README.txt and leave other txt as resources.
List<ArchiveEntry> txtEntries = archive.getEntriesWithFormat(URI.create("http://purl.org/NET/mediatypes/text-xplain"));
for (ArchiveEntry entry : txtEntries) {
String path = entry.getEntityPath();
if (path.indexOf(pathToResource) == 0) {
// If a txt entry has a description then it must be a README.
if (entry.getDescriptions().size() > 0) {
readme = loadTextEntry(entry);
} else {
resourceEntries.add(entry);
}
}
}
resourceEntries.addAll(archive.getEntriesWithFormat(URIS.get("csv")));
resourceEntries.addAll(archive.getEntriesWithFormat(URIS.get("rdata")));
for (final ArchiveEntry entry : resourceEntries) {
String path = entry.getEntityPath();
if (path.indexOf(pathToResource) == 0) {
Path targetPath = workingDirectory.resolve(entry.getFileName());
try {
Files.createFile(targetPath);
entry.extractFile(targetPath.toFile());
}catch (FileAlreadyExistsException e) {
//Do nothing, the resource is already there
}
}
}
// Gets metadata
{
// Create temporary file with metadata
Path temp = Files.createTempFile("metadata", ".json");
List<ArchiveEntry> jsonEntries = archive.getEntriesWithFormat(URIS.get("json"));
for (ArchiveEntry jsonEntry : jsonEntries) {
String path = jsonEntry.getEntityPath();
// read the metaData.json file only!
if (path.indexOf(pathToResource) == 0 && path.endsWith("metaData.json")) {
jsonEntry.extractFile(temp.toFile());
// Loads metadata from temporary file
JsonNode modelNode = MAPPER103.readTree(temp.toFile());
Object version = modelNode.get("version");
if(modelNode.has("modelType")) {
Class<? extends Model> modelClass = FskPortObject.Serializer.modelClasses.get(modelNode.get("modelType").asText());
model = MAPPER104.readValue(temp.toFile(), modelClass);
} else if (version != null) {
// 1.0.3 (with EMF)
GenericModel gm = new GenericModel();
gm.setModelType("genericModel");
gm.setGeneralInformation(SwaggerUtil.convert(MAPPER103.treeToValue(modelNode.get("generalInformation"), metadata.GeneralInformation.class)));
gm.setScope(SwaggerUtil.convert(MAPPER103.treeToValue(modelNode.get("scope"), metadata.Scope.class)));
gm.setDataBackground(SwaggerUtil.convert(MAPPER103.treeToValue(modelNode.get("dataBackground"), metadata.DataBackground.class)));
gm.setModelMath(SwaggerUtil.convert(MAPPER103.treeToValue(modelNode.get("modelMath"), metadata.ModelMath.class)));
model = gm;
} else {
// pre Rakip
GenericModel gm = new GenericModel();
gm.setModelType("genericModel");
modelNode = MAPPER103.readTree(temp.toFile());
de.bund.bfr.knime.fsklab.rakip.GenericModel genericModel = MAPPER103.readValue(temp.toFile(), de.bund.bfr.knime.fsklab.rakip.GenericModel.class);
gm.setGeneralInformation(RakipUtil.convert(genericModel.generalInformation));
gm.setScope(RakipUtil.convert(genericModel.scope));
gm.dataBackground(RakipUtil.convert(genericModel.dataBackground));
gm.modelMath(RakipUtil.convert(genericModel.modelMath));
model = gm;
}
}
}
Files.delete(temp); // Deletes temporary file
}
int selectedIndex = 0;
// Get simulations
List<ArchiveEntry> sedmlEntries = archive.getEntriesWithFormat(URIS.get("sedml"));
for (ArchiveEntry simEntry : sedmlEntries) {
String path = simEntry.getEntityPath();
if (path.indexOf(pathToResource) == 0) {
File simulationsFile = FileUtil.createTempFile("sim", ".sedml");
simEntry.extractFile(simulationsFile);
// Loads simulations from temporary file
SedML sedml = Libsedml.readDocument(simulationsFile).getSedMLModel();
List<org.jlibsedml.Annotation> annotations = sedml.getAnnotation();
if(annotations != null && annotations.size() > 0) {
org.jlibsedml.Annotation selectedIndexAnno= annotations.get(0);
org.jdom.Text e = (org.jdom.Text) selectedIndexAnno.getAnnotationElement().getContent().get(0);
selectedIndex = Integer.parseInt(e.getText());
}
simulations.addAll(loadSimulations(sedml));
}
}
// Get metadata spreadsheet
URI xlsxURI = URIS.get("xlsx");
List<ArchiveEntry> excelEntries = archive.getEntriesWithFormat(xlsxURI);
for (ArchiveEntry excelEntry : excelEntries) {
String path = excelEntry.getEntityPath();
if (path.indexOf(pathToResource) == 0) {
File excelFile = FileUtil.createTempFile("metadata", ".xlsx");
excelEntry.extractFile(excelFile);
spreadsheetPath = excelFile.getAbsolutePath();
}
}
// Retrieve missing libraries from CRAN
HashSet<String> packagesSet = new HashSet<>();
if (!modelScript.isEmpty()) {
packagesSet.addAll(new RScript(modelScript).getLibraries());
}
if (!visualizationScript.isEmpty()) {
packagesSet.addAll(new RScript(visualizationScript).getLibraries());
}
List<String> packagesList = new ArrayList<>(packagesSet);
Path workspacePath = workspace == null ? null : workspace.toPath();
// The reader node is not using currently the plot, if present. Therefore an
// empty string is used.
String plotPath = "";
FskPortObject fskObj = new FskPortObject(modelScript, visualizationScript, model, workspacePath, packagesList,
workingDirectory.toString(), plotPath, readme, spreadsheetPath);
fskObj.simulations.addAll(simulations);
fskObj.selectedSimulationIndex = selectedIndex;
return fskObj;
}
}
/** @return text content out of an {@link ArchiveEntry}. */
private static String loadTextEntry(final ArchiveEntry entry) throws IOException {
// Create temporary file with script
File temp = File.createTempFile("temp", null);
String contents;
try {
// extractFile throws IOException if the file does not exist (was deleted manually) or is
// not writable.
entry.extractFile(temp);
// readFileToString throws IOException if the file was deleted manually
contents = FileUtils.readFileToString(temp, "UTF-8");
} catch (IOException exception) {
throw exception;
} finally {
temp.delete();
}
return contents;
}
/**
* @return list of simulations from a SedML document.
*
* <p>
* In SedML every simulation is encoded as a {@link org.jlibsedml.Model} with the
* parameter values defined as a {@link org.jlibsedml.ChangeAttribute}.
*
* <pre>
* {@code
* <model id="simulation1">
* <listOfChanges>
* <changeAttribute newValue="1" target="a" />
* <changeAttribute newValue="2" target="b" />
* </listOfChanges>
* </model>
* <model id="simulation2">
* <listOfChanges>
* <changeAttribute newValue="3" target="c" />
* <changeAttribute newValue="4" target="d" />
* </listOfChanges>
* </model>
* }
* </pre>
*/
private static List<FskSimulation> loadSimulations(SedML sedml) {
List<FskSimulation> simulations = new ArrayList<>(sedml.getModels().size());
for (org.jlibsedml.Model model : sedml.getModels()) {
Map<String, String> params = model.getListOfChanges().stream()
.filter(change -> change.getChangeKind().equals(SEDMLTags.CHANGE_ATTRIBUTE_KIND))
.map(change -> (ChangeAttribute) change)
.collect(Collectors.toMap(change -> change.getTargetXPath().toString(), ChangeAttribute::getNewValue));
FskSimulation sim = new FskSimulation(model.getId());
sim.getParameters().putAll(params);
simulations.add(sim);
}
return simulations;
}
}