001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2002-2005 Julian Hyde
008// Copyright (C) 2005-2009 Pentaho and others
009// All Rights Reserved.
010*/
011package mondrian.gui;
012
013import mondrian.gui.JdbcMetaData.DbColumn;
014
015import org.apache.log4j.Logger;
016
017import java.util.Enumeration;
018import java.util.List;
019import javax.swing.event.TreeExpansionEvent;
020import javax.swing.event.TreeWillExpandListener;
021import javax.swing.tree.*;
022
023/**
024 * @author sean
025 */
026public class JdbcExplorer
027    extends javax.swing.JPanel
028    implements TreeWillExpandListener
029{
030    private static final Logger LOGGER = Logger.getLogger(JdbcExplorer.class);
031
032    JdbcMetaData jdbcMetaData;
033    JdbcTreeModel model;
034
035    Workbench workbench;
036
037    DefaultMutableTreeNode root;
038
039    DefaultTreeModel treeModel;
040
041    public JdbcExplorer(JdbcMetaData jdbcMetaData, Workbench wb) {
042        workbench = wb;
043        initComponents();
044        setMetaData(jdbcMetaData);
045    }
046
047    public void setMetaData(JdbcMetaData jdbcMetaData) {
048        try {
049            this.jdbcMetaData = jdbcMetaData;
050
051            Node rootNode = new Node(null, NodeType.ROOT, null);
052            root = new DefaultMutableTreeNode(rootNode);
053
054            for (String schemaName : jdbcMetaData.getAllSchemas()) {
055                Node cat = new Node(schemaName, NodeType.CATALOG, null);
056
057                DefaultMutableTreeNode catTreeNode =
058                    new DefaultMutableTreeNode(cat);
059                cat.treeNode = catTreeNode;
060                root.add(catTreeNode);
061
062                List<String> tables = jdbcMetaData.getAllTables(schemaName);
063                for (String tableName : tables) {
064                    Node table = new Node(tableName, NodeType.TABLE, null);
065                    DefaultMutableTreeNode tableTreeNode =
066                        new DefaultMutableTreeNode(table);
067                    table.treeNode = tableTreeNode;
068                    catTreeNode.add(tableTreeNode);
069                }
070
071                cat.gotChildren = true;
072            }
073            rootNode.gotChildren = true;
074
075            treeModel = new DefaultTreeModel(root, true);
076            tree.setModel(treeModel);
077            tree.addTreeWillExpandListener(this);
078
079            updater = new JTreeUpdater(tree);
080        } catch (Exception ex) {
081            LOGGER.error(ex);
082        }
083    }
084
085    public void resetMetaData(JdbcMetaData jdbcMetaData) {
086        setMetaData(jdbcMetaData);
087    }
088
089    public JTreeUpdater getTreeUpdater() {
090        return updater;
091    }
092
093    public void treeWillExpand(TreeExpansionEvent event)
094        throws ExpandVetoException
095    {
096        // The children are lazy loaded
097        LOGGER.debug(
098            "path = " + event.getPath() + ", last object is a "
099            + event.getPath().getLastPathComponent().getClass().getName());
100
101        DefaultMutableTreeNode theTreeNode =
102            (DefaultMutableTreeNode) event.getPath().getLastPathComponent();
103        Node theNode = (Node) theTreeNode.getUserObject();
104        theNode.setChildren();
105
106        logNode(theTreeNode, "will Expand");
107    }
108
109    private void logNode(DefaultMutableTreeNode theTreeNode, String message) {
110        if (!LOGGER.isDebugEnabled()) {
111            return;
112        }
113
114        DefaultMutableTreeNode parentNode =
115            (DefaultMutableTreeNode) theTreeNode.getParent();
116
117        Node theNode = (Node) theTreeNode.getUserObject();
118        Node theParentNode =
119            parentNode == null
120                ? null
121                : (Node) parentNode.getUserObject();
122
123        @SuppressWarnings({"unchecked"})
124        Enumeration<DefaultMutableTreeNode> children = theTreeNode.children();
125
126        LOGGER.debug(
127            message + ": " + theNode + ", " + theNode.type
128            + ", parent " + theParentNode
129            + (theParentNode == null
130                ? ""
131                : ", " + theParentNode.type));
132        while (children.hasMoreElements()) {
133            DefaultMutableTreeNode treeNode = children.nextElement();
134            Node child = (Node) treeNode.getUserObject();
135            LOGGER.debug("\t" + child.toString() + ", " + child.type);
136        }
137    }
138
139    public void treeWillCollapse(TreeExpansionEvent arg0)
140        throws ExpandVetoException
141    {
142    }
143
144    enum NodeType {
145        CATALOG,
146        TABLE,
147        COLUMN,
148        ROOT
149    }
150
151    class Node {
152        final String name;
153        final NodeType type;
154        boolean gotChildren = false;
155        DefaultMutableTreeNode treeNode;
156        final JdbcMetaData.DbColumn columnInfo;
157
158        public Node(
159            String name,
160            NodeType type,
161            DefaultMutableTreeNode treeNode)
162        {
163            this(name, type, treeNode, null);
164        }
165
166        public Node(
167            String name,
168            NodeType type,
169            DefaultMutableTreeNode treeNode,
170            JdbcMetaData.DbColumn columnInfo)
171        {
172            this.name = name;
173            this.type = type;
174            this.treeNode = treeNode;
175            this.columnInfo = columnInfo;
176        }
177
178        public String toString() {
179            if (type == NodeType.ROOT) {
180                return workbench.getResourceConverter().getFormattedString(
181                    "jdbcExplorer.root.name",
182                    "All Schemas");
183            }
184
185            StringBuilder sb = new StringBuilder();
186            if (name == null || name.trim().length() == 0) {
187                switch (type) {
188                case CATALOG:
189                    sb.append(
190                        workbench.getResourceConverter().getFormattedString(
191                            "jdbcExplorer.default.name.catalog",
192                            "Default Schema"));
193                    break;
194                case TABLE:
195                    sb.append(
196                        workbench.getResourceConverter().getFormattedString(
197                            "jdbcExplorer.default.name.table", "Table"));
198                    break;
199                case COLUMN:
200                    sb.append(
201                        workbench.getResourceConverter().getFormattedString(
202                            "jdbcExplorer.default.name.column",
203                            "Column"));
204                    break;
205                }
206            } else {
207                sb.append(name);
208            }
209
210            if (type != NodeType.COLUMN) {
211                return sb.toString();
212            }
213
214            // now for columns
215
216            sb.append(" - ").append(columnInfo.displayType());
217
218            return sb.toString();
219        }
220
221        public void setChildren() {
222            if (!gotChildren) {
223                if (type == NodeType.TABLE) {
224                    DefaultMutableTreeNode theParentTreeNode =
225                        (DefaultMutableTreeNode) treeNode.getParent();
226
227                    Node theParentNode =
228                        (Node) theParentTreeNode.getUserObject();
229
230                    // This is a table, parent is a schema
231
232                    List<DbColumn> columns =
233                        jdbcMetaData.getAllDbColumns(
234                            theParentNode.name, name);
235                    for (DbColumn column : columns) {
236                        Node columnNode = new Node(
237                            column.name, NodeType.COLUMN, treeNode, column);
238                        MutableTreeNode columnTreeNode =
239                            new DefaultMutableTreeNode(columnNode, false);
240                        treeNode.add(columnTreeNode);
241                    }
242                }
243            }
244            gotChildren = true;
245        }
246    }
247
248    /**
249     * This method is called from within the constructor to
250     * initialize the form.
251     * WARNING: Do NOT modify this code. The content of this method is
252     * always regenerated by the Form Editor.
253     */
254    private void initComponents() {//GEN-BEGIN:initComponents
255        jSplitPane1 = new javax.swing.JSplitPane();
256        jScrollPane1 = new javax.swing.JScrollPane();
257        tree = new javax.swing.JTree();
258        jScrollPane2 = new javax.swing.JScrollPane();
259
260        setLayout(new java.awt.BorderLayout());
261
262        jSplitPane1.setDividerLocation(200);
263        jScrollPane1.setViewportView(tree);
264
265        jSplitPane1.setLeftComponent(jScrollPane1);
266
267        jSplitPane1.setRightComponent(jScrollPane2);
268
269        add(jSplitPane1, java.awt.BorderLayout.CENTER);
270    } //GEN-END:initComponents
271
272
273    // Variables declaration - do not modify//GEN-BEGIN:variables
274    private javax.swing.JScrollPane jScrollPane2;
275    private javax.swing.JScrollPane jScrollPane1;
276    private javax.swing.JTree tree;
277    private javax.swing.JSplitPane jSplitPane1;
278    // End of variables declaration//GEN-END:variables
279
280    private JTreeUpdater updater;
281}
282
283// End JdbcExplorer.java