1 package com.explosion.datastream.exql.gui.dbbrowser;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
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
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
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
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
437 this.browser.setCurrentNode((ExqlTreeNode)object);
438 browser.getTool().getViewer().update();
439 }
440 }
441
442 }
443 }
444 }
445 }
446 }