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:08 UTC

[02/14] cayenne git commit: CAY-2337 Save reverse engineering configuration with datamap XML

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DefaultPopUpMenu.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DefaultPopUpMenu.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DefaultPopUpMenu.java
new file mode 100644
index 0000000..8fa7ae1
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DefaultPopUpMenu.java
@@ -0,0 +1,86 @@
+/*****************************************************************
+ *   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.dialog.db.load;
+
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.action.DeleteNodeAction;
+import org.apache.cayenne.modeler.action.EditNodeAction;
+
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JTree;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @since 4.1
+ */
+public class DefaultPopUpMenu extends JPopupMenu {
+
+    protected JMenuItem rename;
+    protected JMenuItem delete;
+    protected DbImportTreeNode selectedElement;
+    protected DbImportTreeNode parentElement;
+    protected JTree tree;
+    protected ProjectController projectController;
+
+    public DefaultPopUpMenu() {
+        rename = new JMenuItem("Rename");
+        delete = new JMenuItem("Delete");
+        this.add(rename);
+        this.add(delete);
+        initListeners();
+    }
+
+    private void initListeners() {
+        rename.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                if ((selectedElement != null) && (parentElement != null)) {
+                    projectController.getApplication().getActionManager().getAction(EditNodeAction.class).actionPerformed(e);
+                }
+            }
+        });
+        delete.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                if ((selectedElement != null) && (parentElement != null)) {
+                    projectController.getApplication().getActionManager().getAction(DeleteNodeAction.class).actionPerformed(e);
+                }
+            }
+        });
+    }
+
+    public void setSelectedElement(DbImportTreeNode selectedElement) {
+        this.selectedElement = selectedElement;
+    }
+
+    public void setParentElement(DbImportTreeNode parentElement) {
+        this.parentElement = parentElement;
+    }
+
+    public void setTree(JTree tree) {
+        this.tree = tree;
+    }
+
+    public void setProjectController(ProjectController projectController) {
+        this.projectController = projectController;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/IncludeTablePopUpMenu.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/IncludeTablePopUpMenu.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/IncludeTablePopUpMenu.java
new file mode 100644
index 0000000..2e64246
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/IncludeTablePopUpMenu.java
@@ -0,0 +1,37 @@
+/*****************************************************************
+ *   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.dialog.db.load;
+
+/**
+ * @since 4.1
+ */
+public class IncludeTablePopUpMenu extends RootPopUpMenu {
+
+    public IncludeTablePopUpMenu() {
+        rename.setVisible(true);
+        delete.setVisible(true);
+        addCatalog.setVisible(false);
+        addSchema.setVisible(false);
+        addIncludeTable.setVisible(false);
+        addExcludeTable.setVisible(false);
+        addIncludeProcedure.setVisible(false);
+        addExcludeProcedure.setVisible(false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
index b98313f..1109753 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
@@ -16,35 +16,115 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
+
 package org.apache.cayenne.modeler.dialog.db.load;
 
 import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
 import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
 import org.apache.cayenne.configuration.server.DbAdapterFactory;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
+import org.apache.cayenne.dbsync.merge.token.MergerToken;
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
+import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Procedure;
 import org.apache.cayenne.project.ProjectSaver;
 import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfiguration;
 import org.apache.cayenne.dbsync.reverse.dbimport.DefaultDbImportAction;
 import org.slf4j.Logger;
 
+import javax.swing.JDialog;
+import javax.swing.JOptionPane;
 import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
 
 public class ModelerDbImportAction extends DefaultDbImportAction {
 
+    private static final String DIALOG_TITLE = "Reverse Engineering Result";
+
     @Inject
     private DataMap targetMap;
 
+    private DbLoadResultDialog resultDialog;
+    private boolean isNothingChanged;
+
     public ModelerDbImportAction(@Inject Logger logger,
                                  @Inject ProjectSaver projectSaver,
                                  @Inject DataSourceFactory dataSourceFactory,
                                  @Inject DbAdapterFactory adapterFactory,
                                  @Inject DataMapLoader mapLoader,
                                  @Inject MergerTokenFactoryProvider mergerTokenFactoryProvider,
+                                 @Inject DataChannelMetaData metaData,
                                  @Inject DataChannelDescriptorLoader dataChannelDescriptorLoader) {
-        super(logger, projectSaver, dataSourceFactory, adapterFactory, mapLoader, mergerTokenFactoryProvider, dataChannelDescriptorLoader);
+        super(logger, projectSaver, dataSourceFactory, adapterFactory, mapLoader, mergerTokenFactoryProvider, dataChannelDescriptorLoader, metaData);
+    }
+
+    @Override
+    protected Collection<MergerToken> log(List<MergerToken> tokens) {
+        resultDialog = new DbLoadResultDialog(DIALOG_TITLE);
+        logger.info("");
+        if (tokens.isEmpty()) {
+            logger.info("Detected changes: No changes to import.");
+            isNothingChanged = true;
+            return tokens;
+        }
+
+        logger.info("Detected changes: ");
+        for (MergerToken token : tokens) {
+            String logString = String.format("    %-20s %s", token.getTokenName(), token.getTokenValue());
+            logger.info(logString);
+            resultDialog.addRowToOutput(logString);
+            isNothingChanged = false;
+        }
+
+        logger.info("");
+        resultDialog.setVisible(true);
+
+        return tokens;
+    }
+
+    @Override
+    protected boolean syncProcedures(DataMap targetDataMap, DataMap loadedDataMap, FiltersConfig filters) {
+        Collection<Procedure> procedures = loadedDataMap.getProcedures();
+
+        boolean hasChanges = false;
+        for (Procedure procedure : procedures) {
+            PatternFilter proceduresFilter = filters.proceduresFilter(procedure.getCatalog(), procedure.getSchema());
+            if (proceduresFilter == null || !proceduresFilter.isIncluded(procedure.getName())) {
+                continue;
+            }
+
+            Procedure oldProcedure = targetDataMap.getProcedure(procedure.getName());
+            // maybe we need to compare oldProcedure's and procedure's fully qualified names?
+            if (oldProcedure != null) {
+                targetDataMap.removeProcedure(procedure.getName());
+                String logString = String.format("    %-20s %s", "Replace procedure ", procedure.getName());
+                logger.info(logString);
+                resultDialog.addRowToOutput(logString);
+            } else {
+                String logString = String.format("    %-20s %s", "Add new procedure ", procedure.getName());
+                logger.info(logString);
+                resultDialog.addRowToOutput(logString);
+            }
+            targetDataMap.addProcedure(procedure);
+            if (!resultDialog.isVisible()) {
+                resultDialog.setVisible(true);
+            }
+            isNothingChanged = false;
+            hasChanges = true;
+        }
+        if ((isNothingChanged)) {
+            JOptionPane optionPane = new JOptionPane("Detected changes: No changes to import.", JOptionPane.PLAIN_MESSAGE);
+            JDialog dialog = optionPane.createDialog(DIALOG_TITLE);
+            dialog.setModal(false);
+            dialog.setAlwaysOnTop(true);
+            dialog.setVisible(true);
+        }
+        return hasChanges;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/RootPopUpMenu.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/RootPopUpMenu.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/RootPopUpMenu.java
new file mode 100644
index 0000000..0e3ef1d
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/RootPopUpMenu.java
@@ -0,0 +1,133 @@
+/*****************************************************************
+ *   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.dialog.db.load;
+
+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.AddSchemaAction;
+
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @since 4.1
+ */
+public class RootPopUpMenu extends DefaultPopUpMenu {
+
+    private static final int FIRST_POSITION = 0;
+
+    protected JMenuItem addItem;
+    protected JMenuItem addCatalog;
+    protected JMenuItem addSchema;
+    protected JMenuItem addIncludeTable;
+    protected JMenuItem addExcludeTable;
+    protected JMenuItem addIncludeColumn;
+    protected JMenuItem addExcludeColumn;
+    protected JMenuItem addIncludeProcedure;
+    protected JMenuItem addExcludeProcedure;
+
+
+    public RootPopUpMenu() {
+        initPopUpMenuElements();
+        initListeners();
+        this.add(addItem, FIRST_POSITION);
+        delete.setVisible(false);
+        rename.setVisible(false);
+    }
+
+    private void initListeners() {
+        addCatalog.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                projectController.getApplication().getActionManager().getAction(AddCatalogAction.class).actionPerformed(e);
+            }
+        });
+        addSchema.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                projectController.getApplication().getActionManager().getAction(AddSchemaAction.class).actionPerformed(e);
+            }
+        });
+        addIncludeTable.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                projectController.getApplication().getActionManager().getAction(AddIncludeTableAction.class).actionPerformed(e);
+            }
+        });
+        addExcludeTable.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                projectController.getApplication().getActionManager().getAction(AddExcludeTableAction.class).actionPerformed(e);
+            }
+        });
+        addIncludeColumn.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                projectController.getApplication().getActionManager().getAction(AddIncludeColumnAction.class).actionPerformed(e);
+            }
+        });
+        addExcludeColumn.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                projectController.getApplication().getActionManager().getAction(AddExcludeColumnAction.class).actionPerformed(e);
+            }
+        });
+        addIncludeProcedure.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                projectController.getApplication().getActionManager().getAction(AddIncludeProcedureAction.class).actionPerformed(e);
+            }
+        });
+        addExcludeProcedure.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                projectController.getApplication().getActionManager().getAction(AddExcludeProcedureAction.class).actionPerformed(e);
+            }
+        });
+    }
+
+    private void initPopUpMenuElements() {
+        addItem = new JMenu("Add");
+        addCatalog = new JMenuItem("Catalog");
+        addSchema = new JMenuItem("Schema");
+        addIncludeTable = new JMenuItem("Include Table");
+        addExcludeTable = new JMenuItem("Exclude Table");
+        addIncludeColumn = new JMenuItem("Include Column");
+        addExcludeColumn = new JMenuItem("Exclude Column");
+        addIncludeProcedure = new JMenuItem("Include Procedure");
+        addExcludeProcedure = new JMenuItem("Exclude Procedure");
+
+        addItem.add(addSchema);
+        addItem.add(addCatalog);
+        addItem.add(addIncludeTable);
+        addItem.add(addExcludeTable);
+        addItem.add(addIncludeColumn);
+        addItem.add(addExcludeColumn);
+        addItem.add(addIncludeProcedure);
+        addItem.add(addExcludeProcedure);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/SchemaPopUpMenu.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/SchemaPopUpMenu.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/SchemaPopUpMenu.java
new file mode 100644
index 0000000..a5f86bc
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/SchemaPopUpMenu.java
@@ -0,0 +1,33 @@
+/*****************************************************************
+ *   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.dialog.db.load;
+
+/**
+ * @since 4.1
+ */
+public class SchemaPopUpMenu extends RootPopUpMenu {
+
+    public SchemaPopUpMenu() {
+        rename.setVisible(true);
+        delete.setVisible(true);
+        addSchema.setVisible(false);
+        addCatalog.setVisible(false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/TransferableNode.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/TransferableNode.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/TransferableNode.java
new file mode 100644
index 0000000..394eb09
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/TransferableNode.java
@@ -0,0 +1,74 @@
+/*****************************************************************
+ *   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.dialog.db.load;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.FilterContainer;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
+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 java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+
+/**
+ * @since 4.1
+ */
+public class TransferableNode extends DbImportTreeNode implements Transferable {
+
+    private static final DataFlavor catalogFlavor = new DataFlavor(Catalog.class, Catalog.class.getSimpleName());
+    private static final DataFlavor schemaFlavor = new DataFlavor(Schema.class, Schema.class.getSimpleName());
+    private static final DataFlavor includeTableFlavor = new DataFlavor(IncludeTable.class, IncludeTable.class.getSimpleName());
+    private static final DataFlavor patternParamFlavor = new DataFlavor(PatternParam.class, PatternParam.class.getSimpleName());
+    public static final DataFlavor[] flavors = new DataFlavor[] { catalogFlavor, schemaFlavor,
+                                                                    includeTableFlavor, patternParamFlavor };
+
+    public TransferableNode(Object userObject) {
+        this.userObject = userObject;
+    }
+
+    @Override
+    public DataFlavor[] getTransferDataFlavors() {
+        return flavors;
+    }
+
+    @Override
+    public boolean isDataFlavorSupported(DataFlavor flavor) {
+        for (DataFlavor dataFlavor : flavors) {
+            if (flavor.equals(dataFlavor)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+        if (isDataFlavorSupported(flavor)) {
+            return userObject;
+        } else {
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DBConnectionInfoEditorView.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DBConnectionInfoEditorView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DBConnectionInfoEditorView.java
index 4fb49a3..1e4abe5 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DBConnectionInfoEditorView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DBConnectionInfoEditorView.java
@@ -56,7 +56,7 @@ public class DBConnectionInfoEditorView extends JPanel {
         url = new JTextField();
         userName = new JTextField();
         password = new JPasswordField();
-        labels = new ArrayList<JLabel>();
+        labels = new ArrayList<>();
 
         // assemble
         FormLayout layout = new FormLayout("right:pref, 3dlu, fill:160dlu:grow", "");

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ColorTreeRenderer.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ColorTreeRenderer.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ColorTreeRenderer.java
new file mode 100644
index 0000000..da0d474
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/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;
+
+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.DbImportNodeHandler.LABEL_COLOR;
+import static org.apache.cayenne.modeler.editor.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 bypassResult = handler.bypassTree(root);
+        if (bypassResult > 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/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java
index 16b0694..5aa2544 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java
@@ -53,8 +53,9 @@ public class DataMapTabbedView extends JTabbedPane {
         // note that those panels that have no internal scrollable tables
         // must be wrapped in a scroll pane
         JScrollPane dataMapView = new JScrollPane(new DataMapView(mediator));
+        JScrollPane dbImportView = new JScrollPane(new DbImportView(mediator));
         addTab("DataMap", dataMapView);
-
+        addTab("DbImport", dbImportView);
     }
 }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapView.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapView.java
index f7cfc49..a313bd0 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapView.java
@@ -275,7 +275,7 @@ public class DataMapView extends JPanel {
                 updateDefaultClientSuperclass();
             }
         });
-        
+
         updateDefaultCatalog.addActionListener(new ActionListener() {
 
             public void actionPerformed(ActionEvent e) {
@@ -489,7 +489,7 @@ public class DataMapView extends JPanel {
         dataMap.setDefaultClientSuperclass(newSuperclass);
         eventController.fireDataMapEvent(new DataMapEvent(this, dataMap));
     }
-    
+
     void setDefaultCatalog(String newCatalog) {
         DataMap dataMap = eventController.getCurrentDataMap();
 
@@ -593,7 +593,7 @@ public class DataMapView extends JPanel {
         LinkDataMapAction action = eventController.getApplication().getActionManager().getAction(LinkDataMapAction.class);
         action.linkDataMap(map, node);
     }
-    
+
     void updateDefaultCatalog() {
         DataMap dataMap = eventController.getCurrentDataMap();
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportModel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportModel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportModel.java
new file mode 100644
index 0000000..749ffb0
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/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;
+
+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/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportNodeHandler.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportNodeHandler.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportNodeHandler.java
new file mode 100644
index 0000000..3b33ad7
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/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;
+
+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 bypasses 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 bypassTree(DbImportTreeNode rootNode) {
+        int bypassResult = 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))) {
+            bypassResult++;
+        }
+
+        if (nodesIsEqual(rootNode)) {
+            bypassResult++;
+        }
+
+        ReverseEngineering reverseEngineering = reverseEngineeringTree.getReverseEngineering();
+        if ((reverseEngineering.getCatalogs().isEmpty()) && (reverseEngineering.getSchemas().isEmpty())
+                && (reverseEngineering.getIncludeTables().isEmpty())
+                && (!dbSchemaNode.isIncludeProcedure())) {
+            bypassResult++;
+        }
+
+        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) {
+                        bypassResult += bypassTree((DbImportTreeNode) rootNode.getChildAt(i));
+                    }
+                    bypassResult++;
+                    hasProcedures = true;
+                }
+            }
+            if ((!rootNode.isExcludeTable()) && (!nodesIsEqual(rootNode))
+                    && (!dbSchemaNode.isIncludeProcedure())) {
+                bypassResult++;
+            } else {
+                if ((!hasProcedures) && (!dbSchemaNode.isIncludeProcedure())) {
+                    bypassResult += EXCLUDE_TABLE_RATE;
+                }
+            }
+        }
+
+        for (int i = 0; i < childCount; i++) {
+            DbImportTreeNode tmpNode = (DbImportTreeNode) rootNode.getChildAt(i);
+            if (tmpNode.getChildCount() > 0) {
+                bypassResult += bypassTree(tmpNode);
+                if (tmpNode.isExcludeTable() || tmpNode.isExcludeProcedure()) {
+                    bypassResult += EXCLUDE_TABLE_RATE;
+                }
+            } else if (compareWithParent(tmpNode) && !(existFirstLevelIncludeTable)) {
+                if (!dbSchemaNode.isIncludeProcedure()) {
+                    bypassResult++;
+                }
+            }
+            if (dbSchemaNode.getParent() != null) {
+                if (nodesIsEqual(tmpNode)) {
+                    if (tmpNode.isExcludeTable() || tmpNode.isExcludeProcedure()) {
+                        bypassResult += EXCLUDE_TABLE_RATE;
+                    }
+                    bypassResult++;
+                }
+            }
+        }
+        return bypassResult;
+    }
+
+    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/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTree.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTree.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTree.java
new file mode 100644
index 0000000..6862c82
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/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;
+
+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/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTreeCellEditor.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTreeCellEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTreeCellEditor.java
new file mode 100644
index 0000000..6c96e31
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/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;
+
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.action.DeleteNodeAction;
+import org.apache.cayenne.modeler.action.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/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTreeCellRenderer.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTreeCellRenderer.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTreeCellRenderer.java
new file mode 100644
index 0000000..82a1cd5
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTreeCellRenderer.java
@@ -0,0 +1,96 @@
+/*****************************************************************
+ *   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.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/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportView.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportView.java
new file mode 100644
index 0000000..453ce00
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/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;
+
+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;
+
+    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;
+    }
+}