SiLeBAT/FSK-Lab

View on GitHub
de.bund.bfr.knime.fsklab.deprecatednodes/src-1_9_0/de/bund/bfr/knime/fsklab/v1_9/editor/FSKEditorJSNodeDialog.java

Summary

Maintainability
F
3 days
Test Coverage
/*
 ***************************************************************************************************
 * 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.editor;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import org.apache.commons.lang3.StringUtils;
import org.knime.core.node.DataAwareNodeDialogPane;
import org.knime.core.node.FlowVariableModel;
import org.knime.core.node.InvalidSettingsException;
import org.knime.core.node.NodeSettingsRO;
import org.knime.core.node.NodeSettingsWO;
import org.knime.core.node.NotConfigurableException;
import org.knime.core.node.port.PortObject;
import org.knime.core.node.port.PortObjectSpec;
import org.knime.core.node.util.FilesHistoryPanel;
import org.knime.core.node.util.FilesHistoryPanel.LocationValidation;
import org.knime.core.node.workflow.FlowVariable;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

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.environment.ExistingEnvironmentManager;
import de.bund.bfr.knime.fsklab.nodes.environment.FilesEnvironmentManager;
import de.bund.bfr.knime.fsklab.nodes.v1_9.NodeUtils;
import de.bund.bfr.knime.fsklab.v1_9.FskPortObject;
import de.bund.bfr.metadata.swagger.Model;

public class FSKEditorJSNodeDialog extends DataAwareNodeDialogPane {

  private static final String README_FILE = "readmeFile";

  /** Absolute path to readme file. */
  private String m_readmeFile;

  private final FSKEditorJSConfig m_config;

  private final DefaultComboBoxModel<ModelType> modelTypeComboBoxModel;
  private final FilesHistoryPanel m_readmePanel;

  private final JTextField m_workingDirectoryField;

  private final JRadioButton m_archivedEnvironmentButton;
  private final JRadioButton m_directoryEnvironmentButton;
  private final JRadioButton m_filesEnvironmentButton;

  private final DefaultTableModel m_filesTableModel;

  private static final ObjectMapper MAPPER = FskPluginObjectMapper.MAPPER104;

  public enum ModelType {

    genericModel("Generic model"),
    dataModel("Data model"),
    consumptionModel("Consumption model"),
    doseResponseModel("Dose-response model"),
    exposureModel("Exposure model"),
    healthModel("Health metrics model"),
    otherModel("Other Empirical models"),
    predictiveModel("Predictive model"),
    processModel("Process model"),
    qraModel("QRA model"),
    riskModel("Risk characterization model"),
    toxicologicalModel("Toxicological reference value model");

    private final String displayString;

    private ModelType(String displayString) {
      this.displayString = displayString;
    }

    @Override
    public String toString() {
      return displayString;
    }
  }

  public FSKEditorJSNodeDialog() {

    m_config = new FSKEditorJSConfig();

    modelTypeComboBoxModel = new DefaultComboBoxModel<>(ModelType.values());

    FlowVariableModel readmeVariable = createFlowVariableModel("readme", FlowVariable.Type.STRING);
    m_readmePanel =
        new FilesHistoryPanel(readmeVariable, "readme", LocationValidation.None, ".txt");

    m_workingDirectoryField = new JTextField(80);
    m_workingDirectoryField.setEditable(false);

    // Radio buttons
    m_archivedEnvironmentButton = new JRadioButton("Archived environment");
    m_directoryEnvironmentButton = new JRadioButton("Directory environment");
    m_filesEnvironmentButton = new JRadioButton("Files environment");

    m_filesTableModel = new DefaultTableModel(0, 1);

    createUI();
  }

  /**
   * Update the dialog with the passed data.
   * 
   * @param modelType Non null model type.
   * @param readmeFile Empty string if not set.
   * @param environment Null if not set.
   */
  private void updateDialog(ModelType modelType, String readmeFile,
      EnvironmentManager environment) {
    modelTypeComboBoxModel.setSelectedItem(modelType);
    m_readmePanel.setSelectedFile(readmeFile);
    clearEnvironmentPanel();

    if (environment != null) {

      if (environment instanceof ArchivedEnvironmentManager) {
        ArchivedEnvironmentManager archivedEnvironment = (ArchivedEnvironmentManager) environment;

        m_archivedEnvironmentButton.setSelected(true);

        // Update m_workingDirectoryField
        m_workingDirectoryField.setEnabled(false);
        m_workingDirectoryField.setText(archivedEnvironment.getArchivePath());

        // Update m_filesTableModel
        for (String entry : archivedEnvironment.getEntries()) {
          String[] row = {entry};
          m_filesTableModel.addRow(row);
        }
      } else if (environment instanceof ExistingEnvironmentManager) {
        ExistingEnvironmentManager directoryManager = (ExistingEnvironmentManager) environment;

        m_archivedEnvironmentButton.setEnabled(false);
        m_directoryEnvironmentButton.setSelected(true);

        // Update m_workingDirectoryField
        m_workingDirectoryField.setEnabled(true);
        m_workingDirectoryField.setText(directoryManager.getEnvironmentPath());

        // Update m_filesTableModel
        File existingWorkingDirectory = new File(directoryManager.getEnvironmentPath());
        File[] files = existingWorkingDirectory.listFiles(File::isFile);
        if (files != null) {
          for (File file : files) {
            String[] row = {file.getAbsolutePath()};
            m_filesTableModel.addRow(row);
          }
        }

      } else if (environment instanceof FilesEnvironmentManager) {
        FilesEnvironmentManager filesManager = (FilesEnvironmentManager) environment;

        m_archivedEnvironmentButton.setEnabled(false);
        m_filesEnvironmentButton.setSelected(true);

        // Update m_workingDirectoryField
        m_workingDirectoryField.setEnabled(false);

        // Update m_filesTableModel
        String[] files = filesManager.getFiles();
        if (files != null) {
          for (String file : files) {
            String[] row = {file};
            m_filesTableModel.addRow(row);
          }
        }
      }
    }
  }

  /** Loads settings from saved settings. */
  @Override
  protected void loadSettingsFrom(NodeSettingsRO settings, PortObjectSpec[] specs)
      throws NotConfigurableException {

    m_config.loadSettingsForDialog(settings, specs[0]);

    ModelType modelType;
    try {
      modelType = ModelType.valueOf(m_config.getModelType());
    } catch (Exception err) {
      modelType = ModelType.genericModel;
    }

    String readmeFile = settings.getString(README_FILE, "");

    updateDialog(modelType, readmeFile, m_config.getEnvironmentManager());
  }

  @Override
  protected void loadSettingsFrom(NodeSettingsRO settings, PortObject[] input)
      throws NotConfigurableException {

    FskPortObject inputObject = (FskPortObject) input[0];
    try {
      m_config.loadSettings(settings);
    } catch (InvalidSettingsException e) {
      throw new NotConfigurableException(e.getMessage(), e);
    }

    ModelType modelType;
    try {
      if (StringUtils.isNotEmpty(m_config.getModelType())) {
        modelType = ModelType.valueOf(m_config.getModelType());
      } else if (inputObject.modelMetadata != null
          && StringUtils.isNotEmpty(inputObject.modelMetadata.getModelType())) {
        modelType = ModelType.valueOf(inputObject.modelMetadata.getModelType());
      } else {
        modelType = ModelType.genericModel;
      }
    } catch (IllegalArgumentException err) {
      modelType = ModelType.genericModel;
    }

    String readmeFile = settings.getString(README_FILE, "");

    // Environment. First load from settings and if empty try to get from input model.
    EnvironmentManager environment;
    if (m_config.getEnvironmentManager() != null) {
      environment = m_config.getEnvironmentManager();
    } else if (inputObject.getEnvironmentManager().isPresent()) {
      environment = inputObject.getEnvironmentManager().get();
    } else {
      environment = null;
    }

    updateDialog(modelType, readmeFile, environment);
  }

  @Override
  protected void saveSettingsTo(NodeSettingsWO settings) throws InvalidSettingsException {

    m_readmePanel.addToHistory();

    String modelType = ((ModelType) modelTypeComboBoxModel.getSelectedItem()).name();

    // If the model class has changed, then discard the metadata for now
    // TODO: the metadata must be converted between schemas
    if (!modelType.equals(m_config.getModelType())) {
      ModelType modelTypeEnum = ModelType.valueOf(modelType);
      Model metadata = NodeUtils.initializeModel(modelTypeEnum);
      try {
        String jsonMetadata = MAPPER.writeValueAsString(metadata);
        m_config.setModelMetaData(jsonMetadata);
      } catch (JsonProcessingException e) {
      }
    }

    m_config.setModelType(modelType);

    m_readmeFile = m_readmePanel.getSelectedFile().trim();
    settings.addString(README_FILE, m_readmeFile);

    // environment
    if (m_archivedEnvironmentButton.isSelected()) {
      // Take archive path
      String archivePath = m_workingDirectoryField.getText();
      // Take entries
      String[] entries = new String[m_filesTableModel.getRowCount()];
      for (int row = 0; row < m_filesTableModel.getRowCount(); row++) {
        entries[row] = (String) m_filesTableModel.getValueAt(row, 0);
      }
      // Create and set environment
      m_config.setEnvironmentManager(new ArchivedEnvironmentManager(archivePath, entries));
    } else if (m_directoryEnvironmentButton.isSelected()) {
      // Take directory path
      String directoryPath = m_workingDirectoryField.getText();
      // Create and set environment
      m_config.setEnvironmentManager(new ExistingEnvironmentManager(directoryPath));
    } else if (m_filesEnvironmentButton.isSelected()) {
      // Take entries
      String[] entries = new String[m_filesTableModel.getRowCount()];
      for (int row = 0; row < m_filesTableModel.getRowCount(); row++) {
        entries[row] = (String) m_filesTableModel.getValueAt(row, 0);
      }
      // Create and set environment
      m_config.setEnvironmentManager(new FilesEnvironmentManager(entries));
    }

    m_config.saveSettings(settings);
  }

  private void createUI() {

    // Model type panel
    final JPanel modelTypePanel = new JPanel(new BorderLayout());
    modelTypePanel.setBorder(
        BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Model Type:"));

    JComboBox<ModelType> combo = new JComboBox<>(modelTypeComboBoxModel);
    modelTypePanel.add(combo, BorderLayout.NORTH);

    modelTypePanel.add(Box.createHorizontalGlue());

    // Readme panel
    final JPanel readmePanel = new JPanel(new BorderLayout());
    readmePanel
        .setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Readme:"));
    readmePanel.add(m_readmePanel, BorderLayout.NORTH);
    readmePanel.add(Box.createHorizontalGlue());

    JPanel container = new JPanel();
    container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
    container.add(modelTypePanel);
    container.add(readmePanel);

    addTab("Options", container);

    // Environment tab

    // Working directory panel
    JButton workingDirectoryButton = new JButton("Browse");
    workingDirectoryButton.addActionListener(new WorkingDirectoryButtonListener());

    JPanel workingDirectoryPanel = new JPanel();
    workingDirectoryPanel.add(new JLabel("Working directory:"));
    workingDirectoryPanel.add(m_workingDirectoryField);
    workingDirectoryPanel.add(workingDirectoryButton);

    // Group the radio buttons.
    ButtonGroup group = new ButtonGroup();
    group.add(m_archivedEnvironmentButton);
    group.add(m_directoryEnvironmentButton);
    group.add(m_filesEnvironmentButton);

    // Register a listener for the radio buttons.
    m_archivedEnvironmentButton.addActionListener(new ArchivedEnvironmentButtonListener());
    m_directoryEnvironmentButton.addActionListener(new DirectoryEnvironmentButtonListener());
    m_filesEnvironmentButton.addActionListener(new FilesEnvironmentButtonListener());

    // Put the radio buttons in a row
    JPanel radioPanel = new JPanel();
    radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.X_AXIS));

    radioPanel.add(m_archivedEnvironmentButton);
    radioPanel.add(m_directoryEnvironmentButton);
    radioPanel.add(m_filesEnvironmentButton);

    // Files table: List files in directory
    JTable table = new JTable(m_filesTableModel);

    JPanel environmentContainer = new JPanel();
    environmentContainer.setLayout(new BoxLayout(environmentContainer, BoxLayout.Y_AXIS));
    environmentContainer.add(workingDirectoryPanel);
    environmentContainer.add(radioPanel);
    environmentContainer.add(table);

    addTab("Environment", environmentContainer);
  }

  private class ArchivedEnvironmentButtonListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
      clearEnvironmentPanel();
      m_workingDirectoryField.setEnabled(false);
    }
  }

  private class DirectoryEnvironmentButtonListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
      m_archivedEnvironmentButton.setEnabled(false);
      clearEnvironmentPanel();
      m_workingDirectoryField.setEnabled(true);
    }
  }

  private class FilesEnvironmentButtonListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
      m_archivedEnvironmentButton.setEnabled(false);
      clearEnvironmentPanel();
      m_workingDirectoryField.setEnabled(true);
    }
  }

  private class WorkingDirectoryButtonListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {

      if (m_directoryEnvironmentButton.isSelected()) {

        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        fileChooser.setMultiSelectionEnabled(false);
        if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {

          // Update m_workingDirectoryField
          File selectedFile = fileChooser.getSelectedFile();
          m_workingDirectoryField.setText(selectedFile.getAbsolutePath());

          // Update table model
          m_filesTableModel.setRowCount(0);
          File[] files = selectedFile.listFiles(File::isFile);
          if (files != null) {
            for (File file : files) {
              String[] row = {file.getAbsolutePath()};
              m_filesTableModel.addRow(row);
            }
          }
        }
      } else if (m_filesEnvironmentButton.isSelected()) {

        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fileChooser.setMultiSelectionEnabled(true);

        // Update table model
        if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
          m_filesTableModel.setRowCount(0);
          for (File file : fileChooser.getSelectedFiles()) {
            String[] row = {file.getAbsolutePath()};
            m_filesTableModel.addRow(row);
          }
        }
      }
    }
  }

  private void clearEnvironmentPanel() {
    m_workingDirectoryField.setText("");
    m_filesTableModel.setRowCount(0); // Clear table
  }
}