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.sql.framework.ui.view.graph;
042:
043: import java.awt.Color;
044: import java.awt.Rectangle;
045: import java.awt.event.KeyEvent;
046: import java.util.Collection;
047: import java.util.HashMap;
048: import java.util.Iterator;
049: import java.util.Map;
050:
051: import javax.swing.Action;
052: import javax.swing.JOptionPane;
053: import javax.swing.event.UndoableEditEvent;
054: import javax.swing.event.UndoableEditListener;
055: import javax.swing.undo.UndoManager;
056:
057: import com.nwoods.jgo.JGoObject;
058: import com.sun.sql.framework.exception.BaseException; /*import com.sun.jbi.ui.devtool.sql.framework.ui.graph.actions.RedoAction;
059: import com.sun.jbi.ui.devtool.sql.framework.ui.graph.actions.UndoAction;*/
060: import org.netbeans.modules.etl.ui.DataObjectProvider;
061: import org.netbeans.modules.etl.ui.ETLDataObject;
062: import org.netbeans.modules.etl.ui.ETLEditorSupport;
063: import org.netbeans.modules.sql.framework.model.GUIInfo;
064: import org.netbeans.modules.sql.framework.model.SQLCanvasObject;
065: import org.netbeans.modules.sql.framework.model.SQLConnectableObject;
066: import org.netbeans.modules.sql.framework.model.SQLDBTable;
067: import org.netbeans.modules.sql.framework.model.SQLDefinition;
068: import org.netbeans.modules.sql.framework.model.SQLInputObject;
069: import org.netbeans.modules.sql.framework.model.SQLObject;
070: import org.netbeans.modules.sql.framework.model.SQLOperator;
071: import org.netbeans.modules.sql.framework.model.TargetColumn;
072: import org.netbeans.modules.sql.framework.model.TargetTable;
073: import org.netbeans.modules.sql.framework.ui.event.SQLDataEvent;
074: import org.netbeans.modules.sql.framework.ui.event.SQLDataListener;
075: import org.netbeans.modules.sql.framework.ui.event.SQLLinkEvent;
076: import org.netbeans.modules.sql.framework.ui.graph.IGraphLink;
077: import org.netbeans.modules.sql.framework.ui.graph.IGraphNode;
078: import org.netbeans.modules.sql.framework.ui.graph.IGraphPort;
079: import org.netbeans.modules.sql.framework.ui.graph.IOperatorXmlInfo;
080: import org.netbeans.modules.sql.framework.ui.graph.impl.GraphView;
081: import org.netbeans.modules.sql.framework.ui.model.CollabSQLUIModel;
082: import org.netbeans.modules.sql.framework.ui.model.SQLUIModel;
083: import org.netbeans.modules.sql.framework.ui.view.IGraphViewContainer;
084: import org.netbeans.modules.sql.framework.ui.view.join.JoinPreviewGraphNode;
085: import org.openide.actions.UndoAction;
086: import org.openide.actions.RedoAction;
087: import org.openide.actions.PrintAction;
088: import org.openide.util.actions.SystemAction;
089: import net.java.hulp.i18n.Logger;
090: import org.netbeans.modules.etl.logger.Localizer;
091: import org.netbeans.modules.etl.logger.LogUtil;
092:
093: /**
094: * @author Ritesh Adval
095: * @version $Revision$
096: */
097: public class SQLGraphView extends GraphView implements SQLDataListener,
098: UndoableEditListener {
099:
100: private static ClipBoard clipBoard = new ClipBoard();
101: private static final String LOG_CATEGORY = SQLGraphView.class
102: .getName();
103: private static transient final Logger mLogger = LogUtil
104: .getLogger(SQLGraphView.class.getName());
105: private static transient final Localizer mLoc = Localizer.get();
106: Color pColor;
107: Color sColor;
108:
109: /** Creates a new instance of SQLGraphView */
110: public SQLGraphView() {
111: super ();
112: setDropEnabled(true);
113: }
114:
115: /**
116: * perform the layout
117: */
118: public void performLayout() {
119: }
120:
121: /**
122: * find the link selected by the user
123: *
124: * @param srcObj link which is connected to a node which hold srcObj as data object
125: * @param destObj link which is connected to a node which hold destObj as data object
126: * @return -
127: */
128: public IGraphLink findLink(Object srcObj, String srcParam,
129: Object destObj, String destParam) {
130:
131: Collection linkCol = getAllGraphLinks();
132: Iterator it = linkCol.iterator();
133:
134: while (it.hasNext()) {
135: IGraphLink link = (IGraphLink) it.next();
136:
137: IGraphPort from = link.getFromGraphPort();
138: IGraphPort to = link.getToGraphPort();
139:
140: IGraphNode srcGraphNode = from.getDataNode();
141: IGraphNode destGraphNode = to.getDataNode();
142:
143: IGraphPort linkSrcPort = srcGraphNode
144: .getOutputGraphPort(srcParam);
145: IGraphPort linkDestPort = destGraphNode
146: .getInputGraphPort(destParam);
147:
148: Object linkSrcObj = srcGraphNode.getDataObject();
149: Object linkDestObj = destGraphNode.getDataObject();
150:
151: if (linkSrcObj == srcObj && linkDestObj == destObj
152: && linkSrcPort == from && linkDestPort == to) {
153: return link;
154: }
155: }
156:
157: return null;
158: }
159:
160: protected void createGraphNode(SQLDataEvent event)
161: throws BaseException {
162: SQLCanvasObject canvasObj = event.getCanvasObject();
163:
164: GUIInfo gInfo = canvasObj.getGUIInfo();
165: if (gInfo != null && !gInfo.isVisible()) {
166: return;
167: }
168:
169: IGraphNode canvasNode = this .findGraphNode(canvasObj);
170: //if graph node already exists then simply return
171: if (canvasNode != null) {
172: return;
173: }
174:
175: AbstractGraphFactory factory = (AbstractGraphFactory) this
176: .getGraphFactory();
177: if (factory == null) {
178: return;
179: }
180:
181: canvasNode = factory.createGraphNode(canvasObj);
182:
183: if (canvasNode != null) {
184: this .addNode(canvasNode);
185: //Per QAI 94710 - disable join type combo box
186: //There should be a better way to do it, such as adding a method to
187: //IGraphNode interface.
188: if (canvasNode instanceof JoinPreviewGraphNode) {
189: ((JoinPreviewGraphNode) canvasNode).setModifiable(this
190: .getDocument().isModifiable());
191: }
192: }
193:
194: // now check if we have a java operator
195: if (canvasObj instanceof SQLOperator) {
196: SQLOperator operator = (SQLOperator) canvasObj;
197: IOperatorXmlInfo opXmlInfo = operator.getOperatorXmlInfo();
198: if (opXmlInfo == null) {
199: throw new IllegalArgumentException(
200: "Operator layer xml info is null.");
201: }
202:
203: if (opXmlInfo.isJavaOperator()) {
204: SQLUIModel model = (SQLUIModel) this .getGraphModel();
205: model.addJavaOperator(operator);
206: }
207: }
208: }
209:
210: private void deleteGraphNode(SQLDataEvent event) {
211: SQLCanvasObject canvasObj = event.getCanvasObject();
212:
213: IGraphNode canvasNode = this .findGraphNode(canvasObj);
214: if (canvasNode != null) {
215: removeNode(canvasNode);
216: }
217:
218: // now check if we have a java operator
219: if (canvasObj instanceof SQLOperator) {
220: SQLOperator operator = (SQLOperator) canvasObj;
221: IOperatorXmlInfo opXmlInfo = operator.getOperatorXmlInfo();
222: if (opXmlInfo == null) {
223: throw new IllegalArgumentException(
224: "Operator layer xml info is null.");
225: }
226:
227: if (opXmlInfo.isJavaOperator()) {
228: SQLUIModel model = (SQLUIModel) this .getGraphModel();
229: model.removeJavaOperator(operator);
230: }
231: }
232: }
233:
234: public void objectCreated(SQLDataEvent evt) throws BaseException {
235: createGraphNode(evt);
236: }
237:
238: public void objectDeleted(SQLDataEvent evt) {
239: deleteGraphNode(evt);
240: }
241:
242: public void linkCreated(SQLLinkEvent evt) {
243: SQLCanvasObject srcObj = evt.getSourceCanvasObject();
244: SQLConnectableObject expObj = evt.getTargetCanvasObject();
245: String srcParam = evt.getSourceFieldName();
246: String destParam = evt.getDestinationFieldName();
247:
248: createLink(srcObj, expObj, srcParam, destParam);
249: }
250:
251: public void createLink(SQLCanvasObject srcObj,
252: SQLConnectableObject expObj, String srcParam,
253: String destParam) {
254:
255: //if link already exist then simply return
256: IGraphLink link = findLink(srcObj, srcParam, expObj, destParam);
257: if (link != null) {
258: return;
259: }
260:
261: SQLCanvasObject destObj = getTopSQLCanvasObject(expObj);
262:
263: IGraphNode srcNode = findGraphNode(srcObj);
264: IGraphNode destNode = findGraphNode(destObj);
265:
266: //if top object is differnt than expObj then we need to get child GraphNode
267: if (destObj != expObj) {
268: destNode = destNode.getChildNode(expObj);
269: }
270:
271: if (srcNode == null || destNode == null) {
272: return;
273: }
274:
275: IGraphPort srcPort = srcNode.getOutputGraphPort(srcParam);
276:
277: IGraphPort destPort = destNode.getInputGraphPort(destParam);
278:
279: if (srcPort == null || destPort == null) {
280: return;
281: }
282:
283: link = new SQLGraphLink(srcPort, destPort);
284:
285: //add link
286: this .getDocument().addObjectAtTail((JGoObject) link);
287: performLayout();
288:
289: if (expObj instanceof TargetTable) {
290: SQLTargetTableArea tt = (SQLTargetTableArea) destNode;
291: SQLInputObject inputObj = expObj.getInput(destParam);
292: TargetColumn tCol = (TargetColumn) inputObj.getSQLObject();
293: if ((tCol != null) && (tCol.isPrimaryKey())) {
294: tt.setConditionIcons();
295: }
296: }
297: }
298:
299: public void linkDeleted(SQLLinkEvent evt) {
300: SQLCanvasObject srcObj = evt.getSourceCanvasObject();
301: SQLConnectableObject destObj = evt.getTargetCanvasObject();
302: String srcParam = evt.getSourceFieldName();
303: String destParam = evt.getDestinationFieldName();
304:
305: IGraphLink link = findLink(srcObj, srcParam, destObj, destParam);
306: if (link != null) {
307: this .getDocument().removeObject((JGoObject) link);
308: performLayout();
309: }
310:
311: if (destObj instanceof TargetTable) {
312: SQLTargetTableArea tt = (SQLTargetTableArea) findGraphNode(destObj);
313: SQLInputObject inputObj = destObj.getInput(destParam);
314: if (inputObj != null) {
315: TargetColumn tCol = (TargetColumn) inputObj
316: .getSQLObject();
317: if ((tCol != null) && (tCol.isPrimaryKey())) {
318: tt.setConditionIcons();
319: }
320: }
321: }
322: }
323:
324: private SQLCanvasObject getTopSQLCanvasObject(SQLObject sqlObj) {
325: if (sqlObj instanceof SQLCanvasObject) {
326: return (SQLCanvasObject) sqlObj;
327: }
328:
329: Object parentObj = sqlObj.getParentObject();
330: while (parentObj != null && parentObj instanceof SQLObject
331: && !(parentObj instanceof SQLCanvasObject)) {
332: parentObj = ((SQLObject) parentObj).getParentObject();
333: }
334:
335: if (parentObj instanceof SQLCanvasObject) {
336: return (SQLCanvasObject) parentObj;
337: }
338:
339: return null;
340: }
341:
342: public boolean doMouseUp(int modifiers, java.awt.Point dc,
343: java.awt.Point vc) {
344:
345: boolean mClick = super .doMouseUp(modifiers, dc, vc);
346:
347: if (this .pickDocObject(dc, false) != null) {
348: return mClick;
349: }
350:
351: int onmask = java.awt.event.InputEvent.BUTTON3_MASK;
352:
353: if ((modifiers & onmask) != 0 && popUpMenu != null) {
354: //if element is not checked out then ask user to check it out before
355: // modifiying it
356:
357: if (!((IGraphViewContainer) this .getGraphViewContainer())
358: .canEdit()) {
359: return false;
360: }
361:
362: if (popUpMenu != null) {
363: popUpMenu.show(this , vc.x, vc.y);
364: return true;
365: }
366: }
367:
368: return false;
369: }
370:
371: public void reset() {
372: resetSelectionColors();
373: }
374:
375: public void childObjectCreated(SQLDataEvent evt) {
376: SQLCanvasObject canvasObj = evt.getCanvasObject();
377: IGraphNode node = this .findGraphNode(canvasObj);
378: SQLObject chldObj = evt.getChildObject();
379: if (node != null && chldObj != null) {
380: node.removeChildObject(chldObj);
381: }
382: }
383:
384: public void childObjectDeleted(SQLDataEvent evt) {
385: SQLCanvasObject canvasObj = evt.getCanvasObject();
386: IGraphNode node = this .findGraphNode(canvasObj);
387: SQLObject chldObj = evt.getChildObject();
388: if (node != null && chldObj != null) {
389: node.addChildObject(chldObj);
390: }
391: }
392:
393: public void objectUpdated(SQLDataEvent evt) {
394: SQLCanvasObject canvasObj = evt.getCanvasObject();
395: IGraphNode node = this .findGraphNode(canvasObj);
396:
397: if (node != null) {
398: node.updateUI();
399: }
400: }
401:
402: /**
403: * Handles key event
404: *
405: * @param evt Description of the Parameter
406: */
407: public void onKeyEvent(KeyEvent evt) {
408: int t = evt.getKeyCode();
409:
410: if (t == KeyEvent.VK_Z && evt.isControlDown()) {
411: undo();
412: } else if (t == KeyEvent.VK_Y && evt.isControlDown()) {
413: redo();
414: } else if (t == KeyEvent.VK_P && evt.isControlDown()) {
415: printDoc();
416: } else if (t == KeyEvent.VK_C && evt.isControlDown()) {
417: copyToClipboard();
418: } else if (t == KeyEvent.VK_V && evt.isControlDown()) {
419: pasteFromClipboard();
420: } else {
421: super .onKeyEvent(evt);
422: }
423: }
424:
425: private void printDoc() {
426: Action printAction = SystemAction.get(PrintAction.class);
427: }
428:
429: private void undo() {
430: SQLUIModel model = (SQLUIModel) this .getGraphModel();
431: UndoManager undoManager = model.getUndoManager();
432: if (undoManager != null && undoManager.canUndo()) {
433: undoManager.undo();
434: updateActions();
435: }
436: }
437:
438: private void redo() {
439: SQLUIModel model = (SQLUIModel) this .getGraphModel();
440: UndoManager undoManager = model.getUndoManager();
441: if (undoManager != null && undoManager.canRedo()) {
442: undoManager.redo();
443: updateActions();
444: }
445: }
446:
447: private void updateActions() {
448: SQLUIModel model = (SQLUIModel) this .getGraphModel();
449: Action undoAction = SystemAction.get(UndoAction.class);
450: //toolBar.getAction(UndoAction.class);
451: Action redoAction = SystemAction.get(RedoAction.class);
452: //toolBar.getAction(RedoAction.class);
453: UndoManager undoManager = model.getUndoManager();
454: if (undoManager != null && undoAction != null
455: && redoAction != null) {
456: undoAction.setEnabled(undoManager.canUndo());
457: redoAction.setEnabled(undoManager.canRedo());
458: }
459: try {
460: ETLDataObject etlDataObject = DataObjectProvider
461: .getProvider().getActiveDataObject();
462: if (model.isDirty()) {
463: ETLEditorSupport editor = etlDataObject
464: .getETLEditorSupport();
465: editor.synchDocument();
466: }
467: } catch (Exception e) {
468: //ignore
469: }
470: }
471:
472: private void copyToClipboard() {
473: clipBoard.setNodes(this .getSelectedNodes());
474: }
475:
476: private void pasteFromClipboard() {
477: Collection nodes = clipBoard.getNodes();
478: if (nodes != null) {
479: Map nodeMap = pasteNodes(nodes);
480: pasteLinks(nodeMap);
481: }
482: }
483:
484: private Map pasteNodes(Collection nodes) {
485: Rectangle bounds = computeBounds(nodes);
486: Map nodeMap = new HashMap();
487: Iterator it = nodes.iterator();
488: while (it.hasNext()) {
489: IGraphNode node = (IGraphNode) it.next();
490: Object dataObj = node.getDataObject();
491: if (dataObj instanceof SQLCanvasObject) {
492: try {
493: SQLCanvasObject obj = (SQLCanvasObject) dataObj;
494: SQLCanvasObject clonedObj = (SQLCanvasObject) obj
495: .cloneSQLObject();
496: clonedObj.reset();
497: GUIInfo guiInfo = clonedObj.getGUIInfo();
498: if (mousePoint != null) {
499: int x = guiInfo.getX();
500: int y = guiInfo.getY();
501: guiInfo.setX(mousePoint.x + x
502: - (int) bounds.getX());
503: guiInfo.setY(mousePoint.y + y
504: - (int) bounds.getY());
505: }
506:
507: SQLUIModel sqlModel = (SQLUIModel) this
508: .getGraphController().getDataModel();
509: //sqlModel.addObject(clonedObj);
510:
511: if (clonedObj instanceof SQLDBTable) {
512: SQLDefinition sqlDef = ((CollabSQLUIModel) sqlModel)
513: .getSQLDefinition();
514: SQLDBTable dbTable = (SQLDBTable) clonedObj;
515: Object existingObj = sqlDef
516: .isTableExists(dbTable);
517: if (existingObj != null) {
518: int retVal = JOptionPane
519: .showConfirmDialog(
520: this ,
521: dbTable.getDisplayName()
522: + " already exists, do you want to overwirte?",
523: "Confirm",
524: JOptionPane.INFORMATION_MESSAGE);
525: if (retVal == JOptionPane.YES_OPTION) {
526: sqlModel
527: .removeObject((SQLObject) existingObj);
528: sqlModel.addObject(clonedObj);
529: } else {
530: continue;
531: }
532: } else {
533: sqlModel.addObject(clonedObj);
534: }
535: } else {
536: sqlModel.addObject(clonedObj);
537: }
538: nodeMap.put(node, clonedObj);
539: } catch (Exception ex) {
540: mLogger.errorNoloc(mLoc.t("PRSR175: Exception{0}",
541: ex.getMessage()), ex);
542: }
543: }
544: }
545: return nodeMap;
546: }
547:
548: private void pasteLinks(Map nodeMap) {
549: Collection srcNodes = nodeMap.keySet();
550: //ArrayList relatedLinks = new ArrayList();
551: Iterator it = srcNodes.iterator();
552: while (it.hasNext()) {
553: IGraphNode node = (IGraphNode) it.next();
554: Collection linksOfNode = node.getAllLinks();
555: Iterator it2 = linksOfNode.iterator();
556: while (it2.hasNext()) {
557: IGraphLink link = (IGraphLink) it2.next();
558: IGraphPort toPort = link.getToGraphPort();
559: IGraphNode toNode = toPort.getDataNode();
560: if (toNode != node && srcNodes.contains(toNode)) {
561: //copy the link
562: mLogger.infoNoloc(mLoc.t(
563: "PRSR176: Find a link between{0} and {1}",
564: node, toNode));
565: Object clonedSrcObj = nodeMap.get(node);
566: Object clonedDestObj = nodeMap.get(toNode);
567: if (clonedSrcObj != null && clonedDestObj != null) {
568: try {
569: String srcFieldName = node
570: .getFieldName(link
571: .getFromGraphPort());
572: String destFieldName = toNode
573: .getFieldName(toPort);
574: SQLUIModel sqlModel = (SQLUIModel) this
575: .getGraphController()
576: .getDataModel();
577: SQLConnectableObject exprObj = (SQLConnectableObject) clonedDestObj;
578: sqlModel.createLink(
579: (SQLCanvasObject) clonedSrcObj,
580: srcFieldName, exprObj,
581: destFieldName);
582: } catch (Exception ex) {
583: mLogger.errorNoloc(mLoc.t(
584: "PRSR177: Exception{0}", ex
585: .getMessage()), ex);
586: }
587: }
588: }
589: }
590: }
591: }
592:
593: private Rectangle computeBounds(Collection nodes) {
594: int minx = Integer.MAX_VALUE;
595: int miny = Integer.MAX_VALUE;
596: int maxx = 0;
597: int maxy = 0;
598: Iterator it = nodes.iterator();
599: while (it.hasNext()) {
600: IGraphNode node = (IGraphNode) it.next();
601: Object dataObj = node.getDataObject();
602: if (dataObj instanceof SQLCanvasObject) {
603: SQLCanvasObject obj = (SQLCanvasObject) dataObj;
604: GUIInfo guiInfo = obj.getGUIInfo();
605: int x = guiInfo.getX();
606: int y = guiInfo.getY();
607: minx = Math.min(x, minx);
608: miny = Math.min(y, miny);
609: maxx = Math.max(x, maxx);
610: maxy = Math.max(y, maxy);
611: }
612: }
613: return new Rectangle(minx, miny, (maxx - minx), (maxy - miny));
614: }
615:
616: private static class ClipBoard {
617:
618: private Collection nodes;
619: private Collection links;
620:
621: /**
622: * Copy nodes to this clipboard
623: *
624: * @param nodes - nodes
625: */
626: public void setNodes(Collection nodes) {
627: this .nodes = nodes;
628: }
629:
630: /**
631: * Copy links to this clipboard
632: *
633: * @param links - links
634: */
635: public void setLinks(Collection links) {
636: this .links = links;
637: }
638:
639: /**
640: * Return nodes in this clipboard
641: *
642: * @return nodes
643: */
644: public Collection getNodes() {
645: return nodes;
646: }
647:
648: /**
649: * Return links in this clipboard
650: *
651: * @return links
652: */
653: public Collection getLinks() {
654: return links;
655: }
656: }
657:
658: /**
659: * can this graph be edited
660: *
661: * @return true if graph is edited
662: */
663: public boolean canEdit() {
664: return ((IGraphViewContainer) this .getGraphViewContainer())
665: .canEdit();
666: }
667:
668: public void undoableEditHappened(UndoableEditEvent e) {
669: updateActions();
670: }
671:
672: /**
673: * Execute a command
674: *
675: * @param command - command
676: * @param args - arguments
677: */
678: public void execute(String command, Object[] args) {
679: if (command == null) {
680: return;
681: }
682: IGraphViewContainer viewContainer = (IGraphViewContainer) this
683: .getGraphViewContainer();
684: viewContainer.execute(command, args);
685: }
686: }
|