SiLeBAT/FSK-Lab

View on GitHub
de.bund.bfr.knime.pmm.nodes/src/de/bund/bfr/knime/pmm/sbmlreader/SBMLReaderNodeModel.java

Summary

Maintainability
C
1 day
Test Coverage
/*******************************************************************************
 * 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.pmm.sbmlreader;

import java.io.File;
import java.io.IOException;

import javax.xml.stream.XMLStreamException;

import org.knime.core.data.DataTableSpec;
import org.knime.core.node.BufferedDataContainer;
import org.knime.core.node.BufferedDataTable;
import org.knime.core.node.CanceledExecutionException;
import org.knime.core.node.ExecutionContext;
import org.knime.core.node.ExecutionMonitor;
import org.knime.core.node.InvalidSettingsException;
import org.knime.core.node.NodeModel;
import org.knime.core.node.NodeSettingsRO;
import org.knime.core.node.NodeSettingsWO;
import org.knime.core.node.defaultnodesettings.SettingsModelString;
import org.sbml.jsbml.SBMLDocument;
import org.sbml.jsbml.SBMLReader;
import org.sbml.jsbml.ext.comp.CompConstants;
import org.sbml.jsbml.ext.comp.CompSBMLDocumentPlugin;
import org.sbml.jsbml.ext.comp.ModelDefinition;
import org.sbml.jsbml.xml.XMLNode;

import de.bund.bfr.knime.pmm.common.generictablemodel.KnimeTuple;
import de.bund.bfr.knime.pmm.common.reader.DataTuple;
import de.bund.bfr.knime.pmm.common.reader.Model1Tuple;
import de.bund.bfr.knime.pmm.common.reader.Model2Tuple;
import de.bund.bfr.knime.pmm.extendedtable.pmmtablemodel.Model1Schema;
import de.bund.bfr.knime.pmm.extendedtable.pmmtablemodel.Model2Schema;
import de.bund.bfr.knime.pmm.extendedtable.pmmtablemodel.SchemaFactory;
import de.bund.bfr.knime.pmm.extendedtable.pmmtablemodel.TimeSeriesSchema;
import de.bund.bfr.pmfml.ModelType;

public class SBMLReaderNodeModel extends NodeModel {

  // configuration keys
  public static final String CFGKEY_FILE = "filename";

  // persistent state
  private SettingsModelString filename = new SettingsModelString(CFGKEY_FILE, "");

  private ModelType modelType;
  private DataTableSpec tableSpec;

  /**
   * Constructor for the node model
   */
  protected SBMLReaderNodeModel() {
    // 0 input ports and 1 input port
    super(0, 1);
  }

  @Override
  protected BufferedDataTable[] execute(final BufferedDataTable[] inData,
      final ExecutionContext exec) throws Exception {

    // Gets model type from the document annotation
    SBMLDocument doc = new SBMLReader().readSBML(filename.getStringValue());

    KnimeTuple tuple;

    if (modelType == ModelType.PRIMARY_MODEL_WDATA || modelType == ModelType.PRIMARY_MODEL_WODATA) {
      tuple = readPrimaryModel(doc);
    } else if (modelType == ModelType.TWO_STEP_SECONDARY_MODEL) {
      tuple = readTwoStepSecondaryModel(doc);
    } else if (modelType == ModelType.ONE_STEP_SECONDARY_MODEL) {
      tuple = readOneStepSecondaryModel(doc);
    } else if (modelType == ModelType.MANUAL_SECONDARY_MODEL) {
      tuple = readManualSecondaryModel(doc);
    } else {
      throw new InvalidSettingsException("Invalid model type.\n"
          + "This error should have been detected in #validateSettings");
    }

    BufferedDataContainer container = exec.createDataContainer(tableSpec);
    container.addRowToTable(tuple);
    container.close();
    exec.setProgress(1.0);

    return new BufferedDataTable[] {container.getTable()};
  }

  @Override
  protected DataTableSpec[] configure(final DataTableSpec[] inSpecs)
      throws InvalidSettingsException {

    /*
     * The modelType is assigned in the validate method. Possible values are: PRIMARY_MODEL_WDATA,
     * PRIMARY_MODEL_WODATA, TWO_STEP_SECONDARY_MODEL, ONE_STEP_SECONDARY_MODEL and
     * MANUAL_SECONDARY_MODEL
     */
    if (modelType == ModelType.PRIMARY_MODEL_WDATA || modelType == ModelType.PRIMARY_MODEL_WODATA) {
      tableSpec = SchemaFactory.createM1DataSchema().createSpec();
    } else if (modelType == ModelType.TWO_STEP_SECONDARY_MODEL
        || modelType == ModelType.MANUAL_SECONDARY_MODEL) {
      tableSpec = SchemaFactory.createM2Schema().createSpec();
    } else if (modelType == ModelType.ONE_STEP_SECONDARY_MODEL) {
      tableSpec = SchemaFactory.createM12DataSchema().createSpec();
    } else {
      throw new InvalidSettingsException("Invalid model type.\n"
          + "This error should have been detected in #validateSettings");
    }

    return new DataTableSpec[] {tableSpec};
  }

  @Override
  protected void saveSettingsTo(final NodeSettingsWO settings) {
    filename.saveSettingsTo(settings);
  }

  @Override
  protected void loadValidatedSettingsFrom(final NodeSettingsRO settings)
      throws InvalidSettingsException {
    filename.loadSettingsFrom(settings);
  }

  @Override
  protected void validateSettings(final NodeSettingsRO settings) throws InvalidSettingsException {

    final String filenameVal = settings.getString(CFGKEY_FILE);

    if (filenameVal.isEmpty()) {
      throw new InvalidSettingsException("Node is not configured. Missing file path");
    }

    if (filenameVal.endsWith(".numl")) {
      throw new InvalidSettingsException("SBML Reader does not support NuML. NuML Reader does.");
    }

    // Gets model type from the document annotation
    SBMLDocument doc;
    try {
      doc = new SBMLReader().readSBML(filenameVal);
    } catch (XMLStreamException | IOException e) {
      throw new InvalidSettingsException(filenameVal + " cannot be opened");
    }

    XMLNode docMetadata = doc.getAnnotation().getNonRDFannotation().getChildElement("metadata", "");
    XMLNode typeNode = docMetadata.getChildElement("type", "");
    String modelTypeString = typeNode.getChild(0).getCharacters();
    modelType = ModelType.valueOf(modelTypeString);

    if (modelType == ModelType.TWO_STEP_TERTIARY_MODEL
        || modelType == ModelType.ONE_STEP_TERTIARY_MODEL
        || modelType == ModelType.MANUAL_TERTIARY_MODEL) {
      throw new InvalidSettingsException("Tertiary models not supported currently");
    }
  }

  @Override
  protected void loadInternals(final File internDir, final ExecutionMonitor exec)
      throws IOException, CanceledExecutionException {}

  @Override
  protected void reset() {}

  protected void saveInternals(final File internDir, final ExecutionMonitor exec)
      throws IOException, CanceledExecutionException {}

  // --- utility methods ---
  private static KnimeTuple readPrimaryModel(final SBMLDocument doc) {
    return mergeTuples(new DataTuple(doc).knimeTuple, new Model1Tuple(doc).knimeTuple);
  }

  private static KnimeTuple readTwoStepSecondaryModel(final SBMLDocument doc) {
    return new Model2Tuple(doc.getModel()).knimeTuple;
  }

  private static KnimeTuple readOneStepSecondaryModel(final SBMLDocument doc) {
    // Parses data columns
    final KnimeTuple dataTuple = new DataTuple(doc).knimeTuple;

    // Parses primary model
    final KnimeTuple m1Tuple = new Model1Tuple(doc).knimeTuple;

    // Parses secondary model
    CompSBMLDocumentPlugin secCompPlugin =
        (CompSBMLDocumentPlugin) doc.getPlugin(CompConstants.shortLabel);
    ModelDefinition secModel = secCompPlugin.getModelDefinition(0);
    final KnimeTuple m2Tuple = new Model2Tuple(secModel).knimeTuple;

    final KnimeTuple row = mergeTuples(dataTuple, m1Tuple, m2Tuple);
    return row;
  }

  private static KnimeTuple readManualSecondaryModel(final SBMLDocument doc) {
    return new Model2Tuple(doc.getModel()).knimeTuple;
  }
  
  // --- other utility methods ---
  
  private static KnimeTuple mergeTuples(final KnimeTuple dataTuple, final KnimeTuple m1Tuple) {
    final KnimeTuple tuple = new KnimeTuple(SchemaFactory.createM1DataSchema());

    // Copies data columns
    tuple.setValue(TimeSeriesSchema.ATT_CONDID, dataTuple.getInt(TimeSeriesSchema.ATT_CONDID));
    tuple.setValue(TimeSeriesSchema.ATT_COMBASEID,
        dataTuple.getString(TimeSeriesSchema.ATT_COMBASEID));
    tuple.setValue(TimeSeriesSchema.ATT_AGENT, dataTuple.getPmmXml(TimeSeriesSchema.ATT_AGENT));
    tuple.setValue(TimeSeriesSchema.ATT_MATRIX, dataTuple.getPmmXml(TimeSeriesSchema.ATT_MATRIX));
    tuple.setValue(TimeSeriesSchema.ATT_TIMESERIES,
        dataTuple.getPmmXml(TimeSeriesSchema.ATT_TIMESERIES));
    tuple.setValue(TimeSeriesSchema.ATT_MISC, dataTuple.getPmmXml(TimeSeriesSchema.ATT_MISC));
    tuple.setValue(TimeSeriesSchema.ATT_MDINFO, dataTuple.getPmmXml(TimeSeriesSchema.ATT_MDINFO));
    tuple.setValue(TimeSeriesSchema.ATT_LITMD, dataTuple.getPmmXml(TimeSeriesSchema.ATT_LITMD));
    tuple.setValue(TimeSeriesSchema.ATT_DBUUID, dataTuple.getString(TimeSeriesSchema.ATT_DBUUID));
    tuple.setValue(TimeSeriesSchema.ATT_METADATA,
        dataTuple.getPmmXml(TimeSeriesSchema.ATT_METADATA));

    // Copies model1 columns
    tuple.setValue(Model1Schema.ATT_MODELCATALOG, m1Tuple.getPmmXml(Model1Schema.ATT_MODELCATALOG));
    tuple.setValue(Model1Schema.ATT_DEPENDENT, m1Tuple.getPmmXml(Model1Schema.ATT_DEPENDENT));
    tuple.setValue(Model1Schema.ATT_INDEPENDENT, m1Tuple.getPmmXml(Model1Schema.ATT_INDEPENDENT));
    tuple.setValue(Model1Schema.ATT_PARAMETER, m1Tuple.getPmmXml(Model1Schema.ATT_PARAMETER));
    tuple.setValue(Model1Schema.ATT_ESTMODEL, m1Tuple.getPmmXml(Model1Schema.ATT_ESTMODEL));
    tuple.setValue(Model1Schema.ATT_MLIT, m1Tuple.getPmmXml(Model1Schema.ATT_MLIT));
    tuple.setValue(Model1Schema.ATT_EMLIT, m1Tuple.getPmmXml(Model1Schema.ATT_EMLIT));
    tuple.setValue(Model1Schema.ATT_DATABASEWRITABLE,
        m1Tuple.getInt(Model1Schema.ATT_DATABASEWRITABLE));
    tuple.setValue(Model1Schema.ATT_DBUUID, m1Tuple.getString(Model1Schema.ATT_DBUUID));
    tuple.setValue(Model1Schema.ATT_METADATA, m1Tuple.getPmmXml(Model1Schema.ATT_METADATA));

    return tuple;
  }

  private static KnimeTuple mergeTuples(final KnimeTuple dataTuple, final KnimeTuple m1Tuple,
      final KnimeTuple m2Tuple) {

    final KnimeTuple tuple = new KnimeTuple(SchemaFactory.createM12DataSchema());

    tuple.setValue(TimeSeriesSchema.ATT_CONDID, dataTuple.getInt(TimeSeriesSchema.ATT_CONDID));
    tuple.setValue(TimeSeriesSchema.ATT_COMBASEID,
        dataTuple.getString(TimeSeriesSchema.ATT_COMBASEID));
    tuple.setValue(TimeSeriesSchema.ATT_AGENT, dataTuple.getPmmXml(TimeSeriesSchema.ATT_AGENT));
    tuple.setValue(TimeSeriesSchema.ATT_MATRIX, dataTuple.getPmmXml(TimeSeriesSchema.ATT_MATRIX));
    tuple.setValue(TimeSeriesSchema.ATT_TIMESERIES,
        dataTuple.getPmmXml(TimeSeriesSchema.ATT_TIMESERIES));
    tuple.setValue(TimeSeriesSchema.ATT_MISC, dataTuple.getPmmXml(TimeSeriesSchema.ATT_MISC));
    tuple.setValue(TimeSeriesSchema.ATT_MDINFO, dataTuple.getPmmXml(TimeSeriesSchema.ATT_MDINFO));
    tuple.setValue(TimeSeriesSchema.ATT_LITMD, dataTuple.getPmmXml(TimeSeriesSchema.ATT_LITMD));
    tuple.setValue(TimeSeriesSchema.ATT_DBUUID, dataTuple.getString(TimeSeriesSchema.ATT_DBUUID));
    tuple.setValue(TimeSeriesSchema.ATT_METADATA,
        dataTuple.getPmmXml(TimeSeriesSchema.ATT_METADATA));

    // Copies model1 columns
    tuple.setValue(Model1Schema.ATT_MODELCATALOG, m1Tuple.getPmmXml(Model1Schema.ATT_MODELCATALOG));
    tuple.setValue(Model1Schema.ATT_DEPENDENT, m1Tuple.getPmmXml(Model1Schema.ATT_DEPENDENT));
    tuple.setValue(Model1Schema.ATT_INDEPENDENT, m1Tuple.getPmmXml(Model1Schema.ATT_INDEPENDENT));
    tuple.setValue(Model1Schema.ATT_PARAMETER, m1Tuple.getPmmXml(Model1Schema.ATT_PARAMETER));
    tuple.setValue(Model1Schema.ATT_ESTMODEL, m1Tuple.getPmmXml(Model1Schema.ATT_ESTMODEL));
    tuple.setValue(Model1Schema.ATT_MLIT, m1Tuple.getPmmXml(Model1Schema.ATT_MLIT));
    tuple.setValue(Model1Schema.ATT_EMLIT, m1Tuple.getPmmXml(Model1Schema.ATT_EMLIT));
    tuple.setValue(Model1Schema.ATT_DATABASEWRITABLE,
        m1Tuple.getInt(Model1Schema.ATT_DATABASEWRITABLE));
    tuple.setValue(Model1Schema.ATT_DBUUID, m1Tuple.getString(Model1Schema.ATT_DBUUID));
    tuple.setValue(Model1Schema.ATT_METADATA, m1Tuple.getPmmXml(Model1Schema.ATT_METADATA));

    // Copies model2 columns
    tuple.setValue(Model2Schema.ATT_MODELCATALOG, m2Tuple.getPmmXml(Model2Schema.ATT_MODELCATALOG));
    tuple.setValue(Model2Schema.ATT_DEPENDENT, m2Tuple.getPmmXml(Model2Schema.ATT_DEPENDENT));
    tuple.setValue(Model2Schema.ATT_INDEPENDENT, m2Tuple.getPmmXml(Model2Schema.ATT_INDEPENDENT));
    tuple.setValue(Model2Schema.ATT_PARAMETER, m2Tuple.getPmmXml(Model2Schema.ATT_PARAMETER));
    tuple.setValue(Model2Schema.ATT_ESTMODEL, m2Tuple.getPmmXml(Model2Schema.ATT_ESTMODEL));
    tuple.setValue(Model2Schema.ATT_MLIT, m2Tuple.getPmmXml(Model2Schema.ATT_MLIT));
    tuple.setValue(Model2Schema.ATT_EMLIT, m2Tuple.getPmmXml(Model2Schema.ATT_EMLIT));
    tuple.setValue(Model2Schema.ATT_DATABASEWRITABLE,
        m2Tuple.getInt(Model2Schema.ATT_DATABASEWRITABLE));
    tuple.setValue(Model2Schema.ATT_DBUUID, m2Tuple.getString(Model2Schema.ATT_DBUUID));
    tuple.setValue(Model2Schema.ATT_GLOBAL_MODEL_ID,
        m2Tuple.getInt(Model2Schema.ATT_GLOBAL_MODEL_ID));
    tuple.setValue(Model2Schema.ATT_METADATA, m2Tuple.getPmmXml(Model2Schema.ATT_METADATA));

    return tuple;
  }
}