0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041: package org.netbeans.modules.sql.framework.ui.view.join;
0042:
0043: import java.awt.BorderLayout;
0044: import java.awt.Dimension;
0045: import java.awt.GridBagConstraints;
0046: import java.awt.GridBagLayout;
0047: import java.awt.GridLayout;
0048: import java.awt.Insets;
0049: import java.awt.event.ActionEvent;
0050: import java.awt.event.ActionListener;
0051: import java.awt.event.MouseAdapter;
0052: import java.awt.event.MouseEvent;
0053: import java.util.ArrayList;
0054: import java.util.Collection;
0055: import java.util.HashSet;
0056: import java.util.Iterator;
0057: import java.util.List;
0058: import java.util.Set;
0059: import javax.swing.BorderFactory;
0060: import javax.swing.ButtonModel;
0061: import javax.swing.DefaultButtonModel;
0062: import javax.swing.DefaultListModel;
0063: import javax.swing.ImageIcon;
0064: import javax.swing.JButton;
0065: import javax.swing.JLabel;
0066: import javax.swing.JList;
0067: import javax.swing.JPanel;
0068: import javax.swing.JScrollPane;
0069: import javax.swing.ListCellRenderer;
0070: import javax.swing.ListSelectionModel;
0071: import javax.swing.event.ChangeEvent;
0072: import javax.swing.event.ChangeListener;
0073: import javax.swing.event.ListSelectionEvent;
0074: import javax.swing.event.ListSelectionListener;
0075: import org.netbeans.modules.sql.framework.model.SQLJoinView;
0076: import org.netbeans.modules.sql.framework.model.SourceTable;
0077: import org.netbeans.modules.sql.framework.model.TargetTable;
0078: import org.netbeans.modules.sql.framework.model.utils.SQLObjectUtil;
0079: import org.netbeans.modules.sql.framework.ui.graph.IGraphView;
0080: import org.netbeans.modules.sql.framework.ui.model.CollabSQLUIModel;
0081: import org.openide.DialogDisplayer;
0082: import org.openide.NotifyDescriptor;
0083: import com.sun.sql.framework.exception.BaseException;
0084: import net.java.hulp.i18n.Logger;
0085: import org.netbeans.modules.etl.logger.Localizer;
0086: import org.netbeans.modules.etl.logger.LogUtil;
0087: import org.netbeans.modules.sql.framework.model.DBTable;
0088: import org.netbeans.modules.sql.framework.model.SQLDBTable;
0089:
0090: /**
0091: * A Basic implementation of list transfer panel
0092: * @author radval
0093: */
0094: public class ListTransferPanel extends JPanel implements
0095: ActionListener, ListSelectionListener {
0096:
0097: private static final String LOG_CATEGORY = ListTransferPanel.class
0098: .getName();
0099: /** Label indicating that all elements should be moved. */
0100: public static final String LBL_ALL = "ALL";
0101: /** Indicates addition of item(s). */
0102: public static final String LBL_ADD = ">";
0103: /** Tooltip to describe addition of selected item(s). */
0104: public static final String TIP_ADD = "Add to selected items";
0105: /** Indicates removal of item(s). */
0106: public static final String LBL_REMOVE = "<";
0107: /** Tooltip to describe addition of selected item(s). */
0108: public static final String TIP_REMOVE = "Remove from selected items";
0109: /** Indicates addition of all source items. */
0110: public static final String LBL_ADD_ALL = LBL_ALL + " " + LBL_ADD;
0111: /** Tooltip to describe addition of all source items. */
0112: public static final String TIP_ADD_ALL = "Add all items";
0113: /** Indicates removal of all destination items. */
0114: public static final String LBL_REMOVE_ALL = LBL_REMOVE + " "
0115: + LBL_ALL;
0116: /** Tooltip to describe removal of all destination items. */
0117: public static final String TIP_REMOVE_ALL = "Remove all items";
0118: /** Describes source list and user task. */
0119: public static final String LBL_SOURCE_MSG = "Select Connection from the list:";
0120: /** Describes destination list */
0121: public static final String LBL_DEST_MSG = "Selected Connections:";
0122: /** Minimum number of visible items in lists */
0123: public static final int MINIMUM_VISIBLE = 5;
0124: /** Maximum number of visible items in lists */
0125: public static final int MAXIMUM_VISIBLE = 10;
0126: /* Set <ChangeListeners> */
0127: private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(
0128: 1);
0129: private JList sourceList;
0130: private JList destList;
0131: private JButton upButton;
0132: private JButton downButton;
0133: private JLabel srcLabel;
0134: private JLabel destLabel;
0135: private String srcLabelStr;
0136: private String destLabelStr;
0137: private Collection srcCollection;
0138: private Collection destCollection;
0139: private ListTransferModel listModel;
0140: private JoinMainPanel jmPanel;
0141: private ArrayList<SourceTable> newTables = new ArrayList<SourceTable>();
0142: private static transient final Logger mLogger = LogUtil
0143: .getLogger(ListTransferPanel.class.getName());
0144: private static transient final Localizer mLoc = Localizer.get();
0145:
0146: public ListTransferPanel(JoinMainPanel jMainPanel,
0147: String sLabelStr, String dLabelStr, Collection sCollection,
0148: Collection dCollection) {
0149:
0150: this .jmPanel = jMainPanel;
0151: this .srcLabelStr = sLabelStr;
0152: this .destLabelStr = dLabelStr;
0153: this .srcCollection = sCollection;
0154: this .destCollection = dCollection;
0155:
0156: initGui();
0157: }
0158:
0159: private void initGui() {
0160: listModel = new ListTransferModel(srcCollection, destCollection);
0161: String largestString = listModel.getPrototypeCell();
0162:
0163: if (largestString.length() < srcLabelStr.length()) {
0164: largestString = srcLabelStr;
0165: } else if (largestString.length() < destLabelStr.length()) {
0166: largestString = destLabelStr;
0167: }
0168:
0169: int visibleCt = Math.min(Math.max(MINIMUM_VISIBLE, listModel
0170: .getMaximumListSize()), MAXIMUM_VISIBLE);
0171:
0172: sourceList = new JList(listModel.getSourceModel());
0173: sourceList
0174: .setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
0175: sourceList.addMouseListener(new MouseAdapter() {
0176:
0177: @Override
0178: public void mouseClicked(MouseEvent e) {
0179: if (e.getClickCount() == 2
0180: && e.getSource() instanceof JList) {
0181: JList list = (JList) e.getSource();
0182: int[] indices = list.getSelectedIndices();
0183: Object[] selections = list.getSelectedValues();
0184: listModel.add(selections, indices);
0185: }
0186: }
0187: });
0188: sourceList.addListSelectionListener(this );
0189: sourceList.setPrototypeCellValue(largestString);
0190: sourceList.setVisibleRowCount(visibleCt);
0191:
0192: destList = new JList(listModel.getDestinationModel());
0193: destList
0194: .setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
0195: destList.addMouseListener(new MouseAdapter() {
0196:
0197: @Override
0198: public void mouseClicked(MouseEvent e) {
0199: if (e.getClickCount() == 2
0200: && e.getSource() instanceof JList) {
0201: JList list = (JList) e.getSource();
0202: int[] indices = list.getSelectedIndices();
0203: Object[] selections = list.getSelectedValues();
0204: if (isRemoveAllowed(selections)) {
0205: listModel.remove(selections, indices);
0206: }
0207: }
0208: }
0209: });
0210: destList.addListSelectionListener(this );
0211: destList.setPrototypeCellValue(largestString);
0212: destList.setVisibleRowCount(visibleCt);
0213:
0214: JPanel searchPanel = new JPanel();
0215: searchPanel.setLayout(new BorderLayout());
0216: srcLabel = new JLabel(srcLabelStr);
0217: srcLabel.getAccessibleContext().setAccessibleName(srcLabelStr);
0218: srcLabel.setLabelFor(sourceList);
0219:
0220: searchPanel.add(srcLabel, BorderLayout.NORTH);
0221:
0222: JScrollPane sourcepane = new JScrollPane(sourceList);
0223: JScrollPane destpane = new JScrollPane(destList);
0224: JPanel buttonPanel = new JPanel();
0225:
0226: JButton addButton = new JButton(LBL_ADD);
0227: addButton.setModel(listModel.getAddButtonModel());
0228: addButton.setToolTipText(TIP_ADD);
0229:
0230: JButton removeButton = new JButton(LBL_REMOVE);
0231: removeButton.setModel(listModel.getRemoveButtonModel());
0232: removeButton.setToolTipText(TIP_REMOVE);
0233:
0234: JButton removeAllButton = new JButton(LBL_REMOVE_ALL);
0235: removeAllButton.setModel(listModel.getRemoveAllButtonModel());
0236: removeAllButton.setToolTipText(TIP_REMOVE_ALL);
0237:
0238: JButton addAllButton = new JButton(LBL_ADD_ALL);
0239: addAllButton.setModel(listModel.getAddAllButtonModel());
0240: addAllButton.setToolTipText(TIP_ADD_ALL);
0241:
0242: addButton.setMargin(new Insets(2, 18, 2, 18));
0243: removeButton.setMargin(new Insets(2, 18, 2, 18));
0244: removeAllButton.setMargin(new Insets(2, 15, 2, 15));
0245: addAllButton.setMargin(new Insets(2, 15, 2, 15));
0246:
0247: buttonPanel.setLayout(new GridLayout(6, 1));
0248:
0249: buttonPanel.add(new JPanel());
0250: buttonPanel.add(addButton);
0251: buttonPanel.add(removeButton);
0252: buttonPanel.add(new JPanel());
0253: buttonPanel.add(removeAllButton);
0254: buttonPanel.add(addAllButton);
0255:
0256: addButton.addActionListener(this );
0257: removeButton.addActionListener(this );
0258: removeAllButton.addActionListener(this );
0259: addAllButton.addActionListener(this );
0260:
0261: JPanel sourcePanel = new JPanel();
0262: sourcePanel.setLayout(new BorderLayout());
0263: sourcePanel.add(searchPanel, BorderLayout.NORTH);
0264: sourcePanel.add(sourcepane, BorderLayout.CENTER);
0265: sourcePanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0,
0266: 5));
0267:
0268: JPanel ctrPanel = new JPanel();
0269: ctrPanel.add(buttonPanel);
0270: ctrPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
0271:
0272: JPanel destPanel = new JPanel();
0273: destLabel = new JLabel(destLabelStr);
0274: destLabel.getAccessibleContext()
0275: .setAccessibleName(destLabelStr);
0276: // destLabel.setDisplayedMnemonic('o');
0277: destLabel.setLabelFor(destList);
0278:
0279: destPanel.setLayout(new BorderLayout());
0280: destPanel.add(destLabel, BorderLayout.NORTH);
0281: destPanel.add(destpane, BorderLayout.CENTER);
0282: destPanel.setBorder(BorderFactory
0283: .createEmptyBorder(0, 5, 0, 10));
0284:
0285: JPanel listPanel = new JPanel();
0286:
0287: GridBagLayout gridbag = new GridBagLayout();
0288: GridBagConstraints c = new GridBagConstraints();
0289: listPanel.setLayout(gridbag);
0290:
0291: // allocate half of the resized space to sourcePanel
0292: c.fill = GridBagConstraints.BOTH;
0293: c.gridx = 0;
0294: c.gridy = 0;
0295: c.weightx = 1.0;
0296: c.weighty = 1.0;
0297: listPanel.add(sourcePanel, c);
0298:
0299: // make ctrPanel non resizeable
0300: c.fill = GridBagConstraints.NONE;
0301: c.gridx = 1;
0302: c.gridy = 0;
0303: c.weightx = 0.0;
0304: c.weighty = 0.0;
0305: listPanel.add(ctrPanel, c);
0306:
0307: // allocate half of the resized space to destPanel
0308: c.fill = GridBagConstraints.BOTH;
0309: c.gridx = 2;
0310: c.gridy = 0;
0311: c.weightx = 1.0;
0312: c.weighty = 1.0;
0313: listPanel.add(destPanel, c);
0314:
0315: // add updown button panel
0316: // initialize up and down target list button panel
0317: JPanel upDownButtonPanel = new JPanel();
0318: upDownButtonPanel.setLayout(new GridBagLayout());
0319: GridBagConstraints buttonPanelC = new GridBagConstraints();
0320:
0321: JPanel upDownPanel = new JPanel();
0322: upDownPanel.setBorder(BorderFactory.createEmptyBorder(16, 0, 0,
0323: 0));
0324:
0325: buttonPanelC.weightx = 1.0;
0326: buttonPanelC.weighty = 0.0;
0327: buttonPanelC.fill = GridBagConstraints.NONE;
0328: buttonPanelC.gridwidth = GridBagConstraints.REMAINDER;
0329: upDownButtonPanel.add(upDownPanel, buttonPanelC);
0330:
0331: upDownPanel.setLayout(new GridBagLayout());
0332: GridBagConstraints buttonC = new GridBagConstraints();
0333: buttonC.weightx = 1.0;
0334: buttonC.weighty = 0.2;
0335: buttonC.fill = GridBagConstraints.NONE;
0336: buttonC.gridwidth = GridBagConstraints.REMAINDER;
0337: buttonC.insets = new Insets(0, 0, 5, 0);
0338:
0339: upButton = new JButton(
0340: new ImageIcon(
0341: ListTransferPanel.class
0342: .getResource("/org/netbeans/modules/sql/framework/ui/resources/images/up.png")));
0343: upButton.setPreferredSize(new Dimension(20, 20));
0344:
0345: downButton = new JButton(
0346: new ImageIcon(
0347: ListTransferPanel.class
0348: .getResource("/org/netbeans/modules/sql/framework/ui/resources/images/down.png")));
0349: downButton.setPreferredSize(new Dimension(20, 20));
0350:
0351: // add button action listener
0352: upButton.addActionListener(this );
0353: downButton.addActionListener(this );
0354:
0355: // JPanel bPanel = new JPanel();
0356: upDownPanel.add(upButton, buttonC);
0357: upDownPanel.add(downButton, buttonC);
0358:
0359: // add a dummy panel
0360: JPanel dummpyPanel2 = new JPanel();
0361: buttonPanelC.weightx = 1.0;
0362: buttonPanelC.weighty = 1.0;
0363: buttonPanelC.fill = GridBagConstraints.BOTH;
0364: buttonPanelC.gridwidth = GridBagConstraints.REMAINDER;
0365: upDownButtonPanel.add(dummpyPanel2, buttonPanelC);
0366:
0367: c.fill = GridBagConstraints.BOTH;
0368: c.gridx = 3;
0369: c.gridy = 0;
0370: c.weightx = 0.0;
0371: c.weighty = 0.0;
0372: listPanel.add(upDownButtonPanel, c);
0373:
0374: setLayout(new BorderLayout());
0375: add(listPanel, BorderLayout.CENTER);
0376: }
0377:
0378: public void reset() {
0379: this .setSourceList(new ArrayList());
0380: this .setDestinationList(new ArrayList());
0381: this .enableButton(true);
0382: newTables.clear();
0383: }
0384:
0385: /**
0386: * set the source list cell renderer
0387: *
0388: * @param cellRenderer list cell renderer
0389: */
0390: public void setSourceListCellRenderer(ListCellRenderer cellRenderer) {
0391: this .sourceList.setCellRenderer(cellRenderer);
0392: }
0393:
0394: /**
0395: * set the target list cell renderer
0396: *
0397: * @param cellRenderer list cell renderer
0398: */
0399: public void setDestinationListCellRenderer(
0400: ListCellRenderer cellRenderer) {
0401: this .destList.setCellRenderer(cellRenderer);
0402: }
0403:
0404: public ListTransferModel getListTransferModel() {
0405: return this .listModel;
0406: }
0407:
0408: /**
0409: * set the source list
0410: *
0411: * @param sList source list
0412: */
0413: public void setSourceList(Collection sList) {
0414: listModel.setSourceList(sList);
0415: this .sourceList.setModel(listModel.getSourceModel());
0416: }
0417:
0418: /**
0419: * set the destination list
0420: *
0421: * @param dList destination list
0422: */
0423: public void setDestinationList(Collection dList) {
0424: listModel.setDestinationList(dList);
0425: this .destList.setModel(listModel.getDestinationModel());
0426: }
0427:
0428: public JList getSourceJList() {
0429: return this .sourceList;
0430: }
0431:
0432: public JList getDestinationJList() {
0433: return this .destList;
0434: }
0435:
0436: /**
0437: * Gets copy of current contents of source list
0438: *
0439: * @return List of current source list contents
0440: */
0441: public List getSourceList() {
0442: return listModel.getSourceList();
0443: }
0444:
0445: /**
0446: * Gets copy of current contents of destination list
0447: *
0448: * @return List of current destination list contents
0449: */
0450: public List<DBTable> getDestinationList() {
0451: return listModel.getDestinationList();
0452: }
0453:
0454: public void addToDestination(Object item) {
0455: DefaultListModel dModel = listModel.getDestinationModel();
0456: dModel.addElement(item);
0457: }
0458:
0459: public void removeFromDestination(Object item) {
0460: DefaultListModel dModel = listModel.getDestinationModel();
0461: dModel.removeElement(item);
0462: }
0463:
0464: public void addToSource(Object item) {
0465: DefaultListModel sModel = listModel.getSourceModel();
0466: sModel.addElement(item);
0467: }
0468:
0469: public void removeFromSource(Object item) {
0470: DefaultListModel sModel = listModel.getSourceModel();
0471: sModel.removeElement(item);
0472: }
0473:
0474: /**
0475: * Add a ChangeListener to this model.
0476: *
0477: * @param l ChangeListener to add
0478: */
0479: public void addChangeListener(ChangeListener l) {
0480: if (l != null) {
0481: synchronized (listeners) {
0482: listeners.add(l);
0483: }
0484: }
0485: }
0486:
0487: /**
0488: * Remove a ChangeListener from this model.
0489: *
0490: * @param l ChangeListener to remove
0491: */
0492: public void removeChangeListener(ChangeListener l) {
0493: if (l != null) {
0494: synchronized (listeners) {
0495: listeners.remove(l);
0496: }
0497: }
0498: }
0499:
0500: /**
0501: * Fires a ChangeEvent to all interested listeners to indicate a state change in one
0502: * or more UI components.
0503: */
0504: public void fireChangeEvent() {
0505: Iterator<ChangeListener> it;
0506:
0507: synchronized (listeners) {
0508: it = new HashSet<ChangeListener>(listeners).iterator();
0509: }
0510:
0511: ChangeEvent ev = new ChangeEvent(this );
0512: while (it.hasNext()) {
0513: it.next().stateChanged(ev);
0514: }
0515: }
0516:
0517: /**
0518: * Invoked whenever one of the transfer buttons is clicked.
0519: *
0520: * @param e ActionEvent to handle
0521: */
0522: public void actionPerformed(ActionEvent e) {
0523: String cmd = e.getActionCommand();
0524:
0525: if (LBL_ADD.equals(cmd)) {
0526: int[] indices = sourceList.getSelectedIndices();
0527: Object[] selections = sourceList.getSelectedValues();
0528: if (isAddAllowed(selections)) {
0529: listModel.add(selections, indices);
0530: }
0531: } else if (LBL_ADD_ALL.equals(cmd)) {
0532: Object[] selections = listModel.getSourceList().toArray();
0533: if (isAddAllowed(selections)) {
0534: listModel.addAll();
0535: }
0536: } else if (LBL_REMOVE.equals(cmd)) {
0537: int[] indices = destList.getSelectedIndices();
0538: Object[] selections = destList.getSelectedValues();
0539: if (isRemoveAllowed(selections)) {
0540: listModel.remove(selections, indices);
0541: }
0542: } else if (LBL_REMOVE_ALL.equals(cmd)) {
0543: Object[] selections = listModel.getDestinationList()
0544: .toArray();
0545: if (isRemoveAllowed(selections)) {
0546: listModel.removeAll();
0547: }
0548: } else if (e.getSource().equals(upButton)) {
0549: this .jmPanel.moveUp();
0550: } else if (e.getSource().equals(downButton)) {
0551: this .jmPanel.moveDown();
0552: } else {
0553: // Log this as an invalid or unknown command.
0554: System.err.println("Unknown cmd: " + cmd);
0555: }
0556: }
0557:
0558: private boolean isRemoveAllowed(Object[] selections) {
0559: IGraphView graphView = this .jmPanel.getMainGraphView();
0560: // if graph view is null then it means this is used in collaboraiton creation
0561: // wizard
0562: // so return true;
0563: if (graphView == null) {
0564: return true;
0565: }
0566:
0567: SQLJoinView joinView = this .jmPanel.getInitialSQLJoinView();
0568: JoinViewGraphNode joinViewNode = (JoinViewGraphNode) graphView
0569: .findGraphNode(joinView);
0570: CollabSQLUIModel sqlModel = (CollabSQLUIModel) graphView
0571: .getGraphModel();
0572:
0573: // no join view exist
0574: if (joinViewNode != null) {
0575: for (int i = 0; i < selections.length; i++) {
0576: SourceTable sTable = (SourceTable) selections[i];
0577: if (joinViewNode.isTableColumnMapped(sTable)) {
0578: NotifyDescriptor d = new NotifyDescriptor.Confirmation(
0579: "Table "
0580: + sTable.getName()
0581: + " has some mappings defined which will be lost. Do you really want to remove this table?",
0582: NotifyDescriptor.WARNING_MESSAGE);
0583: Object response = DialogDisplayer.getDefault()
0584: .notify(d);
0585: if (!response.equals(NotifyDescriptor.OK_OPTION)) {
0586: return false;
0587: }
0588: }
0589: }
0590: }
0591:
0592: NotifyDescriptor nd = new NotifyDescriptor.Confirmation(
0593: "You may lose some user defined conditions in some joins. Do you really want to remove the table?",
0594: NotifyDescriptor.WARNING_MESSAGE);
0595:
0596: Object response = DialogDisplayer.getDefault().notify(nd);
0597: if (!response.equals(NotifyDescriptor.OK_OPTION)) {
0598: return false;
0599: }
0600:
0601: SourceTable sTable = null;
0602: try {
0603: // We need to remove the table from definition if this table was added using
0604: // more table dialog.
0605: for (int i = 0; i < selections.length; i++) {
0606: sTable = (SourceTable) selections[i];
0607: // if its a new table selected using more table dialog then
0608: // we need to add this to sql model
0609: if (newTables.contains(sTable)) {
0610: sqlModel.removeObject(sTable);
0611: newTables.remove(sTable);
0612: }
0613: }
0614: } catch (BaseException ex) {
0615: String tableName = sTable != null ? sTable.getName() : "";
0616: mLogger
0617: .errorNoloc(
0618: mLoc
0619: .t(
0620: "PRSR190: Error Occured while removing the table{0}which user has added using more table dialog",
0621: tableName), ex);
0622: NotifyDescriptor d = new NotifyDescriptor.Message(
0623: "Table "
0624: + tableName
0625: + " which was added using more table dialog, can not be deleted from the model.",
0626: NotifyDescriptor.INFORMATION_MESSAGE);
0627: DialogDisplayer.getDefault().notify(d);
0628: return false;
0629: }
0630:
0631: return true;
0632: }
0633:
0634: private boolean isAddAllowed(Object[] selections) {
0635: IGraphView graphView = this .jmPanel.getMainGraphView();
0636: SQLJoinView joinView = this .jmPanel.getInitialSQLJoinView();
0637: // if graph view is null then it means this is used in collaboraiton creation
0638: // wizard
0639: // so return true;
0640: if (graphView == null) {
0641: return true;
0642: }
0643: CollabSQLUIModel sqlModel = (CollabSQLUIModel) graphView
0644: .getGraphModel();
0645:
0646: // check if tables which we are trying to add are mapped to different target
0647: // tables
0648: // than the one which are already in join view
0649: Iterator it = this .getDestinationList().iterator();
0650: TargetTable joinViewMappedTable = null;
0651: while (it.hasNext()) {
0652: SourceTable sTable = (SourceTable) it.next();
0653: joinViewMappedTable = SQLObjectUtil.getMappedTargetTable(
0654: sTable, sqlModel.getSQLDefinition()
0655: .getTargetTables());
0656: if (joinViewMappedTable != null) {
0657: break;
0658: }
0659: }
0660:
0661: if (joinViewMappedTable != null) {
0662: for (int i = 0; i < selections.length; i++) {
0663: SourceTable sTable = (SourceTable) selections[i];
0664: TargetTable mappedTable = SQLObjectUtil
0665: .getMappedTargetTable(sTable, sqlModel
0666: .getSQLDefinition().getTargetTables());
0667: if (mappedTable != null
0668: && !mappedTable.equals(joinViewMappedTable)) {
0669: NotifyDescriptor d = new NotifyDescriptor.Message(
0670: "Table "
0671: + sTable.getName()
0672: + " has some mappings defined to a different target table, so it can not be added",
0673: NotifyDescriptor.INFORMATION_MESSAGE);
0674: DialogDisplayer.getDefault().notify(d);
0675: return false;
0676: }
0677: }
0678: }
0679:
0680: TargetTable previousMappedTable = null;
0681: SourceTable previousSourceTable = null;
0682:
0683: for (int i = 0; i < selections.length; i++) {
0684: SourceTable sTable = (SourceTable) selections[i];
0685: TargetTable mappedTable = SQLObjectUtil
0686: .getMappedTargetTable(sTable, sqlModel
0687: .getSQLDefinition().getTargetTables());
0688: if (mappedTable != null) {
0689: if (joinView != null) {
0690: SQLJoinView mappedTableJoinView = mappedTable
0691: .getJoinView();
0692: // a target table may
0693: if (mappedTableJoinView != null
0694: && !joinView.equals(mappedTableJoinView)) {
0695: NotifyDescriptor d = new NotifyDescriptor.Message(
0696: "Table "
0697: + sTable.getName()
0698: + " has some mappings defined to a different target table, so it can not be added",
0699: NotifyDescriptor.INFORMATION_MESSAGE);
0700: DialogDisplayer.getDefault().notify(d);
0701: return false;
0702: }
0703: return true;
0704: }
0705: // check if two tables which we are trying to add are mapped to two
0706: // different target tables
0707: if (previousMappedTable != null
0708: && previousSourceTable != null
0709: && !previousMappedTable.equals(mappedTable)) {
0710: NotifyDescriptor d = new NotifyDescriptor.Message(
0711: "Table "
0712: + sTable.getName()
0713: + " and Table "
0714: + previousSourceTable.getName()
0715: + " are mapped to different target table, so these can not be added",
0716: NotifyDescriptor.INFORMATION_MESSAGE);
0717: DialogDisplayer.getDefault().notify(d);
0718: return false;
0719: }
0720:
0721: previousMappedTable = mappedTable;
0722: previousSourceTable = sTable;
0723: }
0724: }
0725:
0726: SourceTable sTable = null;
0727: try {
0728:
0729: // We need to add the table if it is not definition(meaning this table is
0730: // selected in more table dialog) , because if user
0731: // uses this table column in join condition then it will not have an id
0732: // and will cause parsing for that condition column
0733: for (int i = 0; i < selections.length; i++) {
0734: sTable = (SourceTable) selections[i];
0735: // if its a new table selected using more table dialog then
0736: // we need to add this to sql model
0737: if (!sqlModel.exists(sTable)) {
0738: sTable.setUsedInJoin(true);
0739: sqlModel.addObject(sTable);
0740: newTables.add(sTable);
0741: }
0742: }
0743: } catch (BaseException ex) {
0744: String tableName = sTable != null ? sTable.getName() : "";
0745: mLogger
0746: .errorNoloc(
0747: mLoc
0748: .t(
0749: "PRSR191: Error Occured while adding the table {0}to model, which user has added using more table dialog",
0750: tableName), ex);
0751: NotifyDescriptor d = new NotifyDescriptor.Message(
0752: "Table "
0753: + tableName
0754: + " which was added using more table dialog, can not be added to the model.",
0755: NotifyDescriptor.ERROR_MESSAGE);
0756: DialogDisplayer.getDefault().notify(d);
0757: return false;
0758: }
0759:
0760: return true;
0761: }
0762:
0763: /**
0764: * Called whenever the value of the selection changes.
0765: *
0766: * @param e the event that characterizes the change.
0767: */
0768: public void valueChanged(ListSelectionEvent e) {
0769: Object src = e.getSource();
0770:
0771: // Enforce mutually exclusive focus between source and destination
0772: // lists.
0773: if (sourceList.equals(src)) {
0774: if (!destList.isSelectionEmpty()) {
0775: destList.clearSelection();
0776: }
0777: } else if (destList.equals(src)) {
0778: if (!sourceList.isSelectionEmpty()) {
0779: sourceList.clearSelection();
0780: }
0781: } else {
0782: // @todo Log unhandled ListSelectionEvent as DEBUG message.
0783: }
0784: listModel.updateButtonState();
0785: }
0786:
0787: /**
0788: * Container for ListModels associated with source and destination lists of a list
0789: * transfer panel. Holds ButtonModels for controls that indicate selected addition and
0790: * bulk addition to destination list and selected removal and bulk removal of items
0791: * from the destination list.
0792: *
0793: * @author Jonathan Giron
0794: * @author Sanjeeth Duvuru
0795: * @version $Revision$
0796: */
0797: public class ListTransferModel {
0798:
0799: private DefaultListModel source;
0800: private DefaultListModel dest;
0801: private ButtonModel addButtonModel;
0802: private ButtonModel addAllButtonModel;
0803: private ButtonModel removeButtonModel;
0804: private ButtonModel removeAllButtonModel;
0805: private HashSet<ChangeListener> changeListeners;
0806: private String listPrototype;
0807: private boolean enableButton = true;
0808:
0809: /**
0810: * Creates a new instance of ListTransferModel, using the data in the given
0811: * collections to initially populate the source and destination lists.
0812: *
0813: * @param srcColl Collection used to populate source list
0814: * @param dstColl Collection used to populate destination list
0815: */
0816: public ListTransferModel(Collection srcColl, Collection dstColl) {
0817:
0818: if (srcColl == null || dstColl == null) {
0819: throw new IllegalArgumentException(
0820: "Must supply non-null collections for srcColl and dstColl");
0821: }
0822:
0823: listPrototype = "";
0824:
0825: source = new DefaultListModel();
0826: dest = new DefaultListModel();
0827:
0828: addButtonModel = new DefaultButtonModel();
0829: addAllButtonModel = new DefaultButtonModel();
0830: removeButtonModel = new DefaultButtonModel();
0831: removeAllButtonModel = new DefaultButtonModel();
0832:
0833: setSourceList(srcColl);
0834: setDestinationList(dstColl);
0835:
0836: changeListeners = new HashSet<ChangeListener>();
0837: }
0838:
0839: /**
0840: * @see org.openide.WizardDescriptor.Panel#addChangeListener
0841: */
0842: public void addChangeListener(ChangeListener l) {
0843: synchronized (changeListeners) {
0844: changeListeners.add(l);
0845: }
0846: }
0847:
0848: /**
0849: * @see org.openide.WizardDescriptor.Panel#removeChangeListener
0850: */
0851: public void removeChangeListener(ChangeListener l) {
0852: synchronized (changeListeners) {
0853: changeListeners.remove(l);
0854: }
0855: }
0856:
0857: /**
0858: * Gets ListModel associated with source list.
0859: *
0860: * @return source ListModel
0861: */
0862: public DefaultListModel getSourceModel() {
0863: return source;
0864: }
0865:
0866: /**
0867: * Sets source list to include contents of given list. Clears current contents
0868: * before adding items from newList.
0869: *
0870: * @param newList List whose contents will supplant the current contents of the
0871: * source list
0872: */
0873: public void setSourceList(Collection newList) {
0874: if (newList == null) {
0875: throw new IllegalArgumentException(
0876: "Must supply non-null Collection for newList");
0877: }
0878:
0879: if (source == null) {
0880: source = new DefaultListModel();
0881: }
0882:
0883: synchronized (source) {
0884: source.clear();
0885:
0886: Iterator it = newList.iterator();
0887: while (it.hasNext()) {
0888: Object o = it.next();
0889: source.addElement(o);
0890: if (o.toString().trim().length() > listPrototype
0891: .length()) {
0892: listPrototype = o.toString().trim();
0893: }
0894: }
0895: }
0896:
0897: updateButtonState();
0898: }
0899:
0900: /**
0901: * Gets copy of current contents of source list
0902: *
0903: * @return List of current source list contents
0904: */
0905: public List getSourceList() {
0906: ArrayList<Object> srcList = new ArrayList<Object>();
0907:
0908: synchronized (source) {
0909: source.trimToSize();
0910: for (int i = 0; i < source.size(); i++) {
0911: srcList.add(source.get(i));
0912: }
0913: }
0914:
0915: return srcList;
0916: }
0917:
0918: /**
0919: * Gets ListModel associated with destination list.
0920: *
0921: * @return source ListModel
0922: */
0923: public DefaultListModel getDestinationModel() {
0924: return dest;
0925: }
0926:
0927: /**
0928: * Sets destination list to include contents of given list. Clears current
0929: * contents before adding items from newList.
0930: *
0931: * @param newList List whose contents will supplant the current contents of the
0932: * destination list
0933: */
0934: public void setDestinationList(Collection newList) {
0935: if (newList == null) {
0936: throw new IllegalArgumentException(
0937: "Must supply non-null Collection for newList");
0938: }
0939:
0940: if (dest == null) {
0941: dest = new DefaultListModel();
0942: }
0943:
0944: synchronized (dest) {
0945: dest.clear();
0946:
0947: Iterator it = newList.iterator();
0948: while (it.hasNext()) {
0949: Object o = it.next();
0950: dest.addElement(o);
0951: if (o.toString().trim().length() > listPrototype
0952: .length()) {
0953: listPrototype = o.toString().trim();
0954: }
0955: }
0956: }
0957:
0958: updateButtonState();
0959: }
0960:
0961: /**
0962: * Gets copy of current contents of destination list
0963: *
0964: * @return List of current destination list contents
0965: */
0966: public List<DBTable> getDestinationList() {
0967: ArrayList<DBTable> dstList = new ArrayList<DBTable>();
0968:
0969: synchronized (dest) {
0970: dest.trimToSize();
0971: for (int i = 0; i < dest.size(); i++) {
0972: dstList.add((SQLDBTable) dest.get(i));
0973: }
0974: }
0975:
0976: return dstList;
0977: }
0978:
0979: /**
0980: * Moves indicated items from source to destination list.
0981: *
0982: * @param selections array of selected items
0983: * @param indices array of indices, each element corresponding to the item in
0984: * selections array
0985: */
0986: public void add(Object[] selections, int[] indices) {
0987: synchronized (dest) {
0988: synchronized (source) {
0989: for (int i = 0; i < indices.length; i++) {
0990: Object element = selections[i];
0991: dest.addElement(element);
0992: int index = dest.indexOf(element);
0993: source.removeElement(element);
0994: fireTransferEvent(dest, element, index,
0995: TransferEvent.ADDED);
0996: }
0997:
0998: updateButtonState();
0999: }
1000:
1001: // fire change event so that next button can be enabled as we add new
1002: // rows in table
1003: fireChangeEvent();
1004: }
1005:
1006: updateButtonState();
1007: }
1008:
1009: /**
1010: * Gets ButtonModel associated with add button action.
1011: *
1012: * @return add ButtonModel
1013: */
1014: public ButtonModel getAddButtonModel() {
1015: return addButtonModel;
1016: }
1017:
1018: /**
1019: * Moves all remaining items from source to destination list.
1020: */
1021: public void addAll() {
1022: synchronized (dest) {
1023: synchronized (source) {
1024: int size = source.getSize();
1025: for (int i = 0; i < size; i++) {
1026: Object element = source.elementAt(i);
1027: dest.addElement(element);
1028: int index = dest.indexOf(element);
1029: fireTransferEvent(dest, element, index,
1030: TransferEvent.ADDED);
1031: }
1032: source.removeAllElements();
1033: }
1034: }
1035:
1036: updateButtonState();
1037:
1038: // fire change event so that next button can be enabled as we add new rows in
1039: // table
1040: fireChangeEvent();
1041: }
1042:
1043: /**
1044: * Gets ButtonModel associated with add all button action.
1045: *
1046: * @return add all ButtonModel
1047: */
1048: public ButtonModel getAddAllButtonModel() {
1049: return addAllButtonModel;
1050: }
1051:
1052: /**
1053: * Moves indicated items from destination to source list.
1054: *
1055: * @param selections array of selected items
1056: * @param indices array of indices, each element corresponding to the item in
1057: * selections array
1058: */
1059: public void remove(Object[] selections, int[] indices) {
1060: synchronized (dest) {
1061: synchronized (source) {
1062: for (int i = 0; i < indices.length; i++) {
1063: Object element = selections[i];
1064: source.addElement(element);
1065: int index = dest.indexOf(element);
1066: dest.removeElement(element);
1067: fireTransferEvent(dest, element, index,
1068: TransferEvent.REMOVED);
1069: }
1070: }
1071: }
1072:
1073: updateButtonState();
1074:
1075: // fire change event so that next button can be enabled as we remove new rows
1076: // in table
1077: fireChangeEvent();
1078: }
1079:
1080: /**
1081: * Gets ButtonModel associated with remove button action.
1082: *
1083: * @return remove ButtonModel
1084: */
1085: public ButtonModel getRemoveButtonModel() {
1086: return removeButtonModel;
1087: }
1088:
1089: /**
1090: * Moves all remaining items from destination to source list.
1091: */
1092: public void removeAll() {
1093: synchronized (dest) {
1094: synchronized (source) {
1095: int size = dest.getSize();
1096: ArrayList<Object> removed = new ArrayList<Object>();
1097: for (int i = 0; i < size; i++) {
1098: Object element = dest.elementAt(i);
1099: source.addElement(element);
1100: removed.add(element);
1101: }
1102:
1103: for (int i = 0; i < size; i++) {
1104: Object element = removed.get(i);
1105: dest.removeElement(element);
1106: fireTransferEvent(dest, element, i,
1107: TransferEvent.REMOVED);
1108: }
1109: }
1110: }
1111:
1112: updateButtonState();
1113:
1114: // fire change event so that next button can be enabled as we remove new rows
1115: // in table
1116: fireChangeEvent();
1117: }
1118:
1119: /**
1120: * Gets ButtonModel associated with remove all button action
1121: *
1122: * @return remove all ButtonModel
1123: */
1124: public ButtonModel getRemoveAllButtonModel() {
1125: return removeAllButtonModel;
1126: }
1127:
1128: /**
1129: * Updates button states
1130: */
1131: public void updateButtonState() {
1132: if (!enableButton) {
1133: return;
1134: }
1135:
1136: boolean canAddAll = !source.isEmpty();
1137: boolean canRemoveAll = !dest.isEmpty();
1138:
1139: boolean srcSelected = (sourceList != null)
1140: && !sourceList.isSelectionEmpty();
1141: boolean destSelected = (destList != null)
1142: && !destList.isSelectionEmpty();
1143:
1144: boolean canAdd = canAddAll & srcSelected;
1145: boolean canRemove = canRemoveAll & destSelected;
1146:
1147: addButtonModel.setEnabled(canAdd);
1148: addAllButtonModel.setEnabled(canAddAll);
1149: removeButtonModel.setEnabled(canRemove);
1150: removeAllButtonModel.setEnabled(canRemoveAll);
1151: }
1152:
1153: public void enableButton(boolean enable) {
1154: this .enableButton = enable;
1155: addButtonModel.setEnabled(enable);
1156: addAllButtonModel.setEnabled(enable);
1157: removeButtonModel.setEnabled(enable);
1158: removeAllButtonModel.setEnabled(enable);
1159: }
1160:
1161: /**
1162: * Returns index of source item matching the given string.
1163: *
1164: * @param searchStr string to search for in source list
1165: * @param startFrom index from which to start search
1166: * @return index of matching item, or -1 if no match exists
1167: */
1168: public int getSourceIndexFor(String searchStr, int startFrom) {
1169: if (startFrom < 0 || startFrom > source.size()) {
1170: startFrom = 0;
1171: }
1172:
1173: if (searchStr != null && searchStr.trim().length() != 0) {
1174: return source.indexOf(searchStr, startFrom);
1175: }
1176:
1177: return -1;
1178: }
1179:
1180: /**
1181: * Gets prototype String that has the largest width of an item in either list.
1182: *
1183: * @return String whose length is the largest among the items in either list
1184: */
1185: public String getPrototypeCell() {
1186: return listPrototype;
1187: }
1188:
1189: /**
1190: * Gets maximum number of items expected in either the source or destination list.
1191: *
1192: * @return maximum count of items in any one list
1193: */
1194: public int getMaximumListSize() {
1195: return source.size() + dest.size();
1196: }
1197:
1198: private void fireTransferEvent(Object src, Object item,
1199: int index, int type) {
1200: if (src != null && item != null) {
1201: TransferEvent e = new TransferEvent(src, item, index,
1202: type);
1203: synchronized (changeListeners) {
1204: Iterator iter = changeListeners.iterator();
1205: while (iter.hasNext()) {
1206: ChangeListener l = (ChangeListener) iter.next();
1207: l.stateChanged(e);
1208: }
1209: }
1210: }
1211: }
1212: }
1213:
1214: /**
1215: * Extends ChangeEvent to convey information on an item being transferred to or from
1216: * the source of the event.
1217: *
1218: * @author Jonathan Giron
1219: * @version $Revision$
1220: */
1221: public static class TransferEvent extends ChangeEvent {
1222:
1223: /** Indicates addition of an item to the source of the event */
1224: public static final int ADDED = 0;
1225: /** Indicates removal of an item from the source of the event */
1226: public static final int REMOVED = 1;
1227: private Object item;
1228: private int type;
1229: private int idx;
1230:
1231: /**
1232: * Create a new TransferEvent instance with the given source, item and type.
1233: *
1234: * @param source source of this transfer event
1235: * @param item transferred item
1236: * @param type transfer type, either ADDED or REMOVED
1237: * @see #ADDED
1238: * @see #REMOVED
1239: */
1240: public TransferEvent(Object source, Object item, int type) {
1241: super (source);
1242: this .item = item;
1243: this .type = type;
1244: }
1245:
1246: /**
1247: * Create a new TransferEvent instance with the given source, item and type.
1248: *
1249: * @param source source of this transfer event
1250: * @param item transferred item
1251: * @param type transfer type, either ADDED or REMOVED
1252: * @see #ADDED
1253: * @see #REMOVED
1254: */
1255: public TransferEvent(Object source, Object item, int index,
1256: int type) {
1257: super (source);
1258: this .item = item;
1259: this .idx = index;
1260: this .type = type;
1261: }
1262:
1263: /**
1264: * Gets item that was transferred.
1265: *
1266: * @return transferred item
1267: */
1268: public Object getItem() {
1269: return item;
1270: }
1271:
1272: public int getItemIndex() {
1273: return idx;
1274: }
1275:
1276: /**
1277: * Gets type of transfer event.
1278: *
1279: * @return ADDED or REMOVED
1280: */
1281: public int getType() {
1282: return type;
1283: }
1284: }
1285:
1286: public void enableButton(boolean enable) {
1287: // this.listModel.enableButton(enable);
1288: }
1289:
1290: // remove tables which were added using more table dialog, when user cancel join edit
1291: // or first time creation
1292: public void removeMoreTablesOnCancel() {
1293: IGraphView graphView = this .jmPanel.getMainGraphView();
1294: if (graphView != null) {
1295: CollabSQLUIModel sqlModel = (CollabSQLUIModel) graphView
1296: .getGraphModel();
1297: SourceTable sTable = null;
1298:
1299: try {
1300: // We need to remove the table from definition if this table was added using
1301: // more table dialog.
1302: for (int i = 0; i < newTables.size(); i++) {
1303: sTable = newTables.get(i);
1304: // if its a new table selected using more table dialog then
1305: // we need to add this to sql model
1306: sqlModel.removeObject(sTable);
1307: }
1308: } catch (BaseException ex) {
1309: String tableName = sTable != null ? sTable.getName()
1310: : "";
1311: mLogger
1312: .errorNoloc(
1313: mLoc
1314: .t(
1315: "PRSR192: Error Occured while removing the table {0}which user has added using more table dialog",
1316: tableName), ex);
1317: NotifyDescriptor d = new NotifyDescriptor.Message(
1318: "Table "
1319: + tableName
1320: + " which was added using more table dialog, can not be deleted from the model.",
1321: NotifyDescriptor.INFORMATION_MESSAGE);
1322: DialogDisplayer.getDefault().notify(d);
1323: }
1324: }
1325: }
1326: // private boolean existsIn(Collection collection, SQLObject obj) {
1327: // if (collection == null || obj == null) {
1328: // return false;
1329: // }
1330: //
1331: // Iterator iter = collection.iterator();
1332: // boolean exists = false;
1333: // while (iter.hasNext()) {
1334: // Object existing = iter.next();
1335: // if (obj.toString().equals(existing.toString())) {
1336: // exists = true;
1337: // break;
1338: // }
1339: // }
1340: //
1341: // return exists;
1342: // }
1343: }
|