You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2018/03/28 11:22:13 UTC

[07/14] cayenne git commit: CAY-2337 Code refactoring, bugs fixing

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/TreeToolbarPanel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/TreeToolbarPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/TreeToolbarPanel.java
deleted file mode 100644
index 995cf47..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/TreeToolbarPanel.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  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.apache.cayenne.modeler.editor;
-
-import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
-import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeColumn;
-import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeProcedure;
-import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeTable;
-import org.apache.cayenne.dbsync.reverse.dbimport.IncludeColumn;
-import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
-import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
-import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
-import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
-import org.apache.cayenne.modeler.ProjectController;
-import org.apache.cayenne.modeler.action.AddCatalogAction;
-import org.apache.cayenne.modeler.action.AddExcludeColumnAction;
-import org.apache.cayenne.modeler.action.AddExcludeProcedureAction;
-import org.apache.cayenne.modeler.action.AddExcludeTableAction;
-import org.apache.cayenne.modeler.action.AddIncludeColumnAction;
-import org.apache.cayenne.modeler.action.AddIncludeProcedureAction;
-import org.apache.cayenne.modeler.action.AddIncludeTableAction;
-import org.apache.cayenne.modeler.action.AddPatternParamAction;
-import org.apache.cayenne.modeler.action.AddSchemaAction;
-import org.apache.cayenne.modeler.action.DeleteNodeAction;
-import org.apache.cayenne.modeler.action.EditNodeAction;
-import org.apache.cayenne.modeler.action.GetDbConnectionAction;
-import org.apache.cayenne.modeler.action.TreeManipulationAction;
-import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
-
-import javax.swing.JButton;
-import javax.swing.JToolBar;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @since 4.1
- */
-class TreeToolbarPanel extends JToolBar {
-
-    private JButton schemaButton;
-    private JButton catalogButton;
-    private JButton includeTableButton;
-    private JButton excludeTableButton;
-    private JButton includeColumnButton;
-    private JButton excludeColumnButton;
-    private JButton includeProcedureButton;
-    private JButton excludeProcedureButton;
-    private JButton editButton;
-    private JButton deleteButton;
-    private JButton configureButton;
-    private DbImportTree reverseEngineeringTree;
-
-    private Map<Class, List<JButton>> levels;
-    private ProjectController projectController;
-
-    TreeToolbarPanel(ProjectController projectController, DbImportTree reverseEngineeringTree, DraggableTreePanel treePanel) {
-        this.projectController = projectController;
-        this.reverseEngineeringTree = reverseEngineeringTree;
-        createButtons(treePanel);
-        initLevels();
-        addButtons();
-    }
-
-    void unlockButtons() {
-        changeToolbarButtonsState(true);
-        editButton.setEnabled(false);
-        deleteButton.setEnabled(false);
-    }
-
-    private boolean isLabelSelected() {
-        DbImportTreeNode selectedNode = reverseEngineeringTree.getSelectedNode();
-        if (selectedNode.getUserObject().getClass() == String.class) {
-            return true;
-        }
-        return false;
-    }
-
-    void lockButtons() {
-        if ((reverseEngineeringTree.getLastSelectedPathComponent() != null) && (!isLabelSelected())) {
-            DbImportTreeNode selectedNode = ((DbImportTreeNode) reverseEngineeringTree.getLastSelectedPathComponent());
-            DbImportTreeNode parentNode = (DbImportTreeNode) selectedNode.getParent();
-            if (parentNode != null) {
-                lockButtons(parentNode.getUserObject());
-            } else {
-                unlockButtons();
-            }
-        } else {
-            changeToolbarButtonsState(true);
-            editButton.setEnabled(false);
-            deleteButton.setEnabled(false);
-        }
-        if (reverseEngineeringTree.getSelectionPaths() != null) {
-            if (reverseEngineeringTree.getSelectionPaths().length > 1) {
-                changeToolbarButtonsState(false);
-                deleteButton.setEnabled(true);
-            }
-        }
-    }
-
-    private void initLevels() {
-        levels = new HashMap<>();
-
-        List<JButton> rootLevelButtons = new ArrayList<>();
-        rootLevelButtons.add(catalogButton);
-        rootLevelButtons.add(schemaButton);
-        rootLevelButtons.add(includeTableButton);
-        rootLevelButtons.add(excludeTableButton);
-        rootLevelButtons.add(includeColumnButton);
-        rootLevelButtons.add(excludeColumnButton);
-        rootLevelButtons.add(includeProcedureButton);
-        rootLevelButtons.add(excludeProcedureButton);
-
-        List<JButton> catalogLevelButtons = new ArrayList<>();
-        catalogLevelButtons.add(schemaButton);
-        catalogLevelButtons.add(includeTableButton);
-        catalogLevelButtons.add(excludeTableButton);
-        catalogLevelButtons.add(includeColumnButton);
-        catalogLevelButtons.add(excludeColumnButton);
-        catalogLevelButtons.add(includeProcedureButton);
-        catalogLevelButtons.add(excludeProcedureButton);
-
-        List<JButton> schemaLevelButtons = new ArrayList<>();
-        schemaLevelButtons.add(includeTableButton);
-        schemaLevelButtons.add(excludeTableButton);
-        schemaLevelButtons.add(includeColumnButton);
-        schemaLevelButtons.add(excludeColumnButton);
-        schemaLevelButtons.add(includeProcedureButton);
-        schemaLevelButtons.add(excludeProcedureButton);
-
-        List<JButton> includeTableLevelButtons = new ArrayList<>();
-        includeTableLevelButtons.add(includeColumnButton);
-        includeTableLevelButtons.add(excludeColumnButton);
-
-        levels.put(ReverseEngineering.class, rootLevelButtons);
-        levels.put(Catalog.class, catalogLevelButtons);
-        levels.put(Schema.class, schemaLevelButtons);
-        levels.put(IncludeTable.class, includeTableLevelButtons);
-    }
-
-    private void addButtons() {
-        this.setFloatable(false);
-        this.add(catalogButton);
-        this.add(schemaButton);
-        this.addSeparator();
-        this.add(includeTableButton);
-        this.add(excludeTableButton);
-        this.add(includeColumnButton);
-        this.add(excludeColumnButton);
-        this.add(includeProcedureButton);
-        this.add(excludeProcedureButton);
-        this.add(editButton);
-        this.addSeparator();
-        this.add(deleteButton);
-        this.add(configureButton);
-    }
-
-    void changeToolbarButtonsState(boolean state) {
-        schemaButton.setEnabled(state);
-        catalogButton.setEnabled(state);
-        includeTableButton.setEnabled(state);
-        excludeTableButton.setEnabled(state);
-        includeColumnButton.setEnabled(state);
-        excludeColumnButton.setEnabled(state);
-        includeProcedureButton.setEnabled(state);
-        excludeProcedureButton.setEnabled(state);
-        editButton.setEnabled(state);
-        deleteButton.setEnabled(state);
-    }
-
-    private void lockButtons(Object userObject) {
-        changeToolbarButtonsState(false);
-        List<JButton> buttons = levels.get(userObject.getClass());
-        for (JButton button : buttons) {
-            button.setEnabled(true);
-        }
-        editButton.setEnabled(true);
-        deleteButton.setEnabled(true);
-    }
-
-    private <T extends TreeManipulationAction> JButton createButton(Class<T> actionClass, int position) {
-        TreeManipulationAction action = projectController.getApplication().getActionManager().getAction(actionClass);
-        action.setTree(reverseEngineeringTree);
-        return action.buildButton(position);
-    }
-
-    private <T extends AddPatternParamAction> JButton createButton(Class<T> actionClass, int position, Class paramClass) {
-        AddPatternParamAction action = projectController.getApplication().getActionManager().getAction(actionClass);
-        action.setTree(reverseEngineeringTree);
-        action.setParamClass(paramClass);
-        return action.buildButton(position);
-    }
-
-    private void createButtons(DraggableTreePanel panel) {
-        schemaButton = createButton(AddSchemaAction.class, 0);
-        catalogButton = createButton(AddCatalogAction.class, 0);
-        includeTableButton = createButton(AddIncludeTableAction.class, 1);
-        excludeTableButton = createButton(AddExcludeTableAction.class, 2, ExcludeTable.class);
-        includeColumnButton = createButton(AddIncludeColumnAction.class, 2, IncludeColumn.class);
-        excludeColumnButton = createButton(AddExcludeColumnAction.class, 2, ExcludeColumn.class);
-        includeProcedureButton = createButton(AddIncludeProcedureAction.class, 2, IncludeProcedure.class);
-        excludeProcedureButton = createButton(AddExcludeProcedureAction.class, 3, ExcludeProcedure.class);
-        editButton = createButton(EditNodeAction.class, 0);
-        DeleteNodeAction deleteNodeAction = projectController.getApplication().getActionManager().getAction(DeleteNodeAction.class);
-        deleteNodeAction.setTree(reverseEngineeringTree);
-        deleteNodeAction.setPanel(panel);
-        deleteButton = deleteNodeAction.buildButton(0);
-        GetDbConnectionAction action = projectController.getApplication().getActionManager().getAction(GetDbConnectionAction.class);
-        configureButton = action.buildButton(0);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ColorTreeRenderer.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ColorTreeRenderer.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ColorTreeRenderer.java
new file mode 100644
index 0000000..2f58ea4
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ColorTreeRenderer.java
@@ -0,0 +1,146 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  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.apache.cayenne.modeler.editor.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+
+import javax.swing.JTree;
+import java.awt.Color;
+import java.awt.Component;
+
+import static org.apache.cayenne.modeler.editor.dbimport.DbImportNodeHandler.LABEL_COLOR;
+import static org.apache.cayenne.modeler.editor.dbimport.DbImportNodeHandler.NON_INCLUDE_COLOR;
+
+/**
+ * @since 4.1
+ */
+public class ColorTreeRenderer extends DbImportTreeCellRenderer {
+
+    private DbImportNodeHandler handler;
+    private DbImportTree reverseEngineeringTree;
+
+
+    public ColorTreeRenderer() {
+        super();
+        handler = new DbImportNodeHandler();
+    }
+
+    @Override
+    public Component getTreeCellRendererComponent(JTree tree, Object value,
+                                                  boolean sel,
+                                                  boolean expanded,
+                                                  boolean leaf, int row,
+                                                  boolean hasFocus) {
+        super.getTreeCellRendererComponent(tree, value, sel,
+                expanded, leaf, row, hasFocus);
+        DbImportTree renderedTree = (DbImportTree) tree;
+        handler.setDbSchemaNode(node);
+        if (node.isLabel()) {
+            setForeground(LABEL_COLOR);
+            return this;
+        }
+        if (handler.isContainer(node) || (handler.isFirstNodeIsPrimitive(renderedTree))) {
+            handler.setHasEntitiesInEmptyContainer(false);
+        }
+        if (selected) {
+            setForeground(Color.BLACK);
+            node.setColorized(node.isColorized());
+            return this;
+        }
+        DbImportTreeNode root;
+        handler.findFirstLevelIncludeTable();
+        if (!handler.checkTreesLevels(renderedTree)) {
+            setForeground(NON_INCLUDE_COLOR);
+            node.setColorized(false);
+            return this;
+        }
+        if (reverseEngineeringTree.getSelectionPath() != null) {
+            root = reverseEngineeringTree.getSelectedNode();
+        } else {
+            root = reverseEngineeringTree.getRootNode();
+        }
+        renderedTree.getRootNode().setColorized(true);
+
+        int traverseResult = handler.traverseTree(root);
+        if (traverseResult > 0) {
+            // Case on IncludeProcedure on zero level is selected
+            if (root.getUserObject().getClass() == IncludeProcedure.class) {
+                if (handler.nodesIsEqual(root)) {
+                    setForeground(handler.getColorByNodeType(root));
+                    node.setColorized(true);
+                    return this;
+                } else {
+                    setForeground(NON_INCLUDE_COLOR);
+                    node.setColorized(false);
+                    return this;
+                }
+            }
+            // If ReverseEngineering doesn't have catalogs or schemas on zero level
+            if (!handler.isExistCatalogsOrSchemas()) {
+                if ((root.isExcludeTable()) || (root.isExcludeProcedure())) {
+                    if (handler.nodesIsEqual(root)) {
+                        setForeground(handler.getColorByNodeType(root));
+                        node.setColorized(true);
+                        return this;
+                    }
+                    setForeground(NON_INCLUDE_COLOR);
+                    node.setColorized(false);
+                    return this;
+                }
+                if (root.equals(node)) {
+                    setForeground(handler.getColorByNodeType(root));
+                    node.setColorized(true);
+                    return this;
+                }
+            }
+            // Recursion painting, if parent is colorized
+            if (handler.isParentIncluded()) {
+                setForeground(handler.getColorByNodeType(root));
+                node.setColorized(true);
+                return this;
+            }
+        } else {
+            setForeground(NON_INCLUDE_COLOR);
+            node.setColorized(false);
+            return this;
+        }
+        if ((handler.isParentIncluded()) || (reverseEngineeringTree.getSelectionPath() != null)) {
+            setForeground(handler.getColorByNodeType(root));
+            node.setColorized(true);
+            return this;
+        } else {
+            if (!handler.isExistCatalogsOrSchemas()) {
+                setForeground(handler.getColorByNodeType(root));
+                node.setColorized(true);
+                return this;
+            }
+            setForeground(NON_INCLUDE_COLOR);
+            node.setColorized(false);
+            return this;
+        }
+
+    }
+
+    public void setReverseEngineeringTree(DbImportTree reverseEngineeringTree) {
+        this.reverseEngineeringTree = reverseEngineeringTree;
+        handler.setReverseEngineeringTree(reverseEngineeringTree);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DatabaseSchemaLoader.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DatabaseSchemaLoader.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DatabaseSchemaLoader.java
new file mode 100644
index 0000000..64a73b3
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DatabaseSchemaLoader.java
@@ -0,0 +1,184 @@
+package org.apache.cayenne.modeler.editor.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.modeler.ClassLoadingService;
+import org.apache.cayenne.modeler.pref.DBConnectionInfo;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+
+public class DatabaseSchemaLoader {
+
+    private static final String INCLUDE_ALL_PATTERN = "%";
+    private static final String EMPTY_DEFAULT_CATALOG = "";
+    private static final int TABLE_INDEX = 3;
+    private static final int SCHEMA_INDEX = 2;
+    private static final int CATALOG_INDEX = 1;
+
+    private ReverseEngineering databaseReverseEngineering;
+
+    public DatabaseSchemaLoader() {
+        databaseReverseEngineering = new ReverseEngineering();
+    }
+
+    public ReverseEngineering load(DBConnectionInfo connectionInfo, ClassLoadingService loadingService) throws SQLException {
+        try (Connection connection = connectionInfo.makeDataSource(loadingService).getConnection()) {
+            String[] types = {"TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM"};
+            try (ResultSet rs = connection.getMetaData().getCatalogs()) {
+                String defaultCatalog = connection.getCatalog();
+                while (rs.next()) {
+                    ResultSet resultSet;
+                    if (defaultCatalog.equals(EMPTY_DEFAULT_CATALOG)) {
+                        resultSet = connection.getMetaData()
+                                .getTables(rs.getString(1), null, INCLUDE_ALL_PATTERN, types);
+                    } else {
+                        resultSet = connection.getMetaData()
+                                .getTables(defaultCatalog, null, INCLUDE_ALL_PATTERN, types);
+                    }
+                    String tableName = "";
+                    String schemaName = "";
+                    String catalogName = "";
+                    while (resultSet.next()) {
+                        tableName = resultSet.getString(TABLE_INDEX);
+                        schemaName = resultSet.getString(SCHEMA_INDEX);
+                        catalogName = resultSet.getString(CATALOG_INDEX);
+                        packTable(tableName, catalogName, schemaName);
+                    }
+                    packFunctions(connection);
+                }
+            }
+        }
+        return databaseReverseEngineering;
+    }
+
+    private void packFunctions(Connection connection) throws SQLException {
+        Collection<Catalog> catalogs = databaseReverseEngineering.getCatalogs();
+        for (Catalog catalog : catalogs) {
+            ResultSet procResultSet = connection.getMetaData().getProcedures(
+                    catalog.getName(), null, "%"
+            );
+            while (procResultSet.next()) {
+                IncludeProcedure includeProcedure = new IncludeProcedure(procResultSet.getString(3));
+                if (!catalog.getIncludeProcedures().contains(includeProcedure)) {
+                    catalog.addIncludeProcedure(includeProcedure);
+                }
+            }
+        }
+        for (Schema schema : databaseReverseEngineering.getSchemas()) {
+            ResultSet procResultSet = connection.getMetaData().getProcedures(
+                    null, schema.getName(), "%"
+            );
+            while (procResultSet.next()) {
+                IncludeProcedure includeProcedure = new IncludeProcedure(procResultSet.getString(3));
+                if (!schema.getIncludeProcedures().contains(includeProcedure)) {
+                    schema.addIncludeProcedure(includeProcedure);
+                }
+            }
+        }
+        for (Catalog catalog : catalogs) {
+            for (Schema schema : catalog.getSchemas()) {
+                ResultSet procResultSet = connection.getMetaData().getProcedures(
+                        catalog.getName(), schema.getName(), "%"
+                );
+                while (procResultSet.next()) {
+                    IncludeProcedure includeProcedure = new IncludeProcedure(procResultSet.getString(3));
+                    if (!schema.getIncludeProcedures().contains(includeProcedure)) {
+                        schema.addIncludeProcedure(includeProcedure);
+                    }
+                }
+            }
+        }
+    }
+
+    private void packTable(String tableName, String catalogName, String schemaName) {
+        IncludeTable newTable = new IncludeTable();
+        newTable.setPattern(tableName);
+        if ((catalogName == null) && (schemaName == null)) {
+            if (!databaseReverseEngineering.getIncludeTables().contains(newTable)) {
+                databaseReverseEngineering.addIncludeTable(newTable);
+            }
+        }
+        if ((catalogName != null) && (schemaName == null)) {
+            Catalog parentCatalog = getCatalogByName(databaseReverseEngineering.getCatalogs(), catalogName);
+            if (parentCatalog != null) {
+                if (!parentCatalog.getIncludeTables().contains(newTable)) {
+                    parentCatalog.addIncludeTable(newTable);
+                }
+            } else {
+                parentCatalog = new Catalog();
+                parentCatalog.setName(catalogName);
+                if (!parentCatalog.getIncludeTables().contains(newTable)) {
+                    parentCatalog.addIncludeTable(newTable);
+                }
+                databaseReverseEngineering.addCatalog(parentCatalog);
+            }
+        }
+        if ((catalogName == null) && (schemaName != null)) {
+            Schema parentSchema = getSchemaByName(databaseReverseEngineering.getSchemas(), schemaName);
+            if (parentSchema != null) {
+                if (!parentSchema.getIncludeTables().contains(newTable)) {
+                    parentSchema.addIncludeTable(newTable);
+                }
+            } else {
+                parentSchema = new Schema();
+                parentSchema.setName(schemaName);
+                if (!parentSchema.getIncludeTables().contains(newTable)) {
+                    parentSchema.addIncludeTable(newTable);
+                }
+                databaseReverseEngineering.addSchema(parentSchema);
+            }
+        }
+        if ((catalogName != null) && (schemaName != null)) {
+            Catalog parentCatalog = getCatalogByName(databaseReverseEngineering.getCatalogs(), catalogName);
+            Schema parentSchema;
+            if (parentCatalog != null) {
+                parentSchema = getSchemaByName(parentCatalog.getSchemas(), schemaName);
+                if (parentSchema != null) {
+                    if (!parentSchema.getIncludeTables().contains(newTable)) {
+                        parentSchema.addIncludeTable(newTable);
+                    }
+                } else {
+                    parentSchema = new Schema();
+                    parentSchema.setName(schemaName);
+                    if (!parentSchema.getIncludeTables().contains(newTable)) {
+                        parentSchema.addIncludeTable(newTable);
+                    }
+                    parentCatalog.addSchema(parentSchema);
+                }
+            } else {
+                parentCatalog = new Catalog();
+                parentCatalog.setName(catalogName);
+                parentSchema = new Schema();
+                parentSchema.setName(schemaName);
+                if (!parentSchema.getIncludeTables().contains(newTable)) {
+                    parentSchema.addIncludeTable(newTable);
+                }
+                databaseReverseEngineering.addCatalog(parentCatalog);
+            }
+        }
+    }
+
+    private Catalog getCatalogByName(Collection<Catalog> catalogs, String catalogName) {
+        for (Catalog catalog : catalogs) {
+            if (catalog.getName().equals(catalogName)) {
+                return catalog;
+            }
+        }
+        return null;
+    }
+
+    private Schema getSchemaByName(Collection<Schema> schemas, String schemaName) {
+        for (Schema schema : schemas) {
+            if (schema.getName().equals(schemaName)) {
+                return schema;
+            }
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportModel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportModel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportModel.java
new file mode 100644
index 0000000..548f163
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportModel.java
@@ -0,0 +1,75 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  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.apache.cayenne.modeler.editor.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+
+/**
+ * @since 4.1
+ */
+public class DbImportModel extends DefaultTreeModel {
+
+    private DbImportTree dbSchemaTree;
+    private boolean canBeCleaned;
+
+    DbImportModel(TreeNode root) {
+        super(root);
+    }
+
+    private void clearReverseEngineering(ReverseEngineering reverseEngineering) {
+        reverseEngineering.getSchemas().clear();
+        reverseEngineering.getCatalogs().clear();
+        reverseEngineering.getIncludeTables().clear();
+        reverseEngineering.getExcludeTables().clear();
+        reverseEngineering.getIncludeColumns().clear();
+        reverseEngineering.getExcludeColumns().clear();
+        reverseEngineering.getIncludeProcedures().clear();
+        reverseEngineering.getExcludeProcedures().clear();
+    }
+
+    private void preprocessTree() {
+        DbImportTreeNode rootNode = (DbImportTreeNode) getRoot();
+        if (rootNode.getChildCount() == 0) {
+            ReverseEngineering reverseEngineering = ((ReverseEngineering) rootNode.getUserObject());
+            if (canBeCleaned) {
+                clearReverseEngineering(reverseEngineering);
+            }
+            rootNode.add(new DbImportTreeNode(("Configuration is empty.")));
+        }
+    }
+
+    public void reload(TreeNode node) {
+        preprocessTree();
+        super.reload(node);
+        dbSchemaTree.repaint();
+    }
+
+    public void setDbSchemaTree(DbImportTree dbSchemaTree) {
+        this.dbSchemaTree = dbSchemaTree;
+    }
+
+    public void setCanBeCleaned(boolean canBeCleaned) {
+        this.canBeCleaned = canBeCleaned;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportNodeHandler.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportNodeHandler.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportNodeHandler.java
new file mode 100644
index 0000000..ee30a9c
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportNodeHandler.java
@@ -0,0 +1,341 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  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.apache.cayenne.modeler.editor.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeProcedure;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+
+import javax.swing.tree.TreePath;
+import java.awt.Color;
+
+/**
+ * @since 4.1
+ */
+class DbImportNodeHandler {
+
+    private static final Color ACCEPT_COLOR = new Color(60,179,113);
+    private static final Color EXCLUDE_COLOR = new Color(178, 0, 0);
+    static final Color NON_INCLUDE_COLOR = Color.LIGHT_GRAY;
+    static final Color LABEL_COLOR = Color.BLACK;
+    private static final int EXCLUDE_TABLE_RATE = -10000;
+
+    private boolean existFirstLevelIncludeTable;
+    private boolean existCatalogsOrSchemas;
+    private boolean hasEntitiesInEmptyContainer;
+    private DbImportTreeNode dbSchemaNode;
+    private DbImportTree reverseEngineeringTree;
+
+    private boolean namesIsEqual(DbImportTreeNode reverseEngineeringNode) {
+        if (isContainer(reverseEngineeringNode)) {
+            return dbSchemaNode.getSimpleNodeName().equals(reverseEngineeringNode.getSimpleNodeName());
+        } else {
+            return (dbSchemaNode.getSimpleNodeName().toLowerCase().matches(reverseEngineeringNode.getSimpleNodeName().toLowerCase()));
+        }
+    }
+
+    boolean isContainer(DbImportTreeNode node) {
+        return (node.getUserObject().getClass() == Schema.class) || (node.getUserObject().getClass() == Catalog.class);
+    }
+
+    private boolean isEmptyContainer(DbImportTreeNode rootNode) {
+        return ((getChildIncludeTableCount(rootNode) == 0) && (!existFirstLevelIncludeTable));
+    }
+
+    boolean isParentIncluded() {
+        return ((dbSchemaNode.getParent() != null) && (((DbImportTreeNode) dbSchemaNode.getParent()).isColorized()));
+    }
+
+    // Compare node with current rendered node
+    public boolean nodesIsEqual(DbImportTreeNode reverseEngineeringNode) {
+        TreePath[] paths = reverseEngineeringTree.getSelectionPaths();
+        for (TreePath path : paths != null ? paths : new TreePath[0]) {
+            DbImportTreeNode node = (DbImportTreeNode) path.getLastPathComponent();
+            if ((nodesClassesComparation(node.getUserObject().getClass(), dbSchemaNode.getUserObject().getClass()))
+                    && namesIsEqual(node)
+                    && (dbSchemaNode.getLevel() >= node.getLevel())
+                    && (dbSchemaNode.parentsIsEqual(node))) {
+                return true;
+            }
+        }
+        if ((nodesClassesComparation(reverseEngineeringNode.getUserObject().getClass(), dbSchemaNode.getUserObject().getClass()))
+                && namesIsEqual(reverseEngineeringNode)
+                && (dbSchemaNode.getLevel() >= reverseEngineeringNode.getLevel())
+                && (dbSchemaNode.parentsIsEqual(reverseEngineeringNode))) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean checkTreesLevels(DbImportTree dbTree) {
+        if (dbTree.getRootNode().getChildCount() == 0) {
+            return false;
+        }
+        DbImportTreeNode dbNode = (DbImportTreeNode) dbTree.getRootNode().getChildAt(0);
+        int childCount = reverseEngineeringTree.getRootNode().getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            if (((DbImportTreeNode) reverseEngineeringTree.getRootNode().getChildAt(i)).
+                    getUserObject().getClass() == Catalog.class) {
+                if (dbNode.getUserObject().getClass() == Catalog.class) {
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    // Compare reverseEngineeringNode with node.getParent()
+    private boolean compareWithParent(DbImportTreeNode reverseEngineeringNode) {
+        if ((reverseEngineeringNode == null) || (dbSchemaNode.getParent() == null)) {
+            return false;
+        }
+        if ((((DbImportTreeNode)dbSchemaNode.getParent()).getUserObject().getClass() == reverseEngineeringNode.getUserObject().getClass())
+                && (((DbImportTreeNode)dbSchemaNode.getParent()).getSimpleNodeName().equals(reverseEngineeringNode.getSimpleNodeName()))
+                && (((DbImportTreeNode)dbSchemaNode.getParent()).getLevel() >= reverseEngineeringNode.getLevel())
+                && (((DbImportTreeNode)dbSchemaNode.getParent())).parentsIsEqual(reverseEngineeringNode)) {
+            return true;
+        }
+        return false;
+    }
+
+    // Get child IncludeTable's count in node, if exists
+    private int getChildIncludeTableCount(DbImportTreeNode parentNode) {
+        if (parentNode.isIncludeTable()) {
+            return 1;
+        }
+        int childCount = parentNode.getChildCount();
+        int result = 0;
+        for (int i = 0; i < childCount; i++) {
+            DbImportTreeNode tmpNode = (DbImportTreeNode) parentNode.getChildAt(i);
+            if (tmpNode.isIncludeTable()) {
+                result++;
+            }
+        }
+        return result;
+    }
+
+    // Find Exclude-node in configuration
+    private boolean foundExclude(DbImportTreeNode rootNode) {
+        int childCount = rootNode.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            DbImportTreeNode tmpNode = (DbImportTreeNode) rootNode.getChildAt(i);
+            if (tmpNode.getChildCount() > 0) {
+                if (tmpNode.isExcludeTable() || tmpNode.isExcludeProcedure()) {
+                    return true;
+                }
+            }
+            if (dbSchemaNode.getParent() != null) {
+                if (nodesIsEqual(tmpNode)) {
+                    if (tmpNode.isExcludeTable() || tmpNode.isExcludeProcedure()) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /*
+    *  Recursively traverse DbImportTree,
+    *  Increment result if rendered node exists in configuration tree,
+    *  Subtract EXCLUDE_TABLE_RATE from result, if found Exclude-node for rendered node,
+    *  Return 0, if rendered node not found.
+    */
+    int traverseTree(DbImportTreeNode rootNode) {
+        int traverseResult = 0;
+        int childCount = rootNode.getChildCount();
+        boolean hasProcedures = false;
+
+        // Case for empty reverse engineering, which has a include/exclude tables/procedures
+        if ((childCount == 0) && (nodesIsEqual(rootNode))) {
+            traverseResult++;
+        }
+
+        if (nodesIsEqual(rootNode)) {
+            traverseResult++;
+        }
+
+        ReverseEngineering reverseEngineering = reverseEngineeringTree.getReverseEngineering();
+        if ((reverseEngineering.getCatalogs().isEmpty()) && (reverseEngineering.getSchemas().isEmpty())
+                && (reverseEngineering.getIncludeTables().isEmpty())
+                && (!dbSchemaNode.isIncludeProcedure())) {
+            traverseResult++;
+        }
+
+        if (nodesIsEqual(rootNode) && isEmptyContainer(rootNode)) {
+            hasEntitiesInEmptyContainer = true;
+            if (foundExclude(rootNode)) {
+                return EXCLUDE_TABLE_RATE;
+            }
+            return 1;
+        }
+
+        if (compareWithParent(rootNode) && (!rootNode.isReverseEngineering()) &&
+                isEmptyContainer(rootNode) && (dbSchemaNode.isIncludeTable())) {
+            hasEntitiesInEmptyContainer = true;
+            if (foundExclude(rootNode)) {
+                return EXCLUDE_TABLE_RATE;
+            }
+            return 1;
+        }
+
+        if (hasEntitiesInEmptyContainer) {
+            for (int i = 0; i < childCount; i++) {
+                DbImportTreeNode tmpNode = (DbImportTreeNode) rootNode.getChildAt(i);
+                if (dbSchemaNode.isIncludeProcedure() && (nodesIsEqual(tmpNode))) {
+                    int tmpNodeChildCount = tmpNode.getChildCount();
+                    if (tmpNodeChildCount > 0) {
+                        traverseResult += traverseTree((DbImportTreeNode) rootNode.getChildAt(i));
+                    }
+                    traverseResult++;
+                    hasProcedures = true;
+                }
+            }
+            if ((!rootNode.isExcludeTable()) && (!nodesIsEqual(rootNode))
+                    && (!dbSchemaNode.isIncludeProcedure())) {
+                traverseResult++;
+            } else {
+                if ((!hasProcedures) && (!dbSchemaNode.isIncludeProcedure())) {
+                    traverseResult += EXCLUDE_TABLE_RATE;
+                }
+            }
+        }
+
+        for (int i = 0; i < childCount; i++) {
+            DbImportTreeNode tmpNode = (DbImportTreeNode) rootNode.getChildAt(i);
+            if (tmpNode.getChildCount() > 0) {
+                traverseResult += traverseTree(tmpNode);
+                if (tmpNode.isExcludeTable() || tmpNode.isExcludeProcedure()) {
+                    traverseResult += EXCLUDE_TABLE_RATE;
+                }
+            } else if (compareWithParent(tmpNode) && !(existFirstLevelIncludeTable)) {
+                if (!dbSchemaNode.isIncludeProcedure()) {
+                    traverseResult++;
+                }
+            }
+            if (dbSchemaNode.getParent() != null) {
+                if (nodesIsEqual(tmpNode)) {
+                    if (tmpNode.isExcludeTable() || tmpNode.isExcludeProcedure()) {
+                        traverseResult += EXCLUDE_TABLE_RATE;
+                    }
+                    traverseResult++;
+                }
+            }
+        }
+        return traverseResult;
+    }
+
+    Color getColorByNodeType(DbImportTreeNode node) {
+        if ((reverseEngineeringTree.getSelectionPaths() != null) &&(reverseEngineeringTree.getSelectionPaths().length > 1)) {
+            for (TreePath path : reverseEngineeringTree.getSelectionPaths()) {
+                DbImportTreeNode pathNode = (DbImportTreeNode) path.getLastPathComponent();
+                if (pathNode.getSimpleNodeName().equals(dbSchemaNode.getSimpleNodeName())) {
+                    if (pathNode.isExcludeTable() || pathNode.isExcludeProcedure()) {
+                        return EXCLUDE_COLOR;
+                    } else {
+                        return ACCEPT_COLOR;
+                    }
+                }
+            }
+        }
+        if (node.isExcludeTable() || node.isExcludeProcedure()) {
+            return EXCLUDE_COLOR;
+        } else {
+            return ACCEPT_COLOR;
+        }
+    }
+
+    void findFirstLevelIncludeTable() {
+        DbImportTreeNode root = reverseEngineeringTree.getRootNode();
+        int childCount = root.getChildCount();
+        existFirstLevelIncludeTable = false;
+        existCatalogsOrSchemas = false;
+        for (int i = 0; i < childCount; i++) {
+            DbImportTreeNode tmpNode = (DbImportTreeNode) root.getChildAt(i);
+            if (tmpNode.isIncludeTable()) {
+                existFirstLevelIncludeTable = true;
+            }
+            if (isContainer(tmpNode)) {
+                existCatalogsOrSchemas = true;
+            }
+        }
+    }
+
+    // Check, is DatabaseTree started with IncludeTable or IncludeProcedure
+    boolean isFirstNodeIsPrimitive(DbImportTree tree) {
+        final int firstChildIndex = 0;
+        DbImportTreeNode root = tree.getRootNode();
+        if (root.getChildCount() == 0) {
+            return false;
+        }
+        DbImportTreeNode firstElement = (DbImportTreeNode) root.getChildAt(firstChildIndex);
+        if (firstElement.isIncludeTable() || firstElement.isIncludeProcedure()) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean nodesClassesComparation(Class firstClass, Class secondClass) {
+        if (firstClass.equals(secondClass)) {
+            return true;
+        }
+        if ((firstClass.equals(IncludeTable.class)) && (secondClass.equals(ExcludeTable.class))) {
+            return true;
+        }
+        if ((firstClass.equals(ExcludeTable.class)) && (secondClass.equals(IncludeTable.class))) {
+            return true;
+        }
+        if ((firstClass.equals(IncludeProcedure.class)) && (secondClass.equals(ExcludeProcedure.class))) {
+            return true;
+        }
+        if ((firstClass.equals(ExcludeProcedure.class)) && (secondClass.equals(IncludeProcedure.class))) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isExistCatalogsOrSchemas() {
+        return existCatalogsOrSchemas;
+    }
+
+    public boolean getHasEntitiesInEmptyContainer() {
+        return hasEntitiesInEmptyContainer;
+    }
+
+    public void setHasEntitiesInEmptyContainer(boolean newFlag) {
+        hasEntitiesInEmptyContainer = newFlag;
+    }
+
+    public void setDbSchemaNode(DbImportTreeNode dbSchemaNode) {
+        this.dbSchemaNode = dbSchemaNode;
+    }
+
+    public void setReverseEngineeringTree(DbImportTree reverseEngineeringTree) {
+        this.reverseEngineeringTree = reverseEngineeringTree;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTree.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTree.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTree.java
new file mode 100644
index 0000000..c7a0aed
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTree.java
@@ -0,0 +1,207 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  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.apache.cayenne.modeler.editor.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.FilterContainer;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.PatternParam;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.dialog.db.load.TransferableNode;
+
+import javax.swing.JTree;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @since 4.1
+ */
+public class DbImportTree extends JTree {
+
+    private boolean isTransferable;
+    private ReverseEngineering reverseEngineering;
+
+    public DbImportTree(TreeNode node) {
+        super(node);
+    }
+
+    public void translateReverseEngineeringToTree(ReverseEngineering reverseEngineering, boolean isTransferable) {
+        this.isTransferable = isTransferable;
+        this.reverseEngineering = reverseEngineering;
+        DbImportModel model = (DbImportModel) this.getModel();
+        DbImportTreeNode root = (DbImportTreeNode) model.getRoot();
+        root.removeAllChildren();
+        root.setUserObject(reverseEngineering);
+        printCatalogs(reverseEngineering.getCatalogs(), root);
+        printSchemas(reverseEngineering.getSchemas(), root);
+        printIncludeTables(reverseEngineering.getIncludeTables(), root);
+        printParams(reverseEngineering.getExcludeTables(), root);
+        printParams(reverseEngineering.getIncludeColumns(), root);
+        printParams(reverseEngineering.getExcludeColumns(), root);
+        printParams(reverseEngineering.getIncludeProcedures(), root);
+        printParams(reverseEngineering.getExcludeProcedures(), root);
+        model.reload();
+    }
+
+    public DbImportTreeNode findNodeByParentsChain(DbImportTreeNode rootNode, DbImportTreeNode movedNode, int depth) {
+        String parentName = ((DbImportTreeNode) movedNode.getParent()).getSimpleNodeName();
+        if ((rootNode.parentsIsEqual(((DbImportTreeNode) movedNode.getParent())))
+                && (rootNode.getSimpleNodeName().equals(parentName))
+                && ((rootNode.isCatalog()) || (rootNode.isSchema()))) {
+            return rootNode;
+        }
+        for (int i = 0; i < rootNode.getChildCount(); i++) {
+            DbImportTreeNode childNode = (DbImportTreeNode) rootNode.getChildAt(i);
+            DbImportTreeNode node = findNodeByParentsChain(childNode, movedNode, depth++);
+            if (node != null) {
+                return node;
+            }
+        }
+        return null;
+    }
+
+    public DbImportTreeNode findNode(DbImportTreeNode rootNode, DbImportTreeNode movedNode, int depth) {
+        String parentName = movedNode.getSimpleNodeName();
+        if ((rootNode.parentsIsEqual(movedNode))
+                && (rootNode.getSimpleNodeName().equals(parentName))) {
+            return rootNode;
+        }
+        for (int i = 0; i < rootNode.getChildCount(); i++) {
+            DbImportTreeNode childNode = (DbImportTreeNode) rootNode.getChildAt(i);
+            DbImportTreeNode node = findNode(childNode, movedNode, depth++);
+            if (node != null) {
+                return node;
+            }
+        }
+        return null;
+    }
+
+    // Create list of expanded elements
+    private ArrayList<DbImportTreeNode> createTreeExpandList(DbImportTreeNode rootNode, ArrayList<DbImportTreeNode> resultList) {
+        for (int i = 0; i < rootNode.getChildCount(); i++) {
+            DbImportTreeNode childNode = (DbImportTreeNode) rootNode.getChildAt(i);
+            TreePath childPath = new TreePath(childNode.getPath());
+            if (isExpanded(childPath)) {
+                resultList.add(childNode);
+            }
+            if (childNode.getChildCount() > 0) {
+                createTreeExpandList(childNode, resultList);
+            }
+        }
+        return resultList;
+    }
+
+    public ArrayList<DbImportTreeNode> getTreeExpandList() {
+        ArrayList<DbImportTreeNode> resultList = new ArrayList<>();
+        return createTreeExpandList(getRootNode(), resultList);
+    }
+
+    private void expandBeginningWithNode(DbImportTreeNode rootNode, ArrayList<DbImportTreeNode> list) {
+        for (int i = 0; i < rootNode.getChildCount(); i++) {
+            DbImportTreeNode childNode = (DbImportTreeNode) rootNode.getChildAt(i);
+            list.forEach((element) -> {
+                if (element.equals(childNode)) {
+                    this.expandPath(new TreePath(childNode.getPath()));
+                }
+            });
+            if (childNode.getChildCount() > 0) {
+                expandBeginningWithNode(childNode, list);
+            }
+        }
+    }
+
+    public void expandTree(ArrayList<DbImportTreeNode> expandIndexesList) {
+        expandBeginningWithNode(getRootNode(), expandIndexesList);
+    }
+
+    private <T extends PatternParam> void printParams(Collection<T> collection, DbImportTreeNode parent) {
+        for (T element : collection) {
+            DbImportTreeNode node = !isTransferable ? new DbImportTreeNode(element) : new TransferableNode(element);
+            if (!node.getSimpleNodeName().equals("")) {
+                parent.add(node);
+            }
+        }
+    }
+
+    private void printIncludeTables(Collection<IncludeTable> collection, DbImportTreeNode parent) {
+        for (IncludeTable includeTable : collection) {
+            DbImportTreeNode node = !isTransferable ? new DbImportTreeNode(includeTable) : new TransferableNode(includeTable);
+            if (!node.getSimpleNodeName().equals("")) {
+                printParams(includeTable.getIncludeColumns(), node);
+                printParams(includeTable.getExcludeColumns(), node);
+                parent.add(node);
+            }
+        }
+    }
+
+    private void printChildren(FilterContainer container, DbImportTreeNode parent) {
+        printIncludeTables(container.getIncludeTables(), parent);
+        printParams(container.getExcludeTables(), parent);
+        printParams(container.getIncludeColumns(), parent);
+        printParams(container.getExcludeColumns(), parent);
+        printParams(container.getIncludeProcedures(), parent);
+        printParams(container.getExcludeProcedures(), parent);
+    }
+
+    private void printSchemas(Collection<Schema> schemas, DbImportTreeNode parent) {
+        for (Schema schema : schemas) {
+            DbImportTreeNode node = !isTransferable ? new DbImportTreeNode(schema) : new TransferableNode(schema);
+            if (!node.getSimpleNodeName().equals("")) {
+                printChildren(schema, node);
+                parent.add(node);
+            }
+        }
+    }
+
+    private void printCatalogs(Collection<Catalog> catalogs, DbImportTreeNode parent) {
+        for (Catalog catalog : catalogs) {
+            DbImportTreeNode node = !isTransferable ? new DbImportTreeNode(catalog) : new TransferableNode(catalog);
+            if (!node.getSimpleNodeName().equals("")) {
+                printSchemas(catalog.getSchemas(), node);
+                printChildren(catalog, node);
+                parent.add(node);
+            }
+        }
+    }
+
+    public DbImportTreeNode getSelectedNode() {
+        return (DbImportTreeNode) this.getSelectionPath().getLastPathComponent();
+    }
+
+    public DbImportTreeNode getRootNode() {
+        return (DbImportTreeNode) this.getModel().getRoot();
+    }
+
+    public ReverseEngineering getReverseEngineering() {
+        return reverseEngineering;
+    }
+
+    public void setReverseEngineering(ReverseEngineering reverseEngineering) {
+        this.reverseEngineering = reverseEngineering;
+    }
+
+    public boolean isTransferable() {
+        return isTransferable;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellEditor.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellEditor.java
new file mode 100644
index 0000000..2779234
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellEditor.java
@@ -0,0 +1,154 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  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.apache.cayenne.modeler.editor.dbimport;
+
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.action.dbimport.DeleteNodeAction;
+import org.apache.cayenne.modeler.action.dbimport.EditNodeAction;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.util.Util;
+
+import javax.swing.JTree;
+import javax.swing.event.CellEditorListener;
+import javax.swing.event.ChangeEvent;
+import javax.swing.tree.DefaultTreeCellEditor;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.TreePath;
+import java.awt.Component;
+import java.util.EventObject;
+import java.util.regex.Pattern;
+
+/**
+ * @since 4.1
+ */
+public class DbImportTreeCellEditor extends DefaultTreeCellEditor {
+
+    private ProjectController projectController;
+
+    public DbImportTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
+        super(tree, renderer);
+        this.addCellEditorListener(new CellEditorListener() {
+            @Override
+            public void editingStopped(ChangeEvent e) {
+                DbImportTreeCellEditor.this.cancelCellEditing();
+            }
+
+            @Override
+            public void editingCanceled(ChangeEvent e) {
+                editingStopped(e);
+            }
+        });
+
+    }
+
+    @Override
+    public Object getCellEditorValue() {
+        if (tree.getSelectionPath() == null) {
+            return "";
+        }
+        DbImportTreeNode node = (DbImportTreeNode) tree.getSelectionPath().getLastPathComponent();
+        return node.getUserObject();
+    }
+
+    @Override
+    public Component getTreeCellEditorComponent(JTree tree, Object value,
+                                                boolean isSelected, boolean expanded, boolean leaf, int row) {
+        if (value instanceof DbImportTreeNode) {
+            value = ((DbImportTreeNode) value).getSimpleNodeName();
+        }
+        return super.getTreeCellEditorComponent(tree, value, isSelected, expanded,
+                leaf, row);
+    }
+
+    @Override
+    public boolean isCellEditable(EventObject e) {
+        if (tree.getSelectionPath() != null) {
+            // Disable label nodes editing
+            if (((DbImportTreeNode) tree.getSelectionPath().getLastPathComponent()).getUserObject().getClass() == String.class) {
+                return false;
+            }
+            if (tree.getSelectionPath().getLastPathComponent() == tree.getModel().getRoot()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean isValidReverseEngineering() {
+        try {
+            Pattern.compile(super.getCellEditorValue().toString());
+        } catch (Exception exception) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public void cancelCellEditing() {
+        if (tree.getSelectionPath() == null) {
+            return;
+        }
+        if (!Util.isEmptyString(super.getCellEditorValue().toString()) && !insertableNodeExist() && (isValidReverseEngineering())) {
+            EditNodeAction action = projectController.getApplication().getActionManager().getAction(EditNodeAction.class);
+            action.setActionName(super.getCellEditorValue().toString());
+            action.actionPerformed(null);
+        } else {
+            DbImportTreeNode selectedNode = (DbImportTreeNode) tree.getSelectionPath().getLastPathComponent();
+            if (Util.isEmptyString(selectedNode.getSimpleNodeName()) || (insertableNodeExist())) {
+                DeleteNodeAction action = projectController.getApplication().getActionManager().getAction(DeleteNodeAction.class);
+                TreePath parentPath = tree.getSelectionPath().getParentPath();
+                action.actionPerformed(null);
+                tree.setSelectionPath(parentPath);
+            } else {
+                tree.startEditingAtPath(tree.getSelectionPath());
+            }
+        }
+        DbImportTreeNode selectedNode = (DbImportTreeNode) tree.getSelectionPath().getLastPathComponent();
+        ((DbImportModel) tree.getModel()).reload(selectedNode);
+    }
+
+    private boolean equalNodes(int i, DbImportTreeNode parent, DbImportTreeNode selectedElement) {
+        return super.getCellEditorValue().toString().equals(((DbImportTreeNode) parent.getChildAt(i)).getSimpleNodeName()) &&
+                selectedElement.getUserObject().getClass().equals(((DbImportTreeNode) parent.getChildAt(i)).getUserObject().getClass());
+    }
+
+    private boolean insertableNodeExist() {
+        DbImportTreeNode selectedElement;
+        if (tree.getSelectionPath() == null) {
+            selectedElement = (DbImportTreeNode) tree.getModel().getRoot();
+        } else {
+            selectedElement = (DbImportTreeNode) tree.getSelectionPath().getLastPathComponent();
+        }
+        int childCount = selectedElement.getParent().getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            if (equalNodes(i, (DbImportTreeNode) selectedElement.getParent(), selectedElement)) {
+                if (selectedElement.getParent().getChildAt(i) != selectedElement) {
+                    return true;
+                }
+            }
+
+        }
+        return false;
+    }
+
+    public void setProjectController(ProjectController projectController) {
+        this.projectController = projectController;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellRenderer.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellRenderer.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellRenderer.java
new file mode 100644
index 0000000..9d9e505
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellRenderer.java
@@ -0,0 +1,95 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  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.apache.cayenne.modeler.editor.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeColumn;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeProcedure;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeColumn;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.util.ModelerUtil;
+
+import javax.swing.ImageIcon;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import java.awt.Component;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @since 4.1
+ */
+public class DbImportTreeCellRenderer extends DefaultTreeCellRenderer {
+
+    protected DbImportTreeNode node;
+    private Map<Class, String> icons;
+    private Map<Class, String> transferableTreeIcons;
+
+    public DbImportTreeCellRenderer() {
+        super();
+        initIcons();
+        initTrasferableTreeIcons();
+    }
+
+    private void initTrasferableTreeIcons() {
+        transferableTreeIcons = new HashMap<>();
+        transferableTreeIcons.put(Catalog.class, "icon-dbi-catalog.png");
+        transferableTreeIcons.put(Schema.class, "icon-dbi-schema.png");
+        transferableTreeIcons.put(IncludeTable.class, "icon-dbentity.png");
+        transferableTreeIcons.put(IncludeProcedure.class, "icon-stored-procedure.png");
+    }
+
+    private void initIcons() {
+        icons = new HashMap<>();
+        icons.put(Catalog.class, "icon-dbi-catalog.png");
+        icons.put(Schema.class, "icon-dbi-schema.png");
+        icons.put(IncludeTable.class, "icon-dbi-includeTable.png");
+        icons.put(ExcludeTable.class, "icon-dbi-excludeTable.png");
+        icons.put(IncludeColumn.class, "icon-dbi-includeColumn.png");
+        icons.put(ExcludeColumn.class, "icon-dbi-excludeColumn.png");
+        icons.put(IncludeProcedure.class, "icon-dbi-includeProcedure.png");
+        icons.put(ExcludeProcedure.class, "icon-dbi-excludeProcedure.png");
+    }
+
+    private ImageIcon getIconByNodeType(Class nodeClass, boolean isTransferable) {
+        String iconName = !isTransferable ? icons.get(nodeClass) : transferableTreeIcons.get(nodeClass);
+        if (iconName == null) {
+            return null;
+        }
+        return ModelerUtil.buildIcon(iconName);
+    }
+
+    @Override
+    public Component getTreeCellRendererComponent(JTree tree, Object value,
+                                                  boolean sel,
+                                                  boolean expanded,
+                                                  boolean leaf, int row,
+                                                  boolean hasFocus) {
+
+        super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
+        node = (DbImportTreeNode) value;
+        setIcon(getIconByNodeType(node.getUserObject().getClass(), ((DbImportTree) tree).isTransferable()));
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportView.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportView.java
new file mode 100644
index 0000000..3f0bb3b
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportView.java
@@ -0,0 +1,236 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  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.apache.cayenne.modeler.editor.dbimport;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.action.LoadDbSchemaAction;
+import org.apache.cayenne.modeler.action.ReverseEngineeringAction;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.dialog.db.load.TransferableNode;
+import org.apache.cayenne.modeler.util.CayenneAction;
+
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import java.awt.BorderLayout;
+
+/**
+ * @since 4.1
+ */
+public class DbImportView extends JPanel {
+
+    private static final String MAIN_LAYOUT = "fill:160dlu, 5dlu, fill:50dlu, 5dlu, fill:160dlu";
+    private static final String HEADER_LAYOUT = "fill:70dlu, 15dlu, fill:75dlu";
+    private static final String BUTTON_PANEL_LAYOUT = "fill:50dlu";
+    private static final String PROGRESS_PANEL_LAYOUT = "fill:160dlu, 60dlu, fill:160dlu";
+    private static final int ALL_LINE_SPAN = 5;
+
+    private TreeToolbarPanel treeToolbar;
+    private ReverseEngineeringTreePanel treePanel;
+    private ReverseEngineeringConfigPanel configPanel;
+    private DraggableTreePanel draggableTreePanel;
+    private JProgressBar loadDbSchemaProgress;
+    private JProgressBar reverseEngineeringProgress;
+    private CayenneAction.CayenneToolbarButton loadDbSchemaButton;
+
+    private ProjectController projectController;
+
+    public DbImportView(ProjectController projectController) {
+        this.projectController = projectController;
+        initFormElements();
+        initListeners();
+        buildForm();
+        draggableTreePanel.getSourceTree().repaint();
+    }
+
+    private void initListeners() {
+        projectController.addDataMapDisplayListener(e -> {
+            DataMap map = e.getDataMap();
+            treePanel.getReverseEngineeringTree().stopEditing();
+            if (map != null) {
+                treeToolbar.unlockButtons();
+                ReverseEngineering reverseEngineering = DbImportView.this.projectController.getApplication().
+                        getMetaData().get(map, ReverseEngineering.class);
+                if (reverseEngineering == null) {
+                    reverseEngineering = new ReverseEngineering();
+                    DbImportView.this.projectController.getApplication().getMetaData().add(map, reverseEngineering);
+                }
+                configPanel.fillCheckboxes(reverseEngineering);
+                configPanel.initializeTextFields(reverseEngineering);
+                treePanel.updateTree();
+                DbImportTreeNode root = draggableTreePanel.getSourceTree().getRootNode();
+                root.removeAllChildren();
+                draggableTreePanel.updateTree(projectController.getCurrentDataMap());
+                draggableTreePanel.getMoveButton().setEnabled(false);
+                draggableTreePanel.getMoveInvertButton().setEnabled(false);
+            }
+        });
+    }
+
+    private void buildForm() {
+        FormLayout buttonPanelLayout = new FormLayout(BUTTON_PANEL_LAYOUT);
+        DefaultFormBuilder buttonBuilder = new DefaultFormBuilder(buttonPanelLayout);
+        buttonBuilder.append(draggableTreePanel.getMoveButton());
+        buttonBuilder.append(draggableTreePanel.getMoveInvertButton());
+
+        FormLayout layout = new FormLayout(MAIN_LAYOUT);
+        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+        builder.setDefaultDialogBorder();
+        builder.appendSeparator("Database Import Configuration");
+        builder.append(treeToolbar, ALL_LINE_SPAN);
+
+        FormLayout headerLayout = new FormLayout(HEADER_LAYOUT);
+
+        DefaultFormBuilder reverseEngineeringHeaderBuilder = new DefaultFormBuilder(headerLayout);
+        reverseEngineeringHeaderBuilder.append("Import Configuration");
+        ReverseEngineeringAction reverseEngineeringAction = projectController.getApplication().getActionManager().
+                getAction(ReverseEngineeringAction.class);
+        reverseEngineeringAction.setView(this);
+        CayenneAction.CayenneToolbarButton reverseEngineeringButton = (CayenneAction.CayenneToolbarButton)
+                reverseEngineeringAction.buildButton(0);
+        reverseEngineeringButton.setShowingText(true);
+        reverseEngineeringButton.setText("Run Import");
+        reverseEngineeringHeaderBuilder.append(reverseEngineeringButton);
+        builder.append(reverseEngineeringHeaderBuilder.getPanel());
+
+        DefaultFormBuilder databaseHeaderBuilder = new DefaultFormBuilder(headerLayout);
+        databaseHeaderBuilder.append("Database Schema");
+        LoadDbSchemaAction loadDbSchemaAction = projectController.getApplication().getActionManager().
+                getAction(LoadDbSchemaAction.class);
+        loadDbSchemaAction.setDraggableTreePanel(draggableTreePanel);
+        loadDbSchemaButton = (CayenneAction.CayenneToolbarButton) loadDbSchemaAction.buildButton(0);
+        loadDbSchemaButton.setShowingText(true);
+        loadDbSchemaButton.setText("Refresh DB Schema");
+        databaseHeaderBuilder.append(loadDbSchemaButton);
+
+        builder.append("");
+        builder.append(databaseHeaderBuilder.getPanel());
+        builder.append(treePanel);
+        builder.append(buttonBuilder.getPanel());
+        builder.append(draggableTreePanel);
+
+        loadDbSchemaProgress = new JProgressBar();
+        reverseEngineeringProgress = new JProgressBar();
+        loadDbSchemaProgress.setIndeterminate(true);
+        loadDbSchemaProgress.setVisible(false);
+        reverseEngineeringProgress.setIndeterminate(true);
+        reverseEngineeringProgress.setVisible(false);
+        FormLayout progressLayout = new FormLayout(PROGRESS_PANEL_LAYOUT, "fill:10dlu");
+        DefaultFormBuilder progressBarBuilder = new DefaultFormBuilder(progressLayout);
+        progressBarBuilder.append(reverseEngineeringProgress);
+        progressBarBuilder.append(loadDbSchemaProgress);
+        builder.append(progressBarBuilder.getPanel(), ALL_LINE_SPAN);
+
+        builder.append(configPanel, ALL_LINE_SPAN);
+        this.setLayout(new BorderLayout());
+        add(builder.getPanel(), BorderLayout.CENTER);
+    }
+
+    private void initFormElements() {
+        DbImportTreeNode root = new DbImportTreeNode(new ReverseEngineering());
+        DbImportTreeNode draggableTreeRoot = new DbImportTreeNode(new ReverseEngineering());
+        DbImportTree reverseEngineeringTree = new DbImportTree(root);
+        DbImportTree draggableTree = new DbImportTree(new TransferableNode(draggableTreeRoot));
+        DbImportModel model = new DbImportModel(root);
+        model.setCanBeCleaned(true);
+        DbImportModel draggableTreeModel = new DbImportModel(draggableTreeRoot);
+        draggableTreeModel.setCanBeCleaned(false);
+
+        draggableTree.setRootVisible(false);
+        draggableTree.setShowsRootHandles(true);
+        draggableTree.setModel(draggableTreeModel);
+        reverseEngineeringTree.setRootVisible(false);
+        reverseEngineeringTree.setModel(model);
+        reverseEngineeringTree.setShowsRootHandles(true);
+
+        draggableTreePanel = new DraggableTreePanel(projectController, draggableTree, reverseEngineeringTree);
+        treeToolbar = new TreeToolbarPanel(projectController, reverseEngineeringTree, draggableTreePanel);
+        treePanel = new ReverseEngineeringTreePanel(projectController, reverseEngineeringTree, draggableTree);
+        treePanel.setTreeToolbar(treeToolbar);
+
+        model.setDbSchemaTree(draggableTree);
+        draggableTreeModel.setDbSchemaTree(draggableTree);
+        ((ColorTreeRenderer) draggableTreePanel.getSourceTree().getCellRenderer()).
+                setReverseEngineeringTree(reverseEngineeringTree);
+
+        configPanel = new ReverseEngineeringConfigPanel(projectController);
+    }
+
+    public boolean isSkipRelationshipsLoading() {
+        return configPanel.getSkipRelationshipsLoading().isSelected();
+    }
+
+    public boolean isSkipPrimaryKeyLoading() {
+        return configPanel.getSkipPrimaryKeyLoading().isSelected();
+    }
+
+    public boolean isForceDataMapCatalog() {
+        return configPanel.getForceDataMapCatalog().isSelected();
+    }
+
+    public boolean isForceDataMapSchema() {
+        return configPanel.getForceDataMapSchema().isSelected();
+    }
+
+    public boolean isUsePrimitives() {
+        return configPanel.getUsePrimitives().isSelected();
+    }
+
+    public boolean isUseJava7Typed() {
+        return configPanel.getUseJava7Types().isSelected();
+    }
+
+    public String getMeaningfulPk() {
+        return "".equals(configPanel.getMeaningfulPk().getComponent().getText())
+                ? null : configPanel.getMeaningfulPk().getComponent().getText();
+    }
+
+    public String getNamingStrategy() {
+        return (String) configPanel.getStrategyCombo().getSelectedItem();
+    }
+
+    public String getStripFromTableNames() {
+        return configPanel.getStripFromTableNames().getComponent().getText();
+    }
+
+    public JProgressBar getLoadDbSchemaProgress() {
+        return loadDbSchemaProgress;
+    }
+
+    public void lockToolbarButtons() {
+        treeToolbar.changeToolbarButtonsState(false);
+    }
+
+    public void unlockToolbarButtons() {
+        treeToolbar.unlockButtons();
+    }
+
+    public JProgressBar getReverseEngineeringProgress() {
+        return reverseEngineeringProgress;
+    }
+
+    public JButton getLoadDbSchemaButton() {
+        return loadDbSchemaButton;
+    }
+}