001/* 002 * Copyright (c) 2003-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2012-06-12 00:46:03 +0000 (Tue, 12 Jun 2012) $' 007 * '$Revision: 29919 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.ecoinformatics.seek.querybuilder; 031 032import java.awt.BorderLayout; 033import java.awt.Color; 034import java.awt.Dimension; 035import java.awt.GraphicsConfiguration; 036import java.awt.GraphicsEnvironment; 037import java.awt.Insets; 038import java.awt.Rectangle; 039import java.awt.Toolkit; 040import java.awt.event.ActionEvent; 041import java.beans.PropertyChangeEvent; 042import java.beans.PropertyChangeListener; 043import java.io.BufferedWriter; 044import java.io.File; 045import java.io.FileNotFoundException; 046import java.io.FileWriter; 047import java.io.IOException; 048import java.io.Writer; 049import java.util.Vector; 050 051import javax.swing.AbstractAction; 052import javax.swing.Action; 053import javax.swing.Box; 054import javax.swing.BoxLayout; 055import javax.swing.JButton; 056import javax.swing.JComponent; 057import javax.swing.JEditorPane; 058import javax.swing.JFileChooser; 059import javax.swing.JFrame; 060import javax.swing.JMenu; 061import javax.swing.JMenuBar; 062import javax.swing.JMenuItem; 063import javax.swing.JOptionPane; 064import javax.swing.JPanel; 065import javax.swing.JTabbedPane; 066import javax.swing.JTextField; 067import javax.swing.SingleSelectionModel; 068import javax.swing.SwingUtilities; 069import javax.swing.border.EtchedBorder; 070import javax.swing.event.ChangeEvent; 071import javax.swing.event.ChangeListener; 072import javax.swing.event.TableModelEvent; 073import javax.swing.event.TableModelListener; 074import javax.swing.table.TableCellEditor; 075 076import org.kepler.objectmanager.data.DataType; 077import org.kepler.objectmanager.data.db.Attribute; 078import org.kepler.objectmanager.data.db.DSSchemaDef; 079import org.kepler.objectmanager.data.db.DSSchemaIFace; 080import org.kepler.objectmanager.data.db.DSTableDef; 081import org.kepler.objectmanager.data.db.Entity; 082import org.kepler.objectmanager.data.db.QBEditor; 083 084import ptolemy.gui.PtFileChooser; 085import ptolemy.gui.PtFilenameFilter; 086 087/** 088 * The Query Builder app which extends a JPanel. This enables it to be embedded 089 * in an applet or an application. 090 */ 091public class QBApp extends JPanel implements ChangeListener, TableModelListener { 092 093 // The preferred size of the demo 094 private static final int PREFERRED_WIDTH = 720; 095 private static final int PREFERRED_HEIGHT = 640; 096 private static final String ADD_MSG = "Add an item by clicking in the empty \"table\" cell, or drag a \"field\" item from the top panel to the bottom."; 097 private static final String CHANGED_MSG = "Query has Changed."; 098 099 private static final int STD_TAB = 0; 100 // private static final int INTER_TAB = 1; 101 // private static final int ADV_TAB = 2; 102 private static final int SQL_TAB = 1; 103 104 private boolean mDoingDemo = false; 105 private boolean mDoingDemoTests = false; 106 107 private JPanel mDemoPanel = null; 108 109 private boolean mIsChanged = false; 110 private boolean mNoOuterUI = false; 111 112 // Status Bar 113 private JTextField mStatusField = null; 114 private JMenuBar mMenuBar = null; 115 private GenericMenuAction mSaveQueryAction = null; 116 private GenericMenuAction mSaveSchemaAction = null; 117 private JFrame mFrame = null; 118 private QBApplet mApplet = null; 119 120 private JTabbedPane mTabbedPane = null; 121 private int mTabInx = 0; 122 private int mLastTabInx = 0; 123 124 private DSSchemaIFace mSchema = null; 125 private DBQueryDef mQueryDef = null; 126 127 private QBSplitPaneStandard mStdSP = null; 128 // private QBSplitPaneIntermediate mInterSP = null; 129 // private QBSplitPaneAdvanced mAdvSP = null; 130 private QBSplitPaneSQL mSQLSP = null; 131 private QBBuilderInterface mBuilderTab = null; 132 133 private TableModelListener mExternalTMListener = null; 134 private QBEditor qbEditor = null; 135 136 private static final int BUTTONXSIZE = 90; 137 private static final int BUTTONYSIZE = 30; 138 139 /** 140 * Constructor with Applet 141 * 142 * @param aApplet 143 */ 144 public QBApp(QBEditor editor) { 145 qbEditor = editor; 146 mNoOuterUI = true; 147 initialize(); 148 } 149 150 /** 151 * Constructor with Applet 152 * 153 * @param aApplet 154 */ 155 public QBApp(QBApplet aApplet) { 156 this(aApplet, null); 157 } 158 159 /** 160 * QBApp Constructor 161 */ 162 public QBApp(QBApplet aApplet, GraphicsConfiguration gc) { 163 164 // Note that the applet may null if this is started as an application 165 mApplet = aApplet; 166 167 // Create Frame here for app-mode 168 if (!isApplet() && gc != null) { 169 mFrame = new JFrame(gc); 170 } 171 initialize(); 172 } 173 174 /** 175 * General Method for initializing the class 176 * 177 */ 178 private void initialize() { 179 setLayout(new BorderLayout()); 180 181 // set the preferred size of the demo 182 setPreferredSize(new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT)); 183 184 initializeUI(); 185 186 JEditorPane editorPane = new JEditorPane("text/text", 187 "Generated SQL will go here!"); 188 editorPane.setEditable(false); 189 190 // create tab 191 mTabbedPane = new JTabbedPane(); 192 193 DBQueryDef queryDef = null; 194 if (mDoingDemo) { 195 queryDef = createDemoQuery(); 196 loadSchemaIntoUI(createDemoSchema()); 197 } 198 199 add(mTabbedPane, BorderLayout.CENTER); 200 JPanel buttonPane = createButtonPanel(); 201 add(buttonPane, BorderLayout.SOUTH); 202 203 setStatus(ADD_MSG); 204 205 if (mDoingDemo) { 206 loadQuery(queryDef); 207 // mIsChanged = false; 208 // mLastTabInx = mQueryDef.isAdv() ? 1 : 0; 209 // mTabbedPane.setSelectedIndex(mLastTabInx); 210 } 211 212 // Note that 213 // we again must do this on the GUI thread using invokeLater. 214 SwingUtilities.invokeLater(new Runnable() { 215 public void run() { 216 showQBApp(); 217 } 218 }); 219 } 220 221 private JPanel createButtonPanel() { 222 JPanel wholePanel = new JPanel(); 223 wholePanel.setLayout(new BoxLayout(wholePanel, BoxLayout.Y_AXIS)); 224 wholePanel.add(Box.createVerticalStrut(10)); 225 JPanel buttonPanel = new JPanel(); 226 buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)); 227 buttonPanel.add(Box.createHorizontalGlue()); 228 JButton cancelButton = new JButton(new CancelAction(qbEditor)); 229 cancelButton.setPreferredSize(new Dimension(BUTTONXSIZE, BUTTONYSIZE)); 230 JButton OKButton = new JButton(new OKAction(qbEditor)); 231 OKButton.setPreferredSize(new Dimension(BUTTONXSIZE, BUTTONYSIZE)); 232 buttonPanel.add(OKButton); 233 buttonPanel.add(Box.createHorizontalStrut(10)); 234 buttonPanel.add(cancelButton); 235 buttonPanel.add(Box.createHorizontalStrut(10)); 236 wholePanel.add(buttonPanel); 237 wholePanel.add(Box.createVerticalStrut(10)); 238 return wholePanel; 239 } 240 241 /** 242 * Sets a new Schema into the UI and recreates the UI for it 243 * 244 * @param aSchema 245 * the new schema 246 */ 247 public void loadSchemaIntoUI(DSSchemaIFace aSchema) { 248 if (aSchema == null) 249 return; 250 251 mSchema = aSchema; 252 253 // if (mAdvSP != null) 254 // mAdvSP.shutdown(); 255 256 try { 257 mTabbedPane.removeAll(); 258 } catch (Exception e) { 259 System.err.println(e); 260 } 261 262 mStdSP = null; 263 // mInterSP = null; 264 // mAdvSP = null; 265 mSQLSP = null; 266 267 /* 268 * if (!isApplet()) { java.lang.System.gc(); 269 * java.lang.System.runFinalization(); 270 * java.lang.System.runFinalizersOnExit(true); } 271 */ 272 273 // if (!firstTime) return; 274 mStdSP = new QBSplitPaneStandard(mSchema); 275 // mInterSP = new QBSplitPaneIntermediate(mSchema, this); 276 // mAdvSP = new QBSplitPaneAdvanced(mSchema, this); 277 mSQLSP = new QBSplitPaneSQL(); 278 279 // Initialize 280 mStdSP.setTableModelListener(this); 281 // mInterSP.setTableModelListener(this); 282 // mAdvSP.setTableModelListener(this); 283 284 mTabbedPane.add("General", mStdSP); 285 // mTabbedPane.add("Intermediate", mInterSP); 286 // mTabbedPane.add("Advanced", mAdvSP); 287 mTabbedPane.add("SQL", mSQLSP); 288 289 mTabbedPane.getModel().addChangeListener(this); 290 } 291 292 /** 293 * 294 * @return returns a test/demo schema 295 */ 296 private DSSchemaDef createDemoSchema() { 297 DSSchemaDef schema = null; 298 if (mDoingDemo) { 299 schema = new DSSchemaDef("Test Schema"); 300 boolean useTableEntity = true; 301 if (useTableEntity) { 302 Entity table1 = new Entity("", "Employees", "", new Boolean( 303 true), Entity.ROWMAJOR, 0); 304 table1.add(new Attribute("", "EmpNo", DataType.INT)); 305 table1.add(new Attribute("", "First Name", DataType.STR)); 306 table1.add(new Attribute("", "Last Name", DataType.STR)); 307 table1.add(new Attribute("", "Addr 1", DataType.STR)); 308 table1.add(new Attribute("", "Addr 2", DataType.STR)); 309 table1.add(new Attribute("", "City", DataType.STR)); 310 table1.add(new Attribute("", "State", DataType.STR)); 311 table1.add(new Attribute("", "Zip", DataType.STR)); 312 schema.addTable(table1); 313 314 table1 = new Entity("", "EmpDept", "", new Boolean(true), 315 Entity.ROWMAJOR, 0); 316 table1.add(new Attribute("", "EmpNo", DataType.INT)); 317 table1.add(new Attribute("", "DeptNo", DataType.INT)); 318 schema.addTable(table1); 319 320 table1 = new Entity("", "Department", "", new Boolean(true), 321 Entity.ROWMAJOR, 0); 322 table1.add(new Attribute("", "DeptNo", DataType.INT)); 323 table1.add(new Attribute("", "Name", DataType.STR)); 324 for (int i = 0; i < 15; i++) { 325 table1.add(new Attribute("", "User Field " + i, 326 DataType.STR)); 327 } 328 schema.addTable(table1); 329 330 table1 = new Entity("", "EmpDoc", "", new Boolean(true), 331 Entity.ROWMAJOR, 0); 332 table1.add(new Attribute("", "EmpNo", DataType.INT)); 333 table1.add(new Attribute("", "DocNo", DataType.INT)); 334 schema.addTable(table1); 335 336 table1 = new Entity("", "Document", "", new Boolean(true), 337 Entity.ROWMAJOR, 0); 338 table1.add(new Attribute("", "DocNo", DataType.INT)); 339 table1.add(new Attribute("", "Title", DataType.STR)); 340 table1.add(new Attribute("", "Desc", DataType.STR)); 341 table1.add(new Attribute("", "Biblo", DataType.STR)); 342 schema.addTable(table1); 343 344 } else { 345 DSTableDef table1 = new DSTableDef("Employees"); 346 table1.addPrimaryKey("EmpNo", DataType.INT, null); 347 table1.addField("First Name", DataType.STR, null); 348 table1.addField("Last Name", DataType.STR, null); 349 table1.addField("Addr 1", DataType.STR, null); 350 table1.addField("Addr 2", DataType.STR, null); 351 table1.addField("City", DataType.STR, null); 352 table1.addField("State", DataType.STR, null); 353 table1.addField("Zip", DataType.STR, null); 354 schema.addTable(table1); 355 356 table1 = new DSTableDef("EmpDept"); 357 table1.addPrimaryKey("EmpNo", DataType.INT, null); 358 table1.addSecondaryKey("DeptNo", DataType.INT, null); 359 schema.addTable(table1); 360 361 table1 = new DSTableDef("Department"); 362 table1.addPrimaryKey("DeptNo", DataType.INT, null); 363 table1.addField("Name", DataType.STR, null); 364 for (int i = 0; i < 15; i++) { 365 table1.addField("User Field " + i, DataType.STR, null); 366 } 367 schema.addTable(table1); 368 369 table1 = new DSTableDef("EmpDoc"); 370 table1.addPrimaryKey("EmpNo", DataType.INT, null); 371 table1.addSecondaryKey("DocNo", DataType.INT, null); 372 schema.addTable(table1); 373 374 table1 = new DSTableDef("Document"); 375 table1.addPrimaryKey("DocNo", DataType.INT, null); 376 table1.addField("Title", DataType.STR, null); 377 table1.addField("Desc", DataType.STR, null); 378 table1.addField("Biblo", DataType.STR, null); 379 schema.addTable(table1); 380 } 381 } 382 return schema; 383 } 384 385 /** 386 * 387 * @return returns a demo query object 388 */ 389 private DBQueryDef createDemoQuery() { 390 DBQueryDef queryDef = new DBQueryDef(); 391 Vector joins = new Vector(); 392 String tableNames[] = { "Employees", "EmpDept", "EmpDept", 393 "Department", "Employees", "EmpDoc", "EmpDoc", "Document" }; 394 String fieldNames[] = { "EmpNo", "EmpNo", "DeptNo", "DeptNo", "EmpNo", 395 "EmpNo", "DocNo", "DocNo" }; 396 int tableIds[] = { 0, 1, 1, 2, 0, 3, 3, 4 }; 397 for (int i = 0; i < tableNames.length; i++) { 398 Vector missingValue = null; 399 DBSelectTableModelItem item = new DBSelectTableModelItem( 400 tableNames[i], fieldNames[i], "", false, "", "", 401 missingValue); 402 item.setTableId(tableIds[i]); 403 joins.add(item); 404 } 405 queryDef.setJoins(joins); 406 407 int tableFrameIds[] = { 0, 1, 2, 3, 4 }; 408 String tableFrameNames[] = { "Employees", "EmpDept", "Department", 409 "EmpDoc", "Document" }; 410 for (int i = 0; i < tableFrameIds.length; i++) { 411 queryDef.addTable(tableFrameIds[i], tableFrameNames[i], -1, -1); 412 } 413 queryDef.setIsAdv(true); 414 return queryDef; 415 } 416 417 // ******************************************************* 418 // *************** Load UI ****************** 419 // ******************************************************* 420 421 public void initializeUI() { 422 423 JPanel top = new JPanel(); 424 top.setLayout(new BorderLayout()); 425 add(top, BorderLayout.NORTH); 426 427 mMenuBar = createMenus(); 428 if (mMenuBar != null) 429 top.add(mMenuBar, BorderLayout.NORTH); 430 431 mStatusField = new JTextField(""); 432 mStatusField.setEditable(false); 433 add(mStatusField, BorderLayout.SOUTH); 434 435 mDemoPanel = new JPanel(); 436 mDemoPanel.setLayout(new BorderLayout()); 437 mDemoPanel.setBorder(new EtchedBorder()); 438 mDemoPanel.setBackground(Color.green); 439 add(mDemoPanel, BorderLayout.CENTER); 440 441 } 442 443 /** 444 * Set qb tableau 445 * 446 * @param tableau 447 */ 448 public void setQBEditor(QBEditor editor) { 449 this.qbEditor = editor; 450 } 451 452 /** 453 * @param b 454 * */ 455 protected PropertyChangeListener createActionChangeListener(JMenuItem b) { 456 return new ActionChangedListener(b); 457 } 458 459 /** 460 * 461 * @author globus 462 * 463 * TODO To change the template for this generated type comment go to 464 * Window - Preferences - Java - Code Generation - Code and Comments 465 */ 466 private class ActionChangedListener implements PropertyChangeListener { 467 JMenuItem menuItem; 468 469 ActionChangedListener(JMenuItem mi) { 470 super(); 471 this.menuItem = mi; 472 } 473 474 public void propertyChange(PropertyChangeEvent e) { 475 String propertyName = e.getPropertyName(); 476 if (e.getPropertyName().equals(Action.NAME)) { 477 String text = (String) e.getNewValue(); 478 menuItem.setText(text); 479 } else if (propertyName.equals("enabled")) { 480 Boolean enabledState = (Boolean) e.getNewValue(); 481 menuItem.setEnabled(enabledState.booleanValue()); 482 } 483 } 484 } 485 486 /** 487 * Create menus 488 */ 489 public JMenuBar createMenus() { 490 JMenuBar menuBar = null; 491 492 if (!isApplet() && !mNoOuterUI) { 493 menuBar = new JMenuBar(); 494 JMenu fileMenu = (JMenu) menuBar.add(new JMenu("File")); 495 fileMenu.setMnemonic('F'); 496 createMenuItem(fileMenu, "Open Query", "O", "Open Query File", 497 new GenericMenuAction(this, 498 GenericMenuAction.OPEN_QUERY_ACTION), true); 499 createMenuItem(fileMenu, "Save Query", "S", "Save Query", 500 mSaveQueryAction = new GenericMenuAction(this, 501 GenericMenuAction.SAVE_QUERY_ACTION), false); 502 fileMenu.addSeparator(); 503 createMenuItem(fileMenu, "Open Schema", "O", "Open Schema File", 504 new GenericMenuAction(this, 505 GenericMenuAction.OPEN_SCHEMA_ACTION), true); 506 createMenuItem(fileMenu, "Save Schema", "S", "Save Schema", 507 mSaveSchemaAction = new GenericMenuAction(this, 508 GenericMenuAction.SAVE_SCHEMA_ACTION), false); 509 fileMenu.addSeparator(); 510 createMenuItem(fileMenu, "Exit", "x", "Exit Appication", 511 new GenericMenuAction(this, GenericMenuAction.EXIT_ACTION), 512 true); 513 514 if (mDoingDemoTests) { 515 fileMenu = (JMenu) menuBar.add(new JMenu("Tests")); 516 fileMenu.setMnemonic('T'); 517 createMenuItem(fileMenu, "Test Queries", "e", "Test Queries", 518 new GenericMenuAction(this, 519 GenericMenuAction.QUERY_TESTS_ACTION), true); 520 } 521 } 522 523 return menuBar; 524 } 525 526 /** 527 * Creates a generic menu item 528 */ 529 public JMenuItem createMenuItem(JMenu menu, String label, String mnemonic, 530 String accessibleDescription, Action action, boolean enabled) { 531 JMenuItem mi = (JMenuItem) menu.add(new JMenuItem(label)); 532 mi.setMnemonic(mnemonic.charAt(0)); 533 mi.getAccessibleContext().setAccessibleDescription( 534 accessibleDescription); 535 mi.addActionListener(action); 536 if (action == null) { 537 mi.setEnabled(false); 538 } else { 539 action.addPropertyChangeListener(createActionChangeListener(mi)); 540 action.setEnabled(enabled); 541 } 542 return mi; 543 } 544 545 /** 546 * Bring up the QBApp demo by showing the frame (only applicable if coming 547 * up as an application, not an applet); 548 */ 549 public void showQBApp() { 550 if (!isApplet() && getFrame() != null) { 551 // put QBApp in a frame and show it 552 JFrame f = getFrame(); 553 f.setTitle("Query Builder"); 554 f.getContentPane().add(this, BorderLayout.CENTER); 555 f.pack(); 556 557 Rectangle screenRect = f.getGraphicsConfiguration().getBounds(); 558 Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( 559 f.getGraphicsConfiguration()); 560 561 // Make sure we don't place the demo off the screen. 562 int centerWidth = screenRect.width < f.getSize().width ? screenRect.x 563 : screenRect.x + screenRect.width / 2 - f.getSize().width 564 / 2; 565 int centerHeight = screenRect.height < f.getSize().height ? screenRect.y 566 : screenRect.y + screenRect.height / 2 - f.getSize().height 567 / 2; 568 569 centerHeight = centerHeight < screenInsets.top ? screenInsets.top 570 : centerHeight; 571 572 f.setLocation(centerWidth, centerHeight); 573 f.show(); 574 } 575 } 576 577 /** 578 * Determines if this is an applet or application 579 */ 580 public boolean isApplet() { 581 return (mApplet != null); 582 } 583 584 /** 585 * Returns the applet instance 586 */ 587 public QBApplet getApplet() { 588 return mApplet; 589 } 590 591 /** 592 * Returns the frame instance 593 */ 594 public JFrame getFrame() { 595 return mFrame; 596 } 597 598 /** 599 * Returns the menubar 600 */ 601 public JMenuBar getMenuBar() { 602 return mMenuBar; 603 } 604 605 /** 606 * Set the status 607 */ 608 public void setStatus(String s) { 609 // do the following on the gui thread 610 SwingUtilities.invokeLater(new QBAppRunnable(this, s) { 611 public void run() { 612 mQBApp.mStatusField.setText((String) obj); 613 } 614 }); 615 } 616 617 public void setIsChanged(boolean aIsChanged) { 618 mIsChanged = aIsChanged; 619 if (mSaveQueryAction != null) { 620 mSaveQueryAction.setEnabled(aIsChanged); 621 } 622 } 623 624 public void setExternalTMListener(TableModelListener aL) { 625 mExternalTMListener = aL; 626 } 627 628 /** 629 * Saves Query to a file 630 */ 631 public Writer saveFile(String aTitle, String aFilterStr, String aFilterTitle) { 632 PtFileChooser chooser = new PtFileChooser(mFrame, "Save " + aTitle, JFileChooser.SAVE_DIALOG); 633 chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 634 chooser.setSelectedFile(null); 635 final DBFileFilter dbFileFilter = new DBFileFilter(aFilterStr, aFilterTitle); 636 chooser.addChoosableFileFilter(new PtFilenameFilter() { 637 @Override 638 public boolean accept(File file) { 639 return dbFileFilter.accept(file); 640 } 641 642 @Override 643 public boolean accept(File directory, String name) { 644 return dbFileFilter.accept(new File(directory, name)); 645 } 646 647 @Override 648 public String getDescription() { 649 return dbFileFilter.getDescription(); 650 } 651 }); 652 int retval = chooser.showDialog(this, "Save"); 653 if (retval == JFileChooser.APPROVE_OPTION) { 654 // declared here only to make visible to finally clause; generic 655 // reference 656 Writer output = null; 657 try { 658 // use buffering 659 return new BufferedWriter(new FileWriter(chooser 660 .getSelectedFile())); 661 } catch (FileNotFoundException ex) { 662 JOptionPane.showMessageDialog(this, ex.toString()); 663 } catch (IOException ex) { 664 JOptionPane.showMessageDialog(this, ex.toString()); 665 } finally { 666 // flush and close both "output" and its underlying FileWriter 667 try { 668 if (output != null) 669 output.close(); 670 } catch (IOException ex) { 671 JOptionPane.showMessageDialog(this, ex.toString()); 672 } 673 } 674 } 675 return null; 676 } 677 678 /** 679 * Saves Query to a file 680 */ 681 public void saveQueryFile() { 682 Writer output = saveFile("Query", "query", "Query Files"); 683 if (output != null) { 684 DBQueryDef queryDef = new DBQueryDef(); 685 mBuilderTab.fillQueryDef(queryDef); 686 687 try { 688 output.write(DBQueryDefParserEmitter.emitXML(queryDef)); 689 output.close(); 690 setIsChanged(false); 691 setStatus(ADD_MSG); 692 } catch (IOException ex) { 693 JOptionPane.showMessageDialog(this, ex.toString()); 694 } 695 } 696 } 697 698 /** 699 * Saves Query to a file 700 */ 701 public void saveSchemaFile() { 702 Writer output = saveFile("Schema", "schema", "QueSchemary Files"); 703 if (output != null) { 704 try { 705 output.write(DBSchemaParserEmitter.emitXML(mSchema)); 706 output.close(); 707 } catch (IOException ex) { 708 JOptionPane.showMessageDialog(this, ex.toString()); 709 } 710 } 711 } 712 713 /** 714 * Loads the QueryDef object into the UI 715 * 716 * @param aQueryDef 717 * the query def 718 */ 719 protected void loadQuery(DBQueryDef aQueryDef) { 720 if (aQueryDef != null) { 721 mQueryDef = aQueryDef; 722 723 QBBuilderInterface builder = null; 724 int tabInx = SQL_TAB; 725 726 boolean debug = false; 727 /* 728 * if (debug) { int status = mInterSP.buildFromQueryDef(aQueryDef); 729 * if (status == DBQueryDef.BUILD_TOO_COMPLEX_WHERE || status == 730 * DBQueryDef.BUILD_TOO_COMPLEX_JOINS) { 731 * JOptionPane.showMessageDialog(this, 732 * "Switching to the Advanced View,\nthe query is too complex for the Standard Tab." 733 * ); tabInx = ADV_TAB; builder = mAdvSP; 734 * builder.buildFromQueryDef(mQueryDef); } else { tabInx = 735 * INTER_TAB; builder = mInterSP; } } else { if (aQueryDef.isAdv()) 736 * { int status = mInterSP.buildFromQueryDef(aQueryDef); if (status 737 * == DBQueryDef.BUILD_TOO_COMPLEX_WHERE || status == 738 * DBQueryDef.BUILD_TOO_COMPLEX_JOINS) { 739 * JOptionPane.showMessageDialog(this, 740 * "Switching to the Advanced View,\nthe query is too complex for the Intermediate Tab." 741 * ); tabInx = ADV_TAB; builder = mAdvSP; 742 * builder.buildFromQueryDef(mQueryDef); } else { tabInx = 743 * INTER_TAB; builder = mInterSP; } } else { int status = 744 * mStdSP.buildFromQueryDef(aQueryDef); if (status == 745 * DBQueryDef.BUILD_TOO_COMPLEX_WHERE || status == 746 * DBQueryDef.BUILD_TOO_COMPLEX_JOINS) { 747 * mTabbedPane.setSelectedIndex(INTER_TAB); 748 * JOptionPane.showMessageDialog(this, 749 * "Switching to the Intermediate View,\nthe query is too complex for the Standard Tab." 750 * ); tabInx = INTER_TAB; builder = mInterSP; 751 * builder.buildFromQueryDef(mQueryDef); } else { tabInx = STD_TAB; 752 * builder = mStdSP; } } 753 * 754 * } 755 */ 756 757 // only handle stand panel 758 int status = mStdSP.buildFromQueryDef(aQueryDef); 759 if (status == DBQueryDef.BUILD_TOO_COMPLEX_WHERE 760 || status == DBQueryDef.BUILD_TOO_COMPLEX_JOINS) { 761 JOptionPane.showMessageDialog(this, 762 "The query is too complex for the Standard Tab."); 763 } else { 764 tabInx = STD_TAB; 765 builder = mStdSP; 766 } 767 768 if (mBuilderTab == null) { 769 mBuilderTab = builder; 770 mLastTabInx = tabInx; 771 mTabInx = tabInx; 772 } 773 mTabbedPane.setSelectedIndex(tabInx); 774 775 } else { 776 JOptionPane 777 .showMessageDialog(this, 778 "There was an error parsing the query.\nIt could not be loaded."); 779 } 780 setIsChanged(false); 781 setStatus(ADD_MSG); 782 } 783 784 /** 785 * Fills QueryDef from Model 786 */ 787 public void fillQueryDef(DBQueryDef aQueryDef) { 788 if (aQueryDef == null) 789 return; 790 791 mBuilderTab.fillQueryDef(aQueryDef); 792 793 } 794 795 /** 796 * Sets which builder tab should be used if the query is null 797 * 798 */ 799 public void initializeBuilder() { 800 if (mBuilderTab == null) { 801 mBuilderTab = mStdSP; 802 mTabInx = STD_TAB; 803 mLastTabInx = STD_TAB; 804 mTabbedPane.setSelectedIndex(mLastTabInx); 805 } 806 807 } 808 809 /** 810 * Loads a Schema and a Query into the Builder 811 * 812 * @param aSchema 813 * The schema to be used 814 * @param aQueryDef 815 * the query def to be loaded (can be null) 816 */ 817 public void set(DSSchemaIFace aSchema, DBQueryDef aQueryDef) { 818 mQueryDef = aQueryDef; 819 loadSchemaIntoUI(aSchema); 820 if (mQueryDef != null) { 821 loadQuery(mQueryDef); 822 } else { 823 initializeBuilder(); 824 } 825 } 826 827 /** 828 * 829 * Opens a Query and loads into the builder 830 */ 831 public String openFile(String aTitle, String aFilterStr, String aFilterTitle) { 832 PtFileChooser chooser = new PtFileChooser(mFrame, "Open " + aTitle, JFileChooser.OPEN_DIALOG); 833 chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 834 chooser.setSelectedFile(null); 835 final DBFileFilter dbFileFilter = new DBFileFilter(aFilterStr, aFilterTitle); 836 chooser.addChoosableFileFilter(new PtFilenameFilter() { 837 @Override 838 public boolean accept(File file) { 839 return dbFileFilter.accept(file); 840 } 841 842 @Override 843 public boolean accept(File directory, String name) { 844 return dbFileFilter.accept(new File(directory, name)); 845 } 846 847 @Override 848 public String getDescription() { 849 return dbFileFilter.getDescription(); 850 } 851 }); 852 JComponent frame = this; 853 854 // clear the preview from the previous display of the chooser 855 int retval = chooser.showDialog(frame, "Open"); 856 if (retval == JFileChooser.APPROVE_OPTION) { 857 File theFile = chooser.getSelectedFile(); 858 if (theFile != null) { 859 if (theFile.isDirectory()) { 860 // JOptionPane.showMessageDialog(frame, 861 // "You chose this directory: " + theFile.getPath()); 862 } else { 863 return theFile.getPath(); 864 } 865 } 866 867 } else if (retval == JFileChooser.CANCEL_OPTION) { 868 // JOptionPane.showMessageDialog(frame, 869 // "User cancelled operation. No file was chosen."); 870 } else if (retval == JFileChooser.ERROR_OPTION) { 871 JOptionPane.showMessageDialog(frame, 872 "An error occured. No file was chosen."); 873 } else { 874 JOptionPane.showMessageDialog(frame, "Unknown operation occured."); 875 } 876 return null; 877 } 878 879 /** 880 * 881 * Opens a Query and loads into the builder 882 */ 883 public void openQueryFile() { 884 String path = openFile("Query", "query", "Query Files"); 885 if (path != null) { 886 mQueryDef = DBQueryDefParserEmitter.readQueryDef(mSchema, path); 887 if (mQueryDef == null) { 888 JOptionPane.showMessageDialog(this, DBQueryDefParserEmitter 889 .getErrorCodeText(), "Query Error", 890 JOptionPane.ERROR_MESSAGE); 891 } else { 892 mBuilderTab = null; // must be done here 893 loadQuery(mQueryDef); 894 } 895 } 896 } 897 898 /** 899 * 900 * Opens a Query and loads into the builder 901 */ 902 public void openSchemaFile() { 903 String path = openFile("Schema", "schema", "Schema Files"); 904 if (path != null) { 905 906 DSSchemaIFace schema = DBSchemaParserEmitter.readSchemaDef(path); 907 if (schema != null) { 908 mQueryDef = null; 909 loadSchemaIntoUI(schema); 910 initializeBuilder(); 911 } 912 } 913 } 914 915 /** 916 * Helper method 917 * 918 * @param aFileName 919 */ 920 private void runQueryTest(String aFileName) { 921 DBQueryDef queryDef = DBQueryDefParserEmitter.readQueryDef(mSchema, 922 aFileName); 923 System.err.print(aFileName + " - "); 924 System.err.println(queryDef == null ? DBQueryDefParserEmitter 925 .getErrorCodeText() : "OK"); 926 927 } 928 929 /** 930 * 931 * Loads various queries for testing the parser 932 */ 933 public void testQueries() { 934 String dirStr = "/home/globus/"; 935 936 runQueryTest(dirStr + "good.query"); 937 runQueryTest(dirStr + "join_fieldname_bad.query"); 938 // runQueryTest(dirStr + "join_tableid_bad.query"); 939 runQueryTest(dirStr + "join_tablename_bad.query"); 940 runQueryTest(dirStr + "select_fieldname_bad.query"); 941 runQueryTest(dirStr + "select_tablename_bad.query"); 942 runQueryTest(dirStr + "table_tablename_bad.query"); 943 runQueryTest(dirStr + "where_fieldname_bad.query"); 944 runQueryTest(dirStr + "where_tablename_bad.query"); 945 } 946 947 /** 948 * Returns the SQL in a TAB of the builder and sets it into the SQL Tab's 949 * readonly text editor 950 * 951 * @param aLastInx 952 * the last builder tab to be used 953 * @return the SQL string of that tab 954 */ 955 public String processTabForSQL(int aLastInx) { 956 switch (aLastInx) { 957 case 0: 958 return mStdSP.createSQL(); 959 960 // case 1 : 961 // return mInterSP.createSQL(); 962 963 // case 2 : 964 // return mAdvSP.createSQL(); 965 966 case SQL_TAB: 967 // should never get here 968 break; 969 } 970 return null; 971 } 972 973 /** 974 * Return the appropriate builder for a given tab index 975 * 976 * @param aTabIndex 977 * the tabe index 978 * @return the QBBuilderInterface object for the tab index 979 */ 980 private QBBuilderInterface getBuilderFromTabIndex(int aTabIndex) { 981 switch (aTabIndex) { 982 case 0: 983 return mStdSP; 984 // case 1 : return mInterSP; 985 // case 2 : return mAdvSP; 986 } 987 return null; 988 } 989 990 /** 991 * Process when TAB changes 992 */ 993 public void processTabChange() { 994 // Bail if there is no valid Query Obj 995 /* 996 * if (mQueryDef == null) { System.out.println("the mQueryDef= null"); 997 * return; } 998 */ 999 1000 if (mStdSP != null) { 1001 // System.out.println("clear the selection"); 1002 DBSelectTableUIBase table = mStdSP.getSelectedTableView(); 1003 if (table != null) { 1004 TableCellEditor editor = table.getCellEditor(); 1005 if (editor != null) { 1006 editor.stopCellEditing(); 1007 } 1008 } 1009 /* 1010 * int column = table.getSelectedColumn(); 1011 * System.out.println("selected column "+column); int row = 1012 * table.getSelectedRow(); System.out.println("selected row "+row); 1013 * Object obj = table.getModel().getValueAt(row, column); 1014 * System.out.println("!!!!!!!!!the selected value is "+obj); column 1015 * = table.getSelectedColumn(); 1016 * System.out.println("selected column "+column); row = 1017 * table.getSelectedRow(); table.getModel().setValueAt(obj, row, 1018 * column); 1019 * 1020 * obj = table.getModel().getValueAt(row, column); 1021 * System.out.println("!!!!!!!!!the selected value is "+obj); 1022 * table.transferFocus(); 1023 */ 1024 1025 } 1026 1027 // This can happen if the user clicks to the SQL tab and 1028 // then back to the same tab as before 1029 // 1030 // So we do not try to process (or convert) the Query from one tab to 1031 // the next 1032 if (mLastTabInx == mTabInx) { 1033 return; 1034 } 1035 1036 if (mTabInx == SQL_TAB) { 1037 mSQLSP.setText(processTabForSQL(mLastTabInx)); 1038 return; 1039 } 1040 1041 // System.out.println("mTableInx is "+mTabInx); 1042 QBBuilderInterface newBldr = getBuilderFromTabIndex(mTabInx); 1043 // System.out.println("newbldr is "+newBldr); 1044 1045 boolean cachedIsChanged = false; 1046 boolean doSwitch = true; 1047 if (!mBuilderTab.canConvertTo(newBldr)) { 1048 String msg = "Data Loss will occur for this query when switching to from " 1049 + mBuilderTab.getName() + " to " + newBldr.getName(); 1050 Object[] options = { "Continue", "Do Not Switch" }; 1051 int option = JOptionPane.showOptionDialog(null, msg, 1052 "Switching Error", JOptionPane.YES_NO_OPTION, 1053 JOptionPane.WARNING_MESSAGE, null, options, options[0]); 1054 1055 if (option == JOptionPane.NO_OPTION) { 1056 mTabInx = mBuilderTab.getType(); 1057 mTabbedPane.setSelectedIndex(mTabInx); 1058 doSwitch = false; 1059 } 1060 1061 } 1062 1063 if (doSwitch) { 1064 mTabInx = newBldr.getType(); 1065 cachedIsChanged = true; 1066 mQueryDef = new DBQueryDef(); 1067 1068 mBuilderTab.fillQueryDef(mQueryDef); 1069 newBldr.buildFromQueryDef(mQueryDef); 1070 1071 mBuilderTab = newBldr; 1072 1073 mTabbedPane.setSelectedIndex(mTabInx); 1074 } 1075 1076 setIsChanged(cachedIsChanged); 1077 // setStatus(mIsChanged? CHANGED_MSG : msgStr); 1078 1079 } 1080 1081 /** 1082 * @return whether the SQL tab is the current Tab 1083 */ 1084 public boolean isSQLTab() { 1085 return mTabInx == SQL_TAB; 1086 } 1087 1088 /** 1089 * 1090 * @return the SQL string for the "current" or more recent builder tab 1091 */ 1092 public String getSQLString() { 1093 return ""; 1094 } 1095 1096 // ******************************************************* 1097 // ****************** Runnables *********************** 1098 // ******************************************************* 1099 1100 /** 1101 * Generic QBApp runnable. This is intended to run on the AWT gui event 1102 * thread so as not to muck things up by doing gui work off the gui thread. 1103 * Accepts a QBApp and an Object as arguments, which gives subtypes of this 1104 * class the two "must haves" needed in most runnables for this demo. 1105 */ 1106 class QBAppRunnable implements Runnable { 1107 1108 protected QBApp mQBApp; 1109 1110 protected Object obj; 1111 1112 public QBAppRunnable(QBApp aQBApp, Object obj) { 1113 this.mQBApp = aQBApp; 1114 this.obj = obj; 1115 } 1116 1117 public void run() { 1118 } 1119 } 1120 1121 // ******************************************************* 1122 // ******************** Actions *********************** 1123 // ******************************************************* 1124 1125 class GenericMenuAction extends AbstractAction { 1126 public static final int OPEN_QUERY_ACTION = 0; 1127 public static final int SAVE_QUERY_ACTION = 1; 1128 public static final int OPEN_SCHEMA_ACTION = 2; 1129 public static final int SAVE_SCHEMA_ACTION = 3; 1130 public static final int EXIT_ACTION = 4; 1131 public static final int QUERY_TESTS_ACTION = 5; 1132 1133 QBApp mQueryBuilder; 1134 int mActionType; 1135 1136 protected GenericMenuAction(QBApp aQBApp, int aActionType) { 1137 super("Action"); 1138 mQueryBuilder = aQBApp; 1139 mActionType = aActionType; 1140 } 1141 1142 public void actionPerformed(ActionEvent e) { 1143 switch (mActionType) { 1144 case OPEN_QUERY_ACTION: 1145 mQueryBuilder.openQueryFile(); 1146 break; 1147 case SAVE_QUERY_ACTION: 1148 mQueryBuilder.saveQueryFile(); 1149 break; 1150 case OPEN_SCHEMA_ACTION: 1151 mQueryBuilder.openSchemaFile(); 1152 break; 1153 case SAVE_SCHEMA_ACTION: 1154 mQueryBuilder.saveSchemaFile(); 1155 break; 1156 case EXIT_ACTION: { 1157 System.out.println("here!!!!!!!!!!!11"); 1158 if (mIsChanged) { 1159 int x0 = JOptionPane.CLOSED_OPTION; 1160 int x1 = JOptionPane.YES_OPTION; 1161 int x2 = JOptionPane.NO_OPTION; 1162 int x3 = JOptionPane.OK_OPTION; 1163 int x4 = JOptionPane.CLOSED_OPTION; 1164 Object[] options = { "Discard and Exit", "Save and Exit", 1165 "Cancel" }; 1166 String msg = "You have changed the query, do you wish to save it before exiting?"; 1167 int option = JOptionPane.showOptionDialog(null, msg, 1168 "Exiting", JOptionPane.DEFAULT_OPTION, 1169 JOptionPane.WARNING_MESSAGE, null, options, 1170 options[1]); 1171 System.out.println("the option chose is " + option); 1172 if (option == JOptionPane.NO_OPTION) { 1173 mQueryBuilder.saveQueryFile(); 1174 } else if (option == 2) { 1175 return; 1176 } 1177 } 1178 System.exit(0); 1179 } 1180 break; 1181 case QUERY_TESTS_ACTION: 1182 mQueryBuilder.testQueries(); 1183 break; 1184 } 1185 1186 } 1187 } 1188 1189 class CancelAction extends AbstractAction { 1190 QBEditor frame; 1191 1192 protected CancelAction(QBEditor frame) { 1193 super("Cancel"); 1194 this.frame = frame; 1195 } 1196 1197 public void actionPerformed(ActionEvent e) { 1198 if (frame != null) { 1199 frame.closeWindows(); 1200 } 1201 1202 // System.exit(0); 1203 1204 } 1205 } 1206 1207 class OKAction extends AbstractAction { 1208 1209 QBEditor frame; 1210 1211 protected OKAction(QBEditor frame) { 1212 super("OK"); 1213 this.frame = frame; 1214 1215 } 1216 1217 public void actionPerformed(ActionEvent e) { 1218 if (frame != null) { 1219 if (mStdSP != null) { 1220 1221 DBSelectTableUIBase table = mStdSP.getSelectedTableView(); 1222 if (table != null) { 1223 TableCellEditor editor = table.getCellEditor(); 1224 if (editor != null) { 1225 editor.stopCellEditing(); 1226 } 1227 } 1228 } 1229 1230 frame.save(); 1231 } 1232 1233 } 1234 } 1235 1236 // ----------------------------------------------------------------------------- 1237 // -- ChangeListener Interface 1238 // ----------------------------------------------------------------------------- 1239 1240 /** 1241 * Notify when TAB changes 1242 */ 1243 public void stateChanged(ChangeEvent e) { 1244 if (mTabInx != SQL_TAB) { 1245 mLastTabInx = mTabInx; 1246 } 1247 1248 SingleSelectionModel model = (SingleSelectionModel) e.getSource(); 1249 mTabInx = model.getSelectedIndex(); 1250 1251 processTabChange(); 1252 } 1253 1254 // ----------------------------------------------------------------------------- 1255 // -- TableModelListener Interface 1256 // ----------------------------------------------------------------------------- 1257 1258 public void tableChanged(TableModelEvent e) { 1259 setIsChanged(true); 1260 setStatus(CHANGED_MSG); 1261 if (mExternalTMListener != null) { 1262 mExternalTMListener.tableChanged(e); 1263 } 1264 } 1265 1266 // ----------------------------------------------------------------------------- 1267 // -- Application MAIN 1268 // ----------------------------------------------------------------------------- 1269 1270 /** 1271 * QBApp Main. Called only if we're an application, not an applet. 1272 */ 1273 public static void main(String[] args) { 1274 // Create QBApp on the default monitor 1275 QBApp qbApp = new QBApp(null, GraphicsEnvironment 1276 .getLocalGraphicsEnvironment().getDefaultScreenDevice() 1277 .getDefaultConfiguration()); 1278 } 1279 1280}