org.jumpmind.vaadin.ui.sqlexplorer.DbTree.java Source code

Java tutorial

Introduction

Here is the source code for org.jumpmind.vaadin.ui.sqlexplorer.DbTree.java

Source

/**
 * Licensed to JumpMind Inc under one or more contributor
 * license agreements.  See the NOTICE file distributed
 * with this work for additional information regarding
 * copyright ownership.  JumpMind Inc licenses this file
 * to you under the GNU General Public License, version 3.0 (GPLv3)
 * (the "License"); you may not use this file except in compliance
 * with the License.
 *
 * You should have received a copy of the GNU General Public License,
 * version 3.0 (GPLv3) along with this library; if not, see
 * <http://www.gnu.org/licenses/>.
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jumpmind.vaadin.ui.sqlexplorer;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jumpmind.db.model.Table;
import org.jumpmind.db.model.Trigger;
import org.jumpmind.db.platform.IDatabasePlatform;
import org.jumpmind.db.platform.IDdlReader;
import org.jumpmind.vaadin.ui.common.CommonUiUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vaadin.event.Action;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.Tree;

public class DbTree extends Tree {

    public static final String PROPERTY_SCHEMA_NAME = "schemaName";
    public static final String PROPERTY_CATALOG_NAME = "catalogName";

    private static final long serialVersionUID = 1L;

    final Logger log = LoggerFactory.getLogger(getClass());

    public final static String[] TABLE_TYPES = new String[] { "TABLE", "SYSTEM TABLE", "SYSTEM VIEW" };

    public static final String NODE_TYPE_DATABASE = "Database";
    public static final String NODE_TYPE_CATALOG = "Catalog";
    public static final String NODE_TYPE_SCHEMA = "Schema";
    public static final String NODE_TYPE_TABLE = "Table";
    public static final String NODE_TYPE_TRIGGER = "Trigger";

    IDbProvider databaseProvider;

    ISettingsProvider settingsProvider;

    Set<DbTreeNode> expanded = new HashSet<DbTreeNode>();

    Set<DbTreeNode> hasBeenExpanded = new HashSet<DbTreeNode>();

    Map<String, List<DbTreeAction>> actionsByNodeType = new HashMap<String, List<DbTreeAction>>();

    public DbTree(IDbProvider databaseProvider, ISettingsProvider settingsProvider) {
        this.databaseProvider = databaseProvider;
        this.settingsProvider = settingsProvider;
        setWidth(100, Unit.PERCENTAGE);
        setImmediate(true);
        setMultiSelect(true);
        setSelectable(true);
        setItemStyleGenerator(new StyleGenerator());
        Listener listener = new Listener();
        addCollapseListener(listener);
        addExpandListener(listener);
        addActionHandler(new Handler());
    }

    public void registerAction(DbTreeAction action, String... nodeTypes) {
        for (String nodeType : nodeTypes) {
            List<DbTreeAction> actions = actionsByNodeType.get(nodeType);
            if (actions == null) {
                actions = new ArrayList<DbTreeAction>();
                actionsByNodeType.put(nodeType, actions);
            }
            actions.add(action);
        }
    }

    public void refresh() {
        hasBeenExpanded.clear();
        List<IDb> databases = databaseProvider.getDatabases();
        Set<DbTreeNode> expandedItems = new HashSet<DbTreeNode>(expanded);
        expanded.clear();
        Set<DbTreeNode> selected = getSelected();
        removeAllItems();
        DbTreeNode firstNode = null;
        for (IDb database : databases) {
            DbTreeNode databaseNode = new DbTreeNode(this, database.getName(), NODE_TYPE_DATABASE,
                    FontAwesome.DATABASE, null);
            addItem(databaseNode);
            setItemIcon(databaseNode, databaseNode.getIcon());

            if (firstNode == null) {
                firstNode = databaseNode;
            }
        }

        for (DbTreeNode expandedItem : expandedItems) {
            expandItem(expandedItem);
        }

        if (selected == null || selected.size() == 0) {
            selected = new HashSet<DbTreeNode>();
            selected.add(firstNode);
        }
        setValue(selected);
        focus();

    }

    @SuppressWarnings("unchecked")
    public Set<DbTreeNode> getSelected() {
        return (Set<DbTreeNode>) getValue();
    }

    @SuppressWarnings("unchecked")
    public Set<DbTreeNode> getSelected(String type) {
        HashSet<DbTreeNode> nodes = new HashSet<DbTreeNode>();
        Set<DbTreeNode> selected = (Set<DbTreeNode>) getValue();
        for (DbTreeNode treeNode : selected) {
            if (treeNode.getType().equals(type)) {
                nodes.add(treeNode);
            }
        }
        return nodes;
    }

    public Set<Table> getSelectedTables() {
        Set<Table> tables = new HashSet<Table>();
        for (DbTreeNode treeNode : getSelected()) {
            Table table = treeNode.getTableFor();
            if (table != null) {
                tables.add(table);
            }
        }
        return tables;
    }

    protected IDb getDbForNode(DbTreeNode node) {
        while (node.getParent() != null) {
            node = node.getParent();
        }
        String databaseName = node.getName();
        List<IDb> databases = databaseProvider.getDatabases();
        for (IDb database : databases) {
            if (database.getName().equals(databaseName)) {
                return database;
            }
        }
        return null;
    }

    protected void expanded(DbTreeNode treeNode) {
        if (!hasBeenExpanded.contains(treeNode)) {
            hasBeenExpanded.add(treeNode);

            try {
                IDatabasePlatform platform = getDbForNode(treeNode).getPlatform();
                IDdlReader reader = platform.getDdlReader();

                Collection<?> children = getChildren(treeNode);
                if (children == null || children.size() == 0) {
                    if (treeNode.getType().equals(NODE_TYPE_DATABASE)) {
                        List<DbTreeNode> nextLevel = new ArrayList<DbTreeNode>();
                        List<String> catalogs = reader.getCatalogNames();
                        if (catalogs.size() > 0) {
                            if (catalogs.remove(platform.getDefaultCatalog())) {
                                catalogs.add(0, platform.getDefaultCatalog());
                            }
                            for (String catalog : catalogs) {
                                DbTreeNode catalogNode = new DbTreeNode(this, catalog, NODE_TYPE_CATALOG,
                                        FontAwesome.BOOK, treeNode);
                                nextLevel.add(catalogNode);
                            }
                        } else {
                            List<String> schemas = reader.getSchemaNames(null);
                            if (schemas.remove(platform.getDefaultSchema())) {
                                schemas.add(0, platform.getDefaultSchema());
                            }
                            for (String schema : schemas) {
                                DbTreeNode schemaNode = new DbTreeNode(this, schema, NODE_TYPE_SCHEMA,
                                        FontAwesome.BOOK, treeNode);
                                nextLevel.add(schemaNode);
                            }
                        }

                        if (nextLevel.size() == 0) {
                            nextLevel.addAll(getTableTreeNodes(reader, treeNode, null, null));
                        }

                        treeNode.getChildren().addAll(nextLevel);
                        for (DbTreeNode node : nextLevel) {
                            addTreeNode(node);
                        }
                    } else if (treeNode.getType().equals(NODE_TYPE_CATALOG)) {
                        List<String> schemas = reader.getSchemaNames(treeNode.getName());
                        if (schemas.size() > 0) {
                            if (schemas.remove(platform.getDefaultSchema())) {
                                schemas.add(0, platform.getDefaultSchema());
                            }
                            for (String schema : schemas) {
                                DbTreeNode schemaNode = new DbTreeNode(this, schema, NODE_TYPE_SCHEMA,
                                        FontAwesome.BOOK, treeNode);
                                treeNode.getChildren().add(schemaNode);
                                addTreeNode(schemaNode);
                            }
                        } else {
                            addTableNodes(reader, treeNode, treeNode.getName(), null);
                        }

                    } else if (treeNode.getType().equals(NODE_TYPE_SCHEMA)) {
                        String catalogName = null;
                        DbTreeNode parent = (DbTreeNode) getParent(treeNode);
                        if (parent != null && parent.getType().equals(NODE_TYPE_CATALOG)) {
                            catalogName = parent.getName();
                        }
                        addTableNodes(reader, treeNode, catalogName, treeNode.getName());
                    } else if (treeNode.getType().equals(NODE_TYPE_TABLE)) {
                        String catalogName = null, schemaName = null;
                        DbTreeNode parent = (DbTreeNode) getParent(treeNode);
                        if (parent != null && parent.getType().equals(NODE_TYPE_SCHEMA)) {
                            schemaName = parent.getName();
                            DbTreeNode grandparent = (DbTreeNode) getParent(parent);
                            if (grandparent != null && grandparent.getType().equals(NODE_TYPE_CATALOG)) {
                                catalogName = grandparent.getName();
                            }
                        } else if (parent != null && parent.getType().equals(NODE_TYPE_CATALOG)) {
                            catalogName = parent.getName();
                        }
                        addTriggerNodes(reader, treeNode, catalogName, schemaName);
                        System.out.println();
                    }

                    setChildrenAllowed(treeNode, treeNode.getChildren().size() > 0);
                }
            } catch (Exception ex) {
                log.error(ex.getMessage(), ex);
                CommonUiUtils.notify(ex);
            }
        }
    }

    protected void addTreeNode(DbTreeNode node) {
        addItem(node);
        setParent(node, node.getParent());
        setItemIcon(node, node.getIcon());
        setChildrenAllowed(node, !node.getType().equals(NODE_TYPE_TRIGGER));
    }

    protected List<DbTreeNode> getTableTreeNodes(IDdlReader reader, DbTreeNode parent, String catalogName,
            String schemaName) {
        List<DbTreeNode> list = new ArrayList<DbTreeNode>();
        List<String> tables = reader.getTableNames(catalogName, schemaName, TABLE_TYPES);

        Collections.sort(tables, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.toUpperCase().compareTo(o2.toUpperCase());
            }
        });

        for (String tableName : tables) {
            String excludeRegex = settingsProvider.get().getProperties()
                    .get(Settings.SQL_EXPLORER_EXCLUDE_TABLES_REGEX);
            if (!tableName.matches(excludeRegex) && !tableName.toUpperCase().matches(excludeRegex)
                    && !tableName.toLowerCase().matches(excludeRegex)) {

                DbTreeNode treeNode = new DbTreeNode(this, tableName, NODE_TYPE_TABLE, FontAwesome.TABLE, parent);
                if (catalogName != null) {
                    treeNode.getProperties().setProperty(PROPERTY_CATALOG_NAME, catalogName);
                }
                if (schemaName != null) {
                    treeNode.getProperties().setProperty(PROPERTY_SCHEMA_NAME, schemaName);
                }

                list.add(treeNode);
            }
        }
        return list;
    }

    protected void addTableNodes(IDdlReader reader, DbTreeNode parent, String catalogName, String schemaName) {
        List<DbTreeNode> nodes = getTableTreeNodes(reader, parent, catalogName, schemaName);
        for (DbTreeNode treeNode : nodes) {
            parent.getChildren().add(treeNode);
            addTreeNode(treeNode);
        }
    }

    protected List<DbTreeNode> getTriggerTreeNodes(IDdlReader reader, DbTreeNode parent, String catalogName,
            String schemaName) {
        List<DbTreeNode> list = new ArrayList<DbTreeNode>();
        List<Trigger> triggers = reader.getTriggers(catalogName, schemaName, parent.getName());
        for (Trigger trigger : triggers) {
            DbTreeNode treeNode = new DbTreeNode(this, trigger.getName(), NODE_TYPE_TRIGGER, FontAwesome.CROSSHAIRS,
                    parent);
            if (catalogName != null) {
                treeNode.getProperties().setProperty(PROPERTY_CATALOG_NAME, catalogName);
            }
            if (schemaName != null) {
                treeNode.getProperties().setProperty(PROPERTY_SCHEMA_NAME, schemaName);
            }
            list.add(treeNode);
        }
        return list;
    }

    protected void addTriggerNodes(IDdlReader reader, DbTreeNode parent, String catalogName, String schemaName) {
        List<DbTreeNode> nodes = getTriggerTreeNodes(reader, parent, catalogName, schemaName);
        for (DbTreeNode treeNode : nodes) {
            parent.getChildren().add(treeNode);
            addTreeNode(treeNode);
        }
    }

    class Listener implements CollapseListener, ExpandListener {

        private static final long serialVersionUID = 1L;

        @Override
        public void nodeCollapse(CollapseEvent event) {
            expanded.remove(event.getItemId());
        }

        @Override
        public void nodeExpand(ExpandEvent event) {
            DbTreeNode node = (DbTreeNode) event.getItemId();
            expanded.add(node);
            expanded(node);
        }

    }

    class StyleGenerator implements ItemStyleGenerator {
        private static final long serialVersionUID = 1L;

        public String getStyle(Tree source, Object itemId) {
            if (itemId instanceof DbTreeNode) {
                try {
                    DbTreeNode node = (DbTreeNode) itemId;
                    if (node.getType().equals(NODE_TYPE_CATALOG)) {
                        IDatabasePlatform platform = getDbForNode(node).getPlatform();
                        String catalog = platform.getDefaultCatalog();
                        if (catalog != null && catalog.equals(node.getName())) {
                            return "bold";
                        }
                    } else if (node.getType().equals(NODE_TYPE_SCHEMA)) {
                        IDatabasePlatform platform = getDbForNode(node).getPlatform();
                        String schema = platform.getDefaultSchema();
                        if (schema != null && schema.equals(node.getName())) {
                            return "bold";
                        }
                    }
                } catch (Exception e) {
                    log.error("Failed to see if this node is the default catalog and/or schema", e);
                }
            }
            return null;

        }
    }

    class Handler implements com.vaadin.event.Action.Handler {

        private static final long serialVersionUID = 1L;

        @Override
        public Action[] getActions(Object target, Object sender) {
            if (target instanceof DbTreeNode) {
                DbTreeNode treeNode = (DbTreeNode) target;
                List<DbTreeAction> actions = actionsByNodeType.get(treeNode.getType());
                if (actions != null) {
                    return actions.toArray(new Action[actions.size()]);
                }
            }
            return new Action[0];

        }

        @Override
        public void handleAction(Action action, Object sender, Object target) {
            if (action instanceof DbTreeAction) {
                if (!getSelected().contains(target)) {
                    select(target);
                }
                DbTreeNode node = (DbTreeNode) target;
                ((DbTreeAction) action).handle(getSelected(node.getType()));
            }
        }
    }

}