/*
* Copyright (C) 2004 Anthony Smith
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* ----------------------------------------------------------------------------
* TITLE $Id$
* ---------------------------------------------------------------------------
*
* --------------------------------------------------------------------------*/
package opendbcopy.gui.database.dual;
import opendbcopy.config.XMLTags;
import opendbcopy.controller.MainController;
import opendbcopy.gui.DynamicPanel;
import opendbcopy.gui.PluginGui;
import opendbcopy.plugin.model.database.DatabaseModel;
import opendbcopy.plugin.model.exception.MissingElementException;
import opendbcopy.swing.JTableX;
import opendbcopy.swing.RowEditorModel;
import org.jdom.Element;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.Iterator;
import java.util.List;
import java.util.Observable;
import java.util.Vector;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
/**
* class description
*
* @author Anthony Smith
* @version $Revision$
*/
public class PanelMappingTable extends DynamicPanel {
private DatabaseModel model;
private Object[][] dataMapping;
private Object[][] dataProcess;
private RowEditorModel rowModel;
private DefaultCellEditor dce;
private boolean select_all = false;
private BorderLayout borderLayout = new BorderLayout();
private BorderLayout borderLayoutPanelMain = new BorderLayout();
private JPanel panelOptions = new JPanel();
private JPanel panelControl = new JPanel();
private JPanel panelMain = new JPanel();
private JPanel panelTables = null;
private JPanel panelMappingTable = null;
private JPanel panelProcessTable = null;
private JButton buttonSelect = new JButton();
private JScrollPane scrollPane = null;
private JTableX tableMapping = null;
private JTableX tableProcess = null;
private MappingTableModel mappingTableModel = null;
private ProcessTableModel processTableModel = null;
private Vector destinationTablesComboBoxValues = new Vector();
/**
* Creates a new PanelMappingTable object.
*
* @param controller DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
*/
public PanelMappingTable(MainController controller, PluginGui workingMode, Boolean registerAsObserver) throws MissingElementException {
super(controller, workingMode, registerAsObserver);
model = (DatabaseModel) super.model;
rowModel = new RowEditorModel();
guiInit();
}
/**
* DOCUMENT ME!
*
* @param o DOCUMENT ME!
* @param obj DOCUMENT ME!
*/
public final void update(Observable o,
Object obj) {
}
/**
* DOCUMENT ME!
*/
public final void onSelect() {
try {
initTable();
} catch (MissingElementException e) {
postException(e);
}
}
/**
* DOCUMENT ME!
*
* @throws MissingElementException DOCUMENT ME!
*/
public final void initTable() throws MissingElementException {
if (model.isMappingSetup()) {
// means tables have already been loaded once
if (panelTables != null) {
scrollPane.removeAll();
panelMain.remove(scrollPane);
}
mappingTableModel = new MappingTableModel();
processTableModel = new ProcessTableModel();
initMappingTableData();
tableMapping = new JTableX(mappingTableModel);
tableProcess = new JTableX(processTableModel);
// Set up column sizes for two columns
initColumnSizesMappingTable(tableMapping);
// tell the JTableX which RowEditorModel we are using
tableMapping.setRowEditorModel(rowModel);
panelMappingTable = new JPanel();
panelMappingTable.setLayout(new BorderLayout());
panelMappingTable.add(tableMapping.getTableHeader(), BorderLayout.PAGE_START);
panelMappingTable.add(tableMapping, BorderLayout.CENTER);
panelProcessTable = new JPanel();
panelProcessTable.setLayout(new BorderLayout());
panelProcessTable.add(tableProcess.getTableHeader(), BorderLayout.PAGE_START);
panelProcessTable.add(tableProcess, BorderLayout.CENTER);
panelTables = new JPanel(new BorderLayout());
panelTables.add(panelMappingTable, BorderLayout.CENTER);
panelTables.add(panelProcessTable, BorderLayout.EAST);
scrollPane = new JScrollPane(panelTables);
panelMain.add(scrollPane, BorderLayout.CENTER);
buttonSelect.setEnabled(true);
panelMain.updateUI();
} else {
buttonSelect.setEnabled(false);
}
}
/**
* DOCUMENT ME!
*
* @throws MissingElementException DOCUMENT ME!
*/
private void initMappingTableData() throws MissingElementException {
int nbrSourceTables = model.getNbrSourceTables();
dataMapping = new Object[nbrSourceTables][2];
dataProcess = new Object[nbrSourceTables][1];
for (int row = 0; row < mappingTableModel.getRowCount(); row++) {
dataMapping[row][0] = new String("");
dataMapping[row][1] = new String("");
}
for (int row = 0; row < processTableModel.getRowCount(); row++) {
dataProcess[row][0] = new Boolean(false);
}
Iterator itMappingTables = model.getMappingTables().iterator();
int row = 0;
while (itMappingTables.hasNext()) {
Element tableMapping = (Element) itMappingTables.next();
dataMapping[row][0] = tableMapping.getAttributeValue(XMLTags.SOURCE_DB);
// create a new JComboBox and editor for this row
JComboBox combo = getDestinationTableComboBox(tableMapping.getAttributeValue(XMLTags.DESTINATION_DB));
dce = new DefaultCellEditor(combo);
rowModel.addEditorForRow(row, dce);
// set default selected item
dataMapping[row][1] = combo.getSelectedItem();
dataProcess[row][0] = new Boolean(tableMapping.getAttributeValue(XMLTags.PROCESS));
row++;
}
}
/**
* DOCUMENT ME!
*
* @param destinationTableName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws MissingElementException DOCUMENT ME!
*/
private JComboBox getDestinationTableComboBox(String destinationTableName) throws MissingElementException {
JComboBox combo = null;
// initializes vector with destination tables if not already done
createComboBoxVector(model.getDestinationTables());
combo = new JComboBox(destinationTablesComboBoxValues);
// if destinationTableName is empty selects empty element as selected element
combo.setSelectedItem(destinationTableName);
return combo;
}
/**
* DOCUMENT ME!
*
* @param tables DOCUMENT ME!
*/
private void createComboBoxVector(List tables) {
if (destinationTablesComboBoxValues.size() == 0) {
// add empty element
destinationTablesComboBoxValues.add("");
if (tables.size() > 0) {
Iterator itTables = tables.iterator();
while (itTables.hasNext()) {
Element table = (Element) itTables.next();
destinationTablesComboBoxValues.add(table.getAttributeValue(XMLTags.NAME));
}
}
}
}
/**
* DOCUMENT ME!
*
* @throws MissingElementException DOCUMENT ME!
*/
private void guiInit() throws MissingElementException {
borderLayout.setHgap(10);
borderLayout.setVgap(10);
this.setLayout(borderLayout);
panelMain.setLayout(borderLayoutPanelMain);
borderLayoutPanelMain.setHgap(10);
borderLayoutPanelMain.setVgap(10);
buttonSelect.setPreferredSize(new Dimension(160, 25));
panelControl.setMinimumSize(new Dimension(300, 30));
panelControl.setPreferredSize(new Dimension(300, 30));
panelControl.setLayout(new BorderLayout(20, 20));
panelControl.add(buttonSelect, BorderLayout.EAST);
if (select_all) {
buttonSelect.setText(rm.getString("button.selectAll"));
} else {
buttonSelect.setText(rm.getString("button.deselectAll"));
}
buttonSelect.addActionListener(new PanelMappingTable_buttonSelect_actionAdapter(this));
buttonSelect.setEnabled(false);
scrollPane = new JScrollPane(panelTables);
panelMain.add(panelControl, BorderLayout.NORTH);
initTable();
this.add(panelOptions, BorderLayout.SOUTH);
this.add(panelMain, BorderLayout.CENTER);
}
/*
* This method picks good column sizes.
* If all column heads are wider than the column's cells'
* contents, then you can just use column.sizeWidthToFit().
*/
private void initColumnSizesMappingTable(JTable table) {
MappingTableModel model = (MappingTableModel) table.getModel();
TableColumn column = null;
Component comp = null;
int headerWidth = 0;
int cellWidth = 0;
Object[] longValues = model.longValues;
TableCellRenderer headerRenderer = table.getTableHeader().getDefaultRenderer();
for (int i = 0; i < 2; i++) {
column = table.getColumnModel().getColumn(i);
comp = headerRenderer.getTableCellRendererComponent(null, column.getHeaderValue(), false, false, 0, 0);
headerWidth = comp.getPreferredSize().width;
comp = table.getDefaultRenderer(model.getColumnClass(i)).getTableCellRendererComponent(table, longValues[i], false, false, 0, i);
cellWidth = comp.getPreferredSize().width;
column.setPreferredWidth(Math.max(headerWidth, cellWidth));
}
}
/*
* This method picks good column sizes.
* If all column heads are wider than the column's cells'
* contents, then you can just use column.sizeWidthToFit().
*/
private void initColumnSizesProcessTable(JTable table) {
ProcessTableModel model = (ProcessTableModel) table.getModel();
TableColumn column = null;
Component comp = null;
int headerWidth = 0;
int cellWidth = 0;
Object[] longValues = model.longValues;
TableCellRenderer headerRenderer = table.getTableHeader().getDefaultRenderer();
for (int i = 0; i < 2; i++) {
column = table.getColumnModel().getColumn(i);
comp = headerRenderer.getTableCellRendererComponent(null, column.getHeaderValue(), false, false, 0, 0);
headerWidth = comp.getPreferredSize().width;
comp = table.getDefaultRenderer(model.getColumnClass(i)).getTableCellRendererComponent(table, longValues[i], false, false, 0, i);
cellWidth = comp.getPreferredSize().width;
column.setPreferredWidth(Math.max(headerWidth, cellWidth));
}
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
void buttonSelect_actionPerformed(ActionEvent e) {
try {
if (!select_all) {
for (int row = 0; row < processTableModel.getRowCount(); row++) {
processTableModel.setValueAt(new Boolean(false), row, 0);
}
buttonSelect.setText(rm.getString("button.selectAll"));
select_all = true;
} else {
for (int row = 0; row < processTableModel.getRowCount(); row++) {
processTableModel.setValueAt(new Boolean(true), row, 0);
}
buttonSelect.setText(rm.getString("button.deselectAll"));
select_all = false;
}
} catch (Exception ex) {
postException(ex);
}
}
/**
* class description
*
* @author Anthony Smith
* @version $Revision$
*/
class MappingTableModel extends AbstractTableModel {
private String[] columnNames = { rm.getString("text.table.sourceTableView"), rm.getString("text.table.destinationTableView") };
public final Object[] longValues = { "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz" };
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final int getColumnCount() {
return columnNames.length;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final int getRowCount() {
return dataMapping.length;
}
/**
* DOCUMENT ME!
*
* @param col DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final String getColumnName(int col) {
return columnNames[col];
}
/**
* DOCUMENT ME!
*
* @param row DOCUMENT ME!
* @param col DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final Object getValueAt(int row,
int col) {
return dataMapping[row][col];
}
/*
* JTable uses this method to determine the default renderer/
* editor for each cell. If we didn't implement this method,
* then the last column would contain text ("true"/"false"),
* rather than a check box.
*/
public final Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
/*
* Don't need to implement this method unless your table's
* editable.
*/
public final boolean isCellEditable(int row,
int col) {
//Note that the data/cell address is constant,
//no matter where the cell appears onscreen.
if (col < 1) {
return false;
} else {
return true;
}
}
/*
* Don't need to implement this method unless your table's
* data can change.
*/
public final void setValueAt(Object value,
int row,
int col) {
dataMapping[row][col] = value;
Element mapping_table = null;
// check if value is not empty
if (((String) value).length() > 0) {
try {
mapping_table = model.getMappingSourceTable((String) dataMapping[row][col - 1]);
if (mapping_table != null) {
mapping_table.setAttribute(XMLTags.DESTINATION_DB, (String) dataMapping[row][col]);
mapping_table.setAttribute(XMLTags.MAPPED, "true");
// Set the process option automatically
processTableModel.setValueAt(new Boolean(true), row, 0);
// check for column mappings
model.checkForMappings((String) dataMapping[row][col - 1]);
}
} catch (Exception e) {
postException(e);
}
} else {
// Set the process option automatically
processTableModel.setValueAt(new Boolean(false), row, 0);
try {
mapping_table = model.getMappingSourceTable((String) dataMapping[row][col - 1]);
mapping_table.setAttribute(XMLTags.MAPPED, "false");
} catch (Exception e) {
postException(e);
}
}
fireTableCellUpdated(row, col);
}
}
/**
* class description
*
* @author Anthony Smith
* @version $Revision$
*/
class ProcessTableModel extends AbstractTableModel {
private String[] columnNames = { rm.getString("text.table.process") };
public final Object[] longValues = { new Boolean(false) };
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final int getColumnCount() {
return columnNames.length;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final int getRowCount() {
return dataProcess.length;
}
/**
* DOCUMENT ME!
*
* @param col DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final String getColumnName(int col) {
return columnNames[col];
}
/**
* DOCUMENT ME!
*
* @param row DOCUMENT ME!
* @param col DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final Object getValueAt(int row,
int col) {
return dataProcess[row][col];
}
/*
* JTable uses this method to determine the default renderer/
* editor for each cell. If we didn't implement this method,
* then the last column would contain text ("true"/"false"),
* rather than a check box.
*/
public final Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
/*
* Don't need to implement this method unless your table's
* data can change.
*/
public final void setValueAt(Object value,
int row,
int col) {
dataProcess[row][col] = value;
try {
Element mapping_table = model.getMappingSourceTable((String) dataMapping[row][col]);
if (mapping_table != null) {
if (value.equals(new Boolean(true))) {
mapping_table.setAttribute(XMLTags.PROCESS, "true");
} else {
mapping_table.setAttribute(XMLTags.PROCESS, "false");
}
}
} catch (Exception e) {
postException(e);
}
fireTableCellUpdated(row, col);
}
/**
* DOCUMENT ME!
*
* @param row DOCUMENT ME!
* @param col DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final boolean isCellEditable(int row,
int col) {
return true;
}
}
}
/**
* class description
*
* @author Anthony Smith
* @version $Revision$
*/
class PanelMappingTable_buttonSelect_actionAdapter implements java.awt.event.ActionListener {
PanelMappingTable adaptee;
/**
* Creates a new PanelMappingTable_buttonSelect_actionAdapter object.
*
* @param adaptee DOCUMENT ME!
*/
PanelMappingTable_buttonSelect_actionAdapter(PanelMappingTable adaptee) {
this.adaptee = adaptee;
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
public final void actionPerformed(ActionEvent e) {
adaptee.buttonSelect_actionPerformed(e);
}
}