/*
// This software is subject to the terms of the Eclipse Public License v1.0
// Agreement, available at the following URL:
// http://www.eclipse.org/legal/epl-v10.html.
// You must accept the terms of that agreement to use this software.
//
// Copyright (C) 2002-2005 Julian Hyde
// Copyright (C) 2005-2009 Pentaho and others
// All Rights Reserved.
*/
package mondrian.gui;
import org.apache.log4j.Logger;
import java.sql.*;
import java.util.*;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreePath;
/**
*
* @author sean
*/
public class JdbcTreeModel implements javax.swing.tree.TreeModel {
private static final Logger LOGGER = Logger.getLogger(JdbcTreeModel.class);
private Vector treeModelListeners = new Vector();
Connection connection;
DatabaseMetaData metadata;
List catalogs;
Node root;
/** Creates a new instance of JDBCTreeModel */
public JdbcTreeModel(Connection c) {
connection = c;
try {
metadata = connection.getMetaData();
catalogs = new ArrayList();
String catalogName = connection.getCatalog();
Node cat = new Node(catalogName, Node.CATALOG);
ResultSet trs = metadata.getTables(cat.name, null, null, null);
try {
while (trs.next()) {
// Oracle 10g Driver returns bogus BIN$ tables that cause
// exceptions
String tbname = trs.getString("TABLE_NAME");
if (!tbname.matches("(?!BIN\\$).+")) {
continue;
}
Node table = new Node(trs.getString(3), Node.TABLE);
cat.children.add(table);
//get the tables for each catalog.
ResultSet crs =
metadata.getColumns(cat.name, null, table.name, null);
try {
while (crs.next()) {
Node column =
new Node(crs.getString(4), Node.COLUMN);
table.children.add(column);
}
} finally {
try {
if (crs != null) {
crs.close();
}
} catch (Exception e) {
// ignore
}
}
}
} finally {
try {
if (trs != null) {
trs.close();
}
} catch (Exception e) {
// ignore
}
}
root = cat;
} catch (Exception ex) {
LOGGER.error("JdbcTreeModel", ex);
}
}
/** Adds a listener for the <code>TreeModelEvent</code>
* posted after the tree changes.
*
* @param l the listener to add
* @see #removeTreeModelListener
*
*/
public void addTreeModelListener(TreeModelListener l) {
treeModelListeners.add(l);
}
/** Returns the child of <code>parent</code> at index <code>index</code>
* in the parent's
* child array. <code>parent</code> must be a node previously obtained
* from this data source. This should not return <code>null</code>
* if <code>index</code>
* is a valid index for <code>parent</code> (that is <code>index >= 0 &&
* index < getChildCount(parent</code>)).
*
* @param parent a node in the tree, obtained from this data source
* @return the child of <code>parent</code> at index <code>index</code>
*
*/
public Object getChild(Object parent, int index) {
if (parent instanceof Node) {
return ((Node)parent).children.get(index);
}
return null;
}
/** Returns the number of children of <code>parent</code>.
* Returns 0 if the node
* is a leaf or if it has no children. <code>parent</code> must be a node
* previously obtained from this data source.
*
* @param parent a node in the tree, obtained from this data source
* @return the number of children of the node <code>parent</code>
*
*/
public int getChildCount(Object parent) {
if (parent instanceof Node) {
return ((Node)parent).children.size();
}
return 0;
}
/** Returns the index of child in parent. If <code>parent</code>
* is <code>null</code> or <code>child</code> is <code>null</code>,
* returns -1.
*
* @param parent a note in the tree, obtained from this data source
* @param child the node we are interested in
* @return the index of the child in the parent, or -1 if either
* <code>child</code> or <code>parent</code> are <code>null</code>
*
*/
public int getIndexOfChild(Object parent, Object child) {
if (parent instanceof Node) {
return ((Node)parent).children.indexOf(child);
}
return -1;
}
/** Returns the root of the tree. Returns <code>null</code>
* only if the tree has no nodes.
*
* @return the root of the tree
*
*/
public Object getRoot() {
return root;
}
/** Returns <code>true</code> if <code>node</code> is a leaf.
* It is possible for this method to return <code>false</code>
* even if <code>node</code> has no children.
* A directory in a filesystem, for example,
* may contain no files; the node representing
* the directory is not a leaf, but it also has no children.
*
* @param node a node in the tree, obtained from this data source
* @return true if <code>node</code> is a leaf
*
*/
public boolean isLeaf(Object node) {
return getChildCount(node) == 0;
}
/** Removes a listener previously added with
* <code>addTreeModelListener</code>.
*
* @see #addTreeModelListener
* @param l the listener to remove
*
*/
public void removeTreeModelListener(TreeModelListener l) {
treeModelListeners.remove(l);
}
/** Messaged when the user has altered the value for the item identified
* by <code>path</code> to <code>newValue</code>.
* If <code>newValue</code> signifies a truly new value
* the model should post a <code>treeNodesChanged</code> event.
*
* @param path path to the node that the user has altered
* @param newValue the new value from the TreeCellEditor
*
*/
public void valueForPathChanged(TreePath path, Object newValue) {
}
class Node {
static final int CATALOG = 0;
static final int TABLE = 1;
static final int COLUMN = 2;
String name;
int type;
ArrayList children;
public Node(String n, int t) {
name = n;
type = t;
children = new ArrayList();
}
public String toString() {
return name;
}
}
}
// End JdbcTreeModel.java