/*
* NCSA Data To Knowledge (D2K) Project
* Automated Learning Group
* National Center for Supercomputing Applications
* University of Illinois at Urbana-Champaign
* 605 E. Springfield, Champaign, IL 61820
*
* d2k@ncsa.uiuc.edu
*
* Copyright 2003, Board of Trustees of the University of Illinois,
* All Rights Reserved
*
* NCSA Data To Knowledge (D2K) software, source code, binary code, and Java-byte
* code including D2K modules and D2K itineraries (hereafter, Software) is
* copyrighted by the Board of Trustees of the University of Illinois (UI),
* and ownership remains with the UI.
*
* Prior to receiving this Software Source Code, You must have agreed to a
* non-exclusive, non-transferable, restricted License of Software with UI for
* limited Research Use and/or Internal Business Use. The terms of that License
* control the use of this Software Source Code. For the sake of convenience,
* certain provisions of that License are stated here. However, in the event
* of any real or perceived differences between the terms of the License and the
* statements made herein, the License controls.
*
* You may not distribute the Software including the Binary Code and this Source
* Code to third parties.
*
* You may make Derivative Works. You are encouraged to provide information to
* UI regarding Derivative Works and your experience with Software. However, if
* You make any Derivative Work based on or derived from the Software, then You
* will: (1) clearly notify users that such Derivative Work is a modified version
* and uses or is derived from the original NCSA Data To Knowledge (D2K)
* developed at UI, and include specific language in that notice as provided for
* in the License, and (2) acknowledge via citation and provide UI with a copy of
* any report or publication using the Software or Derivative Work.
*
* If You wish to make Commercial Use of the Software or Derivative Works, then
* You should contact the UI, c/o NCSA, to negotiate an appropriate license for
* such Commercial Use. Commercial Use includes sale, lease, license,
* distribution or otherwise making the Software or Derivative Works available to
* third parties, which includes, but is not limited to, integration of all or
* part of the Software or Derivative Work into a product for sale or license by
* or on behalf of You to third parties.
*
* UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
* PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. THE UI
* SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE USERS OF THIS SOFTWARE.
*
* By using or copying this Software, You agree to abide by the copyright law
* and all other applicable laws of the U.S. including, but not limited to,
* export control laws, and the terms of the License. UI shall have the right
* to terminate its license with You immediately upon Your breach of, or
* non-compliance with, any of its terms. You may be held legally responsible
* for any copyright infringement that is caused or encouraged by Your failure
* to abide by the terms of the License.
*/
package ncsa.d2k.modules.core.transform.attribute;
import ncsa.d2k.core.modules.*;
import ncsa.d2k.userviews.swing.*;
import ncsa.d2k.core.modules.UserView;
import ncsa.gui.Constrain;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import ncsa.d2k.modules.core.datatype.table.*;
/**
ChooseAttributes.java (previously ChooseFields)
Allows the user to choose which columns of a table are inputs and outputs.
Then assigns them in an ExampleTable.
@author Peter Groves, c/o David Clutter
*/
public class ChooseAttributes extends UIModule {
/**
Return a description of the function of this module.
@return A description of this module.
*/
public String getModuleInfo() {
String info = "<p>Overview: ";
info += "This module allows the user to choose which columns of a table are inputs and outputs.";
info += "</p><p>Detailed Description: ";
info += "This module outputs an <i>Example Table</i> with the input and output features assigned. ";
info += "Inputs and outputs do not have to be selected, nor do they have to be mutually exclusive. ";
info += "</p><p>Data Handling: ";
info += "This module does not modify the data in the table. It only sets the input and output features.";
return info;
}
/**
Return the name of this module.
@return The name of this module.
*/
public String getModuleName() {
return "Choose Attributes";
}
/**
Return a String array containing the datatypes the inputs to this
module.
@return The datatypes of the inputs.
*/
public String[] getInputTypes() {
String[] types = {"ncsa.d2k.modules.core.datatype.table.Table"};
return types;
}
/**
Return a String array containing the datatypes of the outputs of this
module.
@return The datatypes of the outputs.
*/
public String[] getOutputTypes() {
String[] types = {"ncsa.d2k.modules.core.datatype.table.ExampleTable"};
return types;
}
/**
Return a description of a specific input.
@param i The index of the input
@return The description of the input
*/
public String getInputInfo(int i) {
switch (i) {
case 0: return "The Table to choose inputs and outputs from.";
default: return "No such input";
}
}
/**
Return the name of a specific input.
@param i The index of the input.
@return The name of the input
*/
public String getInputName(int i) {
switch(i) {
case 0:
return "Table";
default: return "No such input";
}
}
/**
Return the description of a specific output.
@param i The index of the output.
@return The description of the output.
*/
public String getOutputInfo(int i) {
switch (i) {
case 0: return "The Example Table with input and output features assigned.";
default: return "No such output";
}
}
/**
Return the name of a specific output.
@param i The index of the output.
@return The name of the output
*/
public String getOutputName(int i) {
switch(i) {
case 0:
return "Example Table";
default: return "No such output";
}
}
public PropertyDescription[] getPropertiesDescriptions() {
return new PropertyDescription[0]; // so that "windowName" property
// is invisible
}
/**
Return the UserView
@returns the UserView
*/
protected UserView createUserView() {
return new AttributeView();
}
/**
Not used
*/
protected String[] getFieldNameMapping() {
return null;
}
/**
Pushes the outputs. Called when the view has finished.
*/
/*public void finish(ExampleTable et) {
this.pushOutput(et, 0);
executionManager.moduleDone(this);
}*/
/**
The user view class
*/
class AttributeView extends JUserPane implements ActionListener {
private Table table; //Old data
private ExampleTable et; //Updated table
private ChooseAttributes module;
private JButton abort;
private JButton done;
private JList inputList;
private JList outputList;
private JLabel inputLabel;
private JLabel outputLabel;
boolean labels;
private HashMap inputToIndexMap;
private HashMap outputToIndexMap;
private JCheckBoxMenuItem miColumnOrder;
private JCheckBoxMenuItem miAlphaOrder;
private JMenuBar menuBar;
/**
Initialize
*/
public void initView(ViewModule v) {
module = (ChooseAttributes)v;
abort = new JButton("Abort");
done = new JButton("Done");
abort.addActionListener(this);
done.addActionListener(this);
menuBar = new JMenuBar();
JMenu m1 = new JMenu("File");
miColumnOrder = new JCheckBoxMenuItem("Column Order");
miColumnOrder.addActionListener(this);
miColumnOrder.setState(true);
miAlphaOrder = new JCheckBoxMenuItem("Alphabetical Order");
miAlphaOrder.addActionListener(this);
miAlphaOrder.setState(false);
m1.add(miColumnOrder);
m1.add(miAlphaOrder);
menuBar.add(m1);
}
public Object getMenu() {
return menuBar;
}
/**
Called when inputs arrive
*/
public void setInput(Object o, int id) {
if(id == 0) {
table = (Table)o;
this.removeAll();
addComponents();
}
}
/**
Make me at least this big
*/
public Dimension getPreferredSize() {
return new Dimension(400, 300);
}
/**
Add all the components
*/
private void addComponents() {
JPanel back = new JPanel();
int numColumns = table.getNumColumns();
/*String[] labels=new String[numColumns];
for(int i = 0; i < numColumns; i++)
labels[i] = table.getColumnLabel(i);
*/
String[] labels = orderedLabels();
if (table.getColumnLabel(0).equals("")) {
miColumnOrder.setEnabled(false);
miAlphaOrder.setEnabled(false);
} else {
miColumnOrder.setEnabled(true);
miAlphaOrder.setEnabled(true);
}
inputList=new JList(/*labels*/);
DefaultListModel dlm = new DefaultListModel();
for(int i = 0; i < labels.length; i++)
dlm.addElement(labels[i]);
inputList.setModel(dlm);
if(table instanceof ExampleTable) {
//inputList.setSelectedIndices(((ExampleTable)table).getInputFeatures());
int[] ins = ((ExampleTable)table).getInputFeatures();
if(ins != null) {
int[] sel = new int[ins.length];
for(int i = 0; i < ins.length; i++) {
String s = table.getColumnLabel(ins[i]);
Integer ii = (Integer)inputToIndexMap.get(s);
sel[i] = ii.intValue();
}
inputList.setSelectedIndices(sel);
}
}
outputList=new JList(/*labels*/);
dlm = new DefaultListModel();
for(int i = 0; i < labels.length; i++)
dlm.addElement(labels[i]);
outputList.setModel(dlm);
if(table instanceof ExampleTable) {
//outputList.setSelectedIndices(((ExampleTable)table).getOutputFeatures());
int[] ins = ((ExampleTable)table).getOutputFeatures();
if(ins != null) {
int[] sel = new int[ins.length];
for(int i = 0; i < ins.length; i++) {
String s = table.getColumnLabel(ins[i]);
Integer ii = (Integer)outputToIndexMap.get(s);
sel[i] = ii.intValue();
}
outputList.setSelectedIndices(sel);
}
}
JScrollPane leftScrollPane=new JScrollPane(inputList);
JScrollPane rightScrollPane=new JScrollPane(outputList);
inputLabel=new JLabel("Input Attributes");
inputLabel.setHorizontalAlignment(SwingConstants.CENTER);
outputLabel=new JLabel("Output Attributes");
outputLabel.setHorizontalAlignment(SwingConstants.CENTER);
back.setLayout(new GridBagLayout());
Constrain.setConstraints(back, inputLabel, 0, 0, 1, 1,
GridBagConstraints.BOTH, GridBagConstraints.CENTER, 0, 0);
Constrain.setConstraints(back, outputLabel, 1, 0, 1, 1,
GridBagConstraints.BOTH, GridBagConstraints.CENTER, 0, 0);
Constrain.setConstraints(back, leftScrollPane, 0, 1, 1, 1,
GridBagConstraints.BOTH, GridBagConstraints.CENTER, 1, 1);
Constrain.setConstraints(back, rightScrollPane, 1, 1, 1, 1,
GridBagConstraints.BOTH, GridBagConstraints.CENTER, 1, 1);
JPanel buttons = new JPanel();
buttons.add(abort);
buttons.add(done);
this.add(back, BorderLayout.CENTER);
this.add(buttons, BorderLayout.SOUTH);
}
/**
Listen for ActionEvents
*/
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if(src == abort)
module.viewCancel();
else if(src == done) {
//if(checkChoices()) {
setFieldsInTable();
//module.finish(et);
pushOutput(et, 0);
viewDone("Done");
et = null;
this.removeAll();
//}
}
else if(src == miColumnOrder) {
String [] labels = orderedLabels();
miAlphaOrder.setState(false);
DefaultListModel dlm = (DefaultListModel)inputList.getModel();
dlm.removeAllElements();
for(int i = 0; i < labels.length; i++) {
dlm.addElement(labels[i]);
}
dlm = (DefaultListModel)outputList.getModel();
dlm.removeAllElements();
for(int i = 0; i < labels.length; i++) {
dlm.addElement(labels[i]);
}
}
else if(src == miAlphaOrder) {
String [] labels = alphabetizeLabels();
miColumnOrder.setState(false);
DefaultListModel dlm = (DefaultListModel)inputList.getModel();
dlm.removeAllElements();
for(int i = 0; i < labels.length; i++) {
dlm.addElement(labels[i]);
}
dlm = (DefaultListModel)outputList.getModel();
dlm.removeAllElements();
for(int i = 0; i < labels.length; i++) {
dlm.addElement(labels[i]);
}
}
}
private final String[] orderedLabels() {
String[] labels=new String[table.getNumColumns()];
inputToIndexMap = new HashMap(labels.length);
outputToIndexMap = new HashMap(labels.length);
for(int i = 0; i < labels.length; i++) {
String label = table.getColumnLabel(i);
if (label.equals(""))
label = new String("Column " + Integer.toString(i));
labels[i] = label;
inputToIndexMap.put(labels[i], new Integer(i));
outputToIndexMap.put(labels[i], new Integer(i));
}
return labels;
}
private final String[] alphabetizeLabels() {
String [] labels = new String[table.getNumColumns()];
inputToIndexMap = new HashMap(labels.length);
outputToIndexMap = new HashMap(labels.length);
for(int i = 0; i < labels.length; i++) {
labels[i] = table.getColumnLabel(i);
inputToIndexMap.put(labels[i], new Integer(i));
outputToIndexMap.put(labels[i], new Integer(i));
}
Arrays.sort(labels, new StringComp());
return labels;
}
private final class StringComp implements Comparator {
public int compare(Object o1, Object o2) {
String s1 = (String)o1;
String s2 = (String)o2;
return s1.toLowerCase().compareTo(s2.toLowerCase());
}
public boolean equals(Object o) {
return super.equals(o);
}
}
private void setFieldsInTable(){
et= table.toExampleTable();
//et.setInputFeatures(inputList.getSelectedIndices());
//et.setOutputFeatures(outputList.getSelectedIndices());
Object[] selected = inputList.getSelectedValues();
int [] inputFeatures = new int[selected.length];
for(int i = 0; i < selected.length; i++) {
String s = (String)selected[i];
Integer ii = (Integer)inputToIndexMap.get(s);
inputFeatures[i] = ii.intValue();
}
selected = outputList.getSelectedValues();
int [] outputFeatures = new int[selected.length];
for(int i = 0; i < selected.length; i++) {
String s = (String)selected[i];
Integer ii = (Integer)outputToIndexMap.get(s);
outputFeatures[i] = ii.intValue();
}
et.setInputFeatures(inputFeatures);
et.setOutputFeatures(outputFeatures);
table = null;
}
/**
Not used
Make sure all choices are valid.
*/
protected boolean checkChoices() {
if(outputList.getSelectedIndex() == -1){
JOptionPane.showMessageDialog(this,
"You must select at least one output",
"Error", JOptionPane.ERROR_MESSAGE);
return false;
}
if(inputList.getSelectedIndex() == -1){
JOptionPane.showMessageDialog(this,
"You must select at least one input",
"Error", JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}
}
}
//QA Comments Anca - added getPropertyDescription
//QA Comments Ruth - used Example Table in what user reads (w/ space)