001    /*
002    // $Id: //open/mondrian/src/main/mondrian/gui/JDBCTreeModel.java#6 $
003    // This software is subject to the terms of the Common Public License
004    // Agreement, available at the following URL:
005    // http://www.opensource.org/licenses/cpl.html.
006    // Copyright (C) 2002-2007 Julian Hyde and others
007    // All Rights Reserved.
008    // You must accept the terms of that agreement to use this software.
009    */
010    package mondrian.gui;
011    
012    import javax.swing.event.TreeModelListener;
013    import javax.swing.tree.TreePath;
014    import java.sql.Connection;
015    import java.sql.DatabaseMetaData;
016    import java.sql.ResultSet;
017    import java.util.ArrayList;
018    import java.util.List;
019    import java.util.Vector;
020    
021    import org.apache.log4j.Logger;
022    
023    /**
024     *
025     * @author  sean
026     * @version $Id: //open/mondrian/src/main/mondrian/gui/JDBCTreeModel.java#6 $
027     */
028    public class JDBCTreeModel implements javax.swing.tree.TreeModel {
029    
030        private static final Logger LOGGER = Logger.getLogger(JDBCTreeModel.class);
031    
032        private Vector treeModelListeners = new Vector();
033        Connection connection;
034        DatabaseMetaData metadata;
035        List catalogs;
036        Node root;
037    
038        /** Creates a new instance of JDBCTreeModel */
039        public JDBCTreeModel(Connection c) {
040            connection = c;
041            try {
042                metadata = connection.getMetaData();
043                catalogs = new ArrayList();
044                String catalogName = connection.getCatalog();
045                Node cat = new Node(catalogName, Node.CATALOG);
046    
047                ResultSet trs = metadata.getTables(cat.name, null, null, null);
048                while (trs.next()) {
049                    Node table = new Node(trs.getString(3), Node.TABLE);
050                    cat.children.add(table);
051                    //get the tables for each catalog.
052                    ResultSet crs = metadata.getColumns(cat.name, null, table.name, null);
053                    while (crs.next()) {
054                        Node column = new Node(crs.getString(4), Node.COLUMN);
055                        table.children.add(column);
056                    }
057                }
058                root = cat;
059    
060            } catch (Exception ex) {
061                LOGGER.error("JDBCTreeModel", ex);
062            }
063        }
064    
065    
066        /** Adds a listener for the <code>TreeModelEvent</code>
067         * posted after the tree changes.
068         *
069         * @param   l       the listener to add
070         * @see     #removeTreeModelListener
071         *
072         */
073        public void addTreeModelListener(TreeModelListener l) {
074            treeModelListeners.add(l);
075        }
076    
077        /** Returns the child of <code>parent</code> at index <code>index</code>
078         * in the parent's
079         * child array.  <code>parent</code> must be a node previously obtained
080         * from this data source. This should not return <code>null</code>
081         * if <code>index</code>
082         * is a valid index for <code>parent</code> (that is <code>index >= 0 &&
083         * index < getChildCount(parent</code>)).
084         *
085         * @param   parent  a node in the tree, obtained from this data source
086         * @return  the child of <code>parent</code> at index <code>index</code>
087         *
088         */
089        public Object getChild(Object parent, int index) {
090            if (parent instanceof Node) {
091                return ((Node)parent).children.get(index);
092            }
093    
094            return null;
095        }
096    
097        /** Returns the number of children of <code>parent</code>.
098         * Returns 0 if the node
099         * is a leaf or if it has no children.  <code>parent</code> must be a node
100         * previously obtained from this data source.
101         *
102         * @param   parent  a node in the tree, obtained from this data source
103         * @return  the number of children of the node <code>parent</code>
104         *
105         */
106        public int getChildCount(Object parent) {
107            if (parent instanceof Node) {
108                return ((Node)parent).children.size();
109            }
110            return 0;
111        }
112    
113        /** Returns the index of child in parent.  If <code>parent</code>
114         * is <code>null</code> or <code>child</code> is <code>null</code>,
115         * returns -1.
116         *
117         * @param parent a note in the tree, obtained from this data source
118         * @param child the node we are interested in
119         * @return the index of the child in the parent, or -1 if either
120         *    <code>child</code> or <code>parent</code> are <code>null</code>
121         *
122         */
123        public int getIndexOfChild(Object parent, Object child) {
124           if (parent instanceof Node) {
125                return ((Node)parent).children.indexOf(child);
126           }
127    
128           return -1;
129        }
130    
131        /** Returns the root of the tree.  Returns <code>null</code>
132         * only if the tree has no nodes.
133         *
134         * @return  the root of the tree
135         *
136         */
137        public Object getRoot() {
138            return root;
139        }
140    
141        /** Returns <code>true</code> if <code>node</code> is a leaf.
142         * It is possible for this method to return <code>false</code>
143         * even if <code>node</code> has no children.
144         * A directory in a filesystem, for example,
145         * may contain no files; the node representing
146         * the directory is not a leaf, but it also has no children.
147         *
148         * @param   node  a node in the tree, obtained from this data source
149         * @return  true if <code>node</code> is a leaf
150         *
151         */
152        public boolean isLeaf(Object node) {
153            return getChildCount(node) == 0;
154        }
155    
156        /** Removes a listener previously added with
157         * <code>addTreeModelListener</code>.
158         *
159         * @see     #addTreeModelListener
160         * @param   l       the listener to remove
161         *
162         */
163        public void removeTreeModelListener(TreeModelListener l) {
164            treeModelListeners.remove(l);
165        }
166    
167        /** Messaged when the user has altered the value for the item identified
168         * by <code>path</code> to <code>newValue</code>.
169         * If <code>newValue</code> signifies a truly new value
170         * the model should post a <code>treeNodesChanged</code> event.
171         *
172         * @param path path to the node that the user has altered
173         * @param newValue the new value from the TreeCellEditor
174         *
175         */
176        public void valueForPathChanged(TreePath path, Object newValue) {
177        }
178    
179        class Node {
180            static final int CATALOG = 0;
181            static final int TABLE = 1;
182            static final int COLUMN = 2;
183            String name;
184            int type;
185            ArrayList children;
186    
187            public Node(String n, int t) {
188                name = n;
189                type = t;
190                children = new ArrayList();
191            }
192    
193            public String toString() {
194                return name;
195            }
196        }
197    }
198    
199    // End JDBCTreeModel.java