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.join;
042:
043: import java.util.ArrayList;
044: import java.util.Collection;
045: import java.util.Enumeration;
046: import java.util.Iterator;
047: import java.util.List;
048: import org.netbeans.modules.sql.framework.model.SQLCanvasObject;
049: import org.netbeans.modules.sql.framework.model.SQLCondition;
050: import org.netbeans.modules.sql.framework.model.SQLConnectableObject;
051: import org.netbeans.modules.sql.framework.model.SQLConstants;
052: import org.netbeans.modules.sql.framework.model.SQLDBColumn;
053: import org.netbeans.modules.sql.framework.model.SQLInputObject;
054: import org.netbeans.modules.sql.framework.model.SQLJoinOperator;
055: import org.netbeans.modules.sql.framework.model.SQLJoinTable;
056: import org.netbeans.modules.sql.framework.model.SQLJoinView;
057: import org.netbeans.modules.sql.framework.model.SQLModelObjectFactory;
058: import org.netbeans.modules.sql.framework.model.SQLObject;
059: import org.netbeans.modules.sql.framework.model.SQLPredicate;
060: import org.netbeans.modules.sql.framework.model.SourceTable;
061: import org.netbeans.modules.sql.framework.model.impl.VisibleSQLPredicateImpl;
062: import org.netbeans.modules.sql.framework.model.utils.SQLObjectUtil;
063: import org.netbeans.modules.sql.framework.ui.graph.IGraphLink;
064: import org.netbeans.modules.sql.framework.ui.graph.IGraphNode;
065: import org.netbeans.modules.sql.framework.ui.graph.IGraphPort;
066: import org.netbeans.modules.sql.framework.ui.graph.IGraphView;
067: import org.netbeans.modules.sql.framework.ui.model.CollabSQLUIModel;
068: import org.netbeans.modules.sql.framework.ui.model.JoinBuilderSQLUIModel;
069: import org.netbeans.modules.sql.framework.ui.model.SQLUIModel;
070: import org.netbeans.modules.sql.framework.ui.view.TableColumnNode;
071: import org.netbeans.modules.sql.framework.ui.view.graph.SQLBasicTableArea;
072: import org.netbeans.modules.sql.framework.ui.view.graph.SQLGraphView;
073: import com.sun.sql.framework.exception.BaseException;
074: import net.java.hulp.i18n.Logger;
075: import org.netbeans.modules.etl.logger.Localizer;
076: import org.netbeans.modules.etl.logger.LogUtil;
077: import org.netbeans.modules.sql.framework.model.DBTable;
078:
079: /**
080: * @author radval
081: */
082: public class JoinUtility {
083:
084: private static final String LOG_CATEGORY = JoinUtility.class
085: .getName();
086: private static transient final Logger mLogger = LogUtil
087: .getLogger(JoinUtility.class.getName());
088: private static transient final Localizer mLoc = Localizer.get();
089:
090: /** Creates a new instance of JoinUtility */
091: private JoinUtility() {
092: }
093:
094: public static void editJoinView(SQLJoinView oldJView,
095: SQLJoinView modifiedJoinView, List joinSources,
096: List tableNodes, IGraphView gView) throws BaseException {
097: //first remove tables which are no longer in modified join
098: removeOldTables(oldJView, modifiedJoinView, gView);
099: //then refresh join graph view in the canvas, remove columns which are unchecked
100: //add columns which newly checked
101: adjustColumnVisiblity(oldJView, modifiedJoinView, joinSources,
102: tableNodes, gView);
103: //then remove all old objects and all all modified objects
104: if (modifiedJoinView != null) {
105: oldJView.removeAllObjects();
106: oldJView.getAllObjects().addAll(
107: modifiedJoinView.getAllObjects());
108: }
109: }
110:
111: private static void removeOldTables(SQLJoinView oldJView,
112: SQLJoinView modifiedJoinView, IGraphView gView)
113: throws BaseException {
114: List newTables = modifiedJoinView.getSourceTables();
115: JoinViewGraphNode jGraphView = (JoinViewGraphNode) gView
116: .findGraphNode(oldJView);
117:
118: Iterator it = oldJView.getSourceTables().iterator();
119:
120: while (it.hasNext()) {
121: SourceTable sTable = (SourceTable) it.next();
122: if (!newTables.contains(sTable)) {
123: if (jGraphView != null) {
124: jGraphView.removeJoinTable(sTable);
125: }
126: }
127: }
128: }
129:
130: private static void adjustColumnVisiblity(SQLJoinView oldJoinView,
131: SQLJoinView modifiedJoinView, List joinSources,
132: List tableNodes, IGraphView gView) throws BaseException {
133: JoinViewGraphNode jGraphView = (JoinViewGraphNode) gView
134: .findGraphNode(oldJoinView);
135: CollabSQLUIModel sqlModel = (CollabSQLUIModel) gView
136: .getGraphModel();
137: if (!oldJoinView.equals(modifiedJoinView)) {
138: sqlModel.setDirty(true);
139: }
140:
141: if (jGraphView == null) {
142: return;
143: }
144:
145: try {
146: Iterator it = joinSources.iterator();
147:
148: while (it.hasNext()) {
149: SourceTable sTable = (SourceTable) it.next();
150: sTable.setUsedInJoin(true);
151: ArrayList<SQLDBColumn> invisibleColumns = new ArrayList<SQLDBColumn>();
152:
153: List columns = sTable.getColumnList();
154: Iterator cIt = columns.iterator();
155:
156: while (cIt.hasNext()) {
157: SQLDBColumn column = (SQLDBColumn) cIt.next();
158: //if coolumn was visible earlier and now became invisible then we
159: // need to remove that
160: //column
161: if (column.isVisible()
162: && !isColumnVisible(column, tableNodes)) {
163: try {
164: //make sure first set visible property to false
165: column.setVisible(false);
166: if (!jGraphView.containsTable(sTable)) {
167: invisibleColumns.add(column);
168: } else {
169: //then call remove
170: jGraphView.removeColumn(column);
171: }
172: } catch (BaseException ex) {
173:
174: mLogger
175: .errorNoloc(
176: mLoc
177: .t(
178: "PRSR186: cannot remove column {0}from joinview table.",
179: column
180: .getName()),
181: ex);
182: throw ex;
183: }
184: //user selected a column to become visible on canvas
185: } else if (!column.isVisible()
186: && isColumnVisible(column, tableNodes)) {
187: jGraphView.addColumn(column);
188: column.setVisible(true);
189: }
190: }
191:
192: //if its a new table selected using more table dialog then
193: //we need to add this to sql model
194: if (!sqlModel.exists(sTable)) {
195: sTable.setUsedInJoin(true);
196: sqlModel.addObject(sTable);
197: }
198:
199: //is table newly added to join view
200: if (!jGraphView.containsTable(sTable)) {
201: //first remove table which is now part of join
202: SQLBasicTableArea node = (SQLBasicTableArea) gView
203: .findGraphNode(sTable);
204: List linkInfos = new ArrayList();
205: if (node != null) {
206: //now remove dangling ref to invisible columns
207: it = invisibleColumns.iterator();
208: while (it.hasNext()) {
209: SQLDBColumn column = (SQLDBColumn) it
210: .next();
211: if (node != null) {
212: node.removeColumnReference(column);
213: }
214: }
215:
216: //record old links
217: linkInfos = transferTableLinksToJoinView(node
218: .getAllLinks());
219: gView.removeNode(node);
220: }
221: //then add table to join view
222: jGraphView.addTable(sTable);
223: //create old links again
224: createOldLinksInJoinView(linkInfos, gView);
225: }
226: }
227:
228: jGraphView.setSize(jGraphView.getMaximumWidth(), jGraphView
229: .getMaximumHeight());
230: } catch (BaseException ex) {
231: mLogger
232: .errorNoloc(
233: mLoc
234: .t(
235: "PRSR187: can not adjust column visibility for joinview.{0}",
236: LOG_CATEGORY), ex);
237:
238: throw ex;
239: }
240: }
241:
242: private static boolean isColumnVisible(SQLDBColumn column,
243: List tableNodes) {
244: Iterator it = tableNodes.iterator();
245: while (it.hasNext()) {
246: TableColumnNode tNode = (TableColumnNode) it.next();
247: Enumeration enu = tNode.children();
248: while (enu.hasMoreElements()) {
249: TableColumnNode cNode = (TableColumnNode) enu
250: .nextElement();
251: SQLDBColumn tColumn = (SQLDBColumn) cNode
252: .getUserObject();
253: if (column.equals(tColumn)) {
254: return cNode.isSelected();
255: }
256: }
257: }
258:
259: return true;
260: }
261:
262: public static void handleNewJoinCreation(SQLJoinView newJoin,
263: List tableNodes, IGraphView gView) throws BaseException {
264: CollabSQLUIModel sqlModel = (CollabSQLUIModel) gView
265: .getGraphModel();
266: ArrayList<LinkInfo> allOldLinks = new ArrayList<LinkInfo>();
267:
268: Iterator tIt = newJoin.getSourceTables().iterator();
269: while (tIt.hasNext()) {
270: SourceTable sTable = (SourceTable) tIt.next();
271: sTable.setUsedInJoin(true);
272: //if its a new table selected using more table dialog then
273: //we need to add this to sql model
274: if (!sqlModel.exists(sTable)) {
275: sqlModel.addObject(sTable);
276: }
277:
278: SQLBasicTableArea node = (SQLBasicTableArea) gView
279: .findGraphNode(sTable);
280: List<LinkInfo> linkInfos = new ArrayList<LinkInfo>();
281: Iterator it = sTable.getColumnList().iterator();
282:
283: while (it.hasNext()) {
284: SQLDBColumn column = (SQLDBColumn) it.next();
285: //if coolumn was visible earlier and now became invisible then we need
286: // to remove that
287: //column
288: if (column.isVisible()
289: && !isColumnVisible(column, tableNodes)) {
290: //make sure first set visible property to false
291: column.setVisible(false);
292: }
293:
294: //now remove dangling ref to invisible columns, if a canvas table is now
295: //becoming part of join view
296: if (node != null && !column.isVisible()) {
297: node.removeColumnReference(column);
298: }
299: }
300:
301: //record old links
302: if (node != null) {
303: linkInfos = transferTableLinksToJoinView(node
304: .getAllLinks());
305: allOldLinks.addAll(linkInfos);
306:
307: //remove table node as it is now part of join view
308: gView.removeNode(node);
309: }
310: }
311: //create join view in the canvas
312: sqlModel.addObject(newJoin);
313:
314: //create old links again
315: createOldLinksInJoinView(allOldLinks, gView);
316: sqlModel.setDirty(true);
317: }
318:
319: private static List<LinkInfo> transferTableLinksToJoinView(
320: List links) {
321: ArrayList<LinkInfo> linkInfos = new ArrayList<LinkInfo>();
322:
323: IGraphNode srcGraphNode = null;
324: IGraphNode destGraphNode = null;
325:
326: Iterator it = links.iterator();
327:
328: while (it.hasNext()) {
329: IGraphLink link = (IGraphLink) it.next();
330:
331: IGraphPort from = link.getFromGraphPort();
332: IGraphPort to = link.getToGraphPort();
333:
334: srcGraphNode = from.getDataNode();
335: destGraphNode = to.getDataNode();
336: String sParam = srcGraphNode.getFieldName(from);
337: String dParam = destGraphNode.getFieldName(to);
338:
339: SQLCanvasObject srcObj = (SQLCanvasObject) srcGraphNode
340: .getDataObject();
341: SQLConnectableObject destObj = (SQLConnectableObject) destGraphNode
342: .getDataObject();
343: linkInfos
344: .add(new LinkInfo(srcObj, destObj, sParam, dParam));
345: }
346:
347: return linkInfos;
348: }
349:
350: private static void createOldLinksInJoinView(List linkInfos,
351: IGraphView graphView) {
352: Iterator it = linkInfos.iterator();
353: while (it.hasNext()) {
354: LinkInfo lInfo = (LinkInfo) it.next();
355:
356: String sParam = lInfo.getSourceParam();
357: String dParam = lInfo.getTargetParam();
358: SQLCanvasObject srcObj = lInfo.getSource();
359: SQLConnectableObject destObj = lInfo.getTarget();
360:
361: ((SQLGraphView) graphView).createLink(srcObj, destObj,
362: sParam, dParam);
363: }
364: }
365:
366: public static void handleAutoJoins(SQLJoinTable jTable,
367: boolean addTable, JoinBuilderSQLUIModel model)
368: throws BaseException {
369: //this list keep track of all joins created so far.
370: ArrayList<SQLObject> allObjectList = new ArrayList<SQLObject>();
371: if (addTable) {
372: allObjectList.add(jTable);
373: }
374:
375: ArrayList<SQLObject> tablesSoFar = new ArrayList<SQLObject>();
376:
377: SQLJoinView joinView = model.getSQLJoinView();
378: tablesSoFar.addAll(joinView.getSQLJoinTables());
379:
380: //find root join from join view this will be previous join
381: SQLJoinOperator previousJoin = null;
382: Collection joins = joinView.getObjectsOfType(SQLConstants.JOIN);
383: Iterator jIt = joins.iterator();
384: while (jIt.hasNext()) {
385: SQLJoinOperator join = (SQLJoinOperator) jIt.next();
386: if (join.isRoot()) {
387: previousJoin = join;
388: break;
389: }
390: }
391:
392: if (tablesSoFar.size() >= 1) {
393:
394: //now find all the auto joins between obj and rest of the joinTables tables
395: //and add them as well
396: List joinList = SQLObjectUtil.getAutoJoins(jTable,
397: tablesSoFar);
398: //create a SQLJoinOperator
399: SQLJoinOperator join = SQLModelObjectFactory.getInstance()
400: .createSQLJoinOperator();
401: //add join to model before calling addInput on it since add Input
402: //keep tracks of storing root join information, so join needs to have
403: //ad id which is set if we add the join first
404: ArrayList<SQLJoinOperator> newJoin = new ArrayList<SQLJoinOperator>();
405: newJoin.add(join);
406: addObjects(newJoin, model);
407:
408: SQLCondition joinCondition = join.getJoinCondition();
409:
410: if (previousJoin == null) {
411: join.addInput(SQLJoinOperator.LEFT,
412: (SQLJoinTable) tablesSoFar.get(0));
413: } else {
414: join.addInput(SQLJoinOperator.LEFT, previousJoin);
415: }
416: join.addInput(SQLJoinOperator.RIGHT, jTable);
417:
418: previousJoin = join;
419:
420: //two or more table join so need to build composite condition
421: if (joinList.size() > 0) {
422: Iterator it1 = joinList.iterator();
423: SQLPredicate previousPredicate = null;
424:
425: if (it1.hasNext()) {
426: SQLJoinOperator joinNew = (SQLJoinOperator) it1
427: .next();
428: SQLCondition joinNewCondition = joinNew
429: .getJoinCondition();
430: previousPredicate = joinNewCondition
431: .getRootPredicate();
432: }
433:
434: while (it1.hasNext()) {
435: SQLJoinOperator joinNew = (SQLJoinOperator) it1
436: .next();
437: SQLCondition joinNewCondition = joinNew
438: .getJoinCondition();
439: SQLPredicate predicate = joinNewCondition
440: .getRootPredicate();
441:
442: VisibleSQLPredicateImpl newPredicate = new VisibleSQLPredicateImpl();
443: newPredicate.setOperatorType("and");
444: newPredicate.addInput(SQLPredicate.LEFT,
445: previousPredicate);
446: newPredicate
447: .addInput(SQLPredicate.RIGHT, predicate);
448: previousPredicate = newPredicate;
449: }
450: SQLObjectUtil.migrateJoinCondition(previousPredicate,
451: joinCondition);
452: // Set condition state from unknown to Graphical.
453: joinCondition
454: .setGuiMode(SQLCondition.GUIMODE_GRAPHICAL);
455: joinCondition.getRootPredicate();
456:
457: join
458: .setJoinConditionType(SQLJoinOperator.SYSTEM_DEFINED_CONDITION);
459: }
460: }
461:
462: addObjects(allObjectList, model);
463: }
464:
465: public static void handleAutoJoins(List joinTables, SQLUIModel model)
466: throws BaseException {
467: //this list keep track of all joins created so far.
468: ArrayList<SQLObject> allObjectList = new ArrayList<SQLObject>();
469:
470: ArrayList<SQLObject> tablesSoFar = new ArrayList<SQLObject>();
471:
472: //then add all the joinTables
473: Iterator it = joinTables.iterator();
474: if (it.hasNext()) {
475: SQLObject obj = (SQLObject) it.next();
476: tablesSoFar.add(obj);
477: allObjectList.add(obj);
478: }
479:
480: SQLJoinOperator previousJoin = null;
481:
482: while (it.hasNext()) {
483: SQLObject obj = (SQLObject) it.next();
484: allObjectList.add(obj);
485:
486: //now find all the auto joins between obj and rest of the joinTables tables
487: //and add them as well
488: List joinList = SQLObjectUtil.getAutoJoins(
489: (SQLJoinTable) obj, tablesSoFar);
490: //create a SQLJoinOperator
491: SQLJoinOperator join = SQLModelObjectFactory.getInstance()
492: .createSQLJoinOperator();
493: //add join to model before calling addInput on it since add Input
494: //keep tracks of storing root join information, so join needs to have
495: //ad id which is set if we add the join first
496: ArrayList<SQLJoinOperator> newJoin = new ArrayList<SQLJoinOperator>();
497: newJoin.add(join);
498: addObjects(newJoin, model);
499:
500: SQLCondition joinCondition = join.getJoinCondition();
501:
502: if (previousJoin == null) {
503: join.addInput(SQLJoinOperator.LEFT,
504: (SQLJoinTable) tablesSoFar.get(0));
505: } else {
506: join.addInput(SQLJoinOperator.LEFT, previousJoin);
507: }
508: join.addInput(SQLJoinOperator.RIGHT, obj);
509:
510: previousJoin = join;
511:
512: //two or more table join so need to build composite condition
513: if (joinList.size() > 0) {
514: Iterator it1 = joinList.iterator();
515: SQLPredicate previousPredicate = null;
516:
517: if (it1.hasNext()) {
518: SQLJoinOperator joinNew = (SQLJoinOperator) it1
519: .next();
520: SQLCondition joinNewCondition = joinNew
521: .getJoinCondition();
522: previousPredicate = joinNewCondition
523: .getRootPredicate();
524: }
525:
526: while (it1.hasNext()) {
527: SQLJoinOperator joinNew = (SQLJoinOperator) it1
528: .next();
529: SQLCondition joinNewCondition = joinNew
530: .getJoinCondition();
531: SQLPredicate predicate = joinNewCondition
532: .getRootPredicate();
533: VisibleSQLPredicateImpl newPredicate = new VisibleSQLPredicateImpl();
534: newPredicate.setOperatorType("and");
535: newPredicate.addInput(SQLPredicate.LEFT,
536: previousPredicate);
537: newPredicate
538: .addInput(SQLPredicate.RIGHT, predicate);
539: previousPredicate = newPredicate;
540: }
541: SQLObjectUtil.migrateJoinCondition(previousPredicate,
542: joinCondition);
543: join
544: .setJoinConditionType(SQLJoinOperator.SYSTEM_DEFINED_CONDITION);
545: }
546:
547: tablesSoFar.add(obj);
548: }
549:
550: addObjects(allObjectList, model);
551: }
552:
553: private static void addObjects(List joinList, SQLUIModel model)
554: throws BaseException {
555: Iterator it = joinList.iterator();
556: while (it.hasNext()) {
557: SQLObject join = (SQLObject) it.next();
558: model.addSQLObject(join);
559: }
560: }
561:
562: public static List<DBTable> getJoinSourceTables(SQLJoinOperator op) {
563: ArrayList<DBTable> tables = new ArrayList<DBTable>();
564:
565: SQLInputObject leftInObj = op.getInput(SQLJoinOperator.LEFT);
566: SQLObject leftObj = leftInObj.getSQLObject();
567:
568: if (leftObj != null) {
569: if (leftObj.getObjectType() == SQLConstants.JOIN) {
570: tables
571: .addAll(getJoinSourceTables((SQLJoinOperator) leftObj));
572: } else {
573: SQLJoinTable jTable = (SQLJoinTable) leftObj;
574: SourceTable sTable = jTable.getSourceTable();
575: tables.add(sTable);
576: }
577: }
578:
579: SQLInputObject rightInObj = op.getInput(SQLJoinOperator.RIGHT);
580: SQLObject rightObj = rightInObj.getSQLObject();
581:
582: if (rightObj != null) {
583: if (rightObj.getObjectType() == SQLConstants.JOIN) {
584: tables
585: .addAll(getJoinSourceTables((SQLJoinOperator) rightObj));
586: } else {
587: SQLJoinTable jTable = (SQLJoinTable) rightObj;
588: tables.add(jTable.getSourceTable());
589: }
590: }
591:
592: return tables;
593: }
594:
595: public static List<SQLJoinTable> getJoinTables(SQLJoinOperator op) {
596: ArrayList<SQLJoinTable> tables = new ArrayList<SQLJoinTable>();
597:
598: SQLInputObject leftInObj = op.getInput(SQLJoinOperator.LEFT);
599: SQLObject leftObj = leftInObj.getSQLObject();
600:
601: if (leftObj != null) {
602: if (leftObj.getObjectType() == SQLConstants.JOIN) {
603: tables.addAll(getJoinTables((SQLJoinOperator) leftObj));
604: } else {
605: SQLJoinTable jTable = (SQLJoinTable) leftObj;
606: tables.add(jTable);
607: }
608: }
609:
610: SQLInputObject rightInObj = op.getInput(SQLJoinOperator.RIGHT);
611: SQLObject rightObj = rightInObj.getSQLObject();
612:
613: if (rightObj != null) {
614: if (rightObj.getObjectType() == SQLConstants.JOIN) {
615: tables
616: .addAll(getJoinTables((SQLJoinOperator) rightObj));
617: } else {
618: SQLJoinTable jTable = (SQLJoinTable) rightObj;
619: tables.add(jTable);
620: }
621: }
622:
623: return tables;
624: }
625: }
|