/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.components.doe.gui.properties;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.exec.OS;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.map.ObjectMapper;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ICellEditorValidator;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerDropAdapter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory;
import de.rcenvironment.components.doe.common.DOEAlgorithms;
import de.rcenvironment.components.doe.common.DOEConstants;
import de.rcenvironment.components.doe.common.DOEUtils;
import de.rcenvironment.core.component.api.LoopComponentConstants;
import de.rcenvironment.core.component.model.endpoint.api.EndpointDescription;
import de.rcenvironment.core.gui.utils.common.components.PropertyTabGuiHelper;
import de.rcenvironment.core.gui.utils.incubator.NumericalTextConstraintListener;
import de.rcenvironment.core.gui.workflow.editor.properties.ValidatingWorkflowNodePropertySection;
import de.rcenvironment.core.utils.common.JsonUtils;
/**
* Section for all design of experiments configurations.
*
* @author Sascha Zur
*/
public class DOESection extends ValidatingWorkflowNodePropertySection {
protected static final Log LOGGER = LogFactory.getLog(DOESection.class);
private static final String ERROR = "Error";
private static final String NULL = "null";
private static final String COULD_NOT_READ_TABLE_ERROR = "Could not read table. ";
private static final int MAX_GUI_ELEMENTS;
// Since there is a bug with linux systems which lets RCE crash, there must be a constraint that
// is lower than the windows constraint for GUI elements.
// The bug is an xserver bug, which occurs having an intel graphics card. It is described in
// this thread:
// https://forums.opensuse.org/showthread.php/389147-X-Error-of-failed-request-BadAlloc-%28insufficient-resources
static {
if (OS.isFamilyUnix()) {
final int value = 2000;
MAX_GUI_ELEMENTS = value;
} else {
final int value = 10000;
MAX_GUI_ELEMENTS = value;
}
}
private Combo algorithmSelection;
private Button loadTable;
private Button saveTable;
private Table table;
private Composite tableComposite;
private Label runLabel;
private Spinner runSpinner;
private Label seedLabel;
private Spinner seedSpinner;
private Button codedValuesButton;
private Text startSample;
private Text endSample;
private TableViewer viewer;
private String[][] tableValues;
private Label outputsWarningLabel;
private Button clearTableButton;
@Override
protected void createCompositeContent(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage) {
super.createCompositeContent(parent, aTabbedPropertySheetPage);
TabbedPropertySheetWidgetFactory factory = aTabbedPropertySheetPage.getWidgetFactory();
final Section sectionProperties = factory.createSection(parent, Section.TITLE_BAR | Section.EXPANDED);
sectionProperties.setText(Messages.sectionHeader);
sectionProperties.marginWidth = 5;
sectionProperties.marginHeight = 5;
Composite mainComposite = new Composite(sectionProperties, SWT.NONE);
mainComposite.setLayout(new GridLayout(1, false));
mainComposite.setBackground(Display.getCurrent().getSystemColor(1));
GridData mainData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
mainComposite.setLayoutData(mainData);
Composite algorithmComposite = new Composite(mainComposite, SWT.NONE);
algorithmComposite.setLayout(new GridLayout(4, false));
algorithmComposite.setBackground(Display.getCurrent().getSystemColor(1));
algorithmSelection = new Combo(algorithmComposite, SWT.BORDER | SWT.READ_ONLY);
algorithmSelection.setItems(DOEConstants.ALGORITMS);
GridData selectionData = new GridData(GridData.FILL_BOTH);
selectionData.horizontalSpan = 2;
algorithmSelection.setLayoutData(selectionData);
seedLabel = new Label(algorithmComposite, SWT.None);
seedLabel.setText(Messages.seedLabel);
seedSpinner = new Spinner(algorithmComposite, SWT.BORDER);
seedSpinner.setMaximum(Integer.MAX_VALUE);
seedSpinner.setData(CONTROL_PROPERTY_KEY, DOEConstants.KEY_SEED_NUMBER);
seedSpinner.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent arg0) {
fillTable();
}
});
Composite runComposite = new Composite(algorithmComposite, SWT.NONE);
GridLayout runLayout = new GridLayout(2, false);
runLayout.marginWidth = 0;
runComposite.setLayout(runLayout);
GridData runData = new GridData();
runData.horizontalSpan = 4;
runData.horizontalIndent = 0;
runComposite.setLayoutData(runData);
runLabel = new Label(runComposite, SWT.NONE);
runSpinner = new Spinner(runComposite, SWT.BORDER);
runSpinner.setData(CONTROL_PROPERTY_KEY, DOEConstants.KEY_RUN_NUMBER);
runSpinner.setMaximum(Integer.MAX_VALUE);
runSpinner.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent arg0) {
fillTable();
}
});
GridData spinnerData = new GridData();
runSpinner.setLayoutData(spinnerData);
GridLayout failedrunLayout = new GridLayout(3, false);
failedrunLayout.marginWidth = 0;
tableComposite = new Composite(mainComposite, SWT.NONE);
tableComposite.setLayout(failedrunLayout);
tableComposite.setBackground(Display.getCurrent().getSystemColor(1));
GridData tableData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
tableComposite.setLayoutData(tableData);
Label startLabel = new Label(tableComposite, SWT.NONE);
startLabel.setText(Messages.sampleStart);
startSample = new Text(tableComposite, SWT.BORDER);
GridData startData = new GridData();
final int minWidthSamples = 60;
startData.widthHint = minWidthSamples;
startData.horizontalSpan = 2;
startSample.addVerifyListener(new NumericalTextConstraintListener(startSample, NumericalTextConstraintListener.ONLY_INTEGER
| NumericalTextConstraintListener.GREATER_OR_EQUAL_ZERO));
startSample.setLayoutData(startData);
startSample.setData(CONTROL_PROPERTY_KEY, DOEConstants.KEY_START_SAMPLE);
new Label(tableComposite, SWT.NONE).setText(Messages.sampleEnd);
endSample = new Text(tableComposite, SWT.BORDER);
GridData endData = new GridData();
endData.widthHint = minWidthSamples;
endData.horizontalSpan = 2;
endSample.setLayoutData(endData);
endSample.addVerifyListener(new NumericalTextConstraintListener(endSample, NumericalTextConstraintListener.ONLY_INTEGER
| NumericalTextConstraintListener.GREATER_OR_EQUAL_ZERO));
endSample.setData(CONTROL_PROPERTY_KEY, DOEConstants.KEY_END_SAMPLE);
addTableComposite();
algorithmSelection.addSelectionListener(new AlgorithmSelectionListener());
sectionProperties.setClient(mainComposite);
}
private void addTableComposite() {
Composite buttonsComp = new Composite(tableComposite, SWT.NONE);
GridLayout tableLayout = new GridLayout(5, false);
tableLayout.marginWidth = 0;
buttonsComp.setLayout(tableLayout);
GridData buttonsData = new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_BOTH);
buttonsData.horizontalSpan = 3;
buttonsComp.setLayoutData(buttonsData);
saveTable = new Button(buttonsComp, SWT.PUSH);
saveTable.setText(Messages.saveTableButton);
saveTable.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent arg0) {
saveTable();
}
@Override
public void widgetDefaultSelected(SelectionEvent arg0) {
widgetSelected(arg0);
}
});
loadTable = new Button(buttonsComp, SWT.PUSH);
loadTable.setText(Messages.loadTableButton);
loadTable.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent arg0) {
loadTable();
}
@Override
public void widgetDefaultSelected(SelectionEvent arg0) {
widgetSelected(arg0);
}
});
GridData loadData = new GridData();
loadTable.setLayoutData(loadData);
clearTableButton = new Button(buttonsComp, SWT.PUSH);
clearTableButton.setText("Clear table");
clearTableButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent arg0) {
setProperty(DOEConstants.KEY_TABLE, "");
fillTableHeader();
fillTable();
refreshSection();
}
@Override
public void widgetDefaultSelected(SelectionEvent arg0) {
widgetSelected(arg0);
}
});
codedValuesButton = new Button(buttonsComp, SWT.CHECK);
codedValuesButton.setText(Messages.codedValuesButton);
codedValuesButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent arg0) {
widgetSelected(arg0);
}
@Override
public void widgetSelected(SelectionEvent arg0) {
fillTable();
}
});
outputsWarningLabel = new Label(buttonsComp, SWT.NONE);
outputsWarningLabel.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
viewer = new TableViewer(buttonsComp, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
int operations = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_DEFAULT;
Transfer[] transferTypes = new Transfer[] { FileTransfer.getInstance() };
viewer.addDropSupport(operations, transferTypes, new TableDropListener(viewer));
viewer.setContentProvider(ArrayContentProvider.getInstance());
viewer.setInput(tableValues);
table = viewer.getTable();
table.setLinesVisible(true);
table.setHeaderVisible(true);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
final int minHeight = 200;
data.minimumHeight = minHeight;
data.horizontalSpan = 5;
table.setLayoutData(data);
}
private void saveTable() {
FileDialog dialog = new FileDialog(tableComposite.getShell(), SWT.SAVE);
dialog.setFilterExtensions(new String[] { "*" + DOEConstants.TABLE_FILE_EXTENTION, "*.*" });
String path = dialog.open();
List<String> outputs = new LinkedList<>();
for (EndpointDescription e : getOutputs()) {
outputs.add(e.getName());
}
Collections.sort(outputs);
DOEUtils.writeTableToCSVFile(tableValues, path, outputs);
}
private void loadTable() {
String path = PropertyTabGuiHelper.selectFileFromFileSystem(tableComposite.getShell(),
new String[] { "*.csv", "*.*" }, "Open table file...");
if (path != null) {
loadTableFromFile(path);
}
}
private boolean loadTableFromFile(String path) {
boolean success = true;
try {
File csvData = new File(path);
CSVParser parser =
CSVParser.parse(FileUtils.readFileToString(csvData),
CSVFormat.newFormat(';').withIgnoreSurroundingSpaces().withAllowMissingColumnNames().withRecordSeparator("\n"));
List<CSVRecord> records = parser.getRecords();
if (Character.isLetter((records.get(0).get(0).charAt(0)))) {
records.remove(0);
}
String[][] values = new String[records.size()][];
int count = 0;
for (CSVRecord record : records) {
int size = getOutputs().size();
values[count] = new String[size];
for (int i = 0; i < size; i++) {
if (record.size() > i) {
String number = record.get(i);
if (number.equals("null")) {
values[count][i] = "";
} else {
Matcher matcher = Pattern.compile("(\\+|-)?\\d+(,|.)?\\d*(e|E)?(\\+|-)?\\d*").matcher(number);
if (count == 0 && i == 0 && matcher.find()) {
number = matcher.group();
}
values[count][i] = number.replaceAll("\"", " ").replaceAll(",", ".");
}
} else {
values[count][i] = "";
}
}
count++;
}
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
setProperty(DOEConstants.KEY_TABLE, mapper.writeValueAsString(values));
setProperty(DOEConstants.KEY_START_SAMPLE, "0");
setProperty(DOEConstants.KEY_END_SAMPLE, Integer.toString(count - 1));
setProperty(DOEConstants.KEY_RUN_NUMBER, Integer.toString(count));
setProperty(DOEConstants.KEY_METHOD, DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE);
algorithmSelection.select(algorithmSelection.indexOf(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE));
refreshSection();
if (values[0] != null && values[0].length > getOutputs().size()) {
MessageDialog.openInformation(this.getComposite().getShell(), "Warning",
"There are more values per run in the loaded table than outputs defined.");
}
} catch (IOException e) {
LOGGER.error(e);
success = false;
if (!success) {
MessageDialog
.openInformation(this.getComposite().getShell(), ERROR, "Could not load table from file.\n\nReason: " + e.getMessage());
}
} catch (NumberFormatException e) {
LOGGER.error(e);
success = false;
if (!success) {
MessageDialog.openInformation(this.getComposite().getShell(), ERROR,
"Could not load table because of a syntax error.\n\nReason: " + e.getMessage());
}
}
return success;
}
private void fillTableHeader() {
if (this.getOutputs() != null) {
String[] titles = new String[this.getOutputs().size()];
int j = 0;
for (EndpointDescription e : this.getOutputs()) {
titles[j++] = e.getName();
}
Arrays.sort(titles);
table.setRedraw(false);
while (table.getColumnCount() > 0) {
table.getColumns()[0].dispose();
}
for (int i = 0; i < titles.length + 1; i++) {
TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
if (i == 0) {
column.getColumn().setText(Messages.sampleNum);
} else {
column.getColumn().setText(titles[i - 1]);
}
final int k = i;
column.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
String returnValue = "";
if (tableValues != null) {
if (k == 0) {
for (int i = 0; i < tableValues.length; i++) {
if (tableValues[i] == (String[]) element) {
returnValue = String.valueOf(i);
}
}
} else {
if (k - 1 < ((String[]) element).length) {
returnValue = String.valueOf(((String[]) element)[k - 1]);
}
}
}
if (returnValue == null || returnValue.equals(NULL)) {
returnValue = "";
}
return returnValue;
}
});
table.getColumn(i).pack();
if (i != 0) {
column.setEditingSupport(new TextEditingSupport(viewer, table, i));
}
}
for (int i = 0; i < titles.length; i++) {
table.getColumn(i).pack();
}
table.setRedraw(true);
}
}
@Override
public void refreshSection() {
super.refreshSection();
aboutToBeShown();
}
@Override
public void aboutToBeShown() {
super.aboutToBeShown();
fillTableHeader();
algorithmSelection.setText(getProperty(DOEConstants.KEY_METHOD));
fillTable();
updateActivation();
if (startSample.getText() != null && !startSample.getText().isEmpty() && getProperty(DOEConstants.KEY_START_SAMPLE) != null
&& !startSample.getText().equals(getProperty(DOEConstants.KEY_START_SAMPLE))) {
startSample.setText(getProperty(DOEConstants.KEY_START_SAMPLE));
}
if (endSample.getText() != null && !endSample.getText().isEmpty() && getProperty(DOEConstants.KEY_END_SAMPLE) != null
&& !endSample.getText().equals(getProperty(DOEConstants.KEY_END_SAMPLE))) {
endSample.setText(getProperty(DOEConstants.KEY_END_SAMPLE));
}
}
/**
* Fill the design table.
*/
public void fillTable() {
table.setRedraw(false);
table.clearAll();
if (getOutputs() == null) {
table.setRedraw(true);
return;
}
int varCount = getOutputs().size();
if (varCount < 2 && !(algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE)
|| algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_MONTE_CARLO))) {
table.setRedraw(true);
return;
}
tableValues = createTableValues();
if (tableValues != null && !(tableValues.length * varCount > MAX_GUI_ELEMENTS)) {
outputsWarningLabel.setVisible(false);
viewer.setInput(tableValues);
String[] endpointNames = new String[this.getOutputs().size()];
int j = 0;
for (EndpointDescription e : this.getOutputs()) {
endpointNames[j++] = e.getName();
}
Arrays.sort(endpointNames);
for (int i = 0; i < tableValues.length; i++) {
TableItem current = null;
if (table.getItemCount() == 0 || table.getItemCount() <= i) {
current = new TableItem(table, SWT.NONE);
} else {
current = table.getItem(i);
}
current.setText(0, String.valueOf(i));
for (int k = 0; k < tableValues[i].length; k++) {
if (!getProperty(DOEConstants.KEY_METHOD).equals(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE)
&& codedValuesButton.getSelection()) {
EndpointDescription currentEndpoint = null;
for (EndpointDescription e : getOutputs()) {
if (e.getName().equals(endpointNames[k])) {
currentEndpoint = e;
}
}
if (currentEndpoint != null && tableValues != null && tableValues[i] != null && tableValues[i][k] != null) {
Double low = Double.valueOf(currentEndpoint.getMetaDataValue(DOEConstants.META_KEY_LOWER));
Double up = Double.valueOf(currentEndpoint.getMetaDataValue(DOEConstants.META_KEY_UPPER));
tableValues[i][k] = String.valueOf(DOEAlgorithms.convertValue(low, up,
Double.parseDouble(tableValues[i][k])));
}
}
}
}
viewer.refresh();
for (TableColumn c : table.getColumns()) {
c.pack();
}
} else if (outputsWarningLabel != null && tableValues != null && (tableValues.length * varCount > MAX_GUI_ELEMENTS)) {
outputsWarningLabel.setVisible(true);
outputsWarningLabel.setText(Messages.tooMuchElements);
outputsWarningLabel.pack();
} else {
viewer.setInput(tableValues);
}
table.setRedraw(true);
}
private String[][] createTableValues() {
int varCount = getOutputs().size();
if (varCount == 0) {
return null;
}
int runCount = 0;
if (runSpinner != null) {
runCount = runSpinner.getSelection();
}
int seedCount = 0;
if (seedSpinner != null) {
seedCount = seedSpinner.getSelection();
}
Double[][] tableValuesDouble = null;
switch (algorithmSelection.getText()) {
case DOEConstants.DOE_ALGORITHM_FULLFACT:
if (runSpinner.getSelection() >= 2) {
tableValuesDouble = DOEAlgorithms.populateTableFullFactorial(varCount, runCount);
} else {
runSpinner.setSelection(2);
}
break;
case DOEConstants.DOE_ALGORITHM_LHC:
tableValuesDouble = DOEAlgorithms.populateTableLatinHypercube(varCount, runCount, seedCount);
break;
case DOEConstants.DOE_ALGORITHM_MONTE_CARLO:
tableValuesDouble = DOEAlgorithms.populateTableMonteCarlo(varCount, runCount, seedCount);
break;
case DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE:
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
try {
if (getProperty(DOEConstants.KEY_TABLE) != null && !getProperty(DOEConstants.KEY_TABLE).isEmpty()) {
tableValuesDouble = mapper.readValue(getProperty(DOEConstants.KEY_TABLE), Double[][].class);
}
if (tableValuesDouble != null && runCount != tableValuesDouble.length) {
tableValuesDouble = Arrays.copyOf(tableValuesDouble, runCount);
}
if (getProperty(DOEConstants.KEY_END_SAMPLE) != null && tableValuesDouble != null
&& !getProperty(DOEConstants.KEY_END_SAMPLE).isEmpty()
&& Double.parseDouble(getProperty(DOEConstants.KEY_END_SAMPLE)) >= tableValuesDouble.length
&& runCount > 0) {
setProperty(DOEConstants.KEY_END_SAMPLE, String.valueOf(runCount - 1));
}
} catch (IOException e) {
LOGGER.error(COULD_NOT_READ_TABLE_ERROR, e);
}
break;
default:
break;
}
if (tableValuesDouble != null && tableValuesDouble.length > 0) {
String[][] returnValues = new String[tableValuesDouble.length][tableValuesDouble[0].length];
for (int i = 0; i < tableValuesDouble.length; i++) {
if (tableValuesDouble[i] != null) {
returnValues[i] = new String[tableValuesDouble[i].length];
for (int j = 0; j < tableValuesDouble[i].length; j++) {
returnValues[i][j] = String.valueOf(tableValuesDouble[i][j]);
}
} else {
returnValues[i] = new String[varCount];
Arrays.fill(returnValues[i], "");
}
}
this.tableValues = returnValues;
return returnValues;
} else {
if (!DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE.equals(algorithmSelection.getText())) {
this.tableValues = new String[0][varCount];
} else {
this.tableValues = new String[runCount][varCount];
}
return this.tableValues;
}
}
private void updateActivation() {
loadTable.setEnabled(algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE));
startSample.setEnabled(algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE));
endSample.setEnabled(algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE));
runLabel.setEnabled(true);
runSpinner.setEnabled(true);
seedSpinner.setEnabled(false);
seedLabel.setEnabled(false);
codedValuesButton.setEnabled(true);
clearTableButton.setEnabled(false);
if (algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_FULLFACT)) {
runLabel.setText(Messages.numLevelsLabel);
} else if (algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_LHC)) {
runLabel.setText(Messages.desiredRunsLabel);
seedSpinner.setEnabled(true);
seedLabel.setEnabled(true);
} else if (algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_MONTE_CARLO)) {
runLabel.setText(Messages.desiredRunsLabel);
seedSpinner.setEnabled(true);
seedLabel.setEnabled(true);
} else {
runLabel.setText(Messages.desiredRunsLabel);
runLabel.setEnabled(true);
runSpinner.setEnabled(true);
codedValuesButton.setEnabled(false);
clearTableButton.setEnabled(true);
}
table.setEnabled(true);
saveTable.setEnabled(true);
loadTable.setEnabled(true);
if (getOutputs().size() >= 2) {
if (algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE)
&& (getProperty(DOEConstants.KEY_TABLE) == null || getProperty(DOEConstants.KEY_TABLE).isEmpty())) {
outputsWarningLabel.setVisible(true);
outputsWarningLabel.setText(Messages.noTableLong);
} else if (algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE)
&& (getProperty(DOEConstants.KEY_TABLE) != null)) {
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
try {
Double[][] tableValuesDouble = mapper.readValue(getProperty(DOEConstants.KEY_TABLE), Double[][].class);
for (int i = 0; (i < Integer.parseInt(
getProperty(DOEConstants.KEY_RUN_NUMBER)) && (tableValuesDouble != null) && i < tableValuesDouble.length); i++) {
for (int j = 0; j < tableValuesDouble[i].length; j++) {
if (tableValuesDouble[i][j] == null) {
outputsWarningLabel.setVisible(true);
outputsWarningLabel.setText(Messages.noTableLong);
}
}
if (outputsWarningLabel.isVisible()) {
break;
}
}
} catch (IOException e) {
logger.error(e.getStackTrace());
}
} else {
outputsWarningLabel.setVisible(false);
}
} else if (getOutputs().size() < 2 && (algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_FULLFACT)
|| algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_LHC))) {
outputsWarningLabel.setVisible(true);
outputsWarningLabel.setText(Messages.minTwoOutputs);
saveTable.setEnabled(false);
loadTable.setEnabled(false);
clearTableButton.setEnabled(false);
table.setEnabled(false);
codedValuesButton.setEnabled(false);
} else if (getOutputs().size() == 1) {
outputsWarningLabel.setVisible(false);
} else {
outputsWarningLabel.setVisible(true);
outputsWarningLabel.setText(Messages.minOneOutput);
saveTable.setEnabled(false);
table.setEnabled(false);
loadTable.setEnabled(false);
clearTableButton.setEnabled(false);
codedValuesButton.setEnabled(false);
}
if (outputsWarningLabel != null && !outputsWarningLabel.isVisible()
&& ((tableValues != null && (tableValues.length * getOutputs().size() > MAX_GUI_ELEMENTS || tableValues.length == 0)))) {
outputsWarningLabel.setVisible(true);
outputsWarningLabel.setText(Messages.tooMuchElements);
}
if (!outputsWarningLabel.isVisible() && algorithmSelection.getText().equals(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE)
&& (tableValues == null || tableValues.length == 0 || tableValues[0] == null)) {
outputsWarningLabel.setVisible(true);
outputsWarningLabel.setText(Messages.noTableLong);
}
outputsWarningLabel.pack();
runLabel.getParent().pack();
}
/**
*
* @author Sascha Zur
*/
private class AlgorithmSelectionListener implements SelectionListener {
@Override
public void widgetDefaultSelected(SelectionEvent arg0) {
widgetSelected(arg0);
}
@Override
public void widgetSelected(SelectionEvent arg0) {
setProperty(DOEConstants.KEY_METHOD, algorithmSelection.getText());
updateActivation();
fillTable();
refreshSection();
}
}
/**
* Adds editing a cell in the table.
*
* @author Sascha Zur
*/
private class TextEditingSupport extends EditingSupport {
private final TextCellEditor editor;
private final int columnNumber;
private final ColumnViewer viewer;
TextEditingSupport(ColumnViewer viewer, Table table, int columnNumber) {
super(viewer);
this.editor = new TextCellEditor(table);
editor.setValidator(new ICellEditorValidator() {
@Override
public String isValid(Object arg0) {
try {
Double.parseDouble((String) arg0);
} catch (NumberFormatException e) {
if (((String) arg0).isEmpty()) {
return null;
}
return "No";
}
return null;
}
});
this.columnNumber = columnNumber;
this.viewer = viewer;
}
@Override
protected boolean canEdit(Object arg0) {
if (getProperty(DOEConstants.KEY_METHOD).equals(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE)) {
return true;
}
return false;
}
@Override
protected CellEditor getCellEditor(Object arg0) {
return editor;
}
@Override
protected Object getValue(Object arg0) {
Object returnValue = ((String[]) arg0)[columnNumber - 1];
if (returnValue == null || returnValue.equals(NULL)) {
returnValue = "";
}
return returnValue;
}
@Override
protected void setValue(Object arg0, Object arg1) {
((String[]) arg0)[columnNumber - 1] = (String) arg1;
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
String[][] eliminateNull = ((String[][]) viewer.getInput());
for (int i = 0; i < eliminateNull.length; i++) {
for (int j = 0; j < eliminateNull[i].length; j++) {
if (eliminateNull[i][j] == null || eliminateNull[i][j].equals(NULL)) {
eliminateNull[i][j] = "";
}
}
}
try {
setProperty(DOEConstants.KEY_TABLE, mapper.writeValueAsString(viewer.getInput()));
} catch (IOException e) {
LOGGER.error(e);
}
viewer.refresh();
refreshSection();
}
}
/**
* Drop listener for the table, so .csv files can be dropped on it and will be loaded.
*
* @author Sascha Zur
*/
public class TableDropListener extends ViewerDropAdapter {
protected TableDropListener(Viewer viewer) {
super(viewer);
}
@Override
public void drop(DropTargetEvent event) {
super.drop(event);
}
@Override
public boolean performDrop(Object arg0) {
String[] fileDrops = (String[]) arg0;
if (fileDrops.length != 1 || !fileDrops[0].endsWith(DOEConstants.TABLE_FILE_EXTENTION)) {
return false;
} else {
String fileLocation = fileDrops[0];
boolean success = loadTableFromFile(fileLocation);
if (success) {
algorithmSelection.select(algorithmSelection.indexOf(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE));
setProperty(DOEConstants.KEY_METHOD, DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE);
updateActivation();
fillTable();
}
}
return true;
}
@Override
public boolean validateDrop(Object arg0, int arg1, TransferData arg2) {
return true;
}
}
@Override
protected Set<EndpointDescription> getOutputs() {
Set<EndpointDescription> outputs = new HashSet<>(super.getOutputs());
Iterator<EndpointDescription> outputsIterator = outputs.iterator();
while (outputsIterator.hasNext()) {
EndpointDescription next = outputsIterator.next();
if (LoopComponentConstants.ENDPOINT_ID_TO_FORWARD.equals(next.getDynamicEndpointIdentifier())
|| LoopComponentConstants.ENDPOINT_NAME_LOOP_DONE.equals(next.getName())
|| DOEConstants.OUTPUT_NAME_NUMBER_OF_SAMPLES.equals(next.getName())) {
outputsIterator.remove();
}
}
return outputs;
}
}