001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.etl.ui.view;
042:
043: import java.awt.BorderLayout;
044: import java.awt.Component;
045: import java.awt.datatransfer.DataFlavor;
046: import java.awt.datatransfer.Transferable;
047: import java.awt.datatransfer.UnsupportedFlavorException;
048: import java.awt.dnd.DnDConstants;
049: import java.awt.dnd.DragGestureEvent;
050: import java.awt.dnd.DragGestureListener;
051: import java.awt.dnd.DragSource;
052: import java.awt.dnd.InvalidDnDOperationException;
053: import java.beans.PropertyChangeEvent;
054: import java.beans.PropertyChangeListener;
055: import java.io.IOException;
056: import java.net.URL;
057: import java.util.Iterator;
058: import java.util.List;
059:
060: import javax.swing.ImageIcon;
061: import javax.swing.JLabel;
062: import javax.swing.JPanel;
063: import javax.swing.JScrollPane;
064: import javax.swing.JTree;
065: import javax.swing.event.TreeSelectionEvent;
066: import javax.swing.event.TreeSelectionListener;
067: import javax.swing.tree.DefaultMutableTreeNode;
068: import javax.swing.tree.DefaultTreeCellRenderer;
069: import javax.swing.tree.DefaultTreeModel;
070: import javax.swing.tree.TreePath;
071:
072: import org.netbeans.modules.etl.ui.DataObjectHelper;
073: import org.netbeans.modules.sql.framework.common.jdbc.SQLDBConnectionDefinition;
074: import org.netbeans.modules.sql.framework.model.SQLConstants;
075: import org.netbeans.modules.sql.framework.model.SQLDBColumn;
076: import org.netbeans.modules.sql.framework.model.SQLDBModel;
077: import org.netbeans.modules.sql.framework.model.SQLDBTable;
078: import org.netbeans.modules.sql.framework.model.SourceColumn;
079: import org.netbeans.modules.sql.framework.model.SourceTable;
080: import org.netbeans.modules.sql.framework.model.TargetTable;
081: import org.netbeans.modules.sql.framework.ui.editor.property.IPropertyGroup;
082: import org.netbeans.modules.sql.framework.ui.editor.property.IPropertySheet;
083: import org.netbeans.modules.sql.framework.ui.editor.property.impl.PropertyViewManager;
084: import org.netbeans.modules.sql.framework.ui.utils.UIUtil;
085: import net.java.hulp.i18n.Logger;
086: import org.netbeans.modules.etl.logger.Localizer;
087: import org.netbeans.modules.etl.logger.LogUtil;
088: import org.netbeans.modules.sql.framework.model.DBTable;
089:
090: /**
091: * @author Ritesh Adval
092: * @version $Revision$
093: */
094: public class DBModelTreeView extends JPanel implements
095: PropertyChangeListener {
096:
097: private String LOG_CATEGORY = DBModelTreeView.class.getName();
098: private JTree tree;
099: private List dbModels;
100: private EditDBModelPanel editPanel;
101: private Component comp;
102: private IPropertySheet propSheet;
103: private static DataFlavor[] mDataFlavorArray = new DataFlavor[1];
104: private static transient final Logger mLogger = LogUtil
105: .getLogger(DBModelTreeView.class.getName());
106: private static transient final Localizer mLoc = Localizer.get();
107: private static URL rootImgUrl = DBModelTreeView.class
108: .getResource("/org/netbeans/modules/sql/framework/ui/resources/images/root.png");
109: private static URL columnImgUrl = DBModelTreeView.class
110: .getResource("/org/netbeans/modules/sql/framework/ui/resources/images/column.png");
111: private static URL tableImgUrl = DBModelTreeView.class
112: .getResource("/org/netbeans/modules/sql/framework/ui/resources/images/SourceTable.png");
113: private static URL targetTableImgUrl = DBModelTreeView.class
114: .getResource("/org/netbeans/modules/sql/framework/ui/resources/images/TargetTable.png");
115: private static ImageIcon rootIcon;
116: private static ImageIcon tableIcon;
117: private static ImageIcon targetTableIcon;
118: private static ImageIcon columnIcon;
119: private IPropertyGroup pGroup;
120:
121: static {
122: try {
123: mDataFlavorArray[0] = new DataFlavor(
124: DataFlavor.javaJVMLocalObjectMimeType);
125: rootIcon = new ImageIcon(rootImgUrl);
126: tableIcon = new ImageIcon(tableImgUrl);
127: columnIcon = new ImageIcon(columnImgUrl);
128: targetTableIcon = new ImageIcon(targetTableImgUrl);
129: } catch (ClassNotFoundException ex) {
130: ex.printStackTrace();
131: }
132: }
133:
134: /**
135: * Creates a new instance of DBModelTreeView.
136: *
137: * @param dbModels List of DatabaseModels whose contents are to be displayed
138: * @param editPanel EditDBModelPanel associated with this view
139: */
140: public DBModelTreeView(List dbModels, EditDBModelPanel editPanel) {
141: super ();
142: this .editPanel = editPanel;
143: this .dbModels = dbModels;
144: if (dbModels == null || dbModels.size() == 0) {
145: return;
146: }
147:
148: initGui();
149: }
150:
151: private void initGui() {
152: DragSource dSource = DragSource.getDefaultDragSource();
153:
154: this .setLayout(new BorderLayout());
155: DefaultTreeModel treeModel = createTreeModel();
156: tree = new JTree();
157:
158: tree.setCellRenderer(new TableTreeCellRenderer());
159: tree.addTreeSelectionListener(new TreeSelectionListener() {
160:
161: public void valueChanged(TreeSelectionEvent e) {
162: if (propSheet != null) {
163: propSheet.commitChanges();
164: if (pGroup != null) {
165: pGroup
166: .removePropertyChangeListener(DBModelTreeView.this );
167: }
168: tree.repaint();
169: }
170:
171: DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
172: .getLastSelectedPathComponent();
173: if (node == null) {
174: return;
175: }
176:
177: Object nodeInfo = node.getUserObject();
178: if (nodeInfo instanceof SQLDBModel) {
179: if (comp != null) {
180: editPanel.remove(comp);
181: }
182: PropertyViewManager pvMgr = DataObjectHelper
183: .getPropertyViewManager();
184: DBModelObj dbObj = new DBModelObj(
185: (SQLDBModel) nodeInfo);
186: propSheet = pvMgr
187: .getPropertySheet(dbObj, "DBModel");
188: comp = propSheet.getPropertySheet();
189: editPanel.setRightComponent(comp);
190: editPanel.updateUI();
191: } else if (nodeInfo instanceof DBTable) {
192: if (comp != null) {
193: editPanel.remove(comp);
194: }
195: PropertyViewManager pvMgr = DataObjectHelper
196: .getPropertyViewManager();
197: DBTableObj dbTab = new DBTableObj(
198: (SQLDBTable) nodeInfo);
199: propSheet = pvMgr
200: .getPropertySheet(dbTab, "DBTable");
201: pGroup = propSheet.getPropertyGroup("default");
202: if (pGroup != null) {
203: pGroup
204: .addPropertyChangeListener(DBModelTreeView.this );
205: }
206: comp = propSheet.getPropertySheet();
207: editPanel.setRightComponent(comp);
208: editPanel.updateUI();
209: } else {
210: editPanel.setRightComponent(new JPanel());
211: editPanel.updateUI();
212: }
213: }
214: });
215:
216: dSource.createDefaultDragGestureRecognizer(tree,
217: DnDConstants.ACTION_COPY_OR_MOVE,
218: new TreeDragGestureListener());
219:
220: tree.setModel(treeModel);
221:
222: tree.setRootVisible(false);
223: tree.setDragEnabled(true);
224: tree.setShowsRootHandles(true);
225:
226: Object root = treeModel.getRoot();
227: Object rootFirstChild = treeModel.getChild(root, 0);
228:
229: Object pathArray[] = new Object[2];
230: pathArray[0] = root;
231: pathArray[1] = rootFirstChild;
232:
233: TreePath tpath = new TreePath(pathArray);
234: tree.setSelectionPath(tpath);
235: JScrollPane treePane = new JScrollPane(tree);
236: this .add(BorderLayout.CENTER, treePane);
237: }
238:
239: /**
240: * Gets current IPropertySheet instance, if any.
241: *
242: * @return current IPropertySheet, possibly null.
243: */
244: public IPropertySheet getPropSheet() {
245: return propSheet;
246: }
247:
248: private DefaultTreeModel createTreeModel() {
249: DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode();
250: DefaultTreeModel treeModel = new DefaultTreeModel(rootNode);
251:
252: Iterator it = dbModels.iterator();
253: while (it.hasNext()) {
254: SQLDBModel dbModel = (SQLDBModel) it.next();
255: DefaultMutableTreeNode dbModelNode = new DefaultMutableTreeNode(
256: dbModel);
257: rootNode.add(dbModelNode);
258: createTableNodes(dbModel, dbModelNode);
259: }
260:
261: return treeModel;
262: }
263:
264: private void createTableNodes(SQLDBModel dbModel,
265: DefaultMutableTreeNode dbModelNode) {
266: Iterator it = dbModel.getTables().iterator();
267: while (it.hasNext()) {
268: DBTable table = (DBTable) it.next();
269: DefaultMutableTreeNode tableNode = new TableNode(table);
270: dbModelNode.add(tableNode);
271: }
272: }
273:
274: private class TableNode extends DefaultMutableTreeNode {
275:
276: private SQLDBTable table;
277:
278: public TableNode(Object userObj) {
279: super (userObj);
280: this .table = (SQLDBTable) userObj;
281: }
282:
283: public String toString() {
284: String displayPrefix = table.getSchema();
285: displayPrefix += (((displayPrefix != null) && displayPrefix
286: .trim().length() != 0) ? "." : "");
287:
288: return displayPrefix + table.getQualifiedName();
289: }
290: }
291:
292: /**
293: * This method gets called when a bound property is changed.
294: *
295: * @param evt A PropertyChangeEvent object describing the event source and the
296: * property that has changed.
297: */
298: public void propertyChange(PropertyChangeEvent evt) {
299: if (propSheet != null) {
300: propSheet.commitChanges();
301: }
302:
303: tree.repaint();
304: }
305:
306: private class TreeDragGestureListener implements
307: DragGestureListener {
308:
309: /**
310: * A <code>DragGestureRecognizer</code> has detected a platform-dependent drag
311: * initiating gesture and is notifying this listener in order for it to initiate
312: * the action for the user.
313: * <P>
314: *
315: * @param dge the <code>DragGestureEvent</code> describing the gesture that has
316: * just occurred
317: */
318: public void dragGestureRecognized(DragGestureEvent dge) {
319: TreePath path = tree.getSelectionPath();
320: if (path != null) {
321: DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) path
322: .getLastPathComponent();
323: Object obj = selNode.getUserObject();
324:
325: if (obj instanceof SourceColumn) {
326: try {
327: dge.startDrag(DragSource.DefaultCopyDrop,
328: new ColumnTransferable(obj));
329: } catch (InvalidDnDOperationException ex) {
330: mLogger.errorNoloc(mLoc.t(
331: "PRSR043: invalid drag and drop{0}",
332: LOG_CATEGORY), ex);
333: }
334: }
335: }
336: }
337: }
338:
339: private class ColumnTransferable implements Transferable {
340:
341: private Object transData;
342:
343: ColumnTransferable(Object obj) {
344: this .transData = obj;
345: }
346:
347: /**
348: * Returns an object which represents the data to be transferred. The class of the
349: * object returned is defined by the representation class of the flavor.
350: *
351: * @param flavor the requested flavor for the data
352: * @return data to be transferred
353: * @throws IOException if the data is no longer available in the requested flavor.
354: * @throws UnsupportedFlavorException if the requested data flavor is not
355: * supported.
356: * @see DataFlavor#getRepresentationClass
357: */
358: public Object getTransferData(DataFlavor flavor)
359: throws UnsupportedFlavorException, IOException {
360: return (isDataFlavorSupported(flavor)) ? transData : null;
361: }
362:
363: /**
364: * Returns an array of DataFlavor objects indicating the flavors the data can be
365: * provided in. The array should be ordered according to preference for providing
366: * the data (from most richly descriptive to least descriptive).
367: *
368: * @return an array of data flavors in which this data can be transferred
369: */
370: public DataFlavor[] getTransferDataFlavors() {
371: return mDataFlavorArray;
372: }
373:
374: /**
375: * Returns whether or not the specified data flavor is supported for this object.
376: *
377: * @param flavor the requested flavor for the data
378: * @return boolean indicating whether or not the data flavor is supported
379: */
380: public boolean isDataFlavorSupported(DataFlavor flavor) {
381: for (int i = 0; i < mDataFlavorArray.length; i++) {
382: if (flavor.equals(mDataFlavorArray[i])) {
383: return true;
384: }
385: }
386:
387: return false;
388: }
389: }
390:
391: /**
392: * Wrapper object around an instance of SQLDBModel. Required to restrict
393: * getter and setter access to SQLDBModel instances by PropertySheet
394: * implementations.
395: */
396: public class DBModelObj {
397:
398: private SQLDBModel dbModel;
399:
400: /**
401: * Creates an instance of DBModelObj associated with the given
402: * SQLDBModel.
403: *
404: * @param dbModel SQLDBModel to be wrapped
405: */
406: public DBModelObj(SQLDBModel dbModel) {
407: this .dbModel = dbModel;
408: }
409:
410: /**
411: * Gets user name.
412: *
413: * @return current user name
414: */
415: public String getUserName() {
416: return dbModel.getConnectionDefinition().getUserName();
417: }
418:
419: /**
420: * Sets username with given String.
421: *
422: * @param userName new user name
423: */
424: public void setUserName(String userName) {
425: ((SQLDBConnectionDefinition) this .dbModel
426: .getConnectionDefinition()).setUserName(userName);
427: }
428:
429: /**
430: * Gets current password.
431: *
432: * @return current password
433: */
434: public String getPassword() {
435: return dbModel.getConnectionDefinition().getPassword();
436: }
437:
438: /**
439: * Sets password with given String.
440: *
441: * @param password new user name
442: */
443: public void setPassword(String password) {
444: ((SQLDBConnectionDefinition) this .dbModel
445: .getConnectionDefinition()).setPassword(password);
446: }
447:
448: /**
449: * Gets current connection URL.
450: *
451: * @return current connection URL
452: */
453: public String getConnectionURL() {
454: return dbModel.getConnectionDefinition().getConnectionURL();
455: }
456:
457: /**
458: * Sets connection URL with given String.
459: *
460: * @param newURL new connection URL
461: */
462: public void setConnectionURL(String newURL) {
463: ((SQLDBConnectionDefinition) this .dbModel
464: .getConnectionDefinition())
465: .setConnectionURL(newURL);
466: }
467: }
468:
469: /**
470: * Wrapper object around an instance of AbstractDBTable. Required to restrict getter
471: * and setter access to AbstractDBTable instances by PropertySheet implementations.
472: */
473: public class DBTableObj {
474:
475: private SQLDBTable dbTable;
476:
477: /**
478: * Creates an instance of DBTableObj associated with the given AbstractDBTable.
479: *
480: * @param dbTable AbstractDBTable to be wrapped
481: */
482: public DBTableObj(SQLDBTable dbTable) {
483: this .dbTable = dbTable;
484: }
485:
486: /**
487: * Sets current schema name.
488: *
489: * @param newSchema new catalog name
490: */
491: public void setSchema(String newSchema) {
492: dbTable.setSchema(newSchema);
493: }
494:
495: /**
496: * Gets current schema name.
497: *
498: * @return current catalog name
499: */
500: public String getSchema() {
501: return dbTable.getSchema();
502: }
503:
504: /**
505: * Gets current catalog name.
506: *
507: * @return current catalog name
508: */
509: public String getCatalog() {
510: return dbTable.getCatalog();
511: }
512:
513: /**
514: * Sets current catalog name.
515: *
516: * @param newCatalog new catalog name
517: */
518: public void setCatalog(String newCatalog) {
519: dbTable.setCatalog(newCatalog);
520: }
521: }
522:
523: private class TableTreeCellRenderer extends DefaultTreeCellRenderer {
524:
525: /**
526: * Configures the renderer based on the passed in components. The value is set
527: * from messaging the tree with <code>convertValueToText</code>, which
528: * ultimately invokes <code>toString</code> on <code>value</code>. The
529: * foreground color is set based on the selection and the icon is set based on on
530: * leaf and expanded.
531: */
532: public Component getTreeCellRendererComponent(JTree tree1,
533: Object value, boolean sel, boolean expanded,
534: boolean leaf, int row, boolean hasFocus1) {
535:
536: JLabel renderer = (JLabel) super
537: .getTreeCellRendererComponent(tree1, value, sel,
538: expanded, leaf, row, hasFocus1);
539: if (value instanceof DefaultMutableTreeNode) {
540: DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;
541: Object obj = treeNode.getUserObject();
542: if (obj instanceof SQLDBModel) {
543: SQLDBModel dbModel = (SQLDBModel) obj;
544: String dbName = dbModel.getModelName();
545:
546: String nbBundle1 = mLoc.t("PRSR001: {0} [Source]",
547: dbName);
548: String nbBundle2 = mLoc.t("PRSR001: {0} [Target]",
549: dbName);
550: switch (dbModel.getObjectType()) {
551: case SQLConstants.SOURCE_DBMODEL:
552: dbName = Localizer.parse(nbBundle1);
553: break;
554:
555: case SQLConstants.TARGET_DBMODEL:
556: dbName = Localizer.parse(nbBundle2);
557: break;
558:
559: default:
560: break;
561: }
562:
563: renderer.setText(dbName);
564: renderer.setIcon(rootIcon);
565: renderer.setToolTipText(dbName);
566: } else if (obj instanceof SourceTable) {
567: renderer.setIcon(tableIcon);
568: renderer.setToolTipText(UIUtil
569: .getTableToolTip((SQLDBTable) obj));
570: } else if (obj instanceof TargetTable) {
571: renderer.setIcon(targetTableIcon);
572: renderer.setToolTipText(UIUtil
573: .getTableToolTip((SQLDBTable) obj));
574: } else if (obj instanceof SQLDBColumn) {
575: renderer.setIcon(columnIcon);
576: renderer.setToolTipText(UIUtil
577: .getColumnToolTip((SQLDBColumn) obj));
578: }
579: }
580:
581: return renderer;
582: }
583: }
584: }
|