/*
Copyright (C) 2006 EBI
This library 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 library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the itmplied 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 library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.biomart.builder.view.gui.dialogs;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import org.biomart.builder.model.Column;
import org.biomart.builder.model.Key;
import org.biomart.builder.model.DataSet.DataSetColumn;
import org.biomart.builder.model.DataSet.DataSetTable;
import org.biomart.builder.model.DataSet.ExpressionColumnDefinition;
import org.biomart.builder.view.gui.panels.DataSetColumnStringTablePanel;
import org.biomart.builder.view.gui.panels.TwoColumnTablePanel;
import org.biomart.common.resources.Resources;
/**
* This dialog asks users to create or modify an expression column.
*
* @author Richard Holland <holland@ebi.ac.uk>
* @version $Revision: 1.29 $, $Date: 2007-08-21 15:19:54 $, modified by
* $Author: rh4 $
* @since 0.5
*/
public class ExpressionColumnDialog extends JDialog {
private static final long serialVersionUID = 1;
private JButton cancel;
private boolean cancelled;
private TwoColumnTablePanel columnAliasModel;
private JButton execute;
private JTextArea expression;
private JCheckBox groupBy;
private DataSetTable table;
/**
* Creates (but does not open) a dialog requesting details of expression
* column.
*
* @param table
* the table to source columns from.
* @param template
* the column to use as a template, if any.
* @param skipIncludeCol
* the column not to include in the selection - to prevent
* self-recursion.
*/
public ExpressionColumnDialog(final DataSetTable table,
final ExpressionColumnDefinition template,
final DataSetColumn skipIncludeCol) {
// Creates the basic dialog.
super();
this.setTitle(template == null ? Resources.get("addExpColDialogTitle")
: Resources.get("modifyExpColDialogTitle"));
this.setModal(true);
// Remembers the dataset tabset this dialog is referring to.
this.table = table;
this.cancelled = true;
// Create the content pane to store the create dialog panel.
final JPanel content = new JPanel(new GridBagLayout());
this.setContentPane(content);
// Create constraints for labels that are not in the last row.
final GridBagConstraints labelConstraints = new GridBagConstraints();
labelConstraints.gridwidth = GridBagConstraints.RELATIVE;
labelConstraints.fill = GridBagConstraints.HORIZONTAL;
labelConstraints.anchor = GridBagConstraints.LINE_END;
labelConstraints.insets = new Insets(0, 2, 0, 0);
// Create constraints for fields that are not in the last row.
final GridBagConstraints fieldConstraints = new GridBagConstraints();
fieldConstraints.gridwidth = GridBagConstraints.REMAINDER;
fieldConstraints.fill = GridBagConstraints.NONE;
fieldConstraints.anchor = GridBagConstraints.LINE_START;
fieldConstraints.insets = new Insets(0, 1, 0, 2);
// Create constraints for labels that are in the last row.
final GridBagConstraints labelLastRowConstraints = (GridBagConstraints) labelConstraints
.clone();
labelLastRowConstraints.gridheight = GridBagConstraints.REMAINDER;
// Create constraints for fields that are in the last row.
final GridBagConstraints fieldLastRowConstraints = (GridBagConstraints) fieldConstraints
.clone();
fieldLastRowConstraints.gridheight = GridBagConstraints.REMAINDER;
// Create the fields that will contain the user's table choices.
final Map defaults = new HashMap();
if (template != null)
for (final Iterator i = template.getAliases().entrySet().iterator(); i
.hasNext();) {
final Map.Entry entry = (Map.Entry) i.next();
final Column col = (Column) table.getColumns().get(
entry.getKey());
if (col != null)
defaults.put(col, entry.getValue());
}
this.expression = new JTextArea(10, 40); // Arbitrary size.
this.columnAliasModel = new DataSetColumnStringTablePanel(defaults,
table.getColumns().values(), skipIncludeCol) {
private static final long serialVersionUID = 1L;
private int alias = 1;
public String getInsertButtonText() {
return Resources.get("insertAliasButton");
}
public String getRemoveButtonText() {
return Resources.get("removeAliasButton");
}
public String getFirstColumnHeader() {
return Resources.get("columnAliasTableColHeader");
}
public String getSecondColumnHeader() {
return Resources.get("columnAliasTableAliasHeader");
}
public Object getNewRowSecondColumn() {
return Resources.get("defaultAlias") + this.alias++;
}
};
this.groupBy = new JCheckBox(Resources.get("groupbyLabel"));
// Create the buttons.
this.cancel = new JButton(Resources.get("cancelButton"));
this.execute = template == null ? new JButton(Resources
.get("addButton")) : new JButton(Resources.get("modifyButton"));
// Add the column aliases table.
JLabel label = new JLabel(Resources.get("columnAliasLabel"));
content.add(label, labelConstraints);
JPanel field = new JPanel();
field.add(this.columnAliasModel);
content.add(field, fieldConstraints);
// Add the expression option.
label = new JLabel(Resources.get("expressionLabel"));
content.add(label, labelConstraints);
field = new JPanel();
field.add(new JScrollPane(this.expression));
content.add(field, fieldConstraints);
// Add the group-by option.
label = new JLabel();
content.add(label, labelConstraints);
field = new JPanel();
field.add(this.groupBy);
content.add(field, fieldConstraints);
// Add the buttons to the dialog.
label = new JLabel();
content.add(label, labelLastRowConstraints);
field = new JPanel();
field.add(this.cancel);
field.add(this.execute);
content.add(field, fieldLastRowConstraints);
// Intercept the cancel button and use it to close this
// dialog without making any changes.
this.cancel.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
ExpressionColumnDialog.this.setVisible(false);
}
});
// Intercept the execute button and use it to create
// the appropriate partition type, then close the dialog.
this.execute.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
if (ExpressionColumnDialog.this.validateFields()) {
ExpressionColumnDialog.this.cancelled = false;
ExpressionColumnDialog.this.setVisible(false);
}
}
});
// Make the execute button the default button.
this.getRootPane().setDefaultButton(this.execute);
// Set some nice defaults.
if (template != null) {
this.expression.setText(template.getExpression());
this.groupBy.setSelected(template.isGroupBy());
// Aliases were already copied in the JTable constructor above.
}
// Set the size of the dialog.
this.pack();
// Move ourselves.
this.setLocationRelativeTo(null);
}
private boolean isEmpty(final String string) {
// Strings are empty if they are null or all whitespace.
return string == null || string.trim().length() == 0;
}
private boolean validateFields() {
// A placeholder to hold the validation messages, if any.
final List messages = new ArrayList();
// We must have an expression!
if (this.isEmpty(this.expression.getText()))
messages.add(Resources.get("fieldIsEmpty", Resources
.get("expression")));
// Validate other fields.
if (this.columnAliasModel.getValues().isEmpty())
messages.add(Resources.get("columnAliasMissing"));
// If group-by is selected, we can't allow them to use columns
// involved in any keys.
if (this.getGroupBy()) {
final Set aliasCols = new HashSet(this.getColumnAliases().keySet());
final Set keyCols = new HashSet();
for (final Iterator i = this.table.getKeys().iterator(); i
.hasNext();)
keyCols.addAll(Arrays.asList(((Key) i.next()).getColumns()));
aliasCols.retainAll(keyCols);
if (!aliasCols.isEmpty())
messages.add(Resources.get("columnAliasIncludesKeyCols"));
}
// If there any messages, display them.
if (!messages.isEmpty())
JOptionPane.showMessageDialog(null,
messages.toArray(new String[0]), Resources
.get("validationTitle"),
JOptionPane.INFORMATION_MESSAGE);
// Validation succeeds if there are no messages.
return messages.isEmpty();
}
/**
* Return <tt>true</tt> if the user cancelled the box.
*
* @return <tt>true</tt> if the box was cancelled.
*/
public boolean getCancelled() {
return this.cancelled;
}
/**
* Return the column aliases the user selected.
*
* @return the aliases.
*/
public Map getColumnAliases() {
return this.columnAliasModel.getValues();
}
/**
* Return the expression the user selected.
*
* @return the expression.
*/
public String getExpression() {
return this.expression.getText().trim();
}
/**
* Return <tt>true</tt> if the user selected the group-by box.
*
* @return the group-by flag.
*/
public boolean getGroupBy() {
return this.groupBy.isSelected();
}
}