blob: af57c4478db3262b50add68c8b01d7cc87374507 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2009 The University of Manchester
*
* Modifications to the initial code base are copyright of their
* respective authors, or their employers as appropriate.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
******************************************************************************/
package net.sf.taverna.t2.activities.spreadsheet.views;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
import javax.swing.ButtonGroup;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import javax.swing.text.PlainDocument;
import net.sf.taverna.t2.activities.spreadsheet.Range;
import net.sf.taverna.t2.activities.spreadsheet.SpreadsheetUtils;
import net.sf.taverna.t2.activities.spreadsheet.il8n.SpreadsheetImportUIText;
import net.sf.taverna.t2.lang.ui.DialogTextArea;
import net.sf.taverna.t2.lang.ui.icons.Icons;
import net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ActivityConfigurationPanel;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import uk.org.taverna.commons.services.ServiceRegistry;
import uk.org.taverna.scufl2.api.activity.Activity;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Configuration panel for the spreadsheet import activity.
*
* @author David Withers
*/
@SuppressWarnings("serial")
public class SpreadsheetImportConfigView extends ActivityConfigurationPanel {
private static final String INCONSISTENT_ROW_MESSAGE = SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.INCONSISTENT_ROW_MESSAGE");
private static final String INCONSISTENT_COLUMN_MESSAGE = SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.INCONSISTENT_COLUMN_MESSAGE");
private static final String FROM_COLUMN_ERROR_MESSAGE = SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.FROM_COLUMN_ERROR_MESSAGE");
private static final String TO_COLUMN_ERROR_MESSAGE = SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.TO_COLUMN_ERROR_MESSAGE");
private static final String FROM_ROW_ERROR_MESSAGE = SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.FROM_ROW_ERROR_MESSAGE");
private static final String TO_ROW_ERROR_MESSAGE = SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.TO_ROW_ERROR_MESSAGE");
private static final String DEFAULT_MESSAGE = SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.DEFAULT_MESSAGE");
private static final String EMPTY_FROM_ROW_ERROR_MESSAGE = SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.EMPTY_FROM_ROW_ERROR_MESSAGE");
private static final String EMPTY_FROM_COLUMN_ERROR_MESSAGE = SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.EMPTY_FROM_COLUMN_ERROR_MESSAGE");
private static final String EMPTY_TO_COLUMN_ERROR_MESSAGE = SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.EMPTY_TO_COLUMN_ERROR_MESSAGE");
private static final String DUPLICATE_PORT_NAME_ERROR_MESSAGE = SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.DUPLICATE_PORT_NAME_ERROR_MESSAGE");
private static Logger logger = Logger.getLogger(SpreadsheetImportConfigView.class);
private JPanel titlePanel, contentPanel, buttonPanel, page1, page2;
private JLabel titleLabel, titleIcon, rowLabel, columnLabel;
private JLabel emptyCellLabel, outputFormatLabel, outputFormatDelimiterLabel, columnMappingLabel;
private DialogTextArea titleMessage;
private JTextField columnFromValue, columnToValue, rowFromValue, rowToValue;
private JTextField emptyCellUserDefinedValue, outputFormatDelimiter;
private JCheckBox rowSelectAllOption, rowExcludeFirstOption, rowIgnoreBlankRows;
private ButtonGroup emptyCellButtonGroup, outputFormatButtonGroup;
private JRadioButton emptyCellEmptyStringOption, emptyCellUserDefinedOption,
emptyCellErrorValueOption;
private JRadioButton outputFormatMultiplePort, outputFormatSinglePort;
private JTable columnMappingTable;
private SpreadsheetImportConfigTableModel columnMappingTableModel;
private JButton nextButton, backButton;
private CardLayout cardLayout = new CardLayout();
private Stack<String> warningMessages = new Stack<String>();
private Stack<String> errorMessages = new Stack<String>();
private ObjectNode newConfiguration;
private final ServiceRegistry serviceRegistry;
/**
* Constructs a configuration view for an SpreadsheetImport Activity.
*
* @param activity
*/
public SpreadsheetImportConfigView(Activity activity, ServiceRegistry serviceRegistry) {
super(activity);
this.serviceRegistry = serviceRegistry;
initialise();
}
@Override
protected void initialise() {
super.initialise();
newConfiguration = getJson().deepCopy();
// title
titlePanel = new JPanel(new BorderLayout());
titlePanel.setBackground(Color.WHITE);
addDivider(titlePanel, SwingConstants.BOTTOM, true);
titleLabel = new JLabel(SpreadsheetImportUIText.getString("SpreadsheetImportConfigView.panelTitle"));
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 13.5f));
titleIcon = new JLabel("");
titleMessage = new DialogTextArea(DEFAULT_MESSAGE);
titleMessage.setMargin(new Insets(5, 10, 10, 10));
// titleMessage.setMinimumSize(new Dimension(0, 30));
titleMessage.setFont(titleMessage.getFont().deriveFont(11f));
titleMessage.setEditable(false);
titleMessage.setFocusable(false);
// titleMessage.setFont(titleLabel.getFont().deriveFont(Font.PLAIN,
// 12f));
// column range
columnLabel = new JLabel(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.columnSectionLabel"));
JsonNode columnRange = newConfiguration.get("columnRange");
columnFromValue = new JTextField(new UpperCaseDocument(), SpreadsheetUtils.getColumnLabel(columnRange.get("start").intValue()), 4);
columnFromValue.setMinimumSize(columnFromValue.getPreferredSize());
columnToValue = new JTextField(new UpperCaseDocument(), SpreadsheetUtils.getColumnLabel(columnRange.get("end").intValue()), 4);
columnToValue.setMinimumSize(columnToValue.getPreferredSize());
columnFromValue.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
}
public void insertUpdate(DocumentEvent e) {
checkValue(columnFromValue.getText());
}
public void removeUpdate(DocumentEvent e) {
checkValue(columnFromValue.getText());
}
private void checkValue(String text) {
if (text.trim().equals("")) {
addErrorMessage(EMPTY_FROM_COLUMN_ERROR_MESSAGE);
} else if (text.trim().matches("[A-Za-z]+")) {
String fromColumn = columnFromValue.getText().toUpperCase();
String toColumn = columnToValue.getText().toUpperCase();
int fromColumnIndex = SpreadsheetUtils.getColumnIndex(fromColumn);
int toColumnIndex = SpreadsheetUtils.getColumnIndex(toColumn);
if (checkColumnRange(fromColumnIndex, toColumnIndex)) {
columnMappingTableModel.setFromColumn(fromColumnIndex);
columnMappingTableModel.setToColumn(toColumnIndex);
newConfiguration.set("columnRange", newConfiguration.objectNode().put("start", fromColumnIndex).put("end", toColumnIndex));
validatePortNames();
}
removeErrorMessage(FROM_COLUMN_ERROR_MESSAGE);
removeErrorMessage(EMPTY_FROM_COLUMN_ERROR_MESSAGE);
} else {
addErrorMessage(FROM_COLUMN_ERROR_MESSAGE);
removeErrorMessage(EMPTY_FROM_COLUMN_ERROR_MESSAGE);
}
}
});
columnToValue.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
}
public void insertUpdate(DocumentEvent e) {
checkValue(columnToValue.getText());
}
public void removeUpdate(DocumentEvent e) {
checkValue(columnToValue.getText());
}
private void checkValue(String text) {
if (text.trim().equals("")) {
addErrorMessage(EMPTY_TO_COLUMN_ERROR_MESSAGE);
} else if (text.trim().matches("[A-Za-z]+")) {
String fromColumn = columnFromValue.getText().toUpperCase();
String toColumn = columnToValue.getText().toUpperCase();
int fromColumnIndex = SpreadsheetUtils.getColumnIndex(fromColumn);
int toColumnIndex = SpreadsheetUtils.getColumnIndex(toColumn);
if (checkColumnRange(fromColumnIndex, toColumnIndex)) {
columnMappingTableModel.setFromColumn(fromColumnIndex);
columnMappingTableModel.setToColumn(toColumnIndex);
newConfiguration.set("columnRange", newConfiguration.objectNode().put("start", fromColumnIndex).put("end", toColumnIndex));
validatePortNames();
}
removeErrorMessage(TO_COLUMN_ERROR_MESSAGE);
removeErrorMessage(EMPTY_TO_COLUMN_ERROR_MESSAGE);
} else {
addErrorMessage(TO_COLUMN_ERROR_MESSAGE);
removeErrorMessage(EMPTY_TO_COLUMN_ERROR_MESSAGE);
}
}
});
// row range
rowLabel = new JLabel(SpreadsheetImportUIText.getString("SpreadsheetImportConfigView.rowSectionLabel"));
addDivider(rowLabel, SwingConstants.TOP, false);
rowSelectAllOption = new JCheckBox(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.selectAllRowsOption"));
rowExcludeFirstOption = new JCheckBox(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.excludeHeaderRowOption"));
rowIgnoreBlankRows = new JCheckBox(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.ignoreBlankRowsOption"));
rowSelectAllOption.setFocusable(false);
rowExcludeFirstOption.setFocusable(false);
JsonNode rowRange = newConfiguration.get("rowRange");
rowFromValue = new JTextField(new NumericDocument(), String.valueOf(rowRange.get("start").intValue() + 1), 4);
if (rowRange.get("end").intValue() == -1) {
rowToValue = new JTextField(new NumericDocument(), "", 4);
} else {
rowToValue = new JTextField(new NumericDocument(), String.valueOf(rowRange.get("end").intValue() + 1), 4);
}
rowFromValue.setMinimumSize(rowFromValue.getPreferredSize());
rowToValue.setMinimumSize(rowToValue.getPreferredSize());
if (newConfiguration.get("allRows").booleanValue()) {
rowSelectAllOption.setSelected(true);
rowFromValue.setEditable(false);
rowFromValue.setEnabled(false);
rowToValue.setEditable(false);
rowToValue.setEnabled(false);
} else {
rowExcludeFirstOption.setEnabled(false);
}
rowExcludeFirstOption.setSelected(newConfiguration.get("excludeFirstRow").booleanValue());
rowIgnoreBlankRows.setSelected(newConfiguration.get("ignoreBlankRows").booleanValue());
rowFromValue.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
}
public void insertUpdate(DocumentEvent e) {
checkValue(rowFromValue.getText());
}
public void removeUpdate(DocumentEvent e) {
checkValue(rowFromValue.getText());
}
private void checkValue(String text) {
if (text.trim().equals("")) {
addErrorMessage(EMPTY_FROM_ROW_ERROR_MESSAGE);
} else if (text.trim().matches("[1-9][0-9]*")) {
checkRowRange(rowFromValue.getText(), rowToValue.getText());
int fromRow = Integer.parseInt(rowFromValue.getText());
((ObjectNode) newConfiguration.get("rowRange")).put("start", fromRow - 1);
removeErrorMessage(FROM_ROW_ERROR_MESSAGE);
removeErrorMessage(EMPTY_FROM_ROW_ERROR_MESSAGE);
} else {
addErrorMessage(FROM_ROW_ERROR_MESSAGE);
removeErrorMessage(EMPTY_FROM_ROW_ERROR_MESSAGE);
}
}
});
rowToValue.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
}
public void insertUpdate(DocumentEvent e) {
checkValue(rowToValue.getText());
}
public void removeUpdate(DocumentEvent e) {
checkValue(rowToValue.getText());
}
private void checkValue(String text) {
if (text.trim().equals("")) {
((ObjectNode) newConfiguration.get("rowRange")).put("end", -1);
removeErrorMessage(TO_ROW_ERROR_MESSAGE);
removeErrorMessage(INCONSISTENT_ROW_MESSAGE);
} else if (text.trim().matches("[0-9]+")) {
checkRowRange(rowFromValue.getText(), rowToValue.getText());
int toRow = Integer.parseInt(rowToValue.getText());
((ObjectNode) newConfiguration.get("rowRange")).put("end", toRow - 1);
removeErrorMessage(TO_ROW_ERROR_MESSAGE);
} else {
addErrorMessage(TO_ROW_ERROR_MESSAGE);
}
}
});
rowSelectAllOption.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
newConfiguration.put("allRows", true);
rowExcludeFirstOption.setEnabled(true);
if (rowExcludeFirstOption.isSelected()) {
rowFromValue.setText("2");
} else {
rowFromValue.setText("1");
}
rowToValue.setText("");
rowFromValue.setEditable(false);
rowFromValue.setEnabled(false);
rowToValue.setEditable(false);
rowToValue.setEnabled(false);
} else {
newConfiguration.put("allRows", false);
rowExcludeFirstOption.setEnabled(false);
rowFromValue.setEditable(true);
rowFromValue.setEnabled(true);
rowToValue.setEditable(true);
rowToValue.setEnabled(true);
}
}
});
rowExcludeFirstOption.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
newConfiguration.put("excludeFirstRow", true);
rowFromValue.setText("2");
((ObjectNode) newConfiguration.get("rowRange")).put("start", 1);
} else {
newConfiguration.put("excludeFirstRow", false);
rowFromValue.setText("1");
((ObjectNode) newConfiguration.get("rowRange")).put("start", 0);
}
}
});
rowIgnoreBlankRows.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
newConfiguration.put("ignoreBlankRows", e.getStateChange() == ItemEvent.SELECTED);
}
});
// empty cells
emptyCellLabel = new JLabel(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.emptyCellSectionLabel"));
addDivider(emptyCellLabel, SwingConstants.TOP, false);
emptyCellButtonGroup = new ButtonGroup();
emptyCellEmptyStringOption = new JRadioButton(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.emptyStringOption"));
emptyCellUserDefinedOption = new JRadioButton(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.userDefinedOption"));
emptyCellErrorValueOption = new JRadioButton(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.generateErrorOption"));
emptyCellEmptyStringOption.setFocusable(false);
emptyCellUserDefinedOption.setFocusable(false);
emptyCellErrorValueOption.setFocusable(false);
emptyCellUserDefinedValue = new JTextField(newConfiguration.get("emptyCellValue").textValue());
emptyCellButtonGroup.add(emptyCellEmptyStringOption);
emptyCellButtonGroup.add(emptyCellUserDefinedOption);
emptyCellButtonGroup.add(emptyCellErrorValueOption);
if (newConfiguration.get("emptyCellPolicy").textValue().equals("GENERATE_ERROR")) {
emptyCellErrorValueOption.setSelected(true);
emptyCellUserDefinedValue.setEnabled(false);
emptyCellUserDefinedValue.setEditable(false);
} else if (newConfiguration.get("emptyCellPolicy").textValue().equals("EMPTY_STRING")) {
emptyCellEmptyStringOption.setSelected(true);
emptyCellUserDefinedValue.setEnabled(false);
emptyCellUserDefinedValue.setEditable(false);
} else {
emptyCellUserDefinedOption.setSelected(true);
emptyCellUserDefinedValue.setText(newConfiguration.get("emptyCellValue").textValue());
emptyCellUserDefinedValue.setEnabled(true);
emptyCellUserDefinedValue.setEditable(true);
}
emptyCellEmptyStringOption.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
newConfiguration.put("emptyCellPolicy", "EMPTY_STRING");
emptyCellUserDefinedValue.setEnabled(false);
emptyCellUserDefinedValue.setEditable(false);
}
});
emptyCellUserDefinedOption.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
newConfiguration.put("emptyCellPolicy", "USER_DEFINED");
emptyCellUserDefinedValue.setEnabled(true);
emptyCellUserDefinedValue.setEditable(true);
emptyCellUserDefinedValue.requestFocusInWindow();
}
});
emptyCellErrorValueOption.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
newConfiguration.put("emptyCellPolicy", "GENERATE_ERROR");
emptyCellUserDefinedValue.setEnabled(false);
emptyCellUserDefinedValue.setEditable(false);
}
});
emptyCellUserDefinedValue.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
newConfiguration.put("emptyCellValue", emptyCellUserDefinedValue.getText());
}
public void insertUpdate(DocumentEvent e) {
newConfiguration.put("emptyCellValue", emptyCellUserDefinedValue.getText());
}
public void removeUpdate(DocumentEvent e) {
newConfiguration.put("emptyCellValue", emptyCellUserDefinedValue.getText());
}
});
// column mappings
columnMappingLabel = new JLabel(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.columnMappingSectionLabel"));
addDivider(columnMappingLabel, SwingConstants.TOP, false);
Map<String, String> columnToPortMapping = new HashMap<>();
if (newConfiguration.has("columnNames")) {
for (JsonNode columnName : newConfiguration.get("columnNames")) {
columnToPortMapping.put(columnName.get("column").textValue(), columnName.get("port").textValue());
}
}
columnMappingTableModel = new SpreadsheetImportConfigTableModel(columnFromValue.getText(),
columnToValue.getText(), columnToPortMapping);
columnMappingTable = new JTable();
columnMappingTable.setRowSelectionAllowed(false);
columnMappingTable.getTableHeader().setReorderingAllowed(false);
columnMappingTable.setGridColor(Color.LIGHT_GRAY);
// columnMappingTable.setFocusable(false);
columnMappingTable.setColumnModel(new DefaultTableColumnModel() {
public TableColumn getColumn(int columnIndex) {
TableColumn column = super.getColumn(columnIndex);
if (columnIndex == 0) {
column.setMaxWidth(100);
}
return column;
}
});
TableCellEditor defaultEditor = columnMappingTable.getDefaultEditor(String.class);
if (defaultEditor instanceof DefaultCellEditor) {
DefaultCellEditor defaultCellEditor = (DefaultCellEditor) defaultEditor;
defaultCellEditor.setClickCountToStart(1);
Component editorComponent = defaultCellEditor.getComponent();
if (editorComponent instanceof JTextComponent) {
final JTextComponent textField = (JTextComponent) editorComponent;
textField.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
updateModel(textField.getText());
}
public void insertUpdate(DocumentEvent e) {
updateModel(textField.getText());
}
public void removeUpdate(DocumentEvent e) {
updateModel(textField.getText());
}
private void updateModel(String text) {
int row = columnMappingTable.getEditingRow();
int column = columnMappingTable.getEditingColumn();
columnMappingTableModel.setValueAt(text, row, column);
ArrayNode columnNames = newConfiguration.arrayNode();
Map<String, String> columnToPortMapping = columnMappingTableModel.getColumnToPortMapping();
for (Entry<String,String> entry : columnToPortMapping.entrySet()) {
columnNames.add(newConfiguration.objectNode().put("column", entry.getKey()).put("port", entry.getValue()));
}
newConfiguration.put("columnNames", columnNames);
validatePortNames();
}
});
}
}
columnMappingTable.setModel(columnMappingTableModel);
// output format
outputFormatLabel = new JLabel(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.outputFormatSectionLabel"));
outputFormatMultiplePort = new JRadioButton(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.multiplePortOption"));
outputFormatSinglePort = new JRadioButton(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.singlePortOption"));
outputFormatMultiplePort.setFocusable(false);
outputFormatSinglePort.setFocusable(false);
outputFormatDelimiterLabel = new JLabel(SpreadsheetImportUIText
.getString("SpreadsheetImportConfigView.userDefinedCsvDelimiter"));
outputFormatDelimiter = new JTextField(newConfiguration.get("csvDelimiter").textValue(), 5);
outputFormatButtonGroup = new ButtonGroup();
outputFormatButtonGroup.add(outputFormatMultiplePort);
outputFormatButtonGroup.add(outputFormatSinglePort);
if (newConfiguration.get("outputFormat").textValue().equals("PORT_PER_COLUMN")) {
outputFormatMultiplePort.setSelected(true);
outputFormatDelimiterLabel.setEnabled(false);
outputFormatDelimiter.setEnabled(false);
} else {
outputFormatSinglePort.setSelected(true);
columnMappingLabel.setEnabled(false);
enableTable(columnMappingTable, false);
}
outputFormatMultiplePort.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
outputFormatDelimiterLabel.setEnabled(false);
outputFormatDelimiter.setEnabled(false);
columnMappingLabel.setEnabled(true);
enableTable(columnMappingTable, true);
newConfiguration.put("outputFormat", "PORT_PER_COLUMN");
}
});
outputFormatSinglePort.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
outputFormatDelimiterLabel.setEnabled(true);
outputFormatDelimiter.setEnabled(true);
columnMappingLabel.setEnabled(false);
enableTable(columnMappingTable, false);
newConfiguration.put("outputFormat", "SINGLE_PORT");
}
});
outputFormatDelimiter.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
handleUpdate();
}
public void insertUpdate(DocumentEvent e) {
handleUpdate();
}
public void removeUpdate(DocumentEvent e) {
handleUpdate();
}
private void handleUpdate() {
String text = null;
try {
text = StringEscapeUtils.unescapeJava(outputFormatDelimiter.getText());
} catch (RuntimeException re) {}
if (text == null || text.length() == 0) {
newConfiguration.put("csvDelimiter", ",");
} else {
newConfiguration.put("csvDelimiter", text.substring(0, 1));
}
}
});
// buttons
nextButton = new JButton(SpreadsheetImportUIText.getString("SpreadsheetImportConfigView.nextButton"));
nextButton.setFocusable(false);
nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
backButton.setVisible(true);
nextButton.setVisible(false);
cardLayout.last(contentPanel);
}
});
backButton = new JButton(SpreadsheetImportUIText.getString("SpreadsheetImportConfigView.backButton"));
backButton.setFocusable(false);
backButton.setVisible(false);
backButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
nextButton.setVisible(true);
backButton.setVisible(false);
cardLayout.first(contentPanel);
}
});
buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
addDivider(buttonPanel, SwingConstants.TOP, true);
removeAll();
layoutPanel();
}
@Override
public void noteConfiguration() {
setJson(newConfiguration);
configureInputPorts(serviceRegistry);
configureOutputPorts(serviceRegistry);
}
@Override
public boolean checkValues() {
return errorMessages.isEmpty();
}
private void layoutPanel() {
setPreferredSize(new Dimension(450, 400));
setLayout(new BorderLayout());
page1 = new JPanel(new GridBagLayout());
page2 = new JPanel(new GridBagLayout());
contentPanel = new JPanel(cardLayout);
contentPanel.add(page1, "page1");
contentPanel.add(page2, "page2");
add(contentPanel, BorderLayout.CENTER);
// title
titlePanel.setBorder(new CompoundBorder(titlePanel.getBorder(), new EmptyBorder(10, 10, 0, 10)));
add(titlePanel, BorderLayout.NORTH);
titlePanel.add(titleLabel, BorderLayout.NORTH);
titlePanel.add(titleIcon, BorderLayout.WEST);
titlePanel.add(titleMessage, BorderLayout.CENTER);
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.gridx = 0;
c.gridwidth = GridBagConstraints.REMAINDER;
// column range
c.insets = new Insets(10, 10, 0, 10);
page1.add(columnLabel, c);
c.insets = new Insets(10, 25, 0, 0);
c.gridwidth = 1;
c.weightx = 0;
page1.add(new JLabel(SpreadsheetImportUIText.getString("SpreadsheetImportConfigView.from")), c);
c.insets = new Insets(10, 0, 0, 0);
c.gridx = 1;
page1.add(columnFromValue, c);
c.gridx = 2;
page1.add(new JLabel(SpreadsheetImportUIText.getString("SpreadsheetImportConfigView.to")), c);
c.gridx = 3;
page1.add(columnToValue, c);
c.gridx = 0;
c.weightx = 1;
c.insets = new Insets(10, 10, 0, 10);
c.gridwidth = GridBagConstraints.REMAINDER;
// row range
page1.add(rowLabel, c);
c.insets = new Insets(10, 25, 0, 0);
c.gridwidth = 1;
c.gridx = 0;
c.weightx = 0;
page1.add(new JLabel(SpreadsheetImportUIText.getString("SpreadsheetImportConfigView.from")), c);
c.insets = new Insets(10, 0, 0, 0);
c.gridx = 1;
page1.add(rowFromValue, c);
c.gridx = 2;
page1.add(new JLabel(SpreadsheetImportUIText.getString("SpreadsheetImportConfigView.to")), c);
c.gridx = 3;
page1.add(rowToValue, c);
c.gridx = 4;
page1.add(rowSelectAllOption, c);
c.gridx = 5;
c.gridwidth = GridBagConstraints.REMAINDER;
c.insets = new Insets(10, 0, 0, 10);
page1.add(rowExcludeFirstOption, c);
c.insets = new Insets(10, 25, 0, 0);
c.gridx = 0;
page1.add(rowIgnoreBlankRows, c);
c.gridx = 0;
// empty cells
c.insets = new Insets(10, 10, 10, 10);
page1.add(emptyCellLabel, c);
c.insets = new Insets(0, 25, 0, 10);
page1.add(emptyCellEmptyStringOption, c);
JPanel userDefinedPanel = new JPanel(new BorderLayout());
userDefinedPanel.add(emptyCellUserDefinedOption, BorderLayout.WEST);
userDefinedPanel.add(emptyCellUserDefinedValue, BorderLayout.CENTER);
page1.add(userDefinedPanel, c);
c.weighty = 1;
c.anchor = GridBagConstraints.NORTHWEST;
page1.add(emptyCellErrorValueOption, c);
// output format
c.insets = new Insets(10, 10, 10, 10);
c.weighty = 0;
c.weightx = 1;
page2.add(outputFormatLabel, c);
c.insets = new Insets(0, 25, 0, 10);
page2.add(outputFormatMultiplePort, c);
page2.add(outputFormatSinglePort, c);
c.insets = new Insets(0, 50, 0, 10);
JPanel outputFormatDelimiterPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
outputFormatDelimiterPanel.add(outputFormatDelimiterLabel);
outputFormatDelimiterPanel.add(outputFormatDelimiter);
page2.add(outputFormatDelimiterPanel, c);
// column mapping
c.insets = new Insets(10, 10, 0, 10);
page2.add(columnMappingLabel, c);
c.insets = new Insets(10, 10, 10, 10);
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
page2.add(new JScrollPane(columnMappingTable), c);
buttonPanel.add(backButton);
buttonPanel.add(nextButton);
add(buttonPanel, BorderLayout.SOUTH);
}
/**
* Displays the message with no icon.
*
* @param message
* the message to display
*/
public void setMessage(String message) {
titleIcon.setIcon(null);
titleMessage.setText(message);
}
/**
* Adds the message to the top of the warning message stack. If the message is already in the
* stack it is moved to the top. If there are no error messages the message is displayed.
*
* @param message
* the warning message to add
*/
public void addWarningMessage(String message) {
if (warningMessages.contains(message)) {
warningMessages.remove(message);
}
warningMessages.push(message);
if (errorMessages.isEmpty()) {
setWarningMessage(message);
}
}
/**
* Removes the message from the warning message stack. If there are no error messages the next
* warning message is displayed. If there are no warning messages the default message is
* displayed.
*
* @param message
* the warning message to remove
*/
public void removeWarningMessage(String message) {
warningMessages.remove(message);
if (errorMessages.isEmpty()) {
if (warningMessages.isEmpty()) {
setMessage(DEFAULT_MESSAGE);
} else {
setWarningMessage(warningMessages.peek());
}
}
}
/**
* Displays the message and a warning icon.
*
* @param message
* the warning message to display
*/
public void setWarningMessage(String message) {
titleIcon.setIcon(Icons.warningIcon);
titleMessage.setText(message);
}
/**
* Adds the message to the top of the error message stack. If the message is already in the
* stack it is moved to the top. The message is then displayed.
*
* @param message
* the error message to add
*/
public void addErrorMessage(String message) {
if (errorMessages.contains(message)) {
errorMessages.remove(message);
}
errorMessages.push(message);
setErrorMessage(message);
}
/**
* Removes the message from the error message stack and displays the next error message. If
* there are no error messages the next warning message is displayed. If there are no warning
* messages the default message is displayed.
*
* @param message
* the error message to remove
*/
public void removeErrorMessage(String message) {
errorMessages.remove(message);
if (errorMessages.isEmpty()) {
if (warningMessages.isEmpty()) {
setMessage(DEFAULT_MESSAGE);
} else {
setWarningMessage(warningMessages.peek());
}
} else {
setErrorMessage(errorMessages.peek());
}
}
/**
* Displays the message and an error icon.
*
* @param message
* the error message to display
*/
public void setErrorMessage(String message) {
titleIcon.setIcon(Icons.severeIcon);
titleMessage.setText(message);
}
protected boolean validatePortNames() {
boolean isValid = true;
Range columnRange = SpreadsheetUtils.getRange(newConfiguration.get("columnRange"));
Map<String, String> mapping = new HashMap<>();
if (newConfiguration.has("columnNames")) {
for (JsonNode columnName : newConfiguration.get("columnNames")) {
mapping.put(columnName.get("column").textValue(), columnName.get("port").textValue());
}
}
Set<String> usedNames = new HashSet<String>();
for (Entry<String, String> entry : mapping.entrySet()) {
if (columnRange.contains(SpreadsheetUtils.getColumnIndex(entry.getKey()))) {
String portName = entry.getValue();
if (!usedNames.add(portName)) {
isValid = false;
break;
}
if (portName.matches("[A-Z]+")) {
if (!mapping.containsKey(portName)) {
int columnIndex = SpreadsheetUtils.getColumnIndex(portName);
if (columnRange.contains(columnIndex)) {
isValid = false;
break;
}
}
}
}
}
if (isValid) {
removeErrorMessage(DUPLICATE_PORT_NAME_ERROR_MESSAGE);
} else {
addErrorMessage(DUPLICATE_PORT_NAME_ERROR_MESSAGE);
}
return isValid;
}
protected boolean checkRowRange(String from, String to) {
boolean result = false;
try {
int fromRow = Integer.parseInt(from);
int toRow = Integer.parseInt(to);
if (toRow < fromRow) {
addErrorMessage(INCONSISTENT_ROW_MESSAGE);
} else {
removeErrorMessage(INCONSISTENT_ROW_MESSAGE);
result = true;
}
} catch (NumberFormatException e) {
logger.warn("Problem checking row range", e);
}
return result;
}
protected boolean checkColumnRange(int fromColumn, int toColumn) {
boolean result = false;
if (toColumn < fromColumn) {
addErrorMessage(INCONSISTENT_COLUMN_MESSAGE);
} else {
removeErrorMessage(INCONSISTENT_COLUMN_MESSAGE);
result = true;
}
return result;
}
/**
* Adds a light gray or etched border to the top or bottom of a JComponent.
*
* @param component
*/
protected void addDivider(JComponent component, final int position, final boolean etched) {
component.setBorder(new Border() {
private final Color borderColor = new Color(.6f, .6f, .6f);
public Insets getBorderInsets(Component c) {
if (position == SwingConstants.TOP) {
return new Insets(5, 0, 0, 0);
} else {
return new Insets(0, 0, 5, 0);
}
}
public boolean isBorderOpaque() {
return false;
}
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
if (position == SwingConstants.TOP) {
if (etched) {
g.setColor(borderColor);
g.drawLine(x, y, x + width, y);
g.setColor(Color.WHITE);
g.drawLine(x, y + 1, x + width, y + 1);
} else {
g.setColor(Color.LIGHT_GRAY);
g.drawLine(x, y, x + width, y);
}
} else {
if (etched) {
g.setColor(borderColor);
g.drawLine(x, y + height - 2, x + width, y + height - 2);
g.setColor(Color.WHITE);
g.drawLine(x, y + height - 1, x + width, y + height - 1);
} else {
g.setColor(Color.LIGHT_GRAY);
g.drawLine(x, y + height - 1, x + width, y + height - 1);
}
}
}
});
}
private void enableTable(JTable table, boolean enabled) {
table.setEnabled(enabled);
Component editor = table.getEditorComponent();
if (editor != null) {
editor.setEnabled(enabled);
}
if (enabled) {
table.setForeground(Color.BLACK);
table.getTableHeader().setForeground(Color.BLACK);
} else {
table.setForeground(Color.LIGHT_GRAY);
table.getTableHeader().setForeground(Color.LIGHT_GRAY);
}
}
static class UpperCaseDocument extends PlainDocument {
@Override
public void replace(int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
if (text.matches("[A-Za-z]+")) {
text = text.toUpperCase();
super.replace(offset, length, text, attrs);
}
}
}
static class NumericDocument extends PlainDocument {
@Override
public void replace(int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
if (text.length() == 0 || text.matches("[0-9]+")) {
text = text.toUpperCase();
super.replace(offset, length, text, attrs);
}
}
}
/**
* Main method for testing the panel.
*
* @param args
* @throws ActivityConfigurationException
*/
// public static void main(String[] args) throws ActivityConfigurationException {
// final JFrame frame = new JFrame();
// SpreadsheetImportActivity activity = new SpreadsheetImportActivity();
// activity.configure(new SpreadsheetImportConfiguration());
// final SpreadsheetImportConfigView config = new SpreadsheetImportConfigView(activity);
// config.setOkAction(new AbstractAction("Finish") {
// public void actionPerformed(ActionEvent arg0) {
// Range columnRange = config.getConfiguration().getColumnRange();
// String fromColumn = SpreadsheetUtils.getColumnLabel(columnRange.getStart());
// String toColumn = SpreadsheetUtils.getColumnLabel(columnRange.getEnd());
// System.out.printf("%s (%s) - %s (%s)", fromColumn, columnRange.getStart(),
// toColumn, columnRange.getEnd());
// frame.setVisible(false);
// frame.dispose();
// }
// });
// config.setCancelAction(new AbstractAction("Cancel") {
// public void actionPerformed(ActionEvent arg0) {
// frame.setVisible(false);
// frame.dispose();
// }
// });
// frame.add(config);
// frame.pack();
// frame.setVisible(true);
// }
}