View Javadoc

1   package com.explosion.datastream.exql.gui.dbbrowser;
2   
3   /*
4    * =============================================================================
5    * 
6    * Copyright 2004 Stephen Cowx
7    * 
8    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
9    * use this file except in compliance with the License. You may obtain a copy of
10   * the License at
11   * 
12   * http://www.apache.org/licenses/LICENSE-2.0
13   * 
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   * 
20   * =============================================================================
21   */
22  
23  import java.awt.BorderLayout;
24  import java.awt.Color;
25  import java.awt.Font;
26  import java.awt.event.MouseAdapter;
27  import java.awt.event.MouseEvent;
28  import java.sql.Connection;
29  
30  import javax.swing.JOptionPane;
31  import javax.swing.JPanel;
32  import javax.swing.JScrollPane;
33  import javax.swing.JTree;
34  import javax.swing.tree.TreePath;
35  
36  import com.explosion.datastream.exql.EXQLConstants;
37  import com.explosion.datastream.exql.EXQLModuleManager;
38  import com.explosion.datastream.exql.gui.EXQLBaseTool;
39  import com.explosion.datastream.exql.gui.ExqlTree;
40  import com.explosion.datastream.exql.gui.ExqlTreeNode;
41  import com.explosion.datastream.exql.gui.MetaDataTreeCellRenderer;
42  import com.explosion.datastream.exql.processes.RefreshCatalogsAndSchemasProcess;
43  import com.explosion.datastream.exql.processes.RefreshTableInformationProcess;
44  import com.explosion.datastream.exql.processes.RefreshTableNamesProcess;
45  import com.explosion.datastream.exql.processes.RefreshTopNodesProcess;
46  import com.explosion.expf.Application;
47  import com.explosion.expfmodules.rdbmsconn.ConnectionDescriptorPreference;
48  import com.explosion.expfmodules.rdbmsconn.RdbmsConnConstants;
49  import com.explosion.expfmodules.rdbmsconn.RdbmsConnModuleManager;
50  import com.explosion.expfmodules.rdbmsconn.connect.ConnectionManager;
51  import com.explosion.expfmodules.rdbmsconn.dbom.DBEntity;
52  import com.explosion.expfmodules.rdbmsconn.dbom.EntityMetaData;
53  import com.explosion.utilities.exception.ExceptionManagerFactory;
54  import com.explosion.utilities.preferences.Preference;
55  import com.explosion.utilities.preferences.groups.PreferenceGroup;
56  import com.explosion.utilities.process.ProcessMonitoringStatusBar;
57  import com.explosion.utilities.process.threads.Finishable;
58  import com.explosion.utilities.process.threads.SimpleProcess;
59  
60  public class DBEntityBrowser extends JPanel implements Finishable
61  {
62  
63      private ExqlTreeNode root;
64      private ExqlTree tree;
65      private JScrollPane pane;
66      private MetaDataTreeCellRenderer renderer;
67      private ProcessMonitoringStatusBar monitoringStatusBar;
68      private PreferenceGroup connectionDescriptor;
69      private int connectionKey = 0;
70      private Connection conn;
71      private EXQLBaseTool tool;
72      private ExqlTreeNode currentNode;
73  
74      public DBEntityBrowser(EXQLBaseTool tool, int connectionKey, ProcessMonitoringStatusBar monitoringStatusBar)
75      {
76          try
77          {
78              this.tool = tool;
79              this.connectionKey = connectionKey;
80              this.monitoringStatusBar = monitoringStatusBar;
81              this.conn = ConnectionManager.getInstance().getConnection(connectionKey);
82              init();
83          } catch (Exception e)
84          {
85              ExceptionManagerFactory.getExceptionManager().manageException(e, "Exception caught while constructing Database MetaData Builder");
86          }
87      }
88          
89      /***
90       *  
91       */
92      public void init() throws Exception
93      {
94          this.setLayout(new BorderLayout());
95          this.setBorder(null);
96          pane = new JScrollPane();
97          pane.setBorder(null);
98          
99          this.add(pane, BorderLayout.CENTER);
100 
101         /* Perform some initialisations */
102         renderer = new MetaDataTreeCellRenderer(this);
103 
104         connectionDescriptor = ConnectionManager.getInstance().getConnectionDescriptor(connectionKey);
105         root = new ExqlTreeNode(connectionDescriptor.getIdentifier());
106 
107         tree = new ExqlTree(root, tool);
108         tree.setBorder(null);
109         
110         tree.setCellRenderer(renderer);
111         pane.getViewport().add(tree);
112        
113         tree.addMouseListener(new TreeMouseListener(this, tree));
114     }
115 
116     /***
117      * Refreshes the metadata tree
118      */
119     public void refresh() throws Exception
120     {
121         ExqlTreeNode node = (ExqlTreeNode) tree.getLastSelectedPathComponent();
122         
123         ConnectionDescriptorPreference driver = (ConnectionDescriptorPreference) connectionDescriptor.getPreference(RdbmsConnConstants.CD_DRIVER);
124         boolean supportsNamespaces = getSupportsNamespaces(driver);
125         
126         if (node == null)
127         {
128             if (supportsNamespaces)
129                 refreshTopNodes();
130              else
131                  refreshTableNames((ExqlTreeNode) tree.getModel().getRoot(), new DBEntity(null,null,null,DBEntity.TYPE_SCHEMA));
132              return;
133         }
134 
135         Object nodeInfo = node.getUserObject();
136         if (node.isRoot())
137         {
138             try
139             {
140                 if (supportsNamespaces)
141                     refreshTopNodes();
142                 else
143                      refreshTableNames((ExqlTreeNode) tree.getModel().getRoot(), new DBEntity(null,null,null,DBEntity.TYPE_SCHEMA));
144                 return;
145                  
146             } catch (Exception ex)
147             {
148                 ExceptionManagerFactory.getExceptionManager().manageException(ex, "Exception caught while refreshing meta data.");
149             }
150         } 
151         else if (nodeInfo instanceof DBEntity)
152         {
153             DBEntity dbed = (DBEntity) nodeInfo;
154             if (dbed.getEntityType() == DBEntity.TYPE_SCHEMA || dbed.getEntityType() == DBEntity.TYPE_CATALOG)
155             {
156                 refreshTableNames(node, dbed);
157             }
158         } 
159     }
160 
161     /***
162      * Returns a boolean value stating whether or not this driver supports namespaces
163      * @param driver
164      * @param supportsNamespaces
165      * @return
166      */
167     private boolean getSupportsNamespaces(ConnectionDescriptorPreference driver)
168     {
169         PreferenceGroup group = RdbmsConnModuleManager.instance().getDriverDescriptorManager().getGroup((String)driver.getValue());
170         return ((Boolean)((Preference)group.getPreference(RdbmsConnConstants.DRVR_DB_SUPPORTS_NAMESPACES)).getValue()).booleanValue();
171     }
172 
173     /***
174      * This method refreshes the tables names for the schema / catalog provided in the 
175      * descriptor
176      * @param node
177      * @param descriptor
178      */
179     protected void refreshTableNames(ExqlTreeNode node, DBEntity descriptor)
180     {
181         try
182         {
183             boolean getFullTableInfo = ((Boolean)EXQLModuleManager.instance().getPreference(EXQLConstants.RDBMS_OPTION_FULL_TABLE_INFO_ON_STARTUP).getValue()).booleanValue();
184             RefreshTableNamesProcess process = new RefreshTableNamesProcess(this, conn, node, descriptor, tool, getFullTableInfo);
185             monitoringStatusBar.setProcessToMonitor(process);
186             monitoringStatusBar.setProgressBarEnabled(false);
187             monitoringStatusBar.startProcess();
188         } catch (Exception ex)
189         {
190             ExceptionManagerFactory.getExceptionManager().manageException(ex, "Exception caught while fetching tables.");
191         }
192     }
193 
194     private void refreshTopNodes() throws Exception
195     {
196         RefreshTopNodesProcess process = new RefreshTopNodesProcess(this, conn, root, tool);
197         monitoringStatusBar.setProcessToMonitor(process);
198         monitoringStatusBar.setProgressBarEnabled(false);
199         monitoringStatusBar.startProcess();
200 
201         restoreDefaultStatus();
202     }
203 
204     private void refreshSchemasAndcatalogs() throws Exception
205     {
206         RefreshCatalogsAndSchemasProcess process = new RefreshCatalogsAndSchemasProcess(this, null, conn, root, tool);
207         monitoringStatusBar.setProcessToMonitor(process);
208         monitoringStatusBar.setProgressBarEnabled(false);
209         monitoringStatusBar.startProcess();
210 
211         restoreDefaultStatus();
212     }
213     
214     protected void refreshEntityInformationAndWaitForCompletion(TabularDataView viewer, ExqlTreeNode node, DBEntity descriptor)
215     {
216         viewer.getDataTable().setEnabled(false);
217         tool.disableComponent();
218         
219         SimpleProcess process = refreshEntityInformation(node, descriptor);
220         if (process != null)
221         {
222             try
223             {
224                 while (process.getPercentComplete() < 100)
225                     Thread.sleep(2);
226             }
227             catch (InterruptedException e1)
228             {
229                ExceptionManagerFactory.getExceptionManager().manageException(e1,"Exception caught while waiting for metadata to be returned.");
230             }
231         }
232     }
233     
234     /***
235      * This method refreshes the tables names for the schema / catalog provided in the 
236      * descriptor
237      * @param node
238      * @param descriptor
239      */
240     protected SimpleProcess refreshEntityInformation(ExqlTreeNode node, DBEntity descriptor)
241     {
242         try
243         {
244             descriptor.clearMetadata();
245             RefreshTableInformationProcess process = new RefreshTableInformationProcess(this, conn, node, descriptor, tool);
246             monitoringStatusBar.setProcessToMonitor(process);
247             monitoringStatusBar.setProgressBarEnabled(false);
248             monitoringStatusBar.startProcess();
249             return monitoringStatusBar;
250         } catch (Exception ex)
251         {
252             ExceptionManagerFactory.getExceptionManager().manageException(ex, "Exception caught while fetching entity information.");
253         }
254         return null;
255     }
256 
257     /***
258      * returns a DBEntity if the selected item in the tree is a table a view or
259      * a synonym
260      */
261     public DBEntity getSelectedTableEntityDescriptor()
262     {
263         ExqlTreeNode node = (ExqlTreeNode) tree.getLastSelectedPathComponent();
264 
265         if (node == null)
266             return null;
267 
268         Object nodeInfo = node.getUserObject();
269         if (nodeInfo instanceof DBEntity)
270         {
271             DBEntity dbed = (DBEntity) nodeInfo;
272             if (dbed.getEntityType() == DBEntity.TYPE_TABLE || dbed.getEntityType() == DBEntity.TYPE_SYNONYM || dbed.getEntityType() == DBEntity.TYPE_SYSTEM_TABLE
273                     || dbed.getEntityType() == DBEntity.TYPE_VIEW) {
274 
275             return dbed; }
276         }
277 
278         return null;
279     }
280 
281     public void finish()
282     {
283         //tree.setModel(new DefaultTreeModel(root));
284         tree.updateUI();
285     }
286 
287     public void restoreDefaultStatus()
288     {
289         monitoringStatusBar.setStatusText("Connected to " + connectionDescriptor.getIdentifier());
290     }
291 
292     /***
293      * This method returns the tree object.
294      */
295     public JTree getMetaDataTree()
296     {
297         return tree;
298     }
299 
300     /***
301      * Applies the properties for this tool;
302      */
303     public void applyPreferences()
304     {
305         renderer.setForeground((Color) EXQLModuleManager.instance().getPreference(EXQLConstants.BROWSER_COLORS_FOREGROUND).getValue());
306         renderer.setBackground((Color) EXQLModuleManager.instance().getPreference(EXQLConstants.BROWSER_COLORS_BACKGROUND).getValue());
307         renderer.setTextNonSelectionColor((Color) EXQLModuleManager.instance().getPreference(EXQLConstants.BROWSER_COLORS_FOREGROUND).getValue());
308         renderer.setTextSelectionColor((Color) EXQLModuleManager.instance().getPreference(EXQLConstants.BROWSER_COLOR_SELECTEDFORGROUND).getValue());
309         renderer.setBackgroundNonSelectionColor((Color) EXQLModuleManager.instance().getPreference(EXQLConstants.BROWSER_COLORS_BACKGROUND).getValue());
310         renderer.setBackgroundSelectionColor((Color) EXQLModuleManager.instance().getPreference(EXQLConstants.BROWSER_COLOR_SELECTEDBACKGROUND).getValue());
311 
312         pane.setForeground((Color) EXQLModuleManager.instance().getPreference(EXQLConstants.BROWSER_COLORS_FOREGROUND).getValue());
313         pane.setBackground((Color) EXQLModuleManager.instance().getPreference(EXQLConstants.BROWSER_COLORS_BACKGROUND).getValue());
314 
315         tree.setForeground((Color) EXQLModuleManager.instance().getPreference(EXQLConstants.BROWSER_COLORS_FOREGROUND).getValue());
316         tree.setBackground((Color) EXQLModuleManager.instance().getPreference(EXQLConstants.BROWSER_COLORS_BACKGROUND).getValue());
317         //if (!EXQLModuleManager.instance().getPreference(EXQLConstants.BROWSER_FONT).isDefaulted())
318             tree.setFont((Font) EXQLModuleManager.instance().getPreference(EXQLConstants.BROWSER_FONT).getValue());
319     }
320 
321     public ProcessMonitoringStatusBar getProcessMonitoringStatusBar()
322     {
323         return this.monitoringStatusBar;
324     }
325 
326     /***
327      * Returns the conn.
328      * 
329      * @return Connection
330      */
331     public Connection getConnection()
332     {
333         return conn;
334     }
335 
336     /***
337      * Returns the tree.
338      * 
339      * @return JTree
340      */
341     public JTree getTree()
342     {
343         return tree;
344     }
345 
346     public void disableComponent()
347     {
348         tree.setEnabled(false);
349     }
350 
351     public void enableComponent()
352     {
353         tree.setEnabled(true);
354     }
355     
356     public EXQLBaseTool getTool()
357     {
358         return tool;
359     }
360     
361     /***
362 	 * @return Returns the currentNode.
363 	 */
364 	public ExqlTreeNode getCurrentNode() {
365 		return currentNode;
366 	}
367 	
368 	/***
369 	 * @param currentNode The currentNode to set.
370 	 */
371 	public void setCurrentNode(ExqlTreeNode currentNode) {
372 		this.currentNode = currentNode;
373 	}
374 }
375 
376 /***
377  * This class listens for changes in the tree.
378  * @author Stephen Cowx
379  * Created on 19-Nov-2004
380  */
381 class TreeMouseListener extends MouseAdapter
382 {
383 
384     private DBEntityBrowser browser;
385     private JTree tree;
386     private TreePath  lastSelectedTableNodeTreePath;
387    
388     public TreeMouseListener(DBEntityBrowser browser, JTree tree)
389     {
390         this.browser = browser;
391         this.tree = tree;
392     }
393 
394     public void mousePressed(MouseEvent e)
395     {
396         int selRow = tree.getRowForLocation(e.getX(), e.getY());
397         TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
398         if (selRow != -1)
399         {
400             if (e.getClickCount() == 2)
401             {
402                 Object object = selPath.getLastPathComponent();
403                 if (object != null && object instanceof ExqlTreeNode)
404                 {
405 
406                     if (((ExqlTreeNode) object).getUserObject() instanceof DBEntity)
407                     {
408                         /* Do we really want to do this ? */
409                         if (browser.getTool().getViewer().getView().getDataTable().isDirty())
410                         {
411                             int decision = JOptionPane.showConfirmDialog(Application.getApplicationFrame(),"Uncommitted changes have taken place.  Do you want to discard changes and continue ?","Uncommitted changes",JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE);
412                             if (decision == JOptionPane.NO_OPTION)
413                             {
414                                tree.setSelectionPath(lastSelectedTableNodeTreePath);
415                                e.consume();
416                                return;
417                             }  
418                         }
419                         
420                         DBEntity descriptor = (DBEntity) ((ExqlTreeNode) object).getUserObject();
421                         EntityMetaData metadata = new EntityMetaData();
422                         browser.getTool().setCurrentEntityMetaData(metadata);
423                         metadata.setDbEntity(descriptor);
424                         
425                         if (descriptor.getEntityType() == DBEntity.TYPE_SCHEMA || descriptor.getEntityType() == DBEntity.TYPE_CATALOG)
426                         {
427                             browser.refreshTableNames((ExqlTreeNode) object, descriptor);
428                             lastSelectedTableNodeTreePath = selPath;
429                         }
430                         else if ( descriptor.getEntityType() == DBEntity.TYPE_TABLE ||
431                                 descriptor.getEntityType() == DBEntity.TYPE_SYNONYM ||
432                                 descriptor.getEntityType() == DBEntity.TYPE_SYSTEM_TABLE||
433                                 descriptor.getEntityType() == DBEntity.TYPE_VIEW )
434                         {
435                             lastSelectedTableNodeTreePath = selPath;
436                             //browser.refreshEntityInformationAndWaitForCompletion(browser.getTool().getViewer().getView(), (ExqlTreeNode) object, descriptor);
437                             this.browser.setCurrentNode((ExqlTreeNode)object);
438                             browser.getTool().getViewer().update();
439                         }
440                     }
441 
442                 }
443             }
444         }
445     }
446 }