Source Code Cross Referenced for QueryBuilderGraphFrame.java in  » IDE-Netbeans » db » org » netbeans » modules » db » sql » visualeditor » querybuilder » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » db » org.netbeans.modules.db.sql.visualeditor.querybuilder 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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.db.sql.visualeditor.querybuilder;
0042:
0043:        import org.openide.nodes.AbstractNode;
0044:
0045:        import java.awt.BorderLayout;
0046:        import java.awt.Dimension;
0047:        import java.awt.Color;
0048:        import java.awt.Font;
0049:        import java.awt.FontMetrics;
0050:        import java.awt.Point;
0051:        import java.awt.event.*;
0052:        import java.awt.Component;
0053:        import java.awt.Graphics;
0054:        import java.awt.Graphics2D;
0055:        import java.awt.Toolkit;
0056:        import java.awt.BasicStroke;
0057:
0058:        import java.awt.dnd.*;
0059:        import java.awt.datatransfer.*;
0060:
0061:        import java.awt.font.FontRenderContext;
0062:        import java.awt.geom.Rectangle2D;
0063:
0064:        import java.util.Collection;
0065:        import java.util.Collections;
0066:        import java.util.Iterator;
0067:        import java.util.ArrayList;
0068:        import java.util.List;
0069:
0070:        import javax.swing.ImageIcon;
0071:        import javax.swing.JPopupMenu;
0072:        import javax.swing.JComponent;
0073:        import javax.swing.JScrollPane;
0074:        import javax.swing.JPanel;
0075:        import javax.swing.JEditorPane;
0076:        import javax.swing.JDesktopPane;
0077:        import javax.swing.JMenu;
0078:        import javax.swing.JMenuItem;
0079:        import javax.swing.JCheckBoxMenuItem;
0080:        import javax.swing.JViewport;
0081:        import javax.swing.SwingUtilities;
0082:        import javax.swing.UIManager;
0083:
0084:        import javax.swing.event.TableModelEvent;
0085:        import javax.swing.event.TableModelListener;
0086:        import javax.swing.event.InternalFrameEvent;
0087:        import javax.swing.event.InternalFrameAdapter;
0088:        import javax.swing.table.DefaultTableModel;
0089:
0090:        import java.sql.*;
0091:
0092:        import org.openide.util.NbBundle;
0093:        import org.openide.nodes.Node;
0094:        import org.openide.NotifyDescriptor;
0095:        import org.openide.DialogDisplayer;
0096:
0097:        import org.netbeans.modules.db.sql.visualeditor.Log;
0098:
0099:        import org.netbeans.modules.db.sql.visualeditor.querymodel.JoinTable;
0100:        import org.netbeans.modules.db.sql.visualeditor.querymodel.Column;
0101:        import org.netbeans.modules.db.sql.visualeditor.querymodel.Expression;
0102:        import org.netbeans.modules.db.sql.visualeditor.querymodel.Value;
0103:        import org.netbeans.modules.db.sql.visualeditor.querymodel.Predicate;
0104:        import org.netbeans.modules.db.sql.visualeditor.querymodel.And;
0105:        import org.netbeans.modules.db.sql.visualeditor.querymodel.Or;
0106:        import org.netbeans.modules.db.sql.visualeditor.querymodel.Table;
0107:        import org.netbeans.modules.db.sql.visualeditor.querymodel.Where;
0108:        import org.netbeans.modules.db.sql.visualeditor.querymodel.SQLQueryFactory;
0109:        import org.netbeans.modules.db.sql.visualeditor.querymodel.ExpressionList;
0110:
0111:        import org.netbeans.api.visual.widget.Widget;
0112:        import org.netbeans.api.visual.widget.ComponentWidget;
0113:        import org.netbeans.api.visual.widget.ConnectionWidget;
0114:
0115:        import org.netbeans.api.visual.anchor.AnchorShape;
0116:        import org.netbeans.api.visual.anchor.AnchorShapeFactory;
0117:
0118:        import org.netbeans.api.visual.action.PopupMenuProvider;
0119:        import org.netbeans.api.visual.action.ActionFactory;
0120:        import org.netbeans.api.visual.action.SelectProvider;
0121:
0122:        /**
0123:         *
0124:         * @author  Sanjay Dhamankar, Jim Davidson
0125:         */
0126:        public class QueryBuilderGraphFrame extends JPanel implements 
0127:                ActionListener, TableModelListener, ItemListener, KeyListener,
0128:                DropTargetListener, PopupMenuProvider {
0129:            // Private/package variables
0130:
0131:            private static final boolean DEBUG = false;
0132:
0133:            private boolean _disableQBGF = false;
0134:
0135:            private QueryBuilder _queryBuilder;
0136:
0137:            private DropTarget _dropTarget;
0138:
0139:            private JDesktopPane _desktopPane = null;
0140:            private QBGFJPanel _canvas = null;
0141:            private QueryBuilderInputTable _queryBuilderInputTable;
0142:            private DefaultTableModel _inputTableModel;
0143:            private JEditorPane _sqlTextArea;
0144:            private DefaultTableModel _resultTableModel;
0145:
0146:            private QBGraphScene _scene;
0147:
0148:            private JScrollPane _desktopScrollPane;
0149:            private JViewport viewport;
0150:
0151:            private FrameSelectionListener _fsl = null;
0152:            // private FrameComponentListener      _fcl = null;
0153:            private ComponentListener _cl = null;
0154:            private JPopupMenu _backgroundPopup;
0155:            private JPopupMenu _tableTitlePopup;
0156:            private AddTableDlg _addTableDlg = null;
0157:
0158:            boolean _firstTableInserted = false;
0159:            //    private Point                       _location;
0160:
0161:            private QBNodeComponent _selectedNode;
0162:
0163:            // constants used in the getNextLocation
0164:            private static final int initX = 40;
0165:            private static final int initY = 40;
0166:
0167:            private static final int offsetX = 20;
0168:            private int offsetY = 20;
0169:
0170:            private static final int MAX_TABLES_IN_A_ROW = 5;
0171:
0172:            private java.util.Random randomVal = new java.util.Random();
0173:
0174:            private JMenuItem runQueryMenuItem;
0175:            private JMenuItem groupByMenuItem;
0176:
0177:            private boolean _checkTableColumnValidity = false;
0178:
0179:            private boolean _inputTableAddCriteria = false;
0180:
0181:            java.net.URL url_primary_key = getClass()
0182:                    .getResource(
0183:                            "/org/netbeans/modules/db/sql/visualeditor/resources/primaryKey.gif"); // NOI18N
0184:            java.net.URL url_foreign_key = getClass()
0185:                    .getResource(
0186:                            "/org/netbeans/modules/db/sql/visualeditor/resources/foreignKey.gif"); // NOI18N
0187:
0188:            // Constructor
0189:
0190:            // Note that this takes as parameter the models that underlie the other three panes.
0191:            // The QBGF could post listeners on each of those panes; the only one currently
0192:            // listened to is inputTableModel
0193:            public QueryBuilderGraphFrame(QueryBuilder queryBuilder,
0194:                    QueryBuilderInputTable queryBuilderInputTable,
0195:                    JEditorPane sqlTextArea, DefaultTableModel resultTableModel) {
0196:                super (new BorderLayout());
0197:
0198:                Log.getLogger().entering("QueryBuilderGraphFrame",
0199:                        "constructor"); // NOI18N
0200:
0201:                _queryBuilder = queryBuilder;
0202:                _queryBuilderInputTable = queryBuilderInputTable;
0203:                _inputTableModel = (DefaultTableModel) _queryBuilderInputTable
0204:                        .getModel();
0205:                _sqlTextArea = sqlTextArea;
0206:                _resultTableModel = resultTableModel;
0207:
0208:                // Listen for events in the input table (column list)
0209:                // Unfortunately, this gets triggered with every change to the model.
0210:                // We need a way to make a group of changes to the input table, then invoke the
0211:                // listener once at the end.
0212:                _inputTableModel.addTableModelListener(this );
0213:
0214:                // Get a list of tables in the DB
0215:
0216:                JMenu menu, subMenu;
0217:                JMenuItem menuItem;
0218:
0219:                // Create three listeners
0220:                _fsl = new FrameSelectionListener();
0221:                // _fcl = new FrameComponentListener();
0222:                _cl = new CompListener();
0223:
0224:                // Create two popup menus
0225:                _backgroundPopup = createBackgroundPopup();
0226:                _tableTitlePopup = createTableTitlePopup();
0227:
0228:                // Add listener to components that can bring up popup menus.
0229:                // Create a listener that will bring up background menu
0230:                // MouseListener backgroundPopupListener = new BackgroundPopupListener();
0231:
0232:                // Add it as listener
0233:                //        _graph.addMouseListener(backgroundPopupListener);
0234:                //         _desktopPane.addMouseListener(backgroundPopupListener);
0235:                //         _desktopScrollPane.addMouseListener(backgroundPopupListener);
0236:
0237:                // Create a new listener for noticing graph selection
0238:                //        _graph.addGraphSelectionListener(new GraphSelListener());
0239:
0240:                // Add the JScrollPane to the QueryBuilderGraphFrame
0241:                //        this.add(_desktopScrollPane,BorderLayout.CENTER);
0242:
0243:                // Make the GraphFrame visible
0244:                setVisible(true);
0245:
0246:                //         _dropTarget = new DropTarget(_queryBuilder.getQueryBuilderPane()._qbSceneView,
0247:                // 				     DnDConstants.ACTION_COPY_OR_MOVE, this);
0248:            }
0249:
0250:            // Set up the links between the QBGraphFrame (old style) and Scene (new style)
0251:            void initScene(QBGraphScene scene, JComponent sceneView) {
0252:                _scene = scene;
0253:                _dropTarget = new DropTarget(sceneView,
0254:                        DnDConstants.ACTION_COPY_OR_MOVE, this );
0255:            }
0256:
0257:            void setDropTarget(Component comp) {
0258:                _dropTarget = new DropTarget(comp,
0259:                        DnDConstants.ACTION_COPY_OR_MOVE, this );
0260:            }
0261:
0262:            // Setter for scene
0263:            void setScene(QBGraphScene qbgScene) {
0264:                _scene = qbgScene;
0265:            }
0266:
0267:            void getCanvasFocus() {
0268:                _canvas.requestFocus(true);
0269:            }
0270:
0271:            void setQBGFEnabled(boolean value) {
0272:                _disableQBGF = !(value);
0273:                if (_disableQBGF) {
0274:                    int frameWidth = (int) this .getSize().getWidth();
0275:                    int frameHeight = (int) this .getSize().getHeight();
0276:
0277:                    //             _canvas.setSize(new Dimension( frameWidth, frameHeight ) );
0278:                    //             _canvas.updateUI();
0279:                    //             _desktopPane.revalidate();
0280:                }
0281:            }
0282:
0283:            void resizeDesktop() {
0284:            }
0285:
0286:            void setActivatedNode(QueryBuilderInternalFrame currentSelectedFrame) {
0287:                if (currentSelectedFrame != null) {
0288:                    TableNode tn = currentSelectedFrame.getNode();
0289:                    _queryBuilder.setActivatedNodes(new Node[] { tn });
0290:                } else {
0291:                    _queryBuilder.setActivatedNodes(new Node[0]);
0292:                }
0293:                _queryBuilder.activateActions();
0294:            }
0295:
0296:            class QBGFJPanel extends JPanel {
0297:                protected void paintComponent(Graphics g) {
0298:                    if (DEBUG) {
0299:                        System.out
0300:                                .println(" paintComponent() called _parseErrorMessage = "
0301:                                        + _queryBuilder.getParseErrorMessage()
0302:                                        + "\n"); // NOI18N
0303:                    }
0304:                    super .paintComponent(g);
0305:                    if (_queryBuilder.getParseErrorMessage() != null) {
0306:                        Graphics2D g2d = (Graphics2D) g;
0307:                        paintCenteredText(g2d);
0308:                        if (DEBUG) {
0309:                            System.out.println(" paintCenteredText() called "
0310:                                    + "\n"); // NOI18N
0311:                        }
0312:                    }
0313:                }
0314:
0315:                /** Paint the "help" text when the page is empty */
0316:                private void paintCenteredText(Graphics2D g) {
0317:                    final int PADDING = 5; // Padding around text that's cleared
0318:                    final int LINESPACING = 3; // Extra pixels between text lines
0319:
0320:                    // This implementation is slow/inefficient, but since it's only run
0321:                    // when the page is empty we know we're not busy
0322:                    String text;
0323:                    text = _queryBuilder.getParseErrorMessage();
0324:                    int textLines = 1;
0325:                    if (DEBUG) {
0326:                        System.out
0327:                                .println(" paintCenteredText() called _parseErrorMessage = "
0328:                                        + _queryBuilder.getParseErrorMessage()
0329:                                        + "\n"); // NOI18N
0330:                    }
0331:                    for (int i = 0, n = text.length(); i < n; i++) {
0332:                        if (text.charAt(i) == '\n') {
0333:                            textLines++;
0334:                        }
0335:                    }
0336:
0337:                    int width = _desktopScrollPane.getViewport().getWidth();
0338:                    int height = _desktopScrollPane.getViewport().getHeight();
0339:
0340:                    this .setSize(new Dimension(width, height));
0341:                    int center = height / 2;
0342:
0343:                    Font font = UIManager.getFont("Label.font"); // NOI18N
0344:                    g.setFont(font);
0345:                    FontMetrics metrics = Toolkit.getDefaultToolkit()
0346:                            .getFontMetrics(font);
0347:                    FontRenderContext frc = g.getFontRenderContext();
0348:                    int lineHeight = metrics.getHeight() + LINESPACING;
0349:
0350:                    int top = center - lineHeight * textLines / 2;
0351:
0352:                    int minx = width;
0353:                    int maxx = 0;
0354:                    int nextLine = 0;
0355:                    for (int line = 0; line < textLines; line++) {
0356:                        int lineEnd = text.indexOf('\n', nextLine);
0357:                        String lineText;
0358:                        if (lineEnd != -1) {
0359:                            lineText = text.substring(nextLine, lineEnd);
0360:                            nextLine = lineEnd + 1;
0361:                        } else {
0362:                            lineText = text.substring(nextLine);
0363:                        }
0364:
0365:                        Rectangle2D bounds1 = font.getStringBounds(lineText,
0366:                                frc);
0367:                        int lx = (width - ((int) bounds1.getWidth())) / 2;
0368:                        if (lx < minx) {
0369:                            minx = lx;
0370:                        }
0371:                        int xw = lx + (int) bounds1.getWidth();
0372:                        if (xw > maxx) {
0373:                            maxx = xw;
0374:                        }
0375:                    }
0376:
0377:                    // Clear background under text
0378:                    Color background = null;
0379:                    background = getBackground();
0380:                    g.setColor(background);
0381:                    int miny = top;
0382:                    int maxy = top + textLines * lineHeight;
0383:                    g.fillRect(minx - PADDING, miny, maxx - minx + 2 * PADDING,
0384:                            maxy - miny + 2 * PADDING);
0385:                    // Draw text
0386:                    g.setColor(java.awt.Color.gray);
0387:                    nextLine = 0;
0388:                    int y = top + 2 * PADDING; // XXX change to padding constant
0389:                    y += metrics.getHeight() - metrics.getDescent();
0390:                    for (int line = 0; line < textLines; line++) {
0391:                        int lineEnd = text.indexOf('\n', nextLine);
0392:                        String lineText;
0393:                        if (lineEnd != -1) {
0394:                            lineText = text.substring(nextLine, lineEnd);
0395:                            nextLine = lineEnd + 1;
0396:                        } else {
0397:                            lineText = text.substring(nextLine);
0398:                        }
0399:
0400:                        Rectangle2D bounds1 = font.getStringBounds(lineText,
0401:                                frc);
0402:                        int lx = (width - ((int) bounds1.getWidth())) / 2;
0403:
0404:                        g.drawString(lineText, lx, y);
0405:                        y += lineHeight;
0406:                    }
0407:                }
0408:            }
0409:
0410:            /** Handle the key typed event from the sql text area. */
0411:            public void keyTyped(KeyEvent e) {
0412:                _checkTableColumnValidity = true;
0413:            }
0414:
0415:            /** Handle the key pressed event. */
0416:            public void keyPressed(KeyEvent e) {
0417:                if (DEBUG)
0418:                    System.out.println(" QBGF : key pressed called. " + "\n"); // NOI18N
0419:                _checkTableColumnValidity = true;
0420:                if (e.isShiftDown()) {
0421:                    int code = e.getKeyCode();
0422:                    switch (code) {
0423:                    // diagram pane
0424:                    case KeyEvent.VK_F10:
0425:                        _backgroundPopup
0426:                                .show(e.getComponent(),
0427:                                        e.getComponent().getX(), e
0428:                                                .getComponent().getY());
0429:                        break;
0430:                    }
0431:                }
0432:                _queryBuilder.handleKeyPress(e);
0433:            }
0434:
0435:            /** Handle the key released event from the sql text area. */
0436:            public void keyReleased(KeyEvent e) {
0437:                _checkTableColumnValidity = true;
0438:            }
0439:
0440:            public void setTableColumnValidity(boolean value) {
0441:                _checkTableColumnValidity = value;
0442:            }
0443:
0444:            // check the table and column validity only if the user manually
0445:            // changes the sql query.
0446:            public boolean checkTableColumnValidity() {
0447:                return (_checkTableColumnValidity && _queryBuilder
0448:                        .getQueryBuilderPane().getQueryBuilderSqlTextArea()
0449:                        .queryChanged());
0450:            }
0451:
0452:            // Adding a method to access _graph as per QE request
0453:
0454:            // Create a popup menu that will appear when the user clicks on the background
0455:            // and similar places.
0456:            JPopupMenu createBackgroundPopup() {
0457:
0458:                JPopupMenu backgroundPopup;
0459:                JMenu menu, subMenu;
0460:                JMenuItem menuItem;
0461:                JMenuItem subMenuItem;
0462:
0463:                //Create the popup menu.
0464:                backgroundPopup = new JPopupMenu();
0465:
0466:                runQueryMenuItem = new JMenuItem(NbBundle.getMessage(
0467:                        QueryBuilderGraphFrame.class, "RUN_QUERY")); // NOI18N
0468:                runQueryMenuItem.addActionListener(this );
0469:                backgroundPopup.add(runQueryMenuItem);
0470:
0471:                menuItem = new JMenuItem(NbBundle.getMessage(
0472:                        QueryBuilderGraphFrame.class, "Add_Table")); // NOI18N
0473:                menuItem.addActionListener(this );
0474:                backgroundPopup.add(menuItem);
0475:
0476:                groupByMenuItem = new JCheckBoxMenuItem(NbBundle.getMessage(
0477:                        QueryBuilderGraphFrame.class, "GROUP_BY")); // NOI18N
0478:                groupByMenuItem.addItemListener(this );
0479:                backgroundPopup.add(groupByMenuItem);
0480:
0481:                return (backgroundPopup);
0482:            }
0483:
0484:            // Create a menu that will appear when the user clicks on the title bar of a node (table)
0485:
0486:            JPopupMenu createTableTitlePopup() {
0487:
0488:                JPopupMenu tableTitlePopup;
0489:                JMenu menu, subMenu;
0490:                JMenuItem menuItem;
0491:                JMenuItem subMenuItem;
0492:
0493:                // Create the popup menu.
0494:                tableTitlePopup = new JPopupMenu();
0495:
0496:                menuItem = new JMenuItem(NbBundle.getMessage(
0497:                        QueryBuilderGraphFrame.class, "REMOVE_FROM_QUERY")); // NOI18N
0498:                menuItem.addActionListener(this );
0499:                tableTitlePopup.add(menuItem);
0500:
0501:                return (tableTitlePopup);
0502:            }
0503:
0504:            // A class for listeners that will bring up the TableTitlePopup menu.
0505:            // An instance of this class will listen on every new InternalFrame
0506:            // (table node)
0507:
0508:            class TableTitlePopupListener extends MouseAdapter {
0509:
0510:                public void mousePressed(MouseEvent e) {
0511:                    maybeShowPopup(e);
0512:                }
0513:
0514:                public void mouseReleased(MouseEvent e) {
0515:                    maybeShowPopup(e);
0516:                }
0517:
0518:                private void maybeShowPopup(MouseEvent e) {
0519:                    if (e.isPopupTrigger() && e.getComponent().isEnabled()) {
0520:                        _tableTitlePopup.show(e.getComponent(), e.getX(), e
0521:                                .getY());
0522:                    }
0523:                }
0524:            }
0525:
0526:            // Specified by PopupMenuProvider
0527:            public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
0528:                if (widget instanceof  QBGraphScene)
0529:                    return _backgroundPopup;
0530:                else {
0531:                    // We have a Widget wrapping a QBNodeComponent
0532:                    QBNodeComponent qbNC = (QBNodeComponent) _scene
0533:                            .findObject(widget);
0534:                    this ._selectedNode = qbNC;
0535:                    return _tableTitlePopup;
0536:                }
0537:            }
0538:
0539:            // Returns just the class name -- no package info.
0540:            protected String getClassName(Object o) {
0541:                String classString = o.getClass().getName();
0542:                int dotIndex = classString.lastIndexOf("."); // NOI18N
0543:                return classString.substring(dotIndex + 1);
0544:            }
0545:
0546:            // Specified by TableModelListener.
0547:            // Invoked when a TableModel generates an event; implemented by JTable.
0548:            // Events come from both QueryBuilderTableModel and
0549:            // QueryBuilderInputTableModel,
0550:            // The QueryBuilderTableModel indicates columns that are
0551:            // selected/deselected; that in turn
0552:            // causes them to be added/dropped from the InputTable
0553:
0554:            public void tableChanged(TableModelEvent e) {
0555:
0556:                // if the graph is disabled, do not handle any events.
0557:                if (_disableQBGF)
0558:                    return;
0559:
0560:                // if the graph is being generated from model, do not handle events.
0561:                if (_queryBuilder._updateModel == false)
0562:                    return;
0563:
0564:                Log.getLogger().finest(
0565:                        "Entering QBGF.tableChanged, source: " + e.getSource()); // NOI18N
0566:
0567:                if (e.getSource() instanceof  QueryBuilderTableModel)
0568:                    tableModelChanged(e);
0569:
0570:                else if (e.getSource() instanceof  QueryBuilderInputTableModel)
0571:                    inputTableModelChanged(e);
0572:            }
0573:
0574:            // Called when we have received a change in a graph node
0575:
0576:            private void tableModelChanged(TableModelEvent e) {
0577:
0578:                Log.getLogger().entering("QueryBuilderGraphFrame",
0579:                        "tableModelChanged");
0580:
0581:                // We have a mouse click inside a graph table node, indicating select/deselect.
0582:                // Propagate the information to the input table
0583:
0584:                // Extract some information from the event
0585:                int row = e.getFirstRow(); // the first row that changed
0586:                int column = e.getColumn(); // the column for this event
0587:
0588:                QueryBuilderTableModel model = (QueryBuilderTableModel) e
0589:                        .getSource();
0590:                String tableSpec = model.getTableSpec();
0591:
0592:                // DB column name
0593:                String columnName = (String) model.getValueAt(row, column + 2);
0594:
0595:                // boolean - Selected/deselected
0596:                Object value = model.getValueAt(row, column);
0597:
0598:                if (value == Boolean.TRUE) { // A column has been selected
0599:
0600:                    // Update the query model if appropriate
0601:                    // Do this first so that it's available when adding the row
0602:                    if (_queryBuilder._updateModel) {
0603:                        _queryBuilder.getQueryModel().addColumn(tableSpec,
0604:                                columnName);
0605:                        _queryBuilderInputTable.selectColumn(tableSpec,
0606:                                columnName, Boolean.TRUE);
0607:                    }
0608:                }
0609:
0610:                else if (value == Boolean.FALSE) { // A column has been deselected
0611:
0612:                    // Update the query model, if we're not being driven by it
0613:                    // Do this before updating the grid, because we use the model to generate sortorder
0614:                    if (_queryBuilder._updateModel) {
0615:                        _queryBuilder.getQueryModel().removeColumn(tableSpec,
0616:                                columnName);
0617:                    }
0618:
0619:                    // do not remove the whole row, just deselect the output column.
0620:                    _queryBuilderInputTable.selectColumn(tableSpec, columnName,
0621:                            Boolean.FALSE);
0622:                }
0623:
0624:                // We used to update the text query after every event.  That
0625:                // caused degraded performance.  Now, we check whether we've
0626:                // received a real event, or we're generating the graph as a
0627:                // batch operation.  Also, we trigger only on TableModel events,
0628:                // so InputTableMode must explicitly invoke
0629:                if (_queryBuilder._updateText) {
0630:                    // An interactive event -- update the text query
0631:                    _queryBuilder.generateText();
0632:                }
0633:            }
0634:
0635:            /**
0636:             * Called when we have received a change in the input table (grid pane)
0637:             * either interactively or because the model was updated from somewhere else
0638:             * @param e the event
0639:             */
0640:            private void inputTableModelChanged(TableModelEvent e) {
0641:
0642:                Log.getLogger().entering("QueryBuilderGraphFrame",
0643:                        "inputTableModelChanged");
0644:
0645:                // if _inputTableAddCriteria is true we should not handle any
0646:                // events. This is set when the events are not directly generated
0647:                // by the user interaction. e.g. when we set value of say
0648:                // Criteria column, CriteriaOrder column will be set a value.
0649:                // To avoid the recursive calls this is used.
0650:                if (_inputTableAddCriteria)
0651:                    return;
0652:
0653:                // Only pay attention to changes to the output column
0654:                // Propagate information to the graph node for this table
0655:
0656:                // ** We could also do this by listening to the checkbox for
0657:                // the particular column in QueryBuilderInputTable, the same
0658:                // as we do for SortType, SortOrder, and AddCriteria **
0659:
0660:                // Extract some information from the event, and dispatch on column
0661:                int column = e.getColumn(); // the column for this event
0662:                int row = e.getFirstRow(); // the first row that changed
0663:                QueryBuilderInputTableModel model = (QueryBuilderInputTableModel) e
0664:                        .getSource();
0665:
0666:                // Column -1 indicates ...
0667:                if (column != -1) {
0668:
0669:                    String columnName = (String) model.getValueAt(row,
0670:                            QueryBuilderInputTable.Column_COLUMN);
0671:                    String tableSpec = (String) model.getValueAt(row,
0672:                            QueryBuilderInputTable.Table_COLUMN);
0673:
0674:                    if (DEBUG)
0675:                        System.out.println("QBGF.iTMC, row: " + row
0676:                                + " columnName: " + columnName + // NOI18N
0677:                                " column: " + column); // NOI18N
0678:
0679:                    if (column == QueryBuilderInputTable.Alias_COLUMN) {
0680:
0681:                        String result = ((String) model.getValueAt(row,
0682:                                QueryBuilderInputTable.Alias_COLUMN)).trim();
0683:                        if (result == null || result.length() == 0) // Clear alias
0684:                            _queryBuilder.getQueryModel().removeDerivedColName(
0685:                                    tableSpec, columnName);
0686:                        else
0687:                            _queryBuilder.getQueryModel().setDerivedColName(
0688:                                    tableSpec, columnName, result);
0689:                    }
0690:                    if (column == QueryBuilderInputTable.Output_COLUMN) {
0691:
0692:                        Boolean value = (Boolean) model.getValueAt(row, column); // Selected/deselected
0693:                        QBNodeComponent node = findGraphNode(tableSpec);
0694:                        QueryBuilderTableModel qbtm = node
0695:                                .getQueryBuilderTableModel();
0696:                        qbtm.selectColumn(columnName, value);
0697:                        // Don't regenerate query, since selectColumn will cause that to happen
0698:                        return;
0699:                    } else if (column == QueryBuilderInputTable.Criteria_COLUMN) {
0700:
0701:                        String result = ((String) model.getValueAt(row,
0702:                                QueryBuilderInputTable.Criteria_COLUMN)).trim();
0703:
0704:                        // The the value is "" remove the criteria order from the combo box
0705:                        if (result != null && result.length() == 0) {
0706:                            // The following lines appear to be unnecessary
0707:                            _inputTableAddCriteria = true;
0708:                            model
0709:                                    .setValueAt(
0710:                                            "",
0711:                                            row,
0712:                                            QueryBuilderInputTable.CriteriaOrder_COLUMN); // NOI18N
0713:                            _inputTableAddCriteria = false;
0714:                            _queryBuilder.getQueryModel().removeCriteria(
0715:                                    tableSpec, columnName, 1);
0716:                        } else if (result
0717:                                .trim()
0718:                                .equals(
0719:                                        QueryBuilderInputTable.Criteria_Uneditable_String)) {
0720:                            return;
0721:                        } else {
0722:                            Predicate pred = checkCriteria(tableSpec,
0723:                                    columnName, result);
0724:                            if (pred == null) {
0725:                                _queryBuilderInputTable.getModel().setValueAt(
0726:                                        "", row, column); // NOI18N
0727:                                return;
0728:                            }
0729:
0730:                            int criteriaCount = _queryBuilder.getQueryModel()
0731:                                    .getCriteriaCount();
0732:                            String order = (String) model
0733:                                    .getValueAt(
0734:                                            row,
0735:                                            QueryBuilderInputTable.CriteriaOrder_COLUMN);
0736:                            if (order != null
0737:                                    && order.trim().length() != 0
0738:                                    && order
0739:                                            .trim()
0740:                                            .equals(
0741:                                                    QueryBuilderInputTable.CriteriaOrder_Uneditable_String)) {
0742:                                return;
0743:                            }
0744:                            int orderNum = ((order == null) || (order.trim()
0745:                                    .length() == 0)) ? criteriaCount + 1
0746:                                    : Integer.parseInt(order);
0747:                            _inputTableAddCriteria = true;
0748:                            model
0749:                                    .setValueAt(
0750:                                            new Integer(orderNum).toString(),
0751:                                            row,
0752:                                            QueryBuilderInputTable.CriteriaOrder_COLUMN);
0753:                            _inputTableAddCriteria = false;
0754:                            if (orderNum < criteriaCount + 1) {
0755:                                _queryBuilder.getQueryModel().replaceCriteria(
0756:                                        tableSpec, columnName, pred, orderNum);
0757:                            } else {
0758:                                _queryBuilder.getQueryModel().addCriteria(
0759:                                        tableSpec, columnName, pred);
0760:                            }
0761:                        }
0762:                        _queryBuilderInputTable.clearSelection();
0763:                        _inputTableAddCriteria = true;
0764:                        // Regenerate the input table, based on the latest change.
0765:                        // Is this necessary?  May be required to get Criteria Order right
0766:                        _queryBuilderInputTable
0767:                                .generateTableWhere(_queryBuilder
0768:                                        .getQueryModel());
0769:                        _inputTableAddCriteria = false;
0770:                    } else if (column == QueryBuilderInputTable.CriteriaOrder_COLUMN) {
0771:
0772:                        String criteria = ((String) model.getValueAt(row,
0773:                                QueryBuilderInputTable.Criteria_COLUMN)).trim();
0774:                        String order = (String) model.getValueAt(row, column);
0775:
0776:                        if ((order != null && order.trim().length() != 0)
0777:                                && (order.trim()
0778:                                        .equals(QueryBuilderInputTable.CriteriaOrder_Uneditable_String))) {
0779:                            return;
0780:                        }
0781:                        // remove the old criteria first anyway
0782:                        _queryBuilder.getQueryModel().removeCriteria(tableSpec,
0783:                                columnName, 1);
0784:
0785:                        if ((order == null) || (order.trim().length() == 0)) {
0786:                            _inputTableAddCriteria = true;
0787:                            model.setValueAt("", row,
0788:                                    QueryBuilderInputTable.Criteria_COLUMN); // NOI18N
0789:                            _inputTableAddCriteria = false;
0790:                        } else {
0791:                            int orderNum = Integer.parseInt(order);
0792:                            Predicate pred = checkCriteria(tableSpec,
0793:                                    columnName, criteria);
0794:                            if (pred == null) {
0795:                                _queryBuilderInputTable.getModel().setValueAt(
0796:                                        "", row, column); // NOI18N
0797:                                return;
0798:                            }
0799:                            if (criteria.trim().length() != 0) {
0800:                                _queryBuilder.getQueryModel().addCriteria(
0801:                                        tableSpec, columnName, pred, orderNum);
0802:                            }
0803:                        }
0804:                        _queryBuilderInputTable.clearSelection();
0805:                        _inputTableAddCriteria = true;
0806:                        _queryBuilderInputTable
0807:                                .generateTableWhere(_queryBuilder
0808:                                        .getQueryModel());
0809:                        _inputTableAddCriteria = false;
0810:                    }
0811:                    // Regenerate the query, if someone else isn't doing it
0812:                    if (_queryBuilder._updateText) {
0813:                        _queryBuilder.generateText();
0814:                    }
0815:                }
0816:            }
0817:
0818:            /**
0819:             * Given a criteria string retrun Predicate or null if result is
0820:             * an error. Displays appropriate message.
0821:             */
0822:            private Predicate checkCriteria(String tableSpec,
0823:                    String columnName, String result) {
0824:                String op = null;
0825:                String val = null;
0826:                if (result.startsWith(">=")) { // NOI18N
0827:                    op = ">="; // NOI18N
0828:                    val = result.substring(2).trim();
0829:                } else if (result.startsWith("<=")) { // NOI18N
0830:                    op = "<="; // NOI18N
0831:                    val = result.substring(2).trim();
0832:                } else if (result.startsWith("<>")) { // NOI18N
0833:                    op = "<>"; // NOI18N
0834:                    val = result.substring(2).trim();
0835:                } else if (result.startsWith(">")) { // NOI18N
0836:                    op = ">"; // NOI18N
0837:                    val = result.substring(1).trim();
0838:                } else if (result.startsWith("<")) { // NOI18N
0839:                    op = "<"; // NOI18N
0840:                    val = result.substring(1).trim();
0841:                } else if (result.startsWith("=")) { // NOI18N
0842:                    op = "="; // NOI18N
0843:                    val = result.substring(1).trim();
0844:                } else if (result.toUpperCase().startsWith("LIKE")) { // NOI18N
0845:                    op = " LIKE "; // NOI18N
0846:                    val = result.substring(5).trim();
0847:                } else if (result.toUpperCase().startsWith("IN")) { // NOI18N
0848:                    op = " IN "; // NOI18N
0849:                    val = result.substring(3).trim();
0850:                }
0851:
0852:                // if val or op is still null
0853:                // display an error and clear the cell and return.
0854:                if (op == null || (op.trim().length() == 0) || val == null
0855:                        || (val.trim().length() == 0)) {
0856:                    String msg = NbBundle.getMessage(
0857:                            QueryBuilderGraphFrame.class, "CRITERIA_ERROR"); // NOI18N
0858:                    NotifyDescriptor d = new NotifyDescriptor.Message(msg
0859:                            + "\n\n", NotifyDescriptor.ERROR_MESSAGE); // NOI18N
0860:                    DialogDisplayer.getDefault().notify(d);
0861:                    _queryBuilderInputTable.clearSelection();
0862:                    return null;
0863:                }
0864:
0865:                Column col1 = SQLQueryFactory.createColumn(tableSpec,
0866:                        columnName);
0867:                Predicate pred = SQLQueryFactory.createPredicate(col1, val, op);
0868:
0869:                return pred;
0870:            }
0871:
0872:            public void setCurrentSelectedFrameTitle(String title) {
0873:                if ((QueryBuilderInternalFrame) _desktopPane.getSelectedFrame() != null)
0874:                    ((QueryBuilderInternalFrame) _desktopPane
0875:                            .getSelectedFrame()).setTitle(title);
0876:            }
0877:
0878:            // Add a node (representing a database table) to the query graph
0879:            // If _updateModel is true, add edges corresponding to any FK relationships
0880:            // ToDo: Add provisions for selecting only some of the columns in the table
0881:            // for inclusion in the query.
0882:            private void insertTableInteractively(String fullTableName) {
0883:                Log.getLogger().entering("QueryBuilderGraphFrame",
0884:                        "insertTableInteractively", fullTableName); // NOI18N
0885:
0886:                // fix for 6316681 Opening QE on a rowset where command=null throws NPE
0887:                // If the query model is null then the QueryBuilder was not opened
0888:                // before. So for the initial table populate the command
0889:                // This will initiate the QueryBuilder properly.
0890:                if ((_queryBuilder.getQueryModel() == null)
0891:                        || (_queryBuilder.getQueryModel().genText() == null)) {
0892:                    String query = "select * from " + fullTableName;
0893:                    _queryBuilder.populate(query, false);
0894:                    _queryBuilder.setSqlCommand(query);
0895:                    return;
0896:                }
0897:
0898:                // Disable text query re-generation until we're ready
0899:                QueryBuilder.showBusyCursor(true);
0900:                _queryBuilder._updateText = false;
0901:                try {
0902:                    // Extend to handle full tablespec, including schema
0903:                    String schemaName = null, tableName, tabName;
0904:                    String[] res = fullTableName.split("\\."); // NOI18N
0905:                    if (res.length > 1) {
0906:                        schemaName = res[0];
0907:                        tabName = res[1];
0908:                    } else
0909:                        tabName = fullTableName;
0910:
0911:                    /*
0912:                    if (  !tabName.startsWith("\"") && (tabName.indexOf(' ') != -1) ) {
0913:                        tableName = new String ("\"" + tabName + "\"" );
0914:                    }
0915:                    else {
0916:                     */
0917:                    tableName = new String(tabName);
0918:                    /*
0919:                     }
0920:                     */
0921:
0922:                    // Create the querymodel object representing the table to be added
0923:                    String corrName = _queryBuilder.getQueryModel()
0924:                            .genUniqueName(fullTableName);
0925:                    Table tbl = (corrName == null) ? SQLQueryFactory
0926:                            .createTable(tableName, null, schemaName)
0927:                            : SQLQueryFactory.createTable(tableName, corrName,
0928:                                    schemaName);
0929:                    JoinTable joinTable = SQLQueryFactory.createJoinTable(tbl);
0930:
0931:                    List columnNames = new ArrayList();
0932:                    columnNames.add("*"); // NOI18N
0933:
0934:                    // Insert the table into the model first, so that column insertions can refer to it
0935:                    _queryBuilder.getQueryModel().insertTable(joinTable);
0936:
0937:                    // Insert the node into the graph
0938:                    QBNodeComponent qbNC = insertTable(joinTable, columnNames);
0939:                    //             if ( internalFrame == null ) {
0940:                    //                 QueryBuilder.showBusyCursor( false );
0941:                    //                 return;
0942:                    //             }
0943:
0944:                    // Add appropriate edges in the graph to connect the new node to previous ones,
0945:                    // based entirely on relationships (Foreign Key constraints)
0946:                    // This should be refactored, to do computation of edges separately
0947:                    List edges = insertFKEdges(qbNC, fullTableName);
0948:
0949:                    // Add the relationships for this table into the model, based in the edges
0950:                    _queryBuilder.getQueryModel().addRelationships(joinTable,
0951:                            edges);
0952:
0953:                    // Redraw the new frame.  Must be done after adding edges, to work around
0954:                    // some painting glitches.
0955:                    // redrawFrame(currentSelectedFrame);
0956:                    //            redrawFrame(internalFrame);
0957:
0958:                    //             try {
0959:                    //                 // Make the new frame the selected one
0960:                    // //                internalFrame.setSelected(true);
0961:                    //                 // Update the [0,0] cell for the table model; wasn't this already false?
0962:                    //                 // This will cause an event to fire, but it's not clear what the intent was.
0963:                    // //                internalFrame.getQueryBuilderTableModel().setValueAt(Boolean.FALSE, 0, 0);
0964:                    // //                _desktopPane.setSelectedFrame(internalFrame);
0965:                    // //                setActivatedNode( internalFrame ) ;
0966:                    //             } catch(PropertyVetoException pve) {
0967:                    //             }
0968:
0969:                    _firstTableInserted = true;
0970:                } finally {
0971:                    _queryBuilder._updateText = true;
0972:                    QueryBuilder.showBusyCursor(false);
0973:                }
0974:            }
0975:
0976:            // Add a node to the query graph, based on the parsed query
0977:            // ToDo: Generalize this to support joinTable with conjoined predicates
0978:
0979:            void insertTableFromModel(JoinTable joinTable, List columnNames) {
0980:
0981:                Log.getLogger().entering("QueryBuilderGraphFrame",
0982:                        "insertTableFromModel", joinTable.getTableSpec()); // NOI18N
0983:
0984:                // Save the state of _updateText
0985:                boolean updateText = _queryBuilder._updateText;
0986:                _queryBuilder._updateText = false;
0987:                try {
0988:                    QBNodeComponent qbNC = insertTable(joinTable, columnNames);
0989:                    if (qbNC == null)
0990:                        return;
0991:
0992:                    // Insert the edges that are explicitly specified in the query
0993:                    insertJoinEdges(joinTable);
0994:
0995:                    //            redrawFrame(internalFrame);
0996:
0997:                    // ToDo: This code used to be called twice.  Decide whether there was a reason for it.
0998:                    //             try {
0999:                    //                 // Make the new frame the selected one
1000:                    // //                internalFrame.setSelected(true);
1001:                    //                 // Update the [0,0] cell for the table model; wasn't this already false?
1002:                    //                 // This will cause an event to fire, but it's not clear what the intent was.
1003:                    // //                internalFrame.getQueryBuilderTableModel().setValueAt(Boolean.FALSE, 0, 0);
1004:                    // //                _desktopPane.setSelectedFrame(internalFrame);
1005:                    //                 _queryBuilder.enableDelete();
1006:                    //                 runQueryMenuItem.setEnabled(true);
1007:                    //                 groupByMenuItem.setEnabled(true);
1008:                    //             } catch(PropertyVetoException pve) {
1009:                    //             }
1010:
1011:                    _firstTableInserted = true;
1012:                } finally {
1013:                    _queryBuilder._updateText = updateText;
1014:                }
1015:            }
1016:
1017:            // Insert a table into the query graph
1018:
1019:            QBNodeComponent insertTable(JoinTable joinTable, List columnNames) {
1020:
1021:                Log.getLogger().entering("QueryBuilderGraphFrame",
1022:                        "insertTable", new Object[] { joinTable, columnNames }); // NOI18N
1023:
1024:                // you can not insert a non-existent table.
1025:                String joinTableName = joinTable.getFullTableName();
1026:
1027:                // Create the internal frame
1028:                QBNodeComponent qbNC = createNode(joinTable, columnNames);
1029:
1030:                //         // Add a listener to the title bar (or outside edge) of the new frame
1031:                //         MouseListener tableTitlePopupListener = new TableTitlePopupListener();
1032:                //         // trying to handle different LNFs
1033:                //         try {
1034:                //             if (!System.getProperty("os.name").startsWith("Mac OS")) // NOI18N
1035:                //                 ((BasicInternalFrameUI)internalFrame.getUI()).getNorthPane().addMouseListener(tableTitlePopupListener);
1036:                //             else
1037:                //                 internalFrame.addMouseListener(tableTitlePopupListener);
1038:                //         } catch (Exception e) {
1039:                //             e.printStackTrace();
1040:                //         }
1041:
1042:                // 	// Hack - add a listener on the QBNodeComponent, which will replace the internal frame
1043:                // 	// _tmpLastInsertedGraphNode.addMouseListener(tableTitlePopupListener);
1044:
1045:                //         // Insert the cell, without any edges
1046:                //         Object insertCells[] = new Object[] {insertCell};
1047:                //         _graphModel.insert(insertCells,null,null,null,null);
1048:
1049:                //         // Add listeners that notice when the frame is activated, or moved/resized
1050:                //         internalFrame.addInternalFrameListener(_fsl);
1051:                //         internalFrame.addComponentListener(_fcl);
1052:
1053:                //         // Add the internal frame to the desktopPane.  Per the JInternalFrame demo this seems to be
1054:                //         // necessary (marked VERY IMPORTANT), but needs to be undone if we delete it.
1055:                //         _desktopPane.add(internalFrame);
1056:
1057:                refresh();
1058:
1059:                return qbNC;
1060:            }
1061:
1062:            // Create an internal frame, which will represent a table in the graph
1063:            // ToDo: Modify this to return a QBNodeComponent
1064:            QBNodeComponent createNode(JoinTable joinTable,
1065:                    List selectColumnNames) {
1066:
1067:                String fullTableName = joinTable.getFullTableName();
1068:                String[] table = fullTableName.split("\\."); // NOI18N
1069:                String tableName = (table.length > 1) ? table[1] : table[0];
1070:                String corrName = joinTable.getCorrName();
1071:
1072:                String tableSpec = ((corrName != null) ? corrName
1073:                        : fullTableName);
1074:
1075:                Log.getLogger().finest(
1076:                        "Entering QBGF.createNode, fullTableName: "
1077:                                + fullTableName + " corrName: " + corrName); // NOI18N
1078:
1079:                // Correct case of table name...
1080:                try { // TODO JFB shouldn't catch this...
1081:                    String newS = _queryBuilder
1082:                            .checkFullTableName(fullTableName);
1083:                    if (newS != null & !fullTableName.equals(newS)) {
1084:                        fullTableName = newS;
1085:                        Log.getLogger()
1086:                                .finest(
1087:                                        "  fullTableName corrected to "
1088:                                                + fullTableName);
1089:                    }
1090:                } catch (SQLException se) {
1091:                    Log.getLogger()
1092:                            .finest("  fullTableName " + se.getMessage());
1093:                }
1094:
1095:                final String[] columnNames = { "", // "Output",      // NOI18N
1096:                        "", // "KeyIcon"      // NOI18N
1097:                        "" // "Column"        // NOI18N
1098:                };
1099:
1100:                //Create initial internal frame
1101:                Object[][] dbData;
1102:
1103:                List dbColumnNames;
1104:                try {
1105:                    dbColumnNames = _queryBuilder.getColumnNames(fullTableName);
1106:                } catch (SQLException sqle) {
1107:                    dbColumnNames = new ArrayList();
1108:                }
1109:
1110:                // This data will populate the QueryBuilderTableModel, which represents
1111:                // the schema information shown inside the table node
1112:                dbData = new Object[dbColumnNames.size()/* +1 */][3];
1113:                Iterator iterator = dbColumnNames.iterator();
1114:
1115:                // Primary keys and foreign keys are marked with special icons
1116:                List primaryKeys = null, foreignKeyCols = null;
1117:                try {
1118:                    primaryKeys = _queryBuilder.getPrimaryKeys(fullTableName);
1119:                    foreignKeyCols = _queryBuilder
1120:                            .getImportedKeyColumns(fullTableName);
1121:                } catch (SQLException sqle) {
1122:                    // HACK!  log and dispose
1123:                    Log.getLogger().warning(
1124:                            "QueryBuilderGraphFrame:  cannot get info "
1125:                                    + sqle.getLocalizedMessage());
1126:                    primaryKeys = new ArrayList();
1127:                    foreignKeyCols = new ArrayList();
1128:                }
1129:
1130:                int i = 0;
1131:
1132:                // Iterate through the column names
1133:                // Put a check by any that are included in the Select clause
1134:                while (iterator.hasNext() && i < dbColumnNames.size() /* +1 */) {
1135:
1136:                    String columnName = new String(iterator.next().toString());
1137:
1138:                    // Mark them all as selected/deselected, based on Select clause
1139:                    if (selectColumnNames.contains("*")
1140:                            || selectColumnNames.contains(columnName)) // NOI18N
1141:                        dbData[i][0] = Boolean.TRUE;
1142:                    else
1143:                        dbData[i][0] = Boolean.FALSE;
1144:
1145:                    // Check if this is primary or foreign key and then attach appropriate icon
1146:                    // JLabel (String text, Icon image, SwingConstants.LEFT);
1147:                    // We used to use toUpperCase() during comparison, but drop that now that we are
1148:                    // canonicalizing table/column names.
1149:                    if (primaryKeys.contains(columnName.trim()))
1150:                        dbData[i][1] = new ImageIcon(url_primary_key);
1151:                    else if (foreignKeyCols.contains(columnName.trim()))
1152:                        dbData[i][1] = new ImageIcon(url_foreign_key);
1153:                    else
1154:                        dbData[i][1] = null;
1155:
1156:                    dbData[i][2] = columnName;
1157:                    _queryBuilderInputTable.addRow(tableSpec, columnName);
1158:                    _queryBuilderInputTable.selectColumn(tableSpec, columnName,
1159:                            (Boolean) dbData[i][0]);
1160:                    i++;
1161:                }
1162:
1163:                // Create a model from the column info, and wrap it in a frame
1164:                QueryBuilderTableModel qbtModel = new QueryBuilderTableModel(
1165:                        fullTableName, corrName, columnNames, dbData);
1166:                qbtModel.addTableModelListener(this );
1167:
1168:                // This action is now incorporated into the initialization loop above
1169:                // We end up doing it again in order to propagate the events
1170:                // Update the internalframe.  By event propagation, will update the input table.
1171:                // ToDo: Replace this with an explicit update to the InputTableModel.
1172:                // This also sets all db columns to display, which is the wrong thing!!!
1173:                // We need some way to update the input table.  fireTableDataChanged will raise
1174:                // an event, but the listener doesn't handle it right.  Instead, explicitly update
1175:                // the table.
1176:                // Add one row to the input table for each column that appears in this node.
1177:                // The current code for adding rows is designed to support interactive mouse clicks,
1178:                // in tableChanged. We may want to break that out into a separate routine for
1179:                // calling from here.
1180:                for (i = 0; i < qbtModel.getRowCount(); i++) {
1181:                    qbtModel.setValueAt(dbData[i][0], i, 0);
1182:                }
1183:
1184:                String title = (corrName == null) ? tableName : corrName + ": "
1185:                        + tableName; // NOI18N
1186:
1187:                // This is specific to the JGraph implementation, now replaced by GraphLib
1188:                //         QueryBuilderInternalFrame internalFrame = new QueryBuilderInternalFrame(qbtModel, _queryBuilder);
1189:                //         internalFrame.addKeyListener(this);
1190:
1191:                //         // Set the various contents of the internal frame
1192:                //         internalFrame.create();
1193:                //         internalFrame.setTitle(title);
1194:
1195:                // TestGraph
1196:                // Do some extra work to create a node in the new graphlib
1197:                Widget widget = _scene.addNode(title, qbtModel);
1198:                widget.getActions().addAction(
1199:                        ActionFactory.createPopupMenuAction(this ));
1200:                QBNodeComponent qbNC = findComponent(widget);
1201:                widget.setPreferredLocation(getNextGraphLocation(qbNC
1202:                        .getPreferredSize()));
1203:                _scene.validate();
1204:
1205:                return qbNC;
1206:            }
1207:
1208:            /**
1209:             * Returns the next location for placing a node.
1210:             * Right now it uses a standard offset from the previous location.
1211:             */
1212:            Point _gLocation;
1213:
1214:            Point getNextGraphLocation(Dimension size) {
1215:
1216:                Log.getLogger().entering("QueryBuilderGraphFrame",
1217:                        "getNextGraphLocation",
1218:                        new Object[] { size.getWidth(), size.getHeight() }); // NOI18N
1219:
1220:                if (!_firstTableInserted) {
1221:                    _gLocation = new Point(initX, initY);
1222:                } else {
1223:                    _gLocation = new Point((int) (_gLocation.getX()
1224:                            + size.getWidth() + offsetX + randomVal
1225:                            .nextInt((int) size.getWidth() / 2)),
1226:                            (int) (_gLocation.getY() + offsetY + randomVal
1227:                                    .nextInt((int) size.getHeight() / 2)));
1228:                    offsetY *= -1;
1229:                    if (_gLocation.getX() > (int) size.getWidth()
1230:                            * MAX_TABLES_IN_A_ROW) {
1231:                        _gLocation = new Point(initX, (int) _gLocation.getY()
1232:                                + (int) size.getHeight() + 2 * offsetY);
1233:                    }
1234:                }
1235:                return _gLocation;
1236:            }
1237:
1238:            // Graph: return the NodeComponent associated with this Widget
1239:            QBNodeComponent findComponent(Widget widget) {
1240:                List<Widget> widgets = widget.getChildren();
1241:                for (Widget w : widgets) {
1242:                    if (w instanceof  ComponentWidget)
1243:                        return (QBNodeComponent) ((ComponentWidget) w)
1244:                                .getComponent();
1245:                }
1246:                return null;
1247:            }
1248:
1249:            // Insert edges that are implied by Foreign Key constraints between existing nodes
1250:            // and the new one.  Return the list of FKs that are used.
1251:            // ToDo: Enable support for multiple edges between a pair of nodes
1252:
1253:            private List insertFKEdges(QBNodeComponent newNode,
1254:                    String newFullTableName) {
1255:
1256:                Log.getLogger().entering("QueryBuilderGraphFrame",
1257:                        "insertFKEdges",
1258:                        new Object[] { newNode, newFullTableName }); // NOI18N
1259:
1260:                // Get foreign key information, for deciding relationship status
1261:                // Do this once, to avoid repeated calls to database
1262:                List foreignKeys;
1263:                try {
1264:                    foreignKeys = _queryBuilder
1265:                            .getForeignKeys(newFullTableName);
1266:                } catch (SQLException sqle) {
1267:                    foreignKeys = new ArrayList();
1268:                }
1269:                List foreignKeysUsed = new ArrayList();
1270:
1271:                // TestGraph
1272:                // Iterate through the nodes in the scene, drawing arcs to the new node as needed
1273:
1274:                Collection nodes = _scene.getNodes();
1275:                // Iterate through nodes
1276:                for (Object oldNode : nodes) {
1277:
1278:                    // Check whether this node is related to the new one
1279:                    String[] fk;
1280:                    if (oldNode instanceof  QBNodeComponent) // Make sure it's not a dummy
1281:                    // && (root != newCell))                   // how to check this?
1282:                    {
1283:                        String oldFullTableName = ((QBNodeComponent) oldNode)
1284:                                .getFullTableName();
1285:                        if ((fk = _queryBuilder
1286:                                .findForeignKey(oldFullTableName,
1287:                                        newFullTableName, foreignKeys)) != null)
1288:                        // ... and is related to the new cell by an FK?
1289:                        {
1290:                            String oldTableSpec = ((QBNodeComponent) oldNode)
1291:                                    .getTableSpec();
1292:                            String newTableSpec = ((QBNodeComponent) newNode)
1293:                                    .getTableSpec();
1294:                            // Insert an edge between the existing cell and the new one
1295:                            // Directionality (old -> new) is just a convention, since we make the choice
1296:                            // fix for 6270428 : querybuilder Issues with SELF JOIN
1297:                            // having self referential integrity (Employee-Manager Scenario)
1298:                            if (fk[0].equals(fk[2])) {
1299:                                fk[0] = oldTableSpec;
1300:                                fk[2] = newTableSpec;
1301:                            }
1302:                            // Default to INNER
1303:                            insertGraphEdge((QBNodeComponent) oldNode, newNode,
1304:                                    oldFullTableName, newFullTableName,
1305:                                    oldTableSpec, newTableSpec, null, null, fk,
1306:                                    "INNER");
1307:                            foreignKeysUsed.add(fk);
1308:                        }
1309:                    }
1310:                }
1311:
1312:                return foreignKeysUsed;
1313:            }
1314:
1315:            // Insert edges connected to this table, which are implied by the join conditions
1316:            // associate with the table in the FROM list
1317:            void insertJoinEdges(JoinTable joinTable) {
1318:
1319:                Log.getLogger().entering("QueryBuilderGraphFrame",
1320:                        "insertJoinEdges", joinTable); // NOI18N
1321:
1322:                // We're generating the graph from the model.
1323:                // Don't look for new edges to add, but add the edges that are
1324:                // explicitly mentioned in the join condition for this table
1325:                String joinType = joinTable.getJoinType();
1326:
1327:                // We don't have edges if either
1328:                //   - this is the first table
1329:                //   - this is a cross join
1330:                // Otherwise, there will be an edge
1331:                // Extended 10/22 to support Conditions consisting of conjoined predicates
1332:
1333:                if ((joinType != null) && (!joinType.equals("CROSS"))) { // NOI18N
1334:
1335:                    Expression cond = joinTable.getExpression();
1336:                    if (cond instanceof  Predicate) {
1337:                        Predicate pred = (Predicate) cond;
1338:                        insertJoinEdge(pred, joinType);
1339:                    }
1340:                }
1341:            }
1342:
1343:            // Insert the graph edge corrsponding to this predicate
1344:            void insertJoinEdge(Predicate pred, String joinType) {
1345:
1346:                Log.getLogger().entering("QueryBuilderGraphFrame",
1347:                        "insertJoinEdge", new Object[] { pred, joinType }); // NOI18N
1348:
1349:                Value val1 = pred.getVal1();
1350:                Value val2 = pred.getVal2();
1351:
1352:                // Only insert an edge if we're comparing columns, rather than literals
1353:                if ((val1 instanceof  Column) && (val2 instanceof  Column)) {
1354:
1355:                    Column col1 = (Column) val1;
1356:                    String tableSpec1 = col1.getTableSpec();
1357:                    String fullTableName1 = _queryBuilder.getQueryModel()
1358:                            .getFullTableName(tableSpec1);
1359:                    String colName1 = col1.getColumnName();
1360:                    QBNodeComponent node1 = findGraphNode(tableSpec1);
1361:
1362:                    Column col2 = (Column) val2;
1363:                    String tableSpec2 = col2.getTableSpec();
1364:                    String fullTableName2 = _queryBuilder.getQueryModel()
1365:                            .getFullTableName(tableSpec2);
1366:                    String colName2 = col2.getColumnName();
1367:                    QBNodeComponent node2 = findGraphNode(tableSpec2);
1368:
1369:                    // See if there's a foreign key on exactly this combination of tables/columns
1370:                    // If not, we will have no direction label on the join
1371:                    String[] fk = null;
1372:                    try {
1373:                        fk = _queryBuilder.findForeignKey(fullTableName1,
1374:                                colName1, fullTableName2, colName2);
1375:                    } catch (SQLException sqle) {
1376:                        Log.getLogger().warning(
1377:                                "QBGF:  findforeignKey "
1378:                                        + sqle.getLocalizedMessage());
1379:                    }
1380:
1381:                    // Direction is cell1 -> cell2, matching the join
1382:                    // tableName is the table that we are adding
1383:                    insertGraphEdge(node1, node2, fullTableName1,
1384:                            fullTableName2, tableSpec1, tableSpec2, colName1,
1385:                            colName2, fk, joinType);
1386:                }
1387:            }
1388:
1389:            // Insert an edge
1390:            // Like insertEdge, but uses graphLib
1391:            void insertGraphEdge(QBNodeComponent node1, QBNodeComponent node2,
1392:                    String fullTableName1, String fullTableName2,
1393:                    String tableSpec1, String tableSpec2, String colName1,
1394:                    String colName2, String[] fk, String joinType) {
1395:                System.out.println("Entering insertGraphEdge, tableSpec1: "
1396:                        + tableSpec1 + "  tableSpec2: " + tableSpec2);
1397:
1398:                // Create the node object for the edge (for the Property Sheet)
1399:                AbstractNode an;
1400:                if (colName1 == null) {
1401:                    // We are adding the edge interactively, based on the FK
1402:                    // Use the columns specified in the FK
1403:                    if (fullTableName1.equalsIgnoreCase(fk[0]))
1404:                        an = createPropertyNode(tableSpec1, fk[1], tableSpec2,
1405:                                fk[3], joinType, _queryBuilder); // NOI18N
1406:                    else
1407:                        an = createPropertyNode(tableSpec2, fk[1], tableSpec1,
1408:                                fk[3], joinType, _queryBuilder); // NOI18N
1409:                } else {
1410:                    // Adding an edge from the model, based on join condition
1411:                    an = createPropertyNode(tableSpec1, colName1, tableSpec2,
1412:                            colName2, joinType, _queryBuilder); // NOI18N
1413:                }
1414:
1415:                // Now, add an edge to the graph scene, containing the AbstractNode
1416:                Widget widget = _scene.addEdge(an);
1417:                _scene.setEdgeSource(an, node1);
1418:                _scene.setEdgeTarget(an, node2);
1419:
1420:                ConnectionWidget connWidget = (ConnectionWidget) widget;
1421:
1422:                // widget.getActions().addAction(ActionFactory.createSelectAction(new ObjectSelectProvider()));
1423:                connWidget.getActions().addAction(_scene.createSelectAction());
1424:
1425:                AnchorShape triangle = AnchorShapeFactory
1426:                        .createTriangleAnchorShape(18, true, false, 17);
1427:                connWidget.setStroke(new BasicStroke(1.5f,
1428:                        BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND));
1429:                // If we have an FK, draw the appropriate arrowhead, otherwise don't do anything
1430:                if (fk != null) {
1431:                    if (fk[0].equalsIgnoreCase(fullTableName1)) {
1432:                        // ((ConnectionWidget)widget).setTargetAnchorShape (AnchorShape.TRIANGLE_FILLED);
1433:                        connWidget.setTargetAnchorShape(triangle);
1434:                    } else {
1435:                        connWidget.setSourceAnchorShape(triangle);
1436:                    }
1437:                }
1438:
1439:                // Mark the edge as activated (updates property sheet)
1440:                _queryBuilder.setActivatedNodes(new Node[] { an });
1441:
1442:                _scene.validate();
1443:            }
1444:
1445:            AbstractNode createPropertyNode(String tableSpec1, String fk1,
1446:                    String tableSpec2, String fk3, String joinType,
1447:                    QueryBuilder _queryBuilder) {
1448:                if ((joinType == null) || (joinType.equals("")))
1449:                    return new CondNode(tableSpec1, fk1, tableSpec2, fk3,
1450:                            _queryBuilder);
1451:                else
1452:                    return new JoinNode(tableSpec1, fk1, tableSpec2, fk3,
1453:                            joinType, _queryBuilder);
1454:            }
1455:
1456:            /**
1457:             * Remove a table (node) from the graph
1458:             */
1459:            void removeTable(QBNodeComponent selectedNode) {
1460:
1461:                String tableSpec = selectedNode.getTableSpec();
1462:
1463:                Log.getLogger().entering("QueryBuilderGraphFrame",
1464:                        "removeTable", tableSpec); // NOI18N
1465:
1466:                // Remove the specified node from the GraphLib scene
1467:                // First remove all edges
1468:                Collection edges = _scene.findNodeEdges(selectedNode, true,
1469:                        true);
1470:                for (Object edge : edges) {
1471:                    // Edge is a JoinNode or CondNode
1472:                    _scene.removeEdge(edge);
1473:                }
1474:
1475:                // Now remove the node
1476:                _scene.removeNode(selectedNode);
1477:
1478:                // Update the input table model, by removing all rows that mention this table
1479:                _queryBuilderInputTable.removeRows(tableSpec);
1480:
1481:                // Now update the QueryModel
1482:                // Note that we always do this, since the model-driven graph generation never contain deletion
1483:                _queryBuilder.getQueryModel().removeTable(tableSpec);
1484:
1485:                _queryBuilder.generate();
1486:
1487:                // update the groupby checkbox menu item.
1488:                setGroupBy(_queryBuilder.getQueryModel().hasGroupBy());
1489:            }
1490:
1491:            // Generate the Graph and Table from a query model
1492:            // General algorithm:
1493:            //    - Select clause defines the internal frame (node for each Table)
1494:            //    - From clause defines the structure of the Graph
1495:            //    - Where clause has no effect on Graph, but does affect the tabular version
1496:            //    - Group by, Having, Order by are not shown in the Graph at all
1497:            // Select clause entries in the table are filled in as a side effect during createNode
1498:
1499:            void generateGraph(QueryModel query) {
1500:
1501:                Log.getLogger().entering("QueryBuilderGraphFrame",
1502:                        "generateGraph");
1503:
1504:                if (_disableQBGF)
1505:                    return;
1506:
1507:                // Reset the graph and input table
1508:                // This is also done in QBP.clear()
1509:                // ToDo: Decide whether we need to restore this
1510:                // clearGraph();
1511:
1512:                _queryBuilder._updateModel = false;
1513:                try {
1514:                    generateGraphFrom(query);
1515:                    generateGraphWhere(query);
1516:                    generateGraphOrderBy(query);
1517:                    refresh();
1518:                } catch (Exception e) {
1519:                    e.printStackTrace();
1520:                } finally {
1521:                    _queryBuilder._updateModel = true;
1522:                }
1523:            }
1524:
1525:            // Reset the graph and input table to an empty state
1526:            // This could be implemented in various ways; either retain the same data structure
1527:            // but explicitly empty it, or just create a new instance.  We favor explicit emptying,
1528:            // except for the graph model
1529:            // No longer used, since we just re-create the scene
1530:            //    synchronized void clearGraph() {
1531:            //        
1532:            //        Log.getLogger().entering("QueryBuilderGraphFrame", "clearGraph"); // NOI18N
1533:            //        // This is used in certain places
1534:            //        _firstTableInserted=false;
1535:            //        
1536:            //        // Clear the InputTableModel
1537:            //        _inputTableModel.setRowCount(0);
1538:            //        
1539:            //	// Clear the scene, by removing each component
1540:            //	Collection nodes = _scene.getNodes();
1541:            //	for (Object node : nodes) {
1542:            //	    System.out.println("Removing Node: " + node + ((QBNodeComponent)node).getNodeName());
1543:            //	    _scene.removeNodeWithEdges(node);
1544:            //	}
1545:            //// 	Collection edges = _scene.getEdges();
1546:            //// 	for (Object edge : edges) {
1547:            //// 	    _scene.removeEdge(edge);
1548:            //// 	    System.out.println("Removing Edge: " + edge);
1549:            //// 	}
1550:            //    }
1551:
1552:            // Generate the graph corresponding to the FROM clause.
1553:            // Also updates the table entries corresponding to the SELECT clause;
1554:            // that should be refactored.
1555:
1556:            private void generateGraphFrom(QueryModel query) {
1557:
1558:                Log.getLogger().entering("QueryBuilderGraphFrame",
1559:                        "generateGraphFrom"); // NOI18N
1560:
1561:                // Start with the From clause
1562:                List tables = query.getFrom().getTableList();
1563:
1564:                // Iterate through the list of tables, adding them to the graph
1565:                for (int i = 0; i < tables.size(); i++) {
1566:
1567:                    JoinTable joinTable = (JoinTable) tables.get(i);
1568:                    String tableSpec = joinTable.getTableSpec();
1569:                    String fullTableName = joinTable.getFullTableName();
1570:
1571:                    // We also need to use the SELECT list to set the columns in the
1572:                    // interior of the table node.  We could pass in the whole FROM list,
1573:                    // and scan in with each table, or we could partition it once, and
1574:                    // pass in the relevant entries with each table.  If we go the
1575:                    // partitioning approach, we could revise the model to use it.
1576:                    List columnNames = new ArrayList();
1577:                    query.getColumnNames(tableSpec, columnNames);
1578:                    insertTableFromModel(joinTable, columnNames);
1579:                }
1580:            }
1581:
1582:            // check if the where clause has any duplicate columns
1583:            // e.g. if the where caluse is like "where table.c > 10 AND table.c < 20"
1584:            // then this will return true. Current decisoin is not to display multiple
1585:            // columns in the grid pane.
1586:            private boolean whereHasDuplicateColumns(List whereColumns,
1587:                    Predicate expr) {
1588:                List columns = new ArrayList();
1589:                expr.getReferencedColumns(columns);
1590:                for (int i = 0; i < columns.size(); i++) {
1591:                    if (DEBUG) {
1592:                        System.out
1593:                                .println("expr getReferencedColumn i = "
1594:                                        + i
1595:                                        + " "
1596:                                        + ((Column) columns.get(i))
1597:                                                .genText(null));
1598:                    }
1599:
1600:                    Column c = (Column) columns.get(i);
1601:                    int found = 0;
1602:                    for (int j = 0; j < whereColumns.size(); j++) {
1603:                        if (((Column) whereColumns.get(j)).equals(c)) {
1604:                            found++;
1605:                            if (DEBUG) {
1606:                                System.out
1607:                                        .println("where getReferencedColumn j = "
1608:                                                + j
1609:                                                + " "
1610:                                                + " found = "
1611:                                                + found
1612:                                                + ((Column) whereColumns.get(j))
1613:                                                        .genText(null));
1614:                            }
1615:                        }
1616:                        if (found > 1) // more than one instance
1617:                            return true;
1618:                    }
1619:                }
1620:                return false;
1621:            }
1622:
1623:            // Generate the Graph and Table entries corresponding to the WHERE clause
1624:            // Graph: edges  Table: criteria
1625:
1626:            private void generateGraphWhere(QueryModel query) {
1627:
1628:                Log.getLogger().entering("QueryBuilderGraphFrame",
1629:                        "generateGraphWhere"); // NOI18N
1630:
1631:                // if this is true we should not handle any events in tableChanged.
1632:                _inputTableAddCriteria = true;
1633:
1634:                // Now handle the WHERE clause
1635:                // For now, assume a single predicate, possibly parameterized
1636:                // Each predicate becomes a row in the InputTable, with an appte entry in Criteria
1637:                // Example code for adding rows to the table is in tableChanged
1638:                // For each predicate (col = [ value | ? ] )
1639:                // ToDo: handle all values, not just *, ?
1640:                // ToDo: introduce a different class for join predicates
1641:                Where where = query.getWhere();
1642:                if (where != null) {
1643:
1644:                    Expression expr = where.getExpression();
1645:
1646:                    List whereColumns = new ArrayList();
1647:                    where.getReferencedColumns(whereColumns);
1648:
1649:                    if (expr == null) {
1650:                        _inputTableAddCriteria = false;
1651:                        return;
1652:                    } else if (expr instanceof  Predicate) {
1653:                        if (whereHasDuplicateColumns(whereColumns,
1654:                                (Predicate) expr)) // more than one instance
1655:                            insertPredicate((Predicate) expr, -1);
1656:                        else
1657:                            insertPredicate((Predicate) expr, 0);
1658:                    } else if (expr instanceof  And) {
1659:                        insertAndOr(expr, whereColumns, 0);
1660:                    } else if (expr instanceof  Or) {
1661:                        insertAndOr(expr, whereColumns, 0);
1662:                    }
1663:                }
1664:                _inputTableAddCriteria = false;
1665:            }
1666:
1667:            // insert AND / OR expression in the grid pane. if a column appears
1668:            // more than once in the where clause then we display the "****" in the
1669:            // criteria column and the order is displayed as "*".
1670:            private void insertAndOr(Expression expr, List whereColumns,
1671:                    int order) {
1672:                ExpressionList exprList = (ExpressionList) expr;
1673:                for (int i = 0; i < exprList.size(); i++) {
1674:                    expr = exprList.getExpression(i);
1675:                    if (expr instanceof  Predicate) {
1676:                        if (whereHasDuplicateColumns(whereColumns,
1677:                                (Predicate) expr))
1678:                            // more than one instance
1679:                            insertPredicate((Predicate) expr, -1);
1680:                        else
1681:                            insertPredicate((Predicate) expr, order++);
1682:                    } else if (expr instanceof  And) {
1683:                        insertAndOr(expr, whereColumns, order++);
1684:                    } else if (expr instanceof  Or) {
1685:                        insertAndOr(expr, whereColumns, order++);
1686:                    }
1687:                }
1688:            }
1689:
1690:            /**
1691:             * Insert the predicate into visual editor, either as a graph edge (for
1692:             * a relationship) or as a table entry (for a criterion).
1693:             * Order is the initial value for the criteria order.
1694:             * if order is -1, then add "*****" to criteria column and "*" to
1695:             * order column and make both of them uneditable.
1696:             */
1697:            private void insertPredicate(Predicate pred, int order) {
1698:
1699:                Value val1 = pred.getVal1();
1700:                Value val2 = pred.getVal2();
1701:
1702:                if ((val1 instanceof  Column) && (val2 instanceof  Column)) {
1703:                    // Comparing two columns -- insert an edge
1704:                    insertJoinEdge(pred, "");
1705:                } else {
1706:                    // Assume that the right hand side is a literal value
1707:                    // This will result in an entry into the InputTable
1708:                    String marker = pred.getVal2().toString();
1709:
1710:                    // Treat this like any other literal value now
1711:                    // if (marker.equals("?")) {}
1712:
1713:                    // We can only count on the tableSpec; tableName might contain corrName
1714:                    Column col = (Column) val1;
1715:                    String tableSpec = col.getTableSpec();
1716:                    String columnName = col.getColumnName();
1717:
1718:                    // Create the value that we're going to put into the table
1719:                    String val = pred.getOp() + " " + marker; // NOI18N
1720:
1721:                    // If we're inserting a criterion, get order.  -1 is a special case, meaning ""
1722:                    if (order == -1) {
1723:                        _queryBuilderInputTable
1724:                                .addCriterion(
1725:                                        tableSpec,
1726:                                        columnName,
1727:                                        QueryBuilderInputTable.Criteria_Uneditable_String,
1728:                                        QueryBuilderInputTable.CriteriaOrder_Uneditable_String);
1729:                    } else {
1730:                        String orderString = (order == -1) ? "" : new Integer(
1731:                                order + 1).toString();
1732:
1733:                        // Update the appropriate row, or add a new one
1734:                        _queryBuilderInputTable.addCriterion(tableSpec,
1735:                                columnName, val, orderString);
1736:                    }
1737:                }
1738:            }
1739:
1740:            // Update the InputTable to show the OrderBy specs
1741:
1742:            private void generateGraphOrderBy(QueryModel query) {
1743:
1744:                // Delegate this to the InputTable, which is the only component affected
1745:                _queryBuilderInputTable.generateTableOrderBy(query);
1746:            }
1747:
1748:            /**
1749:             * Finds a graph node with the specified name (tableSpec)
1750:             */
1751:            QBNodeComponent findGraphNode(String tableSpec) {
1752:
1753:                Log.getLogger().entering("QueryBuilderGraphFrame",
1754:                        "findGraphNode", tableSpec); // NOI18N
1755:
1756:                Collection nodes = _scene.getNodes();
1757:                for (Object node : nodes) {
1758:                    if ((node instanceof  QBNodeComponent)
1759:                            && ((QBNodeComponent) node).getTableSpec().equals(
1760:                                    tableSpec))
1761:                        return (QBNodeComponent) node;
1762:                }
1763:
1764:                return null;
1765:            }
1766:
1767:            // Top-level method for adding a table to the query.
1768:            // Called from the "Add Table" menu item
1769:            public void addTable() {
1770:                Log.getLogger().entering("QueryBuilderGraphFrame", "addTable"); // NOI18N
1771:
1772:                // if ( _queryBuilder.checkDatabaseAndDisable(null) == false ) return;
1773:
1774:                QueryBuilder.showBusyCursor(true);
1775:                try {
1776:
1777:                    List tableNames = _queryBuilder.getAllTables();
1778:                    String[] tableStrings = new String[tableNames.size()];
1779:                    tableNames.toArray(tableStrings);
1780:                    _addTableDlg = new AddTableDlg(tableStrings, true);
1781:                    if (DEBUG)
1782:                        System.out
1783:                                .println("Database tablenames: " + tableNames); // NOI18N
1784:
1785:                    // It's not clear why we need to do this here, since we passed
1786:                    // tables into the constructor
1787:                    // _addTableDlg.setTableValues(_tableStrings) ;
1788:                    if (_addTableDlg.getReturnStatus() == 1) {
1789:                        // <change/> Moving to NB winsys.
1790:                        //            WindowManager.getDefault().showBusyCursor(true);
1791:                        SwingUtilities.invokeLater(new Runnable() {
1792:                            public void run() {
1793:                                Object[] selectedTables = _addTableDlg
1794:                                        .getSelectedValues();
1795:                                //                    refresh();
1796:                                //                    QueryBuilder.showBusyCursor ( true );
1797:                                for (int i = 0; i < selectedTables.length; i++) {
1798:                                    final String finalVal = (String) selectedTables[i];
1799:                                    insertTableInteractively(finalVal);
1800:                                }
1801:                                _queryBuilder.generateText();
1802:                                runQueryMenuItem.setEnabled(true);
1803:                                groupByMenuItem.setEnabled(true);
1804:                                _queryBuilder.getQueryBuilderPane()
1805:                                        .getQueryBuilderSqlTextArea()
1806:                                        .setRunQueryMenuEnabled(true);
1807:                                _queryBuilder.getQueryBuilderPane()
1808:                                        .getQueryBuilderSqlTextArea()
1809:                                        .setParseQueryMenuEnabled(true);
1810:                                //                    QueryBuilder.showBusyCursor ( false );
1811:                            }
1812:                        });
1813:                        // <change/> Moving to NB winsys.
1814:                        //            WindowManager.getDefault().showBusyCursor(false);
1815:                    }
1816:                    // somehow the graph still thinks we are not changed enough to redraw.
1817:                    // this causes the edges not to get drawn, as well as the scroll bars
1818:                    // not getting updated.
1819:                    //             QueryBuilderInternalFrame currentSelectedFrame =
1820:                    //                     (QueryBuilderInternalFrame)_desktopPane.getSelectedFrame();
1821:                    //             if ( currentSelectedFrame  != null ) {
1822:                    //                 redrawFrameWithMove( currentSelectedFrame );
1823:                    //             }
1824:                } catch (SQLException sqe) {
1825:                    // JDTODO - We need a consistent approach to handling SQL Exceptions.  Best is probably to expose them to user.
1826:                    // This comes up a number of places in QBGF.
1827:                    // _queryBuilder.checkDatabaseAndDisable(null) ;
1828:                } finally {
1829:                    QueryBuilder.showBusyCursor(false);
1830:                }
1831:            }
1832:
1833:            /**
1834:             * Responds to a menu selection
1835:             *
1836:             * Current choices are "Add Table", "Run Query", "Remove From Query"
1837:             */
1838:            public void actionPerformed(ActionEvent e) {
1839:
1840:                Log.getLogger().entering("QueryBuilderGraphFrame",
1841:                        "actionPerformed"); //NOI18N
1842:
1843:                JMenuItem source = (JMenuItem) (e.getSource());
1844:
1845:                if (source.getText().equals(
1846:                        NbBundle.getMessage(QueryBuilderGraphFrame.class,
1847:                                "Add_Table"))) { // NOI18N
1848:                    addTable();
1849:                }
1850:
1851:                else if (source.getText().equals(
1852:                        NbBundle.getMessage(QueryBuilderGraphFrame.class,
1853:                                "RUN_QUERY"))) // NOI18N
1854:                {
1855:                    // Execute the query
1856:                    _queryBuilder.executeQuery(_sqlTextArea.getText());
1857:                }
1858:
1859:                else if (source.getText().equals(
1860:                        NbBundle.getMessage(QueryBuilderGraphFrame.class,
1861:                                "REMOVE_FROM_QUERY"))) { // NOI18N
1862:                    removeTable();
1863:                }
1864:            }
1865:
1866:            //     public boolean isSelectionEmpty() {
1867:            //         // if there are no tables, selection should be empty.
1868:            //         if ( _firstTableInserted == false ) return true;
1869:            //         QueryBuilderInternalFrame currentSelectedFrame =
1870:            //                 (QueryBuilderInternalFrame)_desktopPane.getSelectedFrame();
1871:            //         return ( currentSelectedFrame == null );
1872:            //     }
1873:
1874:            // Remove the table node from the graph (and model)
1875:            // update delete menu
1876:            public void removeNode(TableNode node) {
1877:                //         QueryBuilder.showBusyCursor( true );
1878:
1879:                //         // remove the selected table to fix
1880:                //         // 6253516 : "delete" key doesn't work for same tables in QE.
1881:                //         removeTable();
1882:                //         QueryBuilder.showBusyCursor( false );
1883:            }
1884:
1885:            // Remove the condition node from the graph (and model)
1886:            // update delete menu
1887:            public void removeNode(CondNode node) {
1888:                //         QueryBuilder.showBusyCursor( true );
1889:                //         String[] rel = new String[4];
1890:                //         rel[0] = node.getTable1();
1891:                //         rel[1] = node.getColumn1();
1892:                //         rel[2] = node.getTable2();
1893:                //         rel[3] = node.getColumn2();
1894:
1895:                //         if (DEBUG) {
1896:                //             System.out.println(" QBGF.removeNode() table1 = " + rel[0] + " column1 = " + rel[1] + "  table2 = " + rel[2] + " column2 = " + rel[3] + "\n" ); // NOI18N
1897:                //         }
1898:
1899:                //         Predicate pred = SQLQueryFactory.createPredicate(rel);
1900:                //         _queryBuilder._updateText=false;
1901:                //         _queryBuilder.getQueryModel().removeCondition( pred );
1902:                //         Object cell = _graph.getSelectionCell();
1903:                //         if (cell instanceof DefaultEdge) {
1904:                //             _graphModel.remove(new Object[] {cell});
1905:                //         }
1906:                //         _queryBuilder._updateText=true;
1907:                //         _queryBuilder.generateText();
1908:                //         _queryBuilder.activateActions();
1909:                //         QueryBuilder.showBusyCursor( false );
1910:            }
1911:
1912:            // Remove the join node from the graph (and model)
1913:            // update delete menu
1914:            public void removeNode(JoinNode node) {
1915:                //         QueryBuilder.showBusyCursor( true );
1916:                //         String[] rel = new String[4];
1917:                //         rel[0] = node.getTable1();
1918:                //         rel[1] = node.getColumn1();
1919:                //         rel[2] = node.getTable2();
1920:                //         rel[3] = node.getColumn2();
1921:
1922:                //         if (DEBUG) {
1923:                //             System.out.println(" QBGF.removeNode() table1 = " + rel[0] + " column1 = " + rel[1] + "  table2 = " + rel[2] + " column2 = " + rel[3] + "\n" ); // NOI18N
1924:                //         }
1925:
1926:                //         _queryBuilder._updateText=false;
1927:                //         _queryBuilder.getQueryModel().removeJoinNode( rel[0], rel[1], rel[2], rel[3] );
1928:                //         Object cell = _graph.getSelectionCell();
1929:                //         if (cell instanceof DefaultEdge) {
1930:                //             _graphModel.remove(new Object[] {cell});
1931:                //         }
1932:                //         _queryBuilder._updateText=true;
1933:                //         _queryBuilder.generateText();
1934:                //         _queryBuilder.activateActions();
1935:                //         QueryBuilder.showBusyCursor( false );
1936:            }
1937:
1938:            // Remove the selected frame from the graph (and model)
1939:            // update delete menu
1940:            public void removeTable() {
1941:
1942:                Log.getLogger().entering("QueryBuilderGraphFrame",
1943:                        "removeTable"); //NOI18N
1944:
1945:                QueryBuilder.showBusyCursor(true);
1946:                // Important: suppress bogus regeneration of the text query
1947:                _queryBuilder._updateText = false;
1948:                try {
1949:                    removeTable(_selectedNode);
1950:                } finally {
1951:                    _queryBuilder._updateText = true;
1952:                }
1953:
1954:                // enable/disable group_by menu item
1955:                if (_sqlTextArea.getText() == null) {
1956:                    runQueryMenuItem.setEnabled(false);
1957:                    groupByMenuItem.setEnabled(false);
1958:                    _queryBuilder.getQueryBuilderPane()
1959:                            .getQueryBuilderSqlTextArea()
1960:                            .setRunQueryMenuEnabled(false);
1961:                    _queryBuilder.getQueryBuilderPane()
1962:                            .getQueryBuilderSqlTextArea()
1963:                            .setParseQueryMenuEnabled(false);
1964:                } else if (_sqlTextArea.getText().trim().length() == 0) {
1965:                    runQueryMenuItem.setEnabled(false);
1966:                    groupByMenuItem.setEnabled(false);
1967:                    _queryBuilder.getQueryBuilderPane()
1968:                            .getQueryBuilderSqlTextArea()
1969:                            .setRunQueryMenuEnabled(false);
1970:                    _queryBuilder.getQueryBuilderPane()
1971:                            .getQueryBuilderSqlTextArea()
1972:                            .setParseQueryMenuEnabled(false);
1973:                } else {
1974:                    runQueryMenuItem.setEnabled(true);
1975:                    groupByMenuItem.setEnabled(true);
1976:                    _queryBuilder.getQueryBuilderPane()
1977:                            .getQueryBuilderSqlTextArea()
1978:                            .setRunQueryMenuEnabled(true);
1979:                    _queryBuilder.getQueryBuilderPane()
1980:                            .getQueryBuilderSqlTextArea()
1981:                            .setParseQueryMenuEnabled(true);
1982:                }
1983:                QueryBuilder.showBusyCursor(false);
1984:            }
1985:
1986:            // Responds to a CheckBoxMenuItem -- Group by
1987:
1988:            public void itemStateChanged(ItemEvent e) {
1989:
1990:                JMenuItem source = (JMenuItem) (e.getSource());
1991:
1992:                if (source.getText().equals(
1993:                        NbBundle.getMessage(QueryBuilderGraphFrame.class,
1994:                                "GROUP_BY"))) { // NOI18N
1995:
1996:                    // Add or remove a Group by clause
1997:                    if (e.getStateChange() == ItemEvent.SELECTED) {
1998:                        // Add a Group By to the model
1999:                        _queryBuilder.getQueryModel().addGroupBy();
2000:                    } else {
2001:                        // Remove a Group By from the model
2002:                        _queryBuilder.getQueryModel().removeGroupBy();
2003:                    }
2004:                    _queryBuilder.generateText();
2005:                }
2006:            }
2007:
2008:            // Set the checkbox in the GroupBy menu item
2009:            public void setGroupBy(boolean b) {
2010:                groupByMenuItem.setSelected(b);
2011:            }
2012:
2013:            // somehow the graph still thinks we are not changed enough to redraw.
2014:            // this causes the edges not to get drawn, as well as the scroll bars
2015:            // not getting updated.
2016:            void redrawFrameWithMove(QueryBuilderInternalFrame frame) {
2017:                //         if (frame != null)
2018:                //             // && frame.isShowing()
2019:                //         {
2020:                //             HashMap map = new HashMap();
2021:                //             Map atts = GraphConstants.createMap();
2022:
2023:                //             GraphConstants.setBounds(atts,frame.getBounds());
2024:                //             map.put(frame.getGraphCell(),atts);
2025:                //             // Update the graph model with the new attributes, which include frame bounds(?)
2026:                //             _graphModel.edit(map,null,null,null);
2027:                //         }
2028:
2029:                //         // the 2 lines below need to be there for this to work
2030:                //         // but they should not be there in redrawFrame.
2031:                //         // That is the only difference between redrawFrame and
2032:                //         // redrawFrameWithMove
2033:                //         _desktopPane.setBounds(_canvas.getBounds());
2034:                //         _desktopPane.updateUI();
2035:
2036:                //         resizeDesktop();
2037:                //         _queryBuilder.getQueryBuilderPane().getQueryBuilderSqlTextArea().requestFocus(true);
2038:            }
2039:
2040:            // Redraw an internal frame?
2041:
2042:            private void redrawFrame(QueryBuilderInternalFrame frame) {
2043:                //         if (frame != null)
2044:                //             // && frame.isShowing()
2045:                //         {
2046:                //             HashMap map = new HashMap();
2047:                //             Map atts = GraphConstants.createMap();
2048:
2049:                //             GraphConstants.setBounds(atts,frame.getBounds());
2050:                //             map.put(frame.getGraphCell(),atts);
2051:                //             // Update the graph model with the new attributes, which include frame bounds(?)
2052:                //             _graphModel.edit(map,null,null,null);
2053:                //         }
2054:            }
2055:
2056:            // Manually refresh the graph display -- copied from ComponentListener below
2057:            // The forum suggested something like graphDidChange(); revalidate(); but not tried
2058:            // ToDo: Decide whether we need something like this with GraphLib
2059:            void refresh() {
2060:                //          _graph.graphDidChange();
2061:                //          _graph.revalidate();
2062:                //          if (DEBUG) {
2063:                //              System.out.println(" refresh() called " + "\n" ); // NOI18N
2064:                //              System.out.println(" width = " + _graph.getSize().getWidth() + " Height = " + _graph.getSize().getHeight() + "\n" ); // NOI18N
2065:                //          }
2066:                //          resizeDesktop();
2067:            }
2068:
2069:            // Inner classes, mostly for Listeners
2070:
2071:            // A listener that will bring up the background menu
2072:
2073:            //     class BackgroundPopupListener extends MouseAdapter {
2074:
2075:            //         public void mousePressed(MouseEvent e) {
2076:            //             maybeShowPopup(e);
2077:            //         }
2078:
2079:            //         public void mouseReleased(MouseEvent e) {
2080:            //             maybeShowPopup(e);
2081:            //         }
2082:
2083:            //         private void maybeShowPopup(MouseEvent e) {
2084:            //             if ( _disableQBGF ) return;
2085:            //             if (e.isPopupTrigger() ) {
2086:            //                 Object cell = _graph.getFirstCellForLocation(e.getX(), e.getY());
2087:            //                 if ( ( cell != null ) && ( cell instanceof DefaultEdge ) ) {
2088:            //                     // do not show popup.
2089:            //                     // bug 4979403 right click and double click the Join edge
2090:            //                     return;
2091:            //                 }
2092:            //                 if (e.getComponent().isEnabled() )
2093:            //                     _backgroundPopup.show( e.getComponent(), e.getX(), e.getY() );
2094:            //             }
2095:            //         }
2096:            //     }
2097:            /**
2098:             * An adapter class for receiving internal frame events.  Used
2099:             * to detect when a Frame (graph node representing a table) is selected
2100:             */
2101:            private class FrameSelectionListener extends InternalFrameAdapter {
2102:
2103:                public void internalFrameActivated(InternalFrameEvent ife) {
2104:                    Object source = (Object) (ife.getSource());
2105:
2106:                    // When any internal frame is activated, enable these two listeners?
2107:                    //          _apifa.setEnabled(true);
2108:                    //          _acifa.setEnabled(true);
2109:
2110:                    // Finally, bring up property sheet. Ignore event, just check which frame is selected.
2111:                    QueryBuilderInternalFrame currentSelectedFrame = (QueryBuilderInternalFrame) _desktopPane
2112:                            .getSelectedFrame();
2113:                    setActivatedNode(currentSelectedFrame);
2114:                }
2115:
2116:                public void internalFrameDeactivated(InternalFrameEvent ife) {
2117:                    //          _apifa.setEnabled(false);
2118:                    //          _acifa.setEnabled(false);
2119:                }
2120:            }
2121:
2122:            // An adapter class for receiving component events
2123:            // This listens for events from the desktopPane
2124:
2125:            private class CompListener extends ComponentAdapter {
2126:
2127:                public void componentResized(ComponentEvent ce) {
2128:                    if (_disableQBGF) {
2129:                        return;
2130:                    } else {
2131:                        refresh();
2132:                    }
2133:                }
2134:            }
2135:
2136:            // An adapter class for receiving component events
2137:            // This listens for events from nodes (internal frames)
2138:
2139:            //     private class FrameComponentListener extends ComponentAdapter {
2140:
2141:            //         // The following two methods are defined on the ComponentListener interface
2142:            //         public void componentResized(ComponentEvent ce) {
2143:            //             componentMoved(ce);
2144:            //         }
2145:
2146:            //         public void componentMoved(ComponentEvent ce) {
2147:            //             HashMap map = new HashMap();
2148:            //             Map atts = GraphConstants.createMap();
2149:            //             QueryBuilderInternalFrame frame = (QueryBuilderInternalFrame)ce.getComponent();
2150:            //             refresh();
2151:
2152:            //             GraphConstants.setBounds(atts,frame.getBounds());
2153:            //             map.put(frame.getGraphCell(),atts);
2154:            //             _graphModel.edit(map,null,null,null);
2155:
2156:            //             resizeDesktop();
2157:            //         }
2158:            //     }
2159:
2160:            /**
2161:             * Listener for detecting changes to the graph selection, to update Property Sheet
2162:             *
2163:             * This only detects selection for edges (joins); nodes are handled elsewhere.
2164:             */
2165:            //     private class GraphSelListener implements GraphSelectionListener {
2166:            //         public void valueChanged(GraphSelectionEvent e) {
2167:            //             Log.getLogger().finest("Graph selection changed, event: "+e); // NOI18N
2168:            //             if (_graph.getSelectionCount() > 0) {
2169:            //                 // Use the first selection; should only be one
2170:            //                 Object cell = _graph.getSelectionCell();
2171:            //                 if ( ( cell != null ) && ( cell instanceof DefaultEdge ) ) {
2172:            //                     // We've selected an edge. Update the Property Sheet, by setting
2173:            //                     // the activated node to the underlying join
2174:            //                     AbstractNode an = (AbstractNode)(((DefaultEdge) cell).getUserObject());
2175:            //                     _queryBuilder.setActivatedNodes(new Node[] { an });
2176:            //                     QueryBuilderInternalFrame currentSelectedFrame =
2177:            //                             (QueryBuilderInternalFrame) _desktopPane.getSelectedFrame();
2178:            //                     try {
2179:            //                         if ( currentSelectedFrame != null ) {
2180:            //                             currentSelectedFrame.setSelected( false );
2181:            //                         }
2182:            //                     } catch ( java.beans.PropertyVetoException pve ) {
2183:            //                         // do nothing
2184:            //                     }
2185:            //                 }
2186:            //             }
2187:            //         }
2188:            //     }
2189:
2190:            // GraphLib class for handling selection
2191:            private class ObjectSelectProvider implements  SelectProvider {
2192:
2193:                public boolean isAimingAllowed(Widget widget,
2194:                        Point localLocation, boolean invertSelection) {
2195:                    return false;
2196:                }
2197:
2198:                public boolean isSelectionAllowed(Widget widget,
2199:                        Point localLocation, boolean invertSelection) {
2200:                    return true;
2201:                }
2202:
2203:                public void select(Widget widget, Point localLocation,
2204:                        boolean invertSelection) {
2205:
2206:                    Object object = _scene.findObject(widget);
2207:                    if ((object != null) && (object instanceof  AbstractNode)) {
2208:                        AbstractNode an = (AbstractNode) object;
2209:                        _queryBuilder.setActivatedNodes(new Node[] { an });
2210:                        _scene.userSelectionSuggested(Collections
2211:                                .singleton(object), invertSelection);
2212:                    }
2213:                }
2214:            }
2215:
2216:            // Utility class for timing
2217:
2218:            public class PerfTimer {
2219:
2220:                long _time;
2221:
2222:                public PerfTimer() {
2223:                    resetTimer();
2224:                }
2225:
2226:                // reset Timer
2227:                public void resetTimer() {
2228:                    // set current time
2229:                    _time = System.currentTimeMillis();
2230:                }
2231:
2232:                public long elapsedTime() {
2233:                    // get elapsed Time
2234:                    return (System.currentTimeMillis() - _time);
2235:                }
2236:
2237:                public void print(String aString) {
2238:                    System.out.println(aString + ": " + this .elapsedTime()
2239:                            + " ms"); // NOI18N
2240:                }
2241:            }
2242:
2243:            public void dragEnter(DropTargetDragEvent e) {
2244:                e.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
2245:            }
2246:
2247:            public void drop(DropTargetDropEvent e) {
2248:                if (_disableQBGF)
2249:                    return;
2250:                try {
2251:                    Transferable tr = e.getTransferable();
2252:                    DataFlavor[] dataFlavors = tr.getTransferDataFlavors();
2253:                    for (int i = 0; i < dataFlavors.length; i++) {
2254:                        Object o = tr.getTransferData(dataFlavors[i]);
2255:                        if (o instanceof  Node) {
2256:                            e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
2257:                            // user should be allowed to drop tables from the
2258:                            // current data source only.
2259:                            List tableNamesArrayList = _queryBuilder
2260:                                    .getAllTables();
2261:                            String fullTableName = ((Node) o).getName();
2262:
2263:                            // Reassign fullTableName to just the table name - minus the schema name
2264:                            String tableName;
2265:                            String justTableName;
2266:                            for (int j = 0; j < tableNamesArrayList.size(); j++) {
2267:                                tableName = (String) tableNamesArrayList.get(j);
2268:                                justTableName = (String) tableName.split("\\.")[1];
2269:                                if (justTableName.equals(fullTableName)) {
2270:                                    fullTableName = tableName;
2271:                                    break;
2272:                                }
2273:                            }
2274:
2275:                            if (tableNamesArrayList.contains(fullTableName)) {
2276:                                insertTableInteractively(fullTableName);
2277:                                _queryBuilder.generateText();
2278:                                runQueryMenuItem.setEnabled(true);
2279:                                groupByMenuItem.setEnabled(true);
2280:                                _queryBuilder.getQueryBuilderPane()
2281:                                        .getQueryBuilderSqlTextArea()
2282:                                        .setRunQueryMenuEnabled(true);
2283:                                _queryBuilder.getQueryBuilderPane()
2284:                                        .getQueryBuilderSqlTextArea()
2285:                                        .setParseQueryMenuEnabled(true);
2286:                                refresh();
2287:                                // _graph.getGraphLayoutCache().reload();
2288:                                resizeDesktop();
2289:                                // somehow the graph still thinks we are not changed
2290:                                // enough to redraw. this causes the edges not to get
2291:                                // drawn, as well as the scroll bars not getting
2292:                                // updated.
2293:
2294:                                // 117724  DnD table null pointer exception occurs - removed code to get the currentSelectedFrame
2295:                                // (QueryBuilderInternalFrame)_desktopPane.getSelectedFrame();                        
2296:                            } else {
2297:                                String msg = NbBundle
2298:                                        .getMessage(
2299:                                                QueryBuilderGraphFrame.class,
2300:                                                "DRAG_AND_DROP_FROM_CURRENT_DATASOURCE");
2301:                                NotifyDescriptor d = new NotifyDescriptor.Message(
2302:                                        msg
2303:                                                + ", "
2304:                                                + _queryBuilder
2305:                                                        .getConnectionInfo()
2306:                                                + "\n\n", // NOI18N
2307:                                        NotifyDescriptor.ERROR_MESSAGE);
2308:                                DialogDisplayer.getDefault().notify(d);
2309:                            }
2310:                            e.dropComplete(true);
2311:                            return;
2312:                        }
2313:                    }
2314:                    e.rejectDrop();
2315:                } catch (Exception ex) {
2316:                    Log.getLogger().finest(
2317:                            "Data transfer exception:  "
2318:                                    + ex.getLocalizedMessage()); // NOI18N
2319:                }
2320:            }
2321:
2322:            public void dragExit(DropTargetEvent e) {
2323:
2324:            }
2325:
2326:            public void dragOver(DropTargetDragEvent e) {
2327:
2328:            }
2329:
2330:            public void dropActionChanged(DropTargetDragEvent e) {
2331:
2332:            }
2333:
2334:            public void dragOver(DragSourceDragEvent e) {
2335:
2336:            }
2337:
2338:            public void dropActionChanged(DragSourceDragEvent e) {
2339:
2340:            }
2341:        }
w__w___w_.j_a_v__a2___s___.c_om | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.