de.bund.bfr.knime.fsklab.deprecatednodes/src-1_9_0/de/bund/bfr/knime/fsklab/v1_9/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.v1_9.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.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeSet;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.jdom.Text;
import org.jlibsedml.ChangeAttribute;
import org.jlibsedml.Libsedml;
import org.jlibsedml.SEDMLTags;
import org.jlibsedml.SedML;
import org.jlibsedml.XMLException;
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.defaultnodesettings.SettingsModelString;
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.SBMLDocument;
import org.sbml.jsbml.SBMLReader;
import org.sbml.jsbml.ext.comp.CompModelPlugin;
import org.sbml.jsbml.ext.comp.CompSBasePlugin;
import org.sbml.jsbml.ext.comp.ReplacedBy;
import org.sbml.jsbml.xml.XMLNode;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
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.FskPluginObjectMapper;
import de.bund.bfr.knime.fsklab.nodes.environment.ArchivedEnvironmentManager;
import de.bund.bfr.knime.fsklab.nodes.environment.EnvironmentManager;
import de.bund.bfr.knime.fsklab.nodes.v1_9.NodeUtils;
import de.bund.bfr.knime.fsklab.rakip.RakipUtil;
import de.bund.bfr.knime.fsklab.v1_9.CombinedFskPortObject;
import de.bund.bfr.knime.fsklab.v1_9.FskPortObject;
import de.bund.bfr.knime.fsklab.v1_9.FskPortObjectSpec;
import de.bund.bfr.knime.fsklab.v1_9.FskSimulation;
import de.bund.bfr.knime.fsklab.v1_9.JoinRelation;
import de.bund.bfr.metadata.swagger.GenericModel;
import de.bund.bfr.metadata.swagger.GenericModelDataBackground;
import de.bund.bfr.metadata.swagger.GenericModelGeneralInformation;
import de.bund.bfr.metadata.swagger.GenericModelModelMath;
import de.bund.bfr.metadata.swagger.GenericModelScope;
import de.bund.bfr.metadata.swagger.Model;
import de.unirostock.sems.cbarchive.ArchiveEntry;
import de.unirostock.sems.cbarchive.CombineArchive;
import metadata.SwaggerUtil;
class ReaderNodeModel extends NoInternalsModel {
private static final PortType[] IN_TYPES = {};
private static final PortType[] OUT_TYPES = {FskPortObject.TYPE};
static final String CFG_FILE = "filename";
private final SettingsModelString filePath = new SettingsModelString(CFG_FILE, null);
public ReaderNodeModel() {
super(IN_TYPES, OUT_TYPES);
}
@Override
protected void saveSettingsTo(NodeSettingsWO settings) {
filePath.saveSettingsTo(settings);
}
@Override
protected void loadValidatedSettingsFrom(NodeSettingsRO settings)
throws InvalidSettingsException {
filePath.loadSettingsFrom(settings);
}
@Override
protected void validateSettings(NodeSettingsRO settings) throws InvalidSettingsException {
filePath.validateSettings(settings);
}
@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 {
String warning = CheckUtils.checkSourceFile(filePath.getStringValue());
if (warning != null) {
setWarningMessage(warning);
}
return new PortObjectSpec[] {FskPortObjectSpec.INSTANCE};
}
@Override
protected PortObject[] execute(PortObject[] inObjects, ExecutionContext exec) throws Exception {
URL url = FileUtil.toURL(filePath.getStringValue());
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(filePath.getStringValue()), 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)) {
// 1. Get SBML URI
URI sbmlURI = FSKML.getURIS(1, 0, 12).get("sbml");
// 2. Get number of SBML documents
final int numberOfSBML = archive.getNumEntriesWithFormat(sbmlURI);
// 3. Get the paths or model folders. A model folder contains a model and is the root
// folder in case of a single model or can be nested folders in case of joined models.
// If there is only one SBML document the archive contains a single model and several
// SBML documents means a joined model.
List<String> modelFolders;
if (numberOfSBML > 1) {
// Get directories inside the archive without duplication. The directories are
// sorted to have the related directories after each other.
// E.g.:
// /SimpleModel2/SimpleModel2 <- Joined model
// /SimpleModel2/SimpleModel2/SimpleModel1 <- Child model 1
// /SimpleModel2/SimpleModel1/SimpleModel2 <- Child model 2
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));
modelFolders = new ArrayList<>(entries);
} else {
modelFolders = Arrays.asList("/");
}
fskObj = readFskPortObject(archive, modelFolders, 0);
}
// ADD PARAMETER SUFFIXES to 1.7.2 version models (combined)
ReaderNodeUtil.updateSuffixes(fskObj);
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) throws Exception {
Map<String, URI> URIS = FSKML.getURIS(1, 0, 12);
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);
FskPortObject secondFskPortObject = readFskPortObject(archive, secondGroup, ++readLevel);
String tempString = firstelement.substring(0, firstelement.length() - 2);
String parentPath = tempString.substring(0, tempString.lastIndexOf('/'));
// Gets metadata
{
// Find metadata entry
Optional<ArchiveEntry> metadataEntry = archive.getEntriesWithFormat(URIS.get("json"))
.stream().filter(entry -> entry.getEntityPath().startsWith(parentPath))
.filter(entry -> StringUtils.countMatches(entry.getEntityPath(),
"/") == StringUtils.countMatches(parentPath, "/") + 1)
.filter(entry -> entry.getEntityPath().endsWith("metaData.json")).findAny();
if (metadataEntry.isPresent()) {
model = readMetadata(metadataEntry.get());
}
}
// Get workspace
URI rdataUri = URIS.get("rdata");
File workspace = null; // null if missing
Optional<ArchiveEntry> workspaceEntry = archive.getEntriesWithFormat(rdataUri).stream()
.filter(entry -> entry.getEntityPath().startsWith(parentPath))
.filter(entry -> StringUtils.countMatches(entry.getEntityPath(),"/")
== StringUtils.countMatches(parentPath, "/") + 1)
.findAny();
if (workspaceEntry.isPresent()) {
ArchiveEntry entry = workspaceEntry.get();
FskMetaDataObject fmdo = new FskMetaDataObject(entry.getDescriptions().get(0));
if (fmdo.getResourceType() == ResourceType.workspace) {
workspace = FileUtil.createTempFile("workspace", ".RData");
entry.extractFile(workspace);
}
}
List<JoinRelation> connectionList = new ArrayList<>();
// Find SBML entry in archive
Optional<ArchiveEntry> sbmlEntry =
archive.getEntriesWithFormat(URIS.get("sbml")).stream().filter(entry -> {
final String path = entry.getEntityPath();
return path.startsWith(parentPath) && StringUtils.countMatches(path,
"/") == StringUtils.countMatches(parentPath, "/") + 1;
}).findAny();
String firstModelId = "";
if (sbmlEntry.isPresent()) {
// Extract entry to temporary file
File temporaryFile = File.createTempFile("model", ".sbml");
sbmlEntry.get().extractFile(temporaryFile);
SBMLDocument sbmlDocument = SBMLReader.read(temporaryFile);
temporaryFile.delete();
// Get first model's id
CompModelPlugin compModelPlugin =
(CompModelPlugin) sbmlDocument.getModel().getExtension("comp");
firstModelId =
compModelPlugin.getNumSubmodels() > 0 ? compModelPlugin.getSubmodel(0).getModelRef()
: "";
for (org.sbml.jsbml.Parameter parameter : sbmlDocument.getModel().getListOfParameters()) {
//********************** CUT THE SHENANIGANS *************************
// Find metadata of target parameter. Connected parameter in 2nd model
// final String parameterId =
// parameter.getId().replaceAll(JoinerNodeModel.SUFFIX_SECOND, "");
// Optional<Parameter> targetParameter = SwaggerUtil
// .getParameter(secondFskPortObject.modelMetadata).stream().filter(currentParameter -> {
// final String currentParameterId =
// currentParameter.getId().replaceAll(JoinerNodeModel.SUFFIX_SECOND, "");
// if (parameterId.equals(currentParameterId)) {
// currentParameter.setId(parameter.getId());
// return true;
// } else {
// return false;
// }
// }).findAny();
//
// // If the metadata of targetParamter is not found, skip to next parameter
// if (!targetParameter.isPresent()) {
// continue;
// }
//********************** CUT THE SHENANIGANS *************************
// // Find metadata of source parameter (connected parameter of 1st model)
final ReplacedBy replacedBy =
((CompSBasePlugin) parameter.getExtension("comp")).getReplacedBy();
//********************** CUT THE SHENANIGANS *************************
// final String replacement =
// replacedBy.getIdRef().replaceAll(JoinerNodeModel.SUFFIX_FIRST, "");
// Optional<Parameter> sourceParameter = SwaggerUtil
// .getParameter(firstFskPortObject.modelMetadata).stream().filter(currentParameter -> {
// final String currentParameterId =
// currentParameter.getId().replaceAll(JoinerNodeModel.SUFFIX_FIRST, "");
// if (replacement.equals(currentParameterId)) {
// currentParameter.setId(replacedBy.getIdRef());
// return true;
// } else {
// return false;
// }
// }).findAny();
//
// // If the metadata of sourceParmeter is not found, skip to next parameter
// if (!sourceParameter.isPresent()) {
// continue;
// }
//********************** CUT THE SHENANIGANS *************************
String command = null;
if (parameter.getAnnotation() != null
&& parameter.getAnnotation().getNonRDFannotation() != null) {
XMLNode nonRDFannotation = parameter.getAnnotation().getNonRDFannotation();
XMLNode commandNode = nonRDFannotation.getChildElement("command", "");
if (commandNode != null
&& commandNode.hasAttr(NodeUtils.METADATA_COMMAND_VALUE)) {
command = commandNode.getAttrValue(NodeUtils.METADATA_COMMAND_VALUE);
}
}
connectionList.add(new JoinRelation(replacedBy.getIdRef(),
parameter.getId(), command, null));
// connectionList.add(new JoinRelation(sourceParameter.get().getId(),
// targetParameter.get().getId(), command, null));
}
}
CombinedFskPortObject topfskObj;
String currentModelID =
SwaggerUtil.getModelName(firstFskPortObject.modelMetadata).replaceAll("\\W", "");
if (currentModelID.equals(firstModelId)) {
topfskObj = new CombinedFskPortObject("", "", model, Optional.empty(), new ArrayList<>(),
firstFskPortObject, secondFskPortObject);
} else {
topfskObj = new CombinedFskPortObject("", "", model, Optional.empty(), new ArrayList<>(),
secondFskPortObject, firstFskPortObject);
}
topfskObj.setViz(getEmbedSecondFSKObject(topfskObj).getViz());
// Get select simulation index and simulations for joined model
Optional<ArchiveEntry> simulationsEntry = archive.getEntriesWithFormat(URIS.get("sedml"))
.stream().filter(entry -> entry.getEntityPath().startsWith(parentPath))
.filter(entry -> StringUtils.countMatches(entry.getEntityPath(),
"/") == StringUtils.countMatches(parentPath, "/") + 1)
.findAny();
if (simulationsEntry.isPresent()) {
SimulationSettings simulationSettings = readSimulationSettings(simulationsEntry.get());
topfskObj.selectedSimulationIndex = simulationSettings.selectedSimulationIndex;
topfskObj.simulations.addAll(simulationSettings.simulations);
}
if (workspace != null) {
topfskObj.setWorkspace(workspace.toPath());
}
topfskObj.setJoinerRelation(connectionList.toArray(new JoinRelation[connectionList.size()]));
return topfskObj;
} else {
String modelScript = "";
String visualizationScript = "";
File workspace = null; // null if missing
String pathToResource = ListOfPaths.get(0);
String readme = "";
// Get entries of the current model
List<ArchiveEntry> entries = archive.getEntries().stream()
.filter(entry -> entry.getEntityPath().indexOf(pathToResource) == 0)
.collect(Collectors.toList());
URI textUri = URI.create("http://purl.org/NET/mediatypes/text-xplain");
URI csvUri = URIS.get("csv");
URI xlsxUri = URIS.get("xlsx");
URI rdataUri = URIS.get("rdata");
URI jsonUri = URIS.get("json");
URI sedmlUri = URIS.get("sedml");
// Gets metadata from metadata entry (metaData.json)
Optional<ArchiveEntry> metadataEntry =
entries.stream().filter(entry -> entry.getFormat().equals(jsonUri))
.filter(entry -> entry.getEntityPath().endsWith("metaData.json")).findAny();
if (metadataEntry.isPresent()) {
model = readMetadata(metadataEntry.get());
}
// The URI of the model script (varies on the language of the model)
// TODO: MAKE IT MORE GENERIC
String languageWrittenIn = StringUtils.defaultString(SwaggerUtil.getLanguageWrittenIn(model), "r");
languageWrittenIn = languageWrittenIn.toLowerCase().startsWith("r") ? "r" : "py" ;
URI scriptUri = URIS.get(languageWrittenIn);
// Load scripts
for (ArchiveEntry entry : entries) {
// workaround to make python models from version 1.7.2 compatible with 1.8.x
// those models had scripts that ended in ".r" instead of ".py"
if (( entry.getFormat().equals(scriptUri) || entry.getFormat().equals(URIS.get("r")) )
&& !entry.getDescriptions().isEmpty()) {
FskMetaDataObject fmdo = new FskMetaDataObject(entry.getDescriptions().get(0));
ResourceType resourceType = fmdo.getResourceType();
if (resourceType == ResourceType.modelScript) {
modelScript = loadTextEntry(entry);
} else if (resourceType == ResourceType.visualizationScript) {
visualizationScript = loadTextEntry(entry);
} else if (resourceType == ResourceType.workspace) {
// Legacy check. Look for R workspace with R URI (from old files)
workspace = FileUtil.createTempFile("workspace", ".RData");
entry.extractFile(workspace);
}
}
}
// Read readme
Optional<ArchiveEntry> readmeEntry = getArchiveEntry(entries, textUri);
if (readmeEntry.isPresent()) {
readme = loadTextEntry(readmeEntry.get());
}
// Extract workspace
Optional<ArchiveEntry> workspaceEntry = getArchiveEntry(entries, rdataUri);
if (workspaceEntry.isPresent()) {
FskMetaDataObject fmdo =
new FskMetaDataObject(workspaceEntry.get().getDescriptions().get(0));
if (fmdo.getResourceType() == ResourceType.workspace) {
workspace = FileUtil.createTempFile("workspace", ".RData");
workspaceEntry.get().extractFile(workspace);
}
}
// Retrieves resources
List<ArchiveEntry> resourceEntries = new ArrayList<>();
// Add r scripts without descriptions (no model or visualization script)
entries.stream().filter(entry -> entry.getFormat().equals(scriptUri) && entry.getDescriptions().isEmpty())
.forEach(resourceEntries::add);
// ... add other entries (not R scripts)
entries.stream().filter(entry -> entry.getFormat().equals(textUri) || entry.getFormat().equals(csvUri)
|| entry.getFormat().equals(xlsxUri) || entry.getFormat().equals(rdataUri)).forEach(resourceEntries::add);
String[] resourcePaths = resourceEntries.stream().map(ArchiveEntry::getEntityPath).toArray(String[]::new);
EnvironmentManager environmentManager =
new ArchivedEnvironmentManager(archive.getZipLocation().getAbsolutePath(), resourcePaths);
// 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, Optional.of(environmentManager), plotPath, readme);
// Read selected simulation index and simulations
Optional<ArchiveEntry> simulationEntry =
entries.stream().filter(entry -> entry.getFormat().equals(sedmlUri)).findAny();
if (simulationEntry.isPresent()) {
SimulationSettings simulationSettings = readSimulationSettings(simulationEntry.get());
fskObj.selectedSimulationIndex = simulationSettings.selectedSimulationIndex;
fskObj.simulations.addAll(simulationSettings.simulations);
}
return fskObj;
}
}
/** @return entry of specific URI out of an {@link ArchiveEntry}. */
private Optional<ArchiveEntry> getArchiveEntry(List<ArchiveEntry> entries, URI uri ){
Optional<ArchiveEntry> archive_entry =
entries.stream().filter(entry -> entry.getFormat().equals(uri))
.filter(entry -> !entry.getDescriptions().isEmpty()).findAny();
return archive_entry;
}
/** @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;
}
private Model readMetadata(ArchiveEntry metadataEntry)
throws JsonProcessingException, IOException {
// Create temporary file with metadata
File temp = File.createTempFile("metadata", ".json");
metadataEntry.extractFile(temp);
// Load metadata from temporary file
final ObjectMapper mapper = FskPluginObjectMapper.MAPPER104;
JsonNode jsonNode = mapper.readTree(temp);
temp.delete(); // Delete temporary file
Model model;
// New swagger models have the modelType property (1.0.4)
if (jsonNode.has("modelType")) {
String modelType = jsonNode.get("modelType").asText();
Class<? extends Model> modelClass = FskPortObject.Serializer.modelClasses.get(modelType);
model = mapper.treeToValue(jsonNode, modelClass);
} else if (jsonNode.has("version")) {
// 1.0.3 (with EMF)
GenericModel gm = new GenericModel();
gm.setModelType("genericModel");
gm.setGeneralInformation(mapper.treeToValue(jsonNode.get("generalInformation"),
GenericModelGeneralInformation.class));
gm.setScope(mapper.treeToValue(jsonNode.get("scope"), GenericModelScope.class));
gm.setDataBackground(
mapper.treeToValue(jsonNode.get("dataBackground"), GenericModelDataBackground.class));
gm.setModelMath(mapper.treeToValue(jsonNode.get("modelMath"), GenericModelModelMath.class));
model = gm;
} else {
// Pre-RAKIP
de.bund.bfr.knime.fsklab.rakip.GenericModel rakipModel =
mapper.treeToValue(jsonNode, de.bund.bfr.knime.fsklab.rakip.GenericModel.class);
GenericModel gm = new GenericModel();
gm.setModelType("genericModel");
gm.setGeneralInformation(RakipUtil.convert(rakipModel.generalInformation));
gm.setScope(RakipUtil.convert(rakipModel.scope));
gm.dataBackground(RakipUtil.convert(rakipModel.dataBackground));
gm.modelMath(RakipUtil.convert(rakipModel.modelMath));
model = gm;
}
return model;
}
private static class SimulationSettings {
final int selectedSimulationIndex;
final List<FskSimulation> simulations;
SimulationSettings(final int selectedSimulationIndex, final List<FskSimulation> simulations) {
this.selectedSimulationIndex = selectedSimulationIndex;
this.simulations = simulations;
}
}
/**
* @return SimulationSettings with selected simulation index and list of simulations.
*
* <p>
* In SedML every simulation is encoded as a {@link org.jlibsedml.Model} with the
* parameter values defined as a {@link org.jlibsedml.ChangeAttribute}.
* </p>
*
* <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 SimulationSettings readSimulationSettings(ArchiveEntry simulationsEntry)
throws IOException, XMLException {
// Create temporary file for extracting SEDML and read it.
File tempFile = File.createTempFile("simulations", ".sedml");
simulationsEntry.extractFile(tempFile);
// Read SEDML and delete temporary file
SedML sedml = Libsedml.readDocument(tempFile).getSedMLModel();
tempFile.delete();
// Read selected simulation
int selectedSimulationIndex = 0;
final List<org.jlibsedml.Annotation> annotations = sedml.getAnnotation();
if (annotations != null && annotations.size() > 0) {
org.jlibsedml.Annotation indexAnnotation = annotations.get(0);
Text indexAnnotationText = (Text) indexAnnotation.getAnnotationElement().getContent().get(0);
selectedSimulationIndex = Integer.parseInt(indexAnnotationText.getText());
}
// Read simulations
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 new SimulationSettings(selectedSimulationIndex, simulations);
}
}