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

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

Repository: cayenne
Updated Branches:
  refs/heads/master 85316fd29 -> d56d9a6a3


http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DraggableTreePanel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DraggableTreePanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DraggableTreePanel.java
new file mode 100644
index 0000000..5418f0f
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DraggableTreePanel.java
@@ -0,0 +1,428 @@
+/*****************************************************************
+ *   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.map.DataMap;
+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.AddSchemaAction;
+import org.apache.cayenne.modeler.action.MoveImportNodeAction;
+import org.apache.cayenne.modeler.action.MoveInvertNodeAction;
+import org.apache.cayenne.modeler.action.TreeManipulationAction;
+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.DropMode;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.TransferHandler;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.TreePath;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @since 4.1
+ */
+public class DraggableTreePanel extends JScrollPane {
+
+    private static final int ROOT_LEVEL = 14;
+    private static final int FIRST_LEVEL = 11;
+    private static final int SECOND_LEVEL = 8;
+    private static final int THIRD_LEVEL = 5;
+    private static final int FOURTH_LEVEL = 2;
+    private static final int FIFTH_LEVEL = 3;
+    private static final String MOVE_BUTTON_LABEL = "Include";
+    private static final String MOVE_INV_BUTTON_LABEL = "Exclude";
+
+    private DbImportTree sourceTree;
+    private DbImportTree targetTree;
+    private CayenneAction.CayenneToolbarButton moveButton;
+    private CayenneAction.CayenneToolbarButton moveInvertButton;
+    private Map<DataMap, ReverseEngineering> databaseStructures;
+
+    private ProjectController projectController;
+    private Map<Class, Integer> levels;
+    private Map<Class, List<Class>> insertableLevels;
+    private Map<Class, Class> actions;
+
+    public DraggableTreePanel(ProjectController projectController, DbImportTree sourceTree, DbImportTree targetTree) {
+        super(sourceTree);
+        this.targetTree = targetTree;
+        this.sourceTree = sourceTree;
+        this.projectController = projectController;
+        this.databaseStructures = new HashMap<>();
+        initLevels();
+        initElement();
+        initActions();
+        initListeners();
+    }
+
+    private void initActions() {
+        actions = new HashMap<>();
+        actions.put(Catalog.class, AddCatalogAction.class);
+        actions.put(Schema.class, AddSchemaAction.class);
+        actions.put(IncludeTable.class, AddIncludeTableAction.class);
+        actions.put(ExcludeTable.class, AddExcludeTableAction.class);
+        actions.put(IncludeColumn.class, AddIncludeColumnAction.class);
+        actions.put(ExcludeColumn.class, AddExcludeColumnAction.class);
+        actions.put(IncludeProcedure.class, AddIncludeProcedureAction.class);
+        actions.put(ExcludeProcedure.class, AddExcludeProcedureAction.class);
+    }
+
+    public void updateTree(DataMap dataMap) {
+        DbImportModel model = (DbImportModel) sourceTree.getModel();
+        model.reload();
+        if (databaseStructures.get(dataMap) != null) {
+            sourceTree.setReverseEngineering(databaseStructures.get(dataMap));
+            sourceTree.translateReverseEngineeringToTree(databaseStructures.get(dataMap), true);
+            sourceTree.setEnabled(true);
+        } else {
+            sourceTree.setEnabled(false);
+        }
+    }
+
+    private void initListeners() {
+        sourceTree.addKeyListener(new KeyListener() {
+            @Override
+            public void keyTyped(KeyEvent e) {}
+
+            @Override
+            public void keyPressed(KeyEvent e) {
+                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                    sourceTree.setSelectionRow(-1);
+                    moveButton.setEnabled(false);
+                    moveInvertButton.setEnabled(false);
+                }
+            }
+
+            @Override
+            public void keyReleased(KeyEvent e) {}
+        });
+        targetTree.addKeyListener(new KeyListener() {
+            @Override
+            public void keyTyped(KeyEvent e) {}
+
+            @Override
+            public void keyPressed(KeyEvent e) {
+                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                    targetTree.setSelectionRow(-1);
+                }
+            }
+
+            @Override
+            public void keyReleased(KeyEvent e) {}
+        });
+        targetTree.addTreeSelectionListener(e -> {
+            DbImportModel model = (DbImportModel) sourceTree.getModel();
+            DbImportTreeNode root = (DbImportTreeNode) model.getRoot();
+            sourceTree.repaint();
+            if (root.getChildCount() > 0) {
+                model.nodesChanged(root, new int[]{root.getChildCount() - 1});
+            }
+            if (canBeMoved()) {
+                moveButton.setEnabled(true);
+                if (canBeInverted()) {
+                    moveInvertButton.setEnabled(true);
+                } else {
+                    moveInvertButton.setEnabled(false);
+                }
+            } else {
+                moveButton.setEnabled(false);
+                moveInvertButton.setEnabled(false);
+            }
+        });
+        targetTree.setDragEnabled(true);
+        targetTree.setTransferHandler(new TransferHandler() {
+
+            @Override
+            public int getSourceActions(JComponent c) {
+                return COPY_OR_MOVE;
+            }
+
+            @Override
+            public boolean canImport(TransferSupport support) {
+                if (!support.isDrop()) {
+                    return false;
+                }
+                return true;
+            }
+
+            @Override
+            public boolean importData(TransferSupport support) {
+                if (!canImport(support)) {
+                    return false;
+                }
+                if (!canBeMoved()) {
+                    return false;
+                }
+                Transferable transferable = support.getTransferable();
+                DbImportTreeNode[] transferData = null;
+                try {
+                    for (DataFlavor dataFlavor : transferable.getTransferDataFlavors()) {
+                        transferData = (DbImportTreeNode[]) transferable.getTransferData(dataFlavor);
+                    }
+                } catch (IOException | UnsupportedFlavorException e) {
+                    return false;
+                }
+                if (transferData != null) {
+                    MoveImportNodeAction action = projectController.getApplication().
+                            getActionManager().getAction(MoveImportNodeAction.class);
+                    action.setSourceTree(sourceTree);
+                    action.setTargetTree(targetTree);
+                    action.setPanel(DraggableTreePanel.this);
+                    action.performAction(null);
+                    return true;
+                }
+                return false;
+            }
+        });
+    }
+
+    private boolean canBeInverted() {
+        if (sourceTree.getSelectionPath() != null) {
+            DbImportTreeNode selectedElement = sourceTree.getSelectedNode();
+            if (selectedElement == null) {
+                return false;
+            }
+            if (levels.get(selectedElement.getUserObject().getClass()) < SECOND_LEVEL) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void initElement() {
+        sourceTree.setDragEnabled(true);
+        sourceTree.setCellRenderer(new ColorTreeRenderer());
+        sourceTree.setDropMode(DropMode.INSERT);
+        sourceTree.setTransferHandler(new TransferHandler() {
+
+            @Override
+            public int getSourceActions(JComponent c) {
+                return COPY;
+            }
+
+            @Override
+            public Transferable createTransferable(JComponent c) {
+                JTree tree = (JTree) c;
+                TreePath[] paths = tree.getSelectionPaths();
+                DbImportTreeNode[] nodes = new DbImportTreeNode[paths.length];
+                for (int i = 0; i < paths.length; i++) {
+                    nodes[i] = (DbImportTreeNode) paths[i].getLastPathComponent();
+                }
+                return new Transferable() {
+                    @Override
+                    public DataFlavor[] getTransferDataFlavors() {
+                        return TransferableNode.flavors;
+                    }
+
+                    @Override
+                    public boolean isDataFlavorSupported(DataFlavor flavor) {
+                        return true;
+                    }
+
+                    @Override
+                    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+                        return nodes;
+                    }
+                };
+            }
+        });
+        sourceTree.addTreeSelectionListener(e -> {
+            if (sourceTree.getLastSelectedPathComponent() != null) {
+                if (canBeMoved()) {
+                    moveButton.setEnabled(true);
+                    if (canBeInverted()) {
+                        moveInvertButton.setEnabled(true);
+                    } else {
+                        moveInvertButton.setEnabled(false);
+                    }
+                } else {
+                    moveInvertButton.setEnabled(false);
+                    moveButton.setEnabled(false);
+                }
+            }
+        });
+
+        sourceTree.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mouseClicked(MouseEvent e) {
+                if (sourceTree.getRowForLocation(e.getX(),e.getY()) == -1) {
+                    sourceTree.setSelectionRow(-1);
+                    moveInvertButton.setEnabled(false);
+                    moveButton.setEnabled(false);
+                }
+            }
+        });
+
+        MoveImportNodeAction action = projectController.getApplication().
+                getActionManager().getAction(MoveImportNodeAction.class);
+        action.setPanel(this);
+        action.setSourceTree(sourceTree);
+        action.setTargetTree(targetTree);
+        moveButton = (CayenneAction.CayenneToolbarButton) action.buildButton();
+        moveButton.setShowingText(true);
+        moveButton.setText(MOVE_BUTTON_LABEL);
+        MoveInvertNodeAction actionInv = projectController.getApplication().
+                getActionManager().getAction(MoveInvertNodeAction.class);
+        actionInv.setPanel(this);
+        actionInv.setSourceTree(sourceTree);
+        actionInv.setTargetTree(targetTree);
+        moveInvertButton = (CayenneAction.CayenneToolbarButton) actionInv.buildButton();
+        moveInvertButton.setShowingText(true);
+        moveInvertButton.setText(MOVE_INV_BUTTON_LABEL);
+
+
+        DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) sourceTree.getCellRenderer();
+        renderer.setLeafIcon(null);
+        renderer.setClosedIcon(null);
+        renderer.setOpenIcon(null);
+    }
+
+    private void initLevels() {
+        levels = new HashMap<>();
+        levels.put(ReverseEngineering.class, ROOT_LEVEL);
+        levels.put(Catalog.class, FIRST_LEVEL);
+        levels.put(Schema.class, SECOND_LEVEL);
+        levels.put(IncludeTable.class, THIRD_LEVEL);
+        levels.put(IncludeColumn.class, FOURTH_LEVEL);
+        levels.put(ExcludeColumn.class, FOURTH_LEVEL);
+        levels.put(ExcludeTable.class, FIFTH_LEVEL);
+        levels.put(IncludeProcedure.class, FIFTH_LEVEL);
+        levels.put(ExcludeProcedure.class, FIFTH_LEVEL);
+
+        insertableLevels = new HashMap<>();
+        List<Class> rootLevelClasses = new ArrayList<>();
+        rootLevelClasses.add(Catalog.class);
+        rootLevelClasses.add(Schema.class);
+        rootLevelClasses.add(IncludeTable.class);
+        rootLevelClasses.add(ExcludeTable.class);
+        rootLevelClasses.add(IncludeColumn.class);
+        rootLevelClasses.add(ExcludeColumn.class);
+        rootLevelClasses.add(IncludeProcedure.class);
+        rootLevelClasses.add(ExcludeProcedure.class);
+
+        List<Class> catalogLevelClasses = new ArrayList<>();
+        catalogLevelClasses.add(Schema.class);
+        catalogLevelClasses.add(IncludeTable.class);
+        catalogLevelClasses.add(ExcludeTable.class);
+        catalogLevelClasses.add(IncludeColumn.class);
+        catalogLevelClasses.add(ExcludeColumn.class);
+        catalogLevelClasses.add(IncludeProcedure.class);
+        catalogLevelClasses.add(ExcludeProcedure.class);
+
+        List<Class> schemaLevelClasses = new ArrayList<>();
+        schemaLevelClasses.add(IncludeTable.class);
+        schemaLevelClasses.add(ExcludeTable.class);
+        schemaLevelClasses.add(IncludeColumn.class);
+        schemaLevelClasses.add(ExcludeColumn.class);
+        schemaLevelClasses.add(IncludeProcedure.class);
+        schemaLevelClasses.add(ExcludeProcedure.class);
+
+        List<Class> includeTableLevelClasses = new ArrayList<>();
+        includeTableLevelClasses.add(IncludeColumn.class);
+        includeTableLevelClasses.add(ExcludeColumn.class);
+
+        insertableLevels.put(ReverseEngineering.class, rootLevelClasses);
+        insertableLevels.put(Catalog.class, catalogLevelClasses);
+        insertableLevels.put(Schema.class, schemaLevelClasses);
+        insertableLevels.put(IncludeTable.class, includeTableLevelClasses);
+    }
+
+    private boolean canBeMoved() {
+        if (sourceTree.getSelectionPath() != null) {
+            DbImportTreeNode selectedElement = sourceTree.getSelectedNode();
+            if (selectedElement == null) {
+                return false;
+            }
+            Class draggableElementClass = selectedElement.getUserObject().getClass();
+            Class reverseEngineeringElementClass;
+            if (targetTree.getSelectionPath() != null) {
+                selectedElement = targetTree.getSelectedNode();
+                DbImportTreeNode parent = (DbImportTreeNode) selectedElement.getParent();
+                if (parent != null) {
+                    reverseEngineeringElementClass = parent.getUserObject().getClass();
+                } else {
+                    reverseEngineeringElementClass = selectedElement.getUserObject().getClass();
+                }
+            } else {
+                reverseEngineeringElementClass = ReverseEngineering.class;
+            }
+            List<Class> containsList = insertableLevels.get(reverseEngineeringElementClass);
+            return containsList.contains(draggableElementClass);
+        }
+        return false;
+    }
+
+    public JButton getMoveButton() {
+        return moveButton;
+    }
+
+    public JButton getMoveInvertButton() {
+        return moveInvertButton;
+    }
+
+    public TreeManipulationAction getActionByNodeType(Class nodeType) {
+        Class actionClass = actions.get(nodeType);
+        if (actionClass != null) {
+            TreeManipulationAction action = (TreeManipulationAction) projectController.getApplication().
+                    getActionManager().getAction(actionClass);
+            return action;
+        }
+        return null;
+    }
+
+    public void bindReverseEngineeringToDatamap(DataMap dataMap, ReverseEngineering reverseEngineering) {
+        databaseStructures.put(dataMap, reverseEngineering);
+    }
+
+    public DbImportTree getSourceTree() {
+        return sourceTree;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringConfigPanel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringConfigPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringConfigPanel.java
new file mode 100644
index 0000000..65c9282
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringConfigPanel.java
@@ -0,0 +1,223 @@
+/*****************************************************************
+ *   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.util.NameGeneratorPreferences;
+import org.apache.cayenne.modeler.util.TextAdapter;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Vector;
+
+/**
+ * @since 4.1
+ */
+public class ReverseEngineeringConfigPanel extends JPanel {
+
+    private static final String DATA_FIELDS_LAYOUT = "right:pref, 3dlu, fill:235dlu";
+
+    private JComboBox<String> strategyCombo;
+    private TextAdapter meaningfulPk;
+    private TextAdapter stripFromTableNames;
+    private JCheckBox skipRelationshipsLoading;
+    private JCheckBox skipPrimaryKeyLoading;
+    private JCheckBox forceDataMapCatalog;
+    private JCheckBox forceDataMapSchema;
+    private JCheckBox usePrimitives;
+    private JCheckBox useJava7Types;
+
+    private ProjectController projectController;
+
+    ReverseEngineeringConfigPanel(ProjectController projectController) {
+        this.projectController = projectController;
+        initFormElements();
+        initListeners();
+        buildView();
+    }
+
+    private void buildView() {
+        FormLayout panelLayout = new FormLayout(DATA_FIELDS_LAYOUT);
+        DefaultFormBuilder panelBuilder = new DefaultFormBuilder(panelLayout);
+        panelBuilder.setDefaultDialogBorder();
+
+        panelBuilder.append("Tables with Meaningful PK Pattern:", meaningfulPk.getComponent());
+        panelBuilder.append("Strip from table names:", stripFromTableNames.getComponent());
+        panelBuilder.append("Skip relationships loading:", skipRelationshipsLoading);
+        panelBuilder.append("Skip primary key loading:", skipPrimaryKeyLoading);
+        panelBuilder.append("Force datamap catalog:", forceDataMapCatalog);
+        panelBuilder.append("Force datamap schema:", forceDataMapSchema);
+        panelBuilder.append("Use Java primitive types:", usePrimitives);
+        panelBuilder.append("Use java.util.Date type:", useJava7Types);
+        panelBuilder.append(strategyCombo);
+
+        add(panelBuilder.getPanel());
+    }
+
+    void fillCheckboxes(ReverseEngineering reverseEngineering) {
+        skipRelationshipsLoading.setSelected(reverseEngineering.getSkipRelationshipsLoading());
+        skipPrimaryKeyLoading.setSelected(reverseEngineering.getSkipPrimaryKeyLoading());
+        forceDataMapCatalog.setSelected(reverseEngineering.isForceDataMapCatalog());
+        forceDataMapSchema.setSelected(reverseEngineering.isForceDataMapSchema());
+        usePrimitives.setSelected(reverseEngineering.isUsePrimitives());
+        useJava7Types.setSelected(reverseEngineering.isUseJava7Types());
+    }
+
+    void initializeTextFields(ReverseEngineering reverseEngineering) {
+        meaningfulPk.setText(reverseEngineering.getMeaningfulPkTables());
+        stripFromTableNames.setText(reverseEngineering.getStripFromTableNames());
+    }
+
+    private ReverseEngineering getReverseEngineeringBySelectedMap() {
+        DataMap dataMap = projectController.getCurrentDataMap();
+        return projectController.getApplication().getMetaData().get(dataMap, ReverseEngineering.class);
+    }
+
+    private void initStrategy() {
+        Vector<String> arr = NameGeneratorPreferences
+                .getInstance()
+                .getLastUsedStrategies();
+        strategyCombo.setModel(new DefaultComboBoxModel<>(arr));
+    }
+
+    private void initFormElements() {
+        strategyCombo = new JComboBox<>();
+        strategyCombo.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setNamingStrategy(
+                    (String) ReverseEngineeringConfigPanel.this.getStrategyCombo().getSelectedItem()
+            );
+            projectController.setDirty(true);
+        });
+        strategyCombo.setVisible(false);
+
+        JTextField meaningfulPkField = new JTextField();
+        meaningfulPkField.setToolTipText("<html>Regular expression to filter tables with meaningful primary keys.<br>" +
+                "Multiple expressions divided by comma can be used.<br>" +
+                "Example: <b>^table1|^table2|^prefix.*|table_name</b></html>");
+        meaningfulPk = new TextAdapter(meaningfulPkField) {
+            protected void updateModel(String text) {
+                getReverseEngineeringBySelectedMap().setMeaningfulPkTables(text);
+                projectController.setDirty(true);
+            }
+        };
+
+        JTextField stripFromTableNamesField = new JTextField();
+        stripFromTableNamesField.setToolTipText("<html>Regex that matches the part of the table name that needs to be stripped off " +
+                "when generating ObjEntity name</html>");
+        stripFromTableNames = new TextAdapter(stripFromTableNamesField) {
+            protected void updateModel(String text) {
+                getReverseEngineeringBySelectedMap().setStripFromTableNames(text);
+                projectController.setDirty(true);
+            }
+        };
+
+        skipRelationshipsLoading = new JCheckBox();
+        skipRelationshipsLoading.setToolTipText("<html>Whether to load relationships.</html>");
+        skipPrimaryKeyLoading = new JCheckBox();
+        skipPrimaryKeyLoading.setToolTipText("<html>Whether to load primary keys.</html>");
+        forceDataMapCatalog = new JCheckBox();
+        forceDataMapCatalog.setToolTipText("<html>Automatically tagging each DbEntity with the actual DB catalog/schema" +
+                "(default behavior) may sometimes be undesirable.<br>  If this is the case then setting <b>forceDataMapCatalog</b> " +
+                "to <b>true</b> will set DbEntity catalog to one in the DataMap.</html>");
+        forceDataMapSchema = new JCheckBox();
+        forceDataMapSchema.setToolTipText("<html>Automatically tagging each DbEntity with the actual DB catalog/schema " +
+                "(default behavior) may sometimes be undesirable.<br> If this is the case then setting <b>forceDataMapSchema</b> " +
+                "to <b>true</b> will set DbEntity schema to one in the DataMap.</html>");
+        useJava7Types = new JCheckBox();
+        useJava7Types.setToolTipText("<html>Use <b>java.util.Date</b> for all columns with <i>DATE/TIME/TIMESTAMP</i> types.<br>" +
+                "By default <b>java.time.*</b> types will be used.</html>");
+        usePrimitives = new JCheckBox();
+        usePrimitives.setToolTipText("<html>Use primitive types (e.g. int) or Object types (e.g. java.lang.Integer)</html>");
+        initStrategy();
+    }
+
+    private void initListeners() {
+        skipRelationshipsLoading.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setSkipRelationshipsLoading(skipRelationshipsLoading.isSelected());
+            projectController.setDirty(true);
+        });
+        skipPrimaryKeyLoading.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setSkipPrimaryKeyLoading(skipPrimaryKeyLoading.isSelected());
+            projectController.setDirty(true);
+        });
+        forceDataMapCatalog.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setForceDataMapCatalog(forceDataMapCatalog.isSelected());
+            projectController.setDirty(true);
+        });
+        forceDataMapSchema.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setForceDataMapSchema(forceDataMapSchema.isSelected());
+            projectController.setDirty(true);
+        });
+        usePrimitives.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setUsePrimitives(usePrimitives.isSelected());
+            projectController.setDirty(true);
+        });
+        useJava7Types.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setUseJava7Types(useJava7Types.isSelected());
+            projectController.setDirty(true);
+        });
+    }
+
+    JComboBox<String> getStrategyCombo() {
+        return strategyCombo;
+    }
+
+    TextAdapter getMeaningfulPk() {
+        return meaningfulPk;
+    }
+
+    TextAdapter getStripFromTableNames() {
+        return stripFromTableNames;
+    }
+
+    JCheckBox getSkipRelationshipsLoading() {
+        return skipRelationshipsLoading;
+    }
+
+    JCheckBox getSkipPrimaryKeyLoading() {
+        return skipPrimaryKeyLoading;
+    }
+
+    JCheckBox getForceDataMapCatalog() {
+        return forceDataMapCatalog;
+    }
+
+    JCheckBox getForceDataMapSchema() {
+        return forceDataMapSchema;
+    }
+
+    JCheckBox getUsePrimitives() {
+        return usePrimitives;
+    }
+
+    JCheckBox getUseJava7Types() {
+        return useJava7Types;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringTreePanel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringTreePanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringTreePanel.java
new file mode 100644
index 0000000..8c50c1e
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringTreePanel.java
@@ -0,0 +1,169 @@
+/*****************************************************************
+ *   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.map.DataMap;
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.dialog.db.load.CatalogPopUpMenu;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.dialog.db.load.DefaultPopUpMenu;
+import org.apache.cayenne.modeler.dialog.db.load.IncludeTablePopUpMenu;
+import org.apache.cayenne.modeler.dialog.db.load.RootPopUpMenu;
+import org.apache.cayenne.modeler.dialog.db.load.SchemaPopUpMenu;
+
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.SwingUtilities;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.TreePath;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @since 4.1
+ */
+class ReverseEngineeringTreePanel extends JScrollPane {
+
+    private DbImportTree reverseEngineeringTree;
+    private DbImportTree dbSchemaTree;
+
+    private ProjectController projectController;
+    private TreeToolbarPanel treeToolbar;
+    private Map<Class, DefaultPopUpMenu> popups;
+
+    ReverseEngineeringTreePanel(ProjectController projectController, DbImportTree reverseEngineeringTree,
+                                DbImportTree dbSchemaTree) {
+        super(reverseEngineeringTree);
+        this.projectController = projectController;
+        this.reverseEngineeringTree = reverseEngineeringTree;
+        this.dbSchemaTree = dbSchemaTree;
+        reverseEngineeringTree.setEditable(true);
+        reverseEngineeringTree.setCellRenderer(new DbImportTreeCellRenderer());
+        DbImportTreeCellEditor editor = new DbImportTreeCellEditor(reverseEngineeringTree,
+                (DefaultTreeCellRenderer) reverseEngineeringTree.getCellRenderer());
+        editor.setProjectController(projectController);
+        reverseEngineeringTree.setCellEditor(editor);
+        initListeners();
+        initPopupMenus();
+        changeIcons();
+    }
+
+    void updateTree() {
+        reverseEngineeringTree.translateReverseEngineeringToTree(getReverseEngineeringBySelectedMap(), false);
+    }
+
+    private void initPopupMenus() {
+        popups = new HashMap<>();
+        popups.put(Catalog.class, new CatalogPopUpMenu());
+        popups.put(Schema.class, new SchemaPopUpMenu());
+        popups.put(ReverseEngineering.class, new RootPopUpMenu());
+        popups.put(String.class, new RootPopUpMenu());
+        popups.put(IncludeTable.class, new IncludeTablePopUpMenu());
+        popups.put(ExcludeTable.class, new DefaultPopUpMenu());
+        popups.put(IncludeColumn.class, new DefaultPopUpMenu());
+        popups.put(ExcludeColumn.class, new DefaultPopUpMenu());
+        popups.put(IncludeProcedure.class, new DefaultPopUpMenu());
+        popups.put(ExcludeProcedure.class, new DefaultPopUpMenu());
+    }
+
+    private void initListeners() {
+        reverseEngineeringTree.addTreeSelectionListener(e -> treeToolbar.lockButtons());
+        reverseEngineeringTree.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mouseClicked(MouseEvent e) {
+                if (reverseEngineeringTree.getRowForLocation(e.getX(), e.getY()) == -1) {
+                    reverseEngineeringTree.setSelectionRow(-1);
+                }
+
+                if (SwingUtilities.isRightMouseButton(e)) {
+                    if (reverseEngineeringTree.isEditing()) {
+                        return;
+                    }
+                    int row = reverseEngineeringTree.getClosestRowForLocation(e.getX(), e.getY());
+                    reverseEngineeringTree.setSelectionRow(row);
+                    DefaultPopUpMenu popupMenu;
+                    DbImportTreeNode selectedElement;
+                    if (reverseEngineeringTree.getSelectionPath() != null) {
+                        selectedElement = reverseEngineeringTree.getSelectedNode();
+                        popupMenu = popups.get(selectedElement.getUserObject().getClass());
+                    } else {
+                        selectedElement = reverseEngineeringTree.getRootNode();
+                        popupMenu = popups.get(ReverseEngineering.class);
+                    }
+                    if (popupMenu != null) {
+                        popupMenu.setProjectController(projectController);
+                        popupMenu.setSelectedElement(selectedElement);
+                        popupMenu.setParentElement((DbImportTreeNode) selectedElement.getParent());
+                        popupMenu.setTree(reverseEngineeringTree);
+                        popupMenu.show(e.getComponent(), e.getX(), e.getY());
+                    }
+                } else if (reverseEngineeringTree.getSelectionPath() != null) {
+                    DbImportTreeNode findedNode = dbSchemaTree.findNode(
+                            dbSchemaTree.getRootNode(), reverseEngineeringTree.getSelectedNode(), 0
+                    );
+                    if (findedNode != null) {
+                        dbSchemaTree.expandPath(new TreePath(((DbImportTreeNode) findedNode.getParent()).getPath()));
+                        scrollToNode(dbSchemaTree, findedNode);
+                    }
+                }
+            }
+        });
+    }
+
+    private void scrollToNode(JTree tree, DbImportTreeNode node) {
+        TreePath path = new TreePath(node.getPath());
+        tree.scrollPathToVisible(path);
+        DraggableTreePanel parentPanel = ((DraggableTreePanel) dbSchemaTree.getParent().getParent());
+        parentPanel.getHorizontalScrollBar().setValue(0);
+    }
+
+    private ReverseEngineering getReverseEngineeringBySelectedMap() {
+        DataMap dataMap = projectController.getCurrentDataMap();
+        return projectController.getApplication().getMetaData().get(dataMap, ReverseEngineering.class);
+    }
+
+    private void changeIcons() {
+        // Deleting standard tree icons
+        DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) reverseEngineeringTree.getCellRenderer();
+        renderer.setLeafIcon(null);
+        renderer.setClosedIcon(null);
+        renderer.setOpenIcon(null);
+    }
+
+    public DbImportTree getReverseEngineeringTree() {
+        return reverseEngineeringTree;
+    }
+
+    void setTreeToolbar(TreeToolbarPanel treeToolbar) {
+        this.treeToolbar = treeToolbar;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/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
new file mode 100644
index 0000000..995cf47
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/TreeToolbarPanel.java
@@ -0,0 +1,229 @@
+/*****************************************************************
+ *   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/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/extension/GraphHandler.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/extension/GraphHandler.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/extension/GraphHandler.java
index ef36fbc..1efdd60 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/extension/GraphHandler.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/extension/GraphHandler.java
@@ -18,6 +18,13 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.graph.extension;
 
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.undo.UndoableEdit;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.xml.DataChannelLoaderListener;
 import org.apache.cayenne.configuration.xml.NamespaceAwareNestedTagHandler;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.graph.GraphBuilder;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java
index 30ea25d..716c3ee 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java
@@ -22,6 +22,7 @@ import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.configuration.xml.DefaultDataChannelMetaData;
 import org.apache.cayenne.configuration.xml.HandlerFactory;
 import org.apache.cayenne.configuration.xml.XMLReaderProvider;
+import org.apache.cayenne.dbsync.xml.DbImportExtension;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.Module;
 import org.apache.cayenne.modeler.Application;
@@ -54,6 +55,7 @@ public class CayenneModelerModule implements Module {
 
         ProjectModule.contributeExtensions(binder)
                 .add(InfoExtension.class)
-                .add(GraphExtension.class);
+                .add(GraphExtension.class)
+                .add(DbImportExtension.class);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java
new file mode 100644
index 0000000..9e7c81e
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java
@@ -0,0 +1,76 @@
+/*****************************************************************
+ *   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.undo;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.editor.DbImportTree;
+
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+import java.util.ArrayList;
+
+/**
+ * @since 4.1
+ */
+public class DbImportTreeUndoableEdit extends AbstractUndoableEdit {
+
+    private ReverseEngineering previousReverseEngineering;
+    private ReverseEngineering nextReverseEngineering;
+    private DbImportTree tree;
+    private ProjectController projectController;
+
+    public DbImportTreeUndoableEdit(ReverseEngineering previousReverseEngineering, ReverseEngineering nextReverseEngineering,
+                                    DbImportTree tree, ProjectController projectController) {
+        this.tree = tree;
+        this.previousReverseEngineering = previousReverseEngineering;
+        this.nextReverseEngineering = nextReverseEngineering;
+        this.projectController = projectController;
+    }
+
+    @Override
+    public boolean canRedo() {
+        return true;
+    }
+
+    @Override
+    public void redo() throws CannotRedoException {
+        tree.stopEditing();
+        tree.setReverseEngineering(this.nextReverseEngineering);
+        ArrayList<DbImportTreeNode> list = tree.getTreeExpandList();
+        projectController.getApplication().getMetaData().add(projectController.getCurrentDataMap(), tree.getReverseEngineering());
+        projectController.setDirty(true);
+        tree.translateReverseEngineeringToTree(tree.getReverseEngineering(), false);
+        tree.expandTree(list);
+    }
+
+    @Override
+    public void undo() throws CannotUndoException {
+        tree.stopEditing();
+        tree.setReverseEngineering(this.previousReverseEngineering);
+        ArrayList<DbImportTreeNode> list = tree.getTreeExpandList();
+        projectController.getApplication().getMetaData().add(projectController.getCurrentDataMap(), tree.getReverseEngineering());
+        projectController.setDirty(true);
+        tree.translateReverseEngineeringToTree(tree.getReverseEngineering(), false);
+        tree.expandTree(list);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/swing/components/image/FilteredIconFactory.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/swing/components/image/FilteredIconFactory.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/swing/components/image/FilteredIconFactory.java
index e6ce46c..d23c524 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/swing/components/image/FilteredIconFactory.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/swing/components/image/FilteredIconFactory.java
@@ -30,6 +30,7 @@ import javax.swing.JComponent;
 import javax.swing.JPanel;
 import javax.swing.UIManager;
 
+
 /**
  * @since 4.0
  */

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-catalog.png
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-catalog.png b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-catalog.png
new file mode 100755
index 0000000..4851be5
Binary files /dev/null and b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-catalog.png differ

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-config.png
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-config.png b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-config.png
new file mode 100755
index 0000000..3b72b2c
Binary files /dev/null and b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-config.png differ

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-excludeColumn.png
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-excludeColumn.png b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-excludeColumn.png
new file mode 100644
index 0000000..94d7349
Binary files /dev/null and b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-excludeColumn.png differ

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-excludeProcedure.png
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-excludeProcedure.png b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-excludeProcedure.png
new file mode 100755
index 0000000..206e98d
Binary files /dev/null and b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-excludeProcedure.png differ

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-excludeTable.png
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-excludeTable.png b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-excludeTable.png
new file mode 100755
index 0000000..05f55d7
Binary files /dev/null and b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-excludeTable.png differ

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-includeColumn.png
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-includeColumn.png b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-includeColumn.png
new file mode 100755
index 0000000..6ac3774
Binary files /dev/null and b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-includeColumn.png differ

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-includeProcedure.png
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-includeProcedure.png b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-includeProcedure.png
new file mode 100755
index 0000000..e081139
Binary files /dev/null and b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-includeProcedure.png differ

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-includeTable.png
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-includeTable.png b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-includeTable.png
new file mode 100755
index 0000000..8256587
Binary files /dev/null and b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-includeTable.png differ

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-refresh.png
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-refresh.png b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-refresh.png
new file mode 100755
index 0000000..a108fe0
Binary files /dev/null and b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-refresh.png differ

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-runImport.png
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-runImport.png b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-runImport.png
new file mode 100755
index 0000000..197089c
Binary files /dev/null and b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-runImport.png differ

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-schema.png
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-schema.png b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-schema.png
new file mode 100755
index 0000000..ce951d4
Binary files /dev/null and b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-schema.png differ


[14/14] cayenne git commit: Cleanup after PR #278

Posted by nt...@apache.org.
Cleanup after PR #278


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/d56d9a6a
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/d56d9a6a
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/d56d9a6a

Branch: refs/heads/master
Commit: d56d9a6a3ddf88af53278e2e78ac4c6950242ea9
Parents: dbee2d1
Author: Nikita Timofeev <st...@gmail.com>
Authored: Wed Mar 28 14:06:36 2018 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Wed Mar 28 14:06:36 2018 +0300

----------------------------------------------------------------------
 .../src/main/resources/assemblies/assembly-mac.xml     | 13 -------------
 cayenne-dbsync/pom.xml                                 |  5 -----
 .../dbsync/reverse/configuration/ToolsModule.java      |  3 +--
 .../org/apache/cayenne/dbsync/xml/CatalogHandler.java  | 10 ++++++++--
 .../java/org/apache/cayenne/CayenneDataObject.java     |  2 --
 modeler/cayenne-modeler/pom.xml                        | 12 ------------
 6 files changed, 9 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/d56d9a6a/assembly/src/main/resources/assemblies/assembly-mac.xml
----------------------------------------------------------------------
diff --git a/assembly/src/main/resources/assemblies/assembly-mac.xml b/assembly/src/main/resources/assemblies/assembly-mac.xml
index a6bd5a9..6ff90db 100644
--- a/assembly/src/main/resources/assemblies/assembly-mac.xml
+++ b/assembly/src/main/resources/assemblies/assembly-mac.xml
@@ -61,19 +61,6 @@
 				<include>KEYS</include>
 			</includes>
 		</fileSet>
-		<fileSet>
-			<directory>target/doc-staging</directory>
-			<outputDirectory>cayenne-${project.version}-macosx/doc</outputDirectory>
-		</fileSet>
-		<fileSet>
-			<directory>../</directory>
-			<outputDirectory>cayenne-${project.version}-macosx/</outputDirectory>
-			<includes>
-				<include>RELEASE-NOTES.txt</include>
-				<include>UPGRADE.txt</include>
-				<include>KEYS</include>
-			</includes>
-		</fileSet>
 	</fileSets>
 
 	<dependencySets>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d56d9a6a/cayenne-dbsync/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/pom.xml b/cayenne-dbsync/pom.xml
index fa5809e..5c68b4d 100644
--- a/cayenne-dbsync/pom.xml
+++ b/cayenne-dbsync/pom.xml
@@ -86,11 +86,6 @@
 			<version>${project.version}</version>
 			<scope>test</scope>
 		</dependency>
-		<dependency>
-			<groupId>org.apache.cayenne</groupId>
-			<artifactId>cayenne-di</artifactId>
-			<version>4.1.M2-SNAPSHOT</version>
-		</dependency>
 	</dependencies>
 
 	<build>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d56d9a6a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
index 0ca291d..ceb1e11 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -65,7 +65,6 @@ import org.apache.cayenne.log.Slf4jJdbcEventLogger;
 import org.apache.cayenne.log.JdbcEventLogger;
 import org.apache.cayenne.project.ProjectModule;
 import org.apache.cayenne.project.extension.ExtensionAwareHandlerFactory;
-import org.apache.cayenne.project.extension.info.InfoExtension;
 import org.apache.cayenne.resource.ClassLoaderResourceLocator;
 import org.apache.cayenne.resource.ResourceLocator;
 import org.slf4j.Logger;
@@ -122,7 +121,7 @@ public class ToolsModule implements Module {
         binder.bind(DataChannelMetaData.class).to(DefaultDataChannelMetaData.class);
         binder.bind(XMLReader.class).toProviderInstance(new XMLReaderProvider(true)).withoutScope();
 
-        ProjectModule.contributeExtensions(binder).add(InfoExtension.class);
+        ProjectModule.contributeExtensions(binder);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d56d9a6a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/CatalogHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/CatalogHandler.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/CatalogHandler.java
index dd71840..06247d3 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/CatalogHandler.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/CatalogHandler.java
@@ -20,8 +20,14 @@
 package org.apache.cayenne.dbsync.xml;
 
 import org.apache.cayenne.configuration.xml.NamespaceAwareNestedTagHandler;
-import org.apache.cayenne.dbsync.reverse.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.ReverseEngineering;
 import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d56d9a6a/cayenne-server/src/main/java/org/apache/cayenne/CayenneDataObject.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/CayenneDataObject.java b/cayenne-server/src/main/java/org/apache/cayenne/CayenneDataObject.java
index 512f712..3cad849 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/CayenneDataObject.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/CayenneDataObject.java
@@ -47,8 +47,6 @@ public class CayenneDataObject extends BaseDataObject {
 
 	private static final long serialVersionUID = -313743913882350400L;
 
-	protected long snapshotVersion = DEFAULT_VERSION;
-
 	protected Map<String, Object> values = new HashMap<>();
 
 	@Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d56d9a6a/modeler/cayenne-modeler/pom.xml
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/pom.xml b/modeler/cayenne-modeler/pom.xml
index 794ebd3..a8ca1c1 100644
--- a/modeler/cayenne-modeler/pom.xml
+++ b/modeler/cayenne-modeler/pom.xml
@@ -20,18 +20,6 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
 	<modelVersion>4.0.0</modelVersion>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
 
     <parent>
 		<groupId>org.apache.cayenne.modeler</groupId>


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

Posted by nt...@apache.org.
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;
+    }
+}


[11/14] cayenne git commit: Merge remote-tracking branch 'remotes/parent/pr/278' into asf-master

Posted by nt...@apache.org.
Merge remote-tracking branch 'remotes/parent/pr/278' into asf-master


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/e158372a
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/e158372a
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/e158372a

Branch: refs/heads/master
Commit: e158372a08a7c8fdeed3f7fa86992abc7fe0089e
Parents: 85316fd 51289d1
Author: Nikita Timofeev <st...@gmail.com>
Authored: Wed Mar 28 12:33:14 2018 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Wed Mar 28 12:33:14 2018 +0300

----------------------------------------------------------------------
 RELEASE-NOTES.txt                               |  72 +--
 .../main/resources/assemblies/assembly-mac.xml  |  13 +
 .../apache/cayenne/tools/DbImporterTask.java    |   3 +
 .../cayenne/tools/DbImporterTaskTest.java       |  41 +-
 cayenne-dbsync/pom.xml                          |   5 +
 .../reverse/configuration/ToolsModule.java      |   3 +-
 .../dbsync/reverse/dbimport/Catalog.java        |  24 +-
 .../reverse/dbimport/DbImportConfiguration.java |   9 +
 .../dbsync/reverse/dbimport/DbImportModule.java |   3 +-
 .../reverse/dbimport/DefaultDbImportAction.java |  59 ++-
 .../dbsync/reverse/dbimport/ExcludeColumn.java  |  15 +-
 .../reverse/dbimport/ExcludeProcedure.java      |  15 +-
 .../dbsync/reverse/dbimport/ExcludeTable.java   |  15 +-
 .../reverse/dbimport/FilterContainer.java       |  25 ++
 .../dbsync/reverse/dbimport/IncludeColumn.java  |  15 +-
 .../reverse/dbimport/IncludeProcedure.java      |  15 +-
 .../dbsync/reverse/dbimport/IncludeTable.java   |  25 +-
 .../dbsync/reverse/dbimport/PatternParam.java   |  19 +
 .../reverse/dbimport/ReverseEngineering.java    |  85 +++-
 .../cayenne/dbsync/reverse/dbimport/Schema.java |  23 +-
 .../reverse/dbimport/SchemaContainer.java       |  12 +-
 .../cayenne/dbsync/reverse/dbload/DbLoader.java |   8 +-
 .../dbsync/reverse/filters/PatternFilter.java   |   4 +
 .../dbsync/reverse/filters/TableFilter.java     |   4 +
 .../cayenne/dbsync/xml/CatalogHandler.java      | 183 ++++++++
 .../cayenne/dbsync/xml/ConfigHandler.java       | 350 +++++++++++++++
 .../cayenne/dbsync/xml/DbImportExtension.java   |  56 +++
 .../dbsync/xml/DbImportLoaderDelegate.java      |  49 ++
 .../dbsync/xml/DbImportSaverDelegate.java       |  46 ++
 .../cayenne/dbsync/xml/IncludeTableHandler.java | 112 +++++
 .../cayenne/dbsync/xml/SchemaHandler.java       | 186 ++++++++
 .../dbimport/DefaultDbImportActionTest.java     |   5 +-
 .../filters/FiltersConfigBuilderTest.java       |  18 +-
 .../org/apache/cayenne/di/BindingBuilder.java   |   3 -
 .../org/apache/cayenne/tools/DbImportTask.java  |  24 +-
 .../org/apache/cayenne/CayenneDataObject.java   |   2 +
 .../apache/cayenne/tools/DbImporterMojo.java    |   3 +
 .../cayenne/tools/CayenneGeneratorMojoTest.java |  28 +-
 .../dbimport/testImportWithoutChanges-pom.xml   |   2 +-
 .../tools/dbimport/testInheritance-pom.xml      |   2 +-
 .../apache/cayenne/tools/dbimporter-pom1.xml    |   2 +-
 .../apache/cayenne/tools/dbimporter-pom3.xml    |   2 +-
 modeler/cayenne-modeler/pom.xml                 |  16 +-
 .../cayenne/modeler/CayenneModelerFrame.java    |   1 -
 .../cayenne/modeler/action/DBWizardAction.java  |  21 +-
 .../modeler/action/DefaultActionManager.java    |  26 ++
 .../modeler/action/GetDbConnectionAction.java   |  75 ++++
 .../modeler/action/LoadDbSchemaAction.java      | 141 ++++++
 .../cayenne/modeler/action/MigrateAction.java   |  11 +-
 .../action/ReverseEngineeringAction.java        |  88 +++-
 .../action/dbimport/AddCatalogAction.java       |  61 +++
 .../action/dbimport/AddExcludeColumnAction.java |  41 ++
 .../dbimport/AddExcludeProcedureAction.java     |  41 ++
 .../action/dbimport/AddExcludeTableAction.java  |  41 ++
 .../action/dbimport/AddIncludeColumnAction.java |  41 ++
 .../dbimport/AddIncludeProcedureAction.java     |  41 ++
 .../action/dbimport/AddIncludeTableAction.java  |  69 +++
 .../action/dbimport/AddPatternParamAction.java  | 117 +++++
 .../action/dbimport/AddSchemaAction.java        |  67 +++
 .../action/dbimport/DeleteNodeAction.java       | 170 +++++++
 .../modeler/action/dbimport/EditNodeAction.java |  88 ++++
 .../action/dbimport/MoveImportNodeAction.java   | 238 ++++++++++
 .../action/dbimport/MoveInvertNodeAction.java   |  35 ++
 .../action/dbimport/TreeManipulationAction.java | 243 ++++++++++
 .../modeler/dialog/db/DataSourceWizard.java     |  56 ++-
 .../modeler/dialog/db/DataSourceWizardView.java |   9 +-
 .../dialog/db/DbActionOptionsDialog.java        |   7 +-
 .../dialog/db/load/CatalogPopUpMenu.java        |  33 ++
 .../dialog/db/load/DbImportTreeNode.java        | 194 ++++++++
 .../dialog/db/load/DbLoadResultDialog.java      | 105 +++++
 .../modeler/dialog/db/load/DbLoaderContext.java |  86 ++--
 .../dialog/db/load/DbLoaderOptionsDialog.java   | 139 ------
 .../dialog/db/load/DefaultPopUpMenu.java        |  86 ++++
 .../dialog/db/load/IncludeTablePopUpMenu.java   |  37 ++
 .../dialog/db/load/ModelerDbImportAction.java   |  61 ++-
 .../modeler/dialog/db/load/RootPopUpMenu.java   | 133 ++++++
 .../modeler/dialog/db/load/SchemaPopUpMenu.java |  33 ++
 .../dialog/db/load/TransferableNode.java        |  74 +++
 .../dialog/pref/DBConnectionInfoEditorView.java |   2 +-
 .../modeler/editor/DataMapTabbedView.java       |   4 +-
 .../cayenne/modeler/editor/DataMapView.java     |   6 +-
 .../editor/dbimport/ColorTreeRenderer.java      | 146 ++++++
 .../editor/dbimport/DatabaseSchemaLoader.java   | 184 ++++++++
 .../modeler/editor/dbimport/DbImportModel.java  |  75 ++++
 .../editor/dbimport/DbImportNodeHandler.java    | 341 ++++++++++++++
 .../modeler/editor/dbimport/DbImportTree.java   | 207 +++++++++
 .../editor/dbimport/DbImportTreeCellEditor.java | 154 +++++++
 .../dbimport/DbImportTreeCellRenderer.java      |  95 ++++
 .../modeler/editor/dbimport/DbImportView.java   | 236 ++++++++++
 .../editor/dbimport/DraggableTreePanel.java     | 449 +++++++++++++++++++
 .../dbimport/ReverseEngineeringConfigPanel.java | 221 +++++++++
 .../dbimport/ReverseEngineeringTreePanel.java   | 173 +++++++
 .../editor/dbimport/TreeToolbarPanel.java       | 231 ++++++++++
 .../modeler/graph/extension/GraphHandler.java   |   9 +-
 .../modeler/init/CayenneModelerModule.java      |   4 +-
 .../modeler/undo/DbImportTreeUndoableEdit.java  |  76 ++++
 .../components/image/FilteredIconFactory.java   |   1 +
 .../cayenne/modeler/images/icon-dbi-catalog.png | Bin 0 -> 288 bytes
 .../cayenne/modeler/images/icon-dbi-config.png  | Bin 0 -> 635 bytes
 .../modeler/images/icon-dbi-excludeColumn.png   | Bin 0 -> 289 bytes
 .../images/icon-dbi-excludeProcedure.png        | Bin 0 -> 365 bytes
 .../modeler/images/icon-dbi-excludeTable.png    | Bin 0 -> 258 bytes
 .../modeler/images/icon-dbi-includeColumn.png   | Bin 0 -> 307 bytes
 .../images/icon-dbi-includeProcedure.png        | Bin 0 -> 386 bytes
 .../modeler/images/icon-dbi-includeTable.png    | Bin 0 -> 288 bytes
 .../cayenne/modeler/images/icon-dbi-refresh.png | Bin 0 -> 547 bytes
 .../modeler/images/icon-dbi-runImport.png       | Bin 0 -> 577 bytes
 .../cayenne/modeler/images/icon-dbi-schema.png  | Bin 0 -> 316 bytes
 108 files changed, 6575 insertions(+), 349 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/e158372a/RELEASE-NOTES.txt
----------------------------------------------------------------------


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

Posted by nt...@apache.org.
CAY-2337 Code refactoring, bugs fixing


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/51289d1c
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/51289d1c
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/51289d1c

Branch: refs/heads/master
Commit: 51289d1c00dd3476beb705088798b86cfe495597
Parents: 2ead78b
Author: Maxim Petrusevich <ma...@gmail.com>
Authored: Wed Mar 28 11:32:33 2018 +0300
Committer: Maxim Petrusevich <ma...@gmail.com>
Committed: Wed Mar 28 11:32:33 2018 +0300

----------------------------------------------------------------------
 .../reverse/dbimport/DefaultDbImportAction.java |  17 +-
 .../reverse/dbimport/SchemaContainer.java       |   2 +-
 .../merge/builders/DbAttributeBuilder.java      |   2 +-
 .../modeler/action/AddCatalogAction.java        |  91 ----
 .../modeler/action/AddExcludeColumnAction.java  |  41 --
 .../action/AddExcludeProcedureAction.java       |  41 --
 .../modeler/action/AddExcludeTableAction.java   |  41 --
 .../modeler/action/AddIncludeColumnAction.java  |  41 --
 .../action/AddIncludeProcedureAction.java       |  41 --
 .../modeler/action/AddIncludeTableAction.java   |  92 ----
 .../modeler/action/AddPatternParamAction.java   | 140 ------
 .../cayenne/modeler/action/AddSchemaAction.java |  97 ----
 .../action/DbEntityCounterpartAction.java       |   3 -
 .../modeler/action/DefaultActionManager.java    |  12 +
 .../modeler/action/DeleteNodeAction.java        | 175 --------
 .../cayenne/modeler/action/EditNodeAction.java  |  93 ----
 .../modeler/action/LoadDbSchemaAction.java      | 183 +-------
 .../modeler/action/MoveImportNodeAction.java    | 235 ----------
 .../modeler/action/MoveInvertNodeAction.java    |  35 --
 .../action/ReverseEngineeringAction.java        |   2 +-
 .../modeler/action/TreeManipulationAction.java  | 197 --------
 .../action/dbimport/AddCatalogAction.java       |  61 +++
 .../action/dbimport/AddExcludeColumnAction.java |  41 ++
 .../dbimport/AddExcludeProcedureAction.java     |  41 ++
 .../action/dbimport/AddExcludeTableAction.java  |  41 ++
 .../action/dbimport/AddIncludeColumnAction.java |  41 ++
 .../dbimport/AddIncludeProcedureAction.java     |  41 ++
 .../action/dbimport/AddIncludeTableAction.java  |  69 +++
 .../action/dbimport/AddPatternParamAction.java  | 117 +++++
 .../action/dbimport/AddSchemaAction.java        |  67 +++
 .../action/dbimport/DeleteNodeAction.java       | 170 +++++++
 .../modeler/action/dbimport/EditNodeAction.java |  88 ++++
 .../action/dbimport/MoveImportNodeAction.java   | 238 ++++++++++
 .../action/dbimport/MoveInvertNodeAction.java   |  35 ++
 .../action/dbimport/TreeManipulationAction.java | 243 ++++++++++
 .../modeler/dialog/db/load/DbLoaderContext.java |   2 +-
 .../dialog/db/load/DefaultPopUpMenu.java        |   4 +-
 .../dialog/db/load/ModelerDbImportAction.java   |  45 +-
 .../modeler/dialog/db/load/RootPopUpMenu.java   |  16 +-
 .../modeler/editor/ColorTreeRenderer.java       | 146 ------
 .../modeler/editor/DataMapTabbedView.java       |   1 +
 .../cayenne/modeler/editor/DbImportModel.java   |  75 ----
 .../modeler/editor/DbImportNodeHandler.java     | 341 --------------
 .../cayenne/modeler/editor/DbImportTree.java    | 207 ---------
 .../modeler/editor/DbImportTreeCellEditor.java  | 154 -------
 .../editor/DbImportTreeCellRenderer.java        |  96 ----
 .../cayenne/modeler/editor/DbImportView.java    | 236 ----------
 .../modeler/editor/DraggableTreePanel.java      | 428 ------------------
 .../editor/ReverseEngineeringConfigPanel.java   | 223 ---------
 .../editor/ReverseEngineeringTreePanel.java     | 169 -------
 .../modeler/editor/TreeToolbarPanel.java        | 229 ----------
 .../editor/dbimport/ColorTreeRenderer.java      | 146 ++++++
 .../editor/dbimport/DatabaseSchemaLoader.java   | 184 ++++++++
 .../modeler/editor/dbimport/DbImportModel.java  |  75 ++++
 .../editor/dbimport/DbImportNodeHandler.java    | 341 ++++++++++++++
 .../modeler/editor/dbimport/DbImportTree.java   | 207 +++++++++
 .../editor/dbimport/DbImportTreeCellEditor.java | 154 +++++++
 .../dbimport/DbImportTreeCellRenderer.java      |  95 ++++
 .../modeler/editor/dbimport/DbImportView.java   | 236 ++++++++++
 .../editor/dbimport/DraggableTreePanel.java     | 449 +++++++++++++++++++
 .../dbimport/ReverseEngineeringConfigPanel.java | 221 +++++++++
 .../dbimport/ReverseEngineeringTreePanel.java   | 173 +++++++
 .../editor/dbimport/TreeToolbarPanel.java       | 231 ++++++++++
 .../modeler/graph/extension/GraphHandler.java   |   6 -
 .../modeler/undo/DbImportTreeUndoableEdit.java  |   2 +-
 65 files changed, 3873 insertions(+), 3893 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
index 2c8f6b2..1a54fa4 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
@@ -397,11 +397,17 @@ public class DefaultDbImportAction implements DbImportAction {
         return true;
     }
 
+    protected void addMessageToLogs(String message, List<String> messages) {
+        messages.add(message);
+    }
+
+    protected void logMessages(List<String> messages) {
+        messages.forEach(logger::info);
+    }
+
     protected boolean syncProcedures(DataMap targetDataMap, DataMap loadedDataMap, FiltersConfig filters) {
         Collection<Procedure> procedures = loadedDataMap.getProcedures();
-        if (procedures.isEmpty()) {
-            return false;
-        }
+        List<String> messages = new LinkedList<>();
 
         boolean hasChanges = false;
         for (Procedure procedure : procedures) {
@@ -414,13 +420,14 @@ public class DefaultDbImportAction implements DbImportAction {
             // maybe we need to compare oldProcedure's and procedure's fully qualified names?
             if (oldProcedure != null) {
                 targetDataMap.removeProcedure(procedure.getName());
-                logger.info("Replace procedure " + procedure.getName());
+                addMessageToLogs("Replace procedure " + procedure.getName(), messages);
             } else {
-                logger.info("Add new procedure " + procedure.getName());
+                addMessageToLogs("Add new procedure " + procedure.getName(), messages);
             }
             targetDataMap.addProcedure(procedure);
             hasChanges = true;
         }
+        logMessages(messages);
         return hasChanges;
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/SchemaContainer.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/SchemaContainer.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/SchemaContainer.java
index e7a9391..8d18417 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/SchemaContainer.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/SchemaContainer.java
@@ -25,7 +25,7 @@ import java.util.LinkedList;
 /**
  * @since 4.0
  */
-public abstract class SchemaContainer extends FilterContainer implements Cloneable {
+public abstract class SchemaContainer extends FilterContainer {
 
     private final Collection<Schema> schemaCollection = new LinkedList<>();
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java
index 5acb389..094a904 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java
@@ -100,7 +100,7 @@ public class DbAttributeBuilder extends DefaultBuilder<DbAttribute> {
 
     @Override
     public DbAttribute build() {
-        if (Util.isEmptyString((obj.getName()))) {
+        if (Util.isEmptyString(obj.getName())) {
             name();
         }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddCatalogAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddCatalogAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddCatalogAction.java
deleted file mode 100644
index 50ebe74..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddCatalogAction.java
+++ /dev/null
@@ -1,91 +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.action;
-
-import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
-import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
-import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
-import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
-
-import javax.swing.tree.TreePath;
-import java.awt.event.ActionEvent;
-
-/**
- * @since 4.1
- */
-public class AddCatalogAction extends TreeManipulationAction {
-
-    private static final String ACTION_NAME = "Add Catalog";
-    private static final String ICON_NAME = "icon-dbi-catalog.png";
-
-    AddCatalogAction(Application application) {
-        super(ACTION_NAME, application);
-        insertableNodeClass = Catalog.class;
-    }
-
-    public String getIconName() {
-        return ICON_NAME;
-    }
-
-    @Override
-    public void performAction(ActionEvent e) {
-        boolean updateSelected = false;
-        tree.stopEditing();
-        String name = insertableNodeName != null ? insertableNodeName : EMPTY_NAME;
-        if (tree.getSelectionPath() == null) {
-            TreePath root = new TreePath(tree.getRootNode());
-            tree.setSelectionPath(root);
-        }
-        if (foundNode == null) {
-            selectedElement = tree.getSelectedNode();
-        } else {
-            selectedElement = foundNode;
-        }
-        parentElement = (DbImportTreeNode) selectedElement.getParent();
-        if (parentElement == null) {
-            parentElement = selectedElement;
-        }
-        Catalog newCatalog = new Catalog(name);
-        ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
-        if (reverseEngineeringIsEmpty()) {
-            tree.getRootNode().removeAllChildren();
-        }
-        if (canBeInserted(selectedElement)) {
-            ((ReverseEngineering) selectedElement.getUserObject()).addCatalog(newCatalog);
-            selectedElement.add(new DbImportTreeNode(newCatalog));
-            updateSelected = true;
-        } else if (canInsert()) {
-            ((ReverseEngineering) parentElement.getUserObject()).addCatalog(newCatalog);
-            parentElement.add(new DbImportTreeNode(newCatalog));
-            updateSelected = false;
-        }
-        if (!isMultipleAction) {
-            updateAfterInsert(updateSelected);
-        }
-        ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
-        if ((!isMultipleAction) && (!insertableNodeName.equals(EMPTY_NAME))) {
-            DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
-                    reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController()
-            );
-            getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeColumnAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeColumnAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeColumnAction.java
deleted file mode 100644
index d36c7e2..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeColumnAction.java
+++ /dev/null
@@ -1,41 +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.action;
-
-import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeColumn;
-import org.apache.cayenne.modeler.Application;
-
-/**
- * @since 4.1
- */
-public class AddExcludeColumnAction extends AddPatternParamAction {
-
-    private static final String ACTION_NAME = "Add Exclude Column";
-    private static final String ICON_NAME = "icon-dbi-excludeColumn.png";
-
-    public AddExcludeColumnAction(Application application) {
-        super(ACTION_NAME, application);
-        insertableNodeClass = ExcludeColumn.class;
-    }
-
-    public String getIconName() {
-        return ICON_NAME;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeProcedureAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeProcedureAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeProcedureAction.java
deleted file mode 100644
index 09ec188..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeProcedureAction.java
+++ /dev/null
@@ -1,41 +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.action;
-
-import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeProcedure;
-import org.apache.cayenne.modeler.Application;
-
-/**
- * @since 4.1
- */
-public class AddExcludeProcedureAction extends AddPatternParamAction {
-
-    private static final String ACTION_NAME = "Add Exclude Procedure";
-    private static final String ICON_NAME = "icon-dbi-excludeProcedure.png";
-
-    public AddExcludeProcedureAction(Application application) {
-        super(ACTION_NAME, application);
-        insertableNodeClass = ExcludeProcedure.class;
-    }
-
-    public String getIconName() {
-        return ICON_NAME;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeTableAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeTableAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeTableAction.java
deleted file mode 100644
index 58baef2..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeTableAction.java
+++ /dev/null
@@ -1,41 +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.action;
-
-import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeTable;
-import org.apache.cayenne.modeler.Application;
-
-/**
- * @since 4.1
- */
-public class AddExcludeTableAction extends AddPatternParamAction {
-
-    private static final String ACTION_NAME = "Add Exclude Table";
-    private static final String ICON_NAME = "icon-dbi-excludeTable.png";
-
-    public AddExcludeTableAction(Application application) {
-        super(ACTION_NAME, application);
-        insertableNodeClass = ExcludeTable.class;
-    }
-
-    public String getIconName() {
-        return ICON_NAME;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeColumnAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeColumnAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeColumnAction.java
deleted file mode 100644
index e2b27b1..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeColumnAction.java
+++ /dev/null
@@ -1,41 +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.action;
-
-import org.apache.cayenne.dbsync.reverse.dbimport.IncludeColumn;
-import org.apache.cayenne.modeler.Application;
-
-/**
- * @since 4.1
- */
-public class AddIncludeColumnAction extends AddPatternParamAction {
-
-    private static final String ACTION_NAME = "Add Include Column";
-    private static final String ICON_NAME = "icon-dbi-includeColumn.png";
-
-    public AddIncludeColumnAction(Application application) {
-        super(ACTION_NAME, application);
-        insertableNodeClass = IncludeColumn.class;
-    }
-
-    public String getIconName() {
-        return ICON_NAME;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeProcedureAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeProcedureAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeProcedureAction.java
deleted file mode 100644
index 6a04a63..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeProcedureAction.java
+++ /dev/null
@@ -1,41 +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.action;
-
-import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
-import org.apache.cayenne.modeler.Application;
-
-/**
- * @since 4.1
- */
-public class AddIncludeProcedureAction extends AddPatternParamAction {
-
-    private static final String ACTION_NAME = "Add Include Procedure";
-    private static final String ICON_NAME = "icon-dbi-includeProcedure.png";
-
-    public AddIncludeProcedureAction(Application application) {
-        super(ACTION_NAME, application);
-        insertableNodeClass = IncludeProcedure.class;
-    }
-
-    public String getIconName() {
-        return ICON_NAME;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeTableAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeTableAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeTableAction.java
deleted file mode 100644
index 136a166..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeTableAction.java
+++ /dev/null
@@ -1,92 +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.action;
-
-import org.apache.cayenne.dbsync.reverse.dbimport.FilterContainer;
-import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
-import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
-import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
-import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
-
-import javax.swing.tree.TreePath;
-import java.awt.event.ActionEvent;
-
-/**
- * @since 4.1
- */
-public class AddIncludeTableAction extends TreeManipulationAction {
-
-    private static final String ACTION_NAME = "Add Include Table";
-    private static final String ICON_NAME = "icon-dbi-includeTable.png";
-
-    AddIncludeTableAction(Application application) {
-        super(ACTION_NAME, application);
-        insertableNodeClass = IncludeTable.class;
-    }
-
-    public String getIconName() {
-        return ICON_NAME;
-    }
-
-    @Override
-    public void performAction(ActionEvent e) {
-        boolean updateSelected = false;
-        tree.stopEditing();
-        String name = insertableNodeName != null ? insertableNodeName : EMPTY_NAME;
-        if (tree.getSelectionPath() == null) {
-            TreePath root = new TreePath(tree.getRootNode());
-            tree.setSelectionPath(root);
-        }
-        if (foundNode == null) {
-            selectedElement = tree.getSelectedNode();
-        } else {
-            selectedElement = foundNode;
-        }
-        parentElement = (DbImportTreeNode) selectedElement.getParent();
-        ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
-        IncludeTable newTable = new IncludeTable(name);
-        if (reverseEngineeringIsEmpty()) {
-            tree.getRootNode().removeAllChildren();
-        }
-        if (canBeInserted(selectedElement)) {
-            ((FilterContainer) selectedElement.getUserObject()).addIncludeTable(newTable);
-            selectedElement.add(new DbImportTreeNode(newTable));
-            updateSelected = true;
-        } else {
-            if (parentElement == null) {
-                parentElement = tree.getRootNode();
-            }
-            ((FilterContainer) parentElement.getUserObject()).addIncludeTable(newTable);
-            parentElement.add(new DbImportTreeNode(newTable));
-            updateSelected = false;
-        }
-        if (!isMultipleAction) {
-            updateAfterInsert(updateSelected);
-        }
-        ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
-        if ((!isMultipleAction) && (!insertableNodeName.equals(EMPTY_NAME))) {
-            DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
-                    reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController()
-            );
-            getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddPatternParamAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddPatternParamAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddPatternParamAction.java
deleted file mode 100644
index 78479fc..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddPatternParamAction.java
+++ /dev/null
@@ -1,140 +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.action;
-
-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.FilterContainer;
-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.PatternParam;
-import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
-import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
-import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
-
-import javax.swing.tree.TreePath;
-import java.awt.event.ActionEvent;
-
-/**
- * @since 4.1
- */
-public abstract class AddPatternParamAction extends TreeManipulationAction {
-
-    private Class paramClass;
-
-    AddPatternParamAction(String name, Application application) {
-        super(name, application);
-    }
-
-    private void addPatternParamToContainer(Class paramClass, Object selectedObject, String name, DbImportTreeNode node) {
-        FilterContainer container = (FilterContainer) selectedObject;
-        PatternParam element = null;
-        if (paramClass == ExcludeTable.class) {
-            element = new ExcludeTable(name);
-            container.addExcludeTable((ExcludeTable) element);
-        } else if (paramClass == IncludeColumn.class) {
-            element = new IncludeColumn(name);
-            container.addIncludeColumn((IncludeColumn) element);
-        } else if (paramClass == ExcludeColumn.class) {
-            element = new ExcludeColumn(name);
-            container.addExcludeColumn((ExcludeColumn) element);
-        } else if (paramClass == IncludeProcedure.class) {
-            element = new IncludeProcedure(name);
-            container.addIncludeProcedure((IncludeProcedure) element);
-        } else if (paramClass == ExcludeProcedure.class) {
-            element = new ExcludeProcedure(name);
-            container.addExcludeProcedure((ExcludeProcedure) element);
-        }
-        node.add(new DbImportTreeNode(element));
-    }
-
-    private void addPatternParamToIncludeTable(Class paramClass, Object selectedObject, String name, DbImportTreeNode node) {
-        IncludeTable includeTable = (IncludeTable) selectedObject;
-        PatternParam element = null;
-        if (paramClass == IncludeColumn.class) {
-            element = new IncludeColumn(name);
-            includeTable.addIncludeColumn((IncludeColumn) element);
-
-        } else if (paramClass == ExcludeColumn.class) {
-            element = new ExcludeColumn(name);
-            includeTable.addExcludeColumn((ExcludeColumn) element);
-        }
-        node.add(new DbImportTreeNode(element));
-    }
-
-    @Override
-    public void performAction(ActionEvent e) {
-        tree.stopEditing();
-        String name = insertableNodeName != null ? insertableNodeName : EMPTY_NAME;
-        boolean updateSelected;
-        if (tree.getSelectionPath() == null) {
-            TreePath root = new TreePath(tree.getRootNode());
-            tree.setSelectionPath(root);
-        }
-        if (foundNode == null) {
-            selectedElement = tree.getSelectedNode();
-        } else {
-            selectedElement = foundNode;
-        }
-        parentElement = (DbImportTreeNode) selectedElement.getParent();
-        Object selectedObject;
-        ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
-        if (reverseEngineeringIsEmpty()) {
-            tree.getRootNode().removeAllChildren();
-        }
-        if (canBeInserted(selectedElement)) {
-            selectedObject = selectedElement.getUserObject();
-            if (selectedObject instanceof FilterContainer) {
-                addPatternParamToContainer(paramClass, selectedObject, name, selectedElement);
-            } else if (selectedObject instanceof IncludeTable) {
-                addPatternParamToIncludeTable(paramClass, selectedObject, name, selectedElement);
-            }
-            updateSelected = true;
-        } else {
-            if (parentElement == null) {
-                parentElement = tree.getRootNode();
-            }
-            selectedObject = parentElement.getUserObject();
-            if (selectedObject instanceof FilterContainer) {
-                addPatternParamToContainer(paramClass, selectedObject, name, parentElement);
-            } else if (selectedObject instanceof IncludeTable) {
-                addPatternParamToIncludeTable(paramClass, selectedObject, name, parentElement);
-            }
-            updateSelected = false;
-        }
-        if (!isMultipleAction) {
-            updateAfterInsert(updateSelected);
-        }
-        ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
-        if ((!isMultipleAction) && (!insertableNodeName.equals(EMPTY_NAME))) {
-            DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
-                    reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController()
-            );
-            getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
-        }
-    }
-
-    public void setParamClass(Class paramClass) {
-        this.paramClass = paramClass;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddSchemaAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddSchemaAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddSchemaAction.java
deleted file mode 100644
index 817b17c..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddSchemaAction.java
+++ /dev/null
@@ -1,97 +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.action;
-
-import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
-import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
-import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
-import org.apache.cayenne.dbsync.reverse.dbimport.SchemaContainer;
-import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
-import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
-
-import javax.swing.tree.TreePath;
-import java.awt.event.ActionEvent;
-
-/**
- * @since 4.1
- */
-public class AddSchemaAction extends TreeManipulationAction {
-
-    private static final String ACTION_NAME = "Add Schema";
-    private static final String ICON_NAME = "icon-dbi-schema.png";
-
-    AddSchemaAction(Application application) {
-        super(ACTION_NAME, application);
-        insertableNodeClass = Schema.class;
-    }
-
-    public String getIconName() {
-        return ICON_NAME;
-    }
-
-    @Override
-    public void performAction(ActionEvent e) {
-        boolean updateSelected = false;
-        tree.stopEditing();
-        String name = insertableNodeName != null ? insertableNodeName : EMPTY_NAME;
-        if (tree.getSelectionPath() == null) {
-            TreePath root = new TreePath(tree.getRootNode());
-            tree.setSelectionPath(root);
-        }
-        if (foundNode == null) {
-            selectedElement = tree.getSelectedNode();
-        } else {
-            selectedElement = foundNode;
-        }
-        parentElement = (DbImportTreeNode) selectedElement.getParent();
-        if (parentElement == null) {
-            parentElement = tree.getRootNode();
-        }
-        Schema newSchema = new Schema(name);
-        ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
-        if (reverseEngineeringIsEmpty()) {
-            tree.getRootNode().removeAllChildren();
-        }
-        if (canBeInserted(selectedElement)) {
-            ((SchemaContainer) selectedElement.getUserObject()).addSchema(newSchema);
-            selectedElement.add(new DbImportTreeNode(newSchema));
-            updateSelected = true;
-        } else if (canInsert()) {
-            if (parentElement.isReverseEngineering()) {
-                ((ReverseEngineering) parentElement.getUserObject()).addSchema(newSchema);
-            } else {
-                ((Catalog) parentElement.getUserObject()).addSchema(newSchema);
-            }
-            parentElement.add(new DbImportTreeNode(newSchema));
-            updateSelected = false;
-        }
-        if (!isMultipleAction) {
-            updateAfterInsert(updateSelected);
-        }
-        ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
-        if ((!isMultipleAction) && (!insertableNodeName.equals(EMPTY_NAME))) {
-            DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
-                    reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController()
-            );
-            getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntityCounterpartAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntityCounterpartAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntityCounterpartAction.java
index b3755cd..700b951 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntityCounterpartAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntityCounterpartAction.java
@@ -21,9 +21,6 @@ package org.apache.cayenne.modeler.action;
 
 import java.util.Iterator;
 
-import javax.swing.tree.TreePath;
-
-import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.ObjEntity;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java
index a626365..3d9d586 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java
@@ -22,6 +22,18 @@ import org.apache.cayenne.configuration.ConfigurationNameMapper;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.action.dbimport.AddCatalogAction;
+import org.apache.cayenne.modeler.action.dbimport.AddExcludeColumnAction;
+import org.apache.cayenne.modeler.action.dbimport.AddExcludeProcedureAction;
+import org.apache.cayenne.modeler.action.dbimport.AddExcludeTableAction;
+import org.apache.cayenne.modeler.action.dbimport.AddIncludeColumnAction;
+import org.apache.cayenne.modeler.action.dbimport.AddIncludeProcedureAction;
+import org.apache.cayenne.modeler.action.dbimport.AddIncludeTableAction;
+import org.apache.cayenne.modeler.action.dbimport.AddSchemaAction;
+import org.apache.cayenne.modeler.action.dbimport.DeleteNodeAction;
+import org.apache.cayenne.modeler.action.dbimport.EditNodeAction;
+import org.apache.cayenne.modeler.action.dbimport.MoveImportNodeAction;
+import org.apache.cayenne.modeler.action.dbimport.MoveInvertNodeAction;
 import org.apache.cayenne.modeler.graph.action.ShowGraphEntityAction;
 import org.apache.cayenne.modeler.util.CayenneAction;
 import org.apache.cayenne.project.ConfigurationNodeParentGetter;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DeleteNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DeleteNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DeleteNodeAction.java
deleted file mode 100644
index 4645ee7..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DeleteNodeAction.java
+++ /dev/null
@@ -1,175 +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.action;
-
-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.FilterContainer;
-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.PatternParam;
-import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
-import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
-import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
-import org.apache.cayenne.modeler.editor.DbImportModel;
-import org.apache.cayenne.modeler.editor.DbImportView;
-import org.apache.cayenne.modeler.editor.DraggableTreePanel;
-import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
-
-import javax.swing.tree.DefaultTreeModel;
-import javax.swing.tree.TreePath;
-import java.awt.event.ActionEvent;
-import java.util.ArrayList;
-
-/**
- * @since 4.1
- */
-public class DeleteNodeAction extends TreeManipulationAction {
-
-    private static final String ACTION_NAME = "Delete";
-    private static final String ICON_NAME = "icon-trash.png";
-
-    private DraggableTreePanel panel;
-
-    DeleteNodeAction(Application application) {
-        super(ACTION_NAME, application);
-    }
-
-    public String getIconName() {
-        return ICON_NAME;
-    }
-
-    private void removePatternParams(FilterContainer container, Object selectedObject) {
-        container.getExcludeTables().remove(selectedObject);
-        container.getIncludeColumns().remove(selectedObject);
-        container.getExcludeColumns().remove(selectedObject);
-        container.getIncludeProcedures().remove(selectedObject);
-        container.getExcludeProcedures().remove(selectedObject);
-    }
-
-    private void deleteChilds(Catalog catalog) {
-        Object selectedObject = this.selectedElement.getUserObject();
-        if (selectedObject instanceof Schema) {
-            catalog.getSchemas().remove(selectedObject);
-        } else if (selectedObject instanceof IncludeTable) {
-            catalog.getIncludeTables().remove(selectedObject);
-        } else if (selectedObject instanceof PatternParam) {
-            removePatternParams(catalog, selectedObject);
-        }
-    }
-
-    private void deleteChilds(Schema schema) {
-        Object selectedObject = this.selectedElement.getUserObject();
-        if (selectedObject instanceof IncludeTable) {
-            schema.getIncludeTables().remove(selectedObject);
-        } else if (selectedObject instanceof PatternParam) {
-            removePatternParams(schema, selectedObject);
-        }
-    }
-
-    private void deleteChilds(IncludeTable includeTable) {
-        Object selectedObject = this.selectedElement.getUserObject();
-        includeTable.getIncludeColumns().remove(selectedObject);
-        includeTable.getExcludeColumns().remove(selectedObject);
-    }
-
-    private void deleteChilds(ReverseEngineering reverseEngineering) {
-        Object selectedObject = this.selectedElement.getUserObject();
-        if (selectedObject instanceof Catalog) {
-            reverseEngineering.getCatalogs().remove(selectedObject);
-        } else if (selectedObject instanceof Schema) {
-            reverseEngineering.getSchemas().remove(selectedObject);
-        } else if (selectedObject instanceof IncludeTable) {
-            reverseEngineering.getIncludeTables().remove(selectedObject);
-        } else if (selectedObject instanceof ExcludeTable) {
-            reverseEngineering.getExcludeTables().remove(selectedObject);
-        } else if (selectedObject instanceof IncludeColumn) {
-            reverseEngineering.getIncludeColumns().remove(selectedObject);
-        } else if (selectedObject instanceof ExcludeColumn) {
-            reverseEngineering.getExcludeColumns().remove(selectedObject);
-        } else if (selectedObject instanceof IncludeProcedure) {
-            reverseEngineering.getIncludeProcedures().remove(selectedObject);
-        } else if (selectedObject instanceof ExcludeProcedure) {
-            reverseEngineering.getExcludeProcedures().remove(selectedObject);
-        }
-    }
-
-    private void updateParentChilds() {
-        DbImportModel model = (DbImportModel) tree.getModel();
-        model.removeNodeFromParent(selectedElement);
-        getProjectController().setDirty(true);
-        model.reload(parentElement);
-    }
-
-    @Override
-    public void performAction(ActionEvent e) {
-        tree.stopEditing();
-        final TreePath[] paths = tree.getSelectionPaths();
-        final DbImportView rootParent = ((DbImportView) panel.getParent().getParent());
-        rootParent.getLoadDbSchemaButton().setEnabled(false);
-        rootParent.getReverseEngineeringProgress().setVisible(true);
-        if (paths != null) {
-            ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
-            rootParent.lockToolbarButtons();
-            for (TreePath path : paths) {
-                selectedElement = (DbImportTreeNode) path.getLastPathComponent();
-                parentElement = (DbImportTreeNode) selectedElement.getParent();
-                if (parentElement != null) {
-                    Object parentUserObject = parentElement.getUserObject();
-                    if (parentUserObject instanceof ReverseEngineering) {
-                        ReverseEngineering reverseEngineering = (ReverseEngineering) parentUserObject;
-                        deleteChilds(reverseEngineering);
-                    } else if (parentUserObject instanceof Catalog) {
-                        Catalog catalog = (Catalog) parentUserObject;
-                        deleteChilds(catalog);
-                    } else if (parentUserObject instanceof Schema) {
-                        Schema schema = (Schema) parentUserObject;
-                        deleteChilds(schema);
-                    } else if (parentUserObject instanceof IncludeTable) {
-                        IncludeTable includeTable = (IncludeTable) parentUserObject;
-                        deleteChilds(includeTable);
-                    }
-                }
-            }
-            if (paths.length > 1) {
-                getProjectController().setDirty(true);
-                ArrayList<DbImportTreeNode> expandList = tree.getTreeExpandList();
-                tree.translateReverseEngineeringToTree(tree.getReverseEngineering(), false);
-                tree.expandTree(expandList);
-            } else {
-                updateParentChilds();
-            }
-            ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
-            getProjectController().getApplication().getUndoManager().addEdit(
-                    new DbImportTreeUndoableEdit(reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController())
-            );
-            rootParent.getLoadDbSchemaButton().setEnabled(true);
-            rootParent.getReverseEngineeringProgress().setVisible(false);
-        }
-    }
-
-    public void setPanel(DraggableTreePanel panel) {
-        this.panel = panel;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/EditNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/EditNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/EditNodeAction.java
deleted file mode 100644
index ac0fa46..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/EditNodeAction.java
+++ /dev/null
@@ -1,93 +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.action;
-
-import org.apache.cayenne.dbsync.reverse.dbimport.FilterContainer;
-import org.apache.cayenne.dbsync.reverse.dbimport.PatternParam;
-import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
-import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
-import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
-import org.apache.cayenne.util.Util;
-
-import java.awt.event.ActionEvent;
-
-/**
- * @since 4.1
- */
-public class EditNodeAction extends TreeManipulationAction {
-
-    private static final String ACTION_NAME = "Rename";
-    private static final String ICON_NAME = "icon-edit.png";
-
-    private String actionName;
-
-    EditNodeAction(Application application) {
-        super(ACTION_NAME, application);
-    }
-
-    public String getIconName() {
-        return ICON_NAME;
-    }
-
-    @Override
-    public void performAction(ActionEvent e) {
-        if (tree.isEditing()) {
-            return;
-        }
-        if (e != null) {
-            if (tree.getSelectionPath() != null) {
-                tree.startEditingAtPath(tree.getSelectionPath());
-            }
-        }
-        if (actionName == null) {
-            return;
-        }
-        if (tree.getSelectionPath() != null) {
-            selectedElement = tree.getSelectedNode();
-            parentElement = (DbImportTreeNode) selectedElement.getParent();
-            if (parentElement != null) {
-                Object selectedObject = selectedElement.getUserObject();
-                ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
-                if (!Util.isEmptyString(actionName)) {
-                    if (selectedObject instanceof FilterContainer) {
-                        ((FilterContainer) selectedObject).setName(actionName);
-                    } else if (selectedObject instanceof PatternParam) {
-                        ((PatternParam) selectedObject).setPattern(actionName);
-                    }
-                    updateModel(true);
-                    selectedElement = null;
-                }
-                ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
-                if (!actionName.equals(EMPTY_NAME)) {
-                    DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
-                            reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController()
-                    );
-                    getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
-                }
-            }
-        }
-    }
-
-    public void setActionName(String name) {
-        this.actionName = name;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java
index 6b8a5c0..671b7c7 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java
@@ -19,26 +19,20 @@
 
 package org.apache.cayenne.modeler.action;
 
-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.Application;
 import org.apache.cayenne.modeler.dialog.db.DataSourceWizard;
-import org.apache.cayenne.modeler.editor.DbImportModel;
-import org.apache.cayenne.modeler.editor.DbImportView;
-import org.apache.cayenne.modeler.editor.DraggableTreePanel;
+import org.apache.cayenne.modeler.editor.dbimport.DatabaseSchemaLoader;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportModel;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportView;
+import org.apache.cayenne.modeler.editor.dbimport.DraggableTreePanel;
 import org.apache.cayenne.modeler.pref.DBConnectionInfo;
 import org.apache.cayenne.modeler.pref.DataMapDefaults;
 import org.apache.cayenne.modeler.util.CayenneAction;
 
 import javax.swing.JOptionPane;
 import java.awt.event.ActionEvent;
-import java.sql.Connection;
-import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.util.Collection;
 
 import static org.apache.cayenne.modeler.pref.DBConnectionInfo.DB_ADAPTER_PROPERTY;
 import static org.apache.cayenne.modeler.pref.DBConnectionInfo.URL_PROPERTY;
@@ -53,16 +47,9 @@ public class LoadDbSchemaAction extends CayenneAction {
 
     private static final String ICON_NAME = "icon-dbi-refresh.png";
     private static final String ACTION_NAME = "Refresh Db Schema";
-    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;
     private DraggableTreePanel draggableTreePanel;
 
-    public LoadDbSchemaAction(Application application) {
+    LoadDbSchemaAction(Application application) {
         super(ACTION_NAME, application);
     }
 
@@ -92,36 +79,17 @@ public class LoadDbSchemaAction extends CayenneAction {
             } else {
                 connectionInfo = getConnectionInfoFromPreferences();
             }
-
-            databaseReverseEngineering = new ReverseEngineering();
-
-            try(Connection connection = connectionInfo.makeDataSource(getApplication().getClassLoadingService()).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);
-                    }
-                }
-
-                draggableTreePanel.getSourceTree().setEnabled(true);
-                draggableTreePanel.getSourceTree().translateReverseEngineeringToTree(databaseReverseEngineering, true);
-                draggableTreePanel.bindReverseEngineeringToDatamap(getProjectController().getCurrentDataMap(), databaseReverseEngineering);
+            try {
+                ReverseEngineering databaseReverseEngineering = new DatabaseSchemaLoader()
+                        .load(connectionInfo, getApplication().getClassLoadingService());
+                draggableTreePanel
+                        .getSourceTree()
+                        .setEnabled(true);
+                draggableTreePanel
+                        .getSourceTree()
+                        .translateReverseEngineeringToTree(databaseReverseEngineering, true);
+                draggableTreePanel
+                        .bindReverseEngineeringToDatamap(getProjectController().getCurrentDataMap(), databaseReverseEngineering);
                 ((DbImportModel) draggableTreePanel.getSourceTree().getModel()).reload();
             } catch (SQLException exception) {
                 JOptionPane.showMessageDialog(
@@ -167,125 +135,6 @@ public class LoadDbSchemaAction extends CayenneAction {
         dataMapDefaults.getCurrentPreference().put(JDBC_DRIVER_PROPERTY, connectWizard.getConnectionInfo().getJdbcDriver());
     }
 
-    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;
-    }
-
     public void setDraggableTreePanel(DraggableTreePanel draggableTreePanel) {
         this.draggableTreePanel = draggableTreePanel;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveImportNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveImportNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveImportNodeAction.java
deleted file mode 100644
index 525f6ab..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveImportNodeAction.java
+++ /dev/null
@@ -1,235 +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.action;
-
-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.Application;
-import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
-import org.apache.cayenne.modeler.editor.DbImportTree;
-import org.apache.cayenne.modeler.editor.DbImportView;
-import org.apache.cayenne.modeler.editor.DraggableTreePanel;
-import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
-import org.apache.cayenne.modeler.util.CayenneAction;
-
-import javax.swing.tree.TreePath;
-import java.awt.event.ActionEvent;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-
-/**
- * @since 4.1
- */
-public class MoveImportNodeAction extends CayenneAction {
-
-    private static final String ICON_NAME = "icon-backward.png";
-    private static final String ACTION_NAME = "Include";
-    private static final String EMPTY_NAME = "";
-
-    private DbImportTree sourceTree;
-    private DbImportTree targetTree;
-    private DraggableTreePanel panel;
-    protected boolean moveInverted;
-    private Map<Class, Class> classMap;
-
-    MoveImportNodeAction(Application application) {
-        super(ACTION_NAME, application);
-    }
-
-    MoveImportNodeAction(String actionName, Application application) {
-        super(actionName, application);
-        initMap();
-    }
-
-    private void initMap() {
-        classMap = new HashMap<>();
-        classMap.put(IncludeTable.class, ExcludeTable.class);
-        classMap.put(IncludeColumn.class, ExcludeColumn.class);
-        classMap.put(IncludeProcedure.class, ExcludeProcedure.class);
-        classMap.put(Schema.class, Schema.class);
-        classMap.put(Catalog.class, Catalog.class);
-    }
-
-    public String getIconName() {
-        return ICON_NAME;
-    }
-
-    private boolean canInsert(TreePath path, DbImportTreeNode foundNode) {
-        DbImportTreeNode sourceElement = (DbImportTreeNode) path.getLastPathComponent();
-        DbImportTreeNode selectedElement;
-        if (foundNode == null) {
-            if (targetTree.getSelectionPath() != null) {
-                DbImportTreeNode node = targetTree.getSelectedNode();
-                if ((node.getUserObject().getClass() == Catalog.class)
-                        || (node.getUserObject().getClass() == Schema.class)
-                        || (node.getUserObject().getClass() == ReverseEngineering.class)) {
-                    selectedElement = targetTree.getSelectedNode();
-                } else {
-                    selectedElement = (DbImportTreeNode) targetTree.getSelectionPath().
-                            getParentPath().getLastPathComponent();
-                }
-            } else {
-                selectedElement = targetTree.getRootNode();
-            }
-        } else {
-            selectedElement = foundNode;
-        }
-        if ((nodeClassesIsSameTypes(sourceElement, selectedElement))
-                && (sourceElement.getSimpleNodeName().equals(selectedElement.getSimpleNodeName()))) {
-            return false;
-        }
-        int childCount = selectedElement.getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            DbImportTreeNode child = (DbImportTreeNode) selectedElement.getChildAt(i);
-            if ((nodeClassesIsSameTypes(sourceElement, child))
-                && (sourceElement.getSimpleNodeName().equals(child.getSimpleNodeName()))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public void performAction(ActionEvent e) {
-        TreePath[] paths = sourceTree.getSelectionPaths();
-        TreeManipulationAction action = null;
-        String insertableName = EMPTY_NAME;
-        DbImportView rootParent = (DbImportView) panel.getParent().getParent();
-        rootParent.getReverseEngineeringProgress().setVisible(true);
-        if (paths != null) {
-            boolean isChanged = false;
-            ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(targetTree.getReverseEngineering());
-            try {
-                for (TreePath path : paths) {
-                    DbImportTreeNode selectedElement = (DbImportTreeNode) path.getLastPathComponent();
-                    DbImportTreeNode previousNode;
-                    DbImportTreeNode foundNode = targetTree.findNodeByParentsChain(
-                            targetTree.getRootNode(), selectedElement, 0
-                    );
-                    // If parent nodes from db schema doesn't exist, create it
-                    if (foundNode == null) {
-                        for (int i = selectedElement.getParents().size() - 2; i >= 0; i--) {
-                            DbImportTreeNode insertedNode = selectedElement.getParents().get(i);
-                            previousNode = targetTree.findNodeByParentsChain(targetTree.getRootNode(), insertedNode, 0);
-                            TreeManipulationAction manipulationAction = panel.getActionByNodeType(
-                                    insertedNode.getUserObject().getClass()
-                            );
-                            if (canInsert(new TreePath(insertedNode.getPath()), previousNode)) {
-                                manipulationAction.setFoundNode(previousNode);
-                                manipulationAction.setInsertableNodeName(insertedNode.getSimpleNodeName());
-                                manipulationAction.setTree(targetTree);
-                                manipulationAction.setMovedFromDbSchema(true);
-                                manipulationAction.actionPerformed(e);
-                                manipulationAction.setFoundNode(null);
-                                manipulationAction.setMultipleAction(false);
-                            }
-                        }
-                    }
-                    // Again find node where we insert our node
-                    foundNode = targetTree.findNodeByParentsChain(targetTree.getRootNode(), selectedElement, 0);
-                    if (!moveInverted) {
-                        action = panel.getActionByNodeType(selectedElement.getUserObject().getClass());
-                    } else {
-                        action = panel.getActionByNodeType(classMap.get(selectedElement.getUserObject().getClass()));
-                    }
-                    if (action != null) {
-                        if (paths.length > 1) {
-                            action.setMultipleAction(true);
-                        } else {
-                            action.setMultipleAction(false);
-                        }
-                        if (canInsert(path, foundNode)) {
-                            insertableName = selectedElement.getSimpleNodeName();
-                            action.setFoundNode(foundNode);
-                            action.setInsertableNodeName(Matcher.quoteReplacement(insertableName));
-                            action.setTree(targetTree);
-                            action.setMovedFromDbSchema(true);
-                            action.actionPerformed(e);
-                            action.setFoundNode(null);
-                            action.resetActionFlags();
-                            isChanged = true;
-                            sourceTree.setSelectionRow(-1);
-                            panel.getMoveButton().setEnabled(false);
-                            panel.getMoveInvertButton().setEnabled(false);
-                        }
-                    }
-                }
-                if ((paths.length > 1) && (targetTree.getSelectionPath() != null)) {
-                    getProjectController().setDirty(true);
-                    ArrayList<DbImportTreeNode> expandList = targetTree.getTreeExpandList();
-                    targetTree.translateReverseEngineeringToTree(targetTree.getReverseEngineering(), false);
-                    targetTree.expandTree(expandList);
-                }
-                if ((isChanged) && (!insertableName.equals(EMPTY_NAME))) {
-                    ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(targetTree.getReverseEngineering());
-                    DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
-                            reverseEngineeringOldCopy, reverseEngineeringNewCopy, targetTree, getProjectController()
-                    );
-                    getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
-                }
-            } finally {
-                rootParent.getReverseEngineeringProgress().setVisible(false);
-                if (action != null) {
-                    action.resetActionFlags();
-                }
-            }
-        }
-    }
-
-    private boolean nodeClassesIsSameTypes(DbImportTreeNode sourceElement, DbImportTreeNode selectedElement) {
-        if (sourceElement.getUserObject().getClass() == selectedElement.getUserObject().getClass()) {
-            return true;
-        }
-        if (sourceElement.getUserObject().getClass() == IncludeTable.class) {
-            if ((selectedElement.getUserObject().getClass() == IncludeTable.class)
-                || (selectedElement.getUserObject().getClass() == ExcludeTable.class)) {
-                return true;
-            }
-        }
-        if (sourceElement.getUserObject().getClass() == IncludeProcedure.class) {
-            if ((selectedElement.getUserObject().getClass() == IncludeProcedure.class)
-                    || (selectedElement.getUserObject().getClass() == ExcludeProcedure.class)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void setSourceTree(DbImportTree sourceTree) {
-        this.sourceTree = sourceTree;
-    }
-
-    public void setTargetTree(DbImportTree targetTree) {
-        this.targetTree = targetTree;
-    }
-
-    public void setPanel(DraggableTreePanel panel) {
-        this.panel = panel;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveInvertNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveInvertNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveInvertNodeAction.java
deleted file mode 100644
index 653cc91..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveInvertNodeAction.java
+++ /dev/null
@@ -1,35 +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.action;
-
-import org.apache.cayenne.modeler.Application;
-
-/**
- * @since 4.1
- */
-public class MoveInvertNodeAction extends MoveImportNodeAction {
-
-    private static final String ACTION_NAME = "Exclude";
-
-    MoveInvertNodeAction(Application application) {
-        super(ACTION_NAME, application);
-        moveInverted = true;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java
index 3bb3a16..89b61db 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java
@@ -24,7 +24,7 @@ import org.apache.cayenne.modeler.dialog.db.DataSourceWizard;
 import org.apache.cayenne.modeler.dialog.db.DbActionOptionsDialog;
 import org.apache.cayenne.modeler.dialog.db.load.DbLoaderContext;
 import org.apache.cayenne.modeler.dialog.db.load.LoadDataMapTask;
-import org.apache.cayenne.modeler.editor.DbImportView;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportView;
 import org.apache.cayenne.modeler.pref.DBConnectionInfo;
 import org.apache.cayenne.modeler.pref.DataMapDefaults;
 


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

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/GetDbConnectionAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/GetDbConnectionAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/GetDbConnectionAction.java
new file mode 100644
index 0000000..17433b0
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/GetDbConnectionAction.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.action;
+
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.DataSourceWizard;
+import org.apache.cayenne.modeler.dialog.db.DbActionOptionsDialog;
+import org.apache.cayenne.modeler.pref.DataMapDefaults;
+
+import java.awt.event.ActionEvent;
+import java.util.Collection;
+
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.DB_ADAPTER_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.URL_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.USER_NAME_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.PASSWORD_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.JDBC_DRIVER_PROPERTY;
+
+/**
+ * @since 4.1
+ */
+public class GetDbConnectionAction extends DBWizardAction<DbActionOptionsDialog> {
+
+    public static final String DIALOG_TITLE = "Configure Connection to Database";
+    private static final String ACTION_NAME = "Configure Connection";
+    private static final String ICON_NAME = "icon-dbi-config.png";
+
+    public GetDbConnectionAction(Application application) {
+        super(ACTION_NAME, application);
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    @Override
+    protected DbActionOptionsDialog createDialog(Collection<String> catalogs, Collection<String> schemas,
+                                                 String currentCatalog, String currentSchema, int command) {
+        // NOOP
+        return null;
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        final DataSourceWizard connectWizard = dataSourceWizardDialog(DIALOG_TITLE);
+        if(connectWizard == null) {
+            return;
+        }
+
+        DataMapDefaults dataMapDefaults = getProjectController().
+                getDataMapPreferences(getProjectController().getCurrentDataMap());
+        dataMapDefaults.getCurrentPreference().put(DB_ADAPTER_PROPERTY, connectWizard.getConnectionInfo().getDbAdapter());
+        dataMapDefaults.getCurrentPreference().put(URL_PROPERTY, connectWizard.getConnectionInfo().getUrl());
+        dataMapDefaults.getCurrentPreference().put(USER_NAME_PROPERTY, connectWizard.getConnectionInfo().getUserName());
+        dataMapDefaults.getCurrentPreference().put(PASSWORD_PROPERTY, connectWizard.getConnectionInfo().getPassword());
+        dataMapDefaults.getCurrentPreference().put(JDBC_DRIVER_PROPERTY, connectWizard.getConnectionInfo().getJdbcDriver());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java
new file mode 100644
index 0000000..6b8a5c0
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/LoadDbSchemaAction.java
@@ -0,0 +1,292 @@
+/*****************************************************************
+ *   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.action;
+
+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.Application;
+import org.apache.cayenne.modeler.dialog.db.DataSourceWizard;
+import org.apache.cayenne.modeler.editor.DbImportModel;
+import org.apache.cayenne.modeler.editor.DbImportView;
+import org.apache.cayenne.modeler.editor.DraggableTreePanel;
+import org.apache.cayenne.modeler.pref.DBConnectionInfo;
+import org.apache.cayenne.modeler.pref.DataMapDefaults;
+import org.apache.cayenne.modeler.util.CayenneAction;
+
+import javax.swing.JOptionPane;
+import java.awt.event.ActionEvent;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.DB_ADAPTER_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.URL_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.USER_NAME_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.PASSWORD_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.JDBC_DRIVER_PROPERTY;
+
+/**
+ * @since 4.1
+ */
+public class LoadDbSchemaAction extends CayenneAction {
+
+    private static final String ICON_NAME = "icon-dbi-refresh.png";
+    private static final String ACTION_NAME = "Refresh Db Schema";
+    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;
+    private DraggableTreePanel draggableTreePanel;
+
+    public LoadDbSchemaAction(Application application) {
+        super(ACTION_NAME, application);
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        final DbImportView rootParent = ((DbImportView) draggableTreePanel.getParent().getParent());
+        rootParent.getLoadDbSchemaProgress().setVisible(true);
+        rootParent.getLoadDbSchemaButton().setEnabled(false);
+        Thread thread = new Thread(() -> {
+            LoadDbSchemaAction.this.setEnabled(false);
+            draggableTreePanel.getMoveButton().setEnabled(false);
+            draggableTreePanel.getMoveInvertButton().setEnabled(false);
+            rootParent.lockToolbarButtons();
+            DBConnectionInfo connectionInfo;
+            if (!datamapPreferencesExist()) {
+                final DataSourceWizard connectWizard = new DataSourceWizard(getProjectController(), "Load Db Schema");
+                connectWizard.setProjectController(getProjectController());
+                if (!connectWizard.startupAction()) {
+                    return;
+                }
+                connectionInfo = connectWizard.getConnectionInfo();
+                saveConnectionInfo(connectWizard);
+            } else {
+                connectionInfo = getConnectionInfoFromPreferences();
+            }
+
+            databaseReverseEngineering = new ReverseEngineering();
+
+            try(Connection connection = connectionInfo.makeDataSource(getApplication().getClassLoadingService()).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);
+                    }
+                }
+
+                draggableTreePanel.getSourceTree().setEnabled(true);
+                draggableTreePanel.getSourceTree().translateReverseEngineeringToTree(databaseReverseEngineering, true);
+                draggableTreePanel.bindReverseEngineeringToDatamap(getProjectController().getCurrentDataMap(), databaseReverseEngineering);
+                ((DbImportModel) draggableTreePanel.getSourceTree().getModel()).reload();
+            } catch (SQLException exception) {
+                JOptionPane.showMessageDialog(
+                        Application.getFrame(),
+                        exception.getMessage(),
+                        "Error db schema loading",
+                        JOptionPane.ERROR_MESSAGE);
+            }
+            finally {
+                rootParent.getLoadDbSchemaButton().setEnabled(true);
+                rootParent.getLoadDbSchemaProgress().setVisible(false);
+                rootParent.unlockToolbarButtons();
+            }
+        });
+        thread.start();
+    }
+
+    private boolean datamapPreferencesExist() {
+        DataMapDefaults dataMapDefaults = getProjectController().
+                getDataMapPreferences(getProjectController().getCurrentDataMap());
+        return dataMapDefaults.getCurrentPreference().get(DB_ADAPTER_PROPERTY, null) != null;
+    }
+
+    private DBConnectionInfo getConnectionInfoFromPreferences() {
+        DBConnectionInfo connectionInfo = new DBConnectionInfo();
+        DataMapDefaults dataMapDefaults = getProjectController().
+                getDataMapPreferences(getProjectController().getCurrentDataMap());
+        connectionInfo.setDbAdapter(dataMapDefaults.getCurrentPreference().get(DB_ADAPTER_PROPERTY, null));
+        connectionInfo.setUrl(dataMapDefaults.getCurrentPreference().get(URL_PROPERTY, null));
+        connectionInfo.setUserName(dataMapDefaults.getCurrentPreference().get(USER_NAME_PROPERTY, null));
+        connectionInfo.setPassword(dataMapDefaults.getCurrentPreference().get(PASSWORD_PROPERTY, null));
+        connectionInfo.setJdbcDriver(dataMapDefaults.getCurrentPreference().get(JDBC_DRIVER_PROPERTY, null));
+        return connectionInfo;
+    }
+
+    private void saveConnectionInfo(DataSourceWizard connectWizard) {
+        DataMapDefaults dataMapDefaults = getProjectController().
+                getDataMapPreferences(getProjectController().getCurrentDataMap());
+        dataMapDefaults.getCurrentPreference().put(DB_ADAPTER_PROPERTY, connectWizard.getConnectionInfo().getDbAdapter());
+        dataMapDefaults.getCurrentPreference().put(URL_PROPERTY, connectWizard.getConnectionInfo().getUrl());
+        dataMapDefaults.getCurrentPreference().put(USER_NAME_PROPERTY, connectWizard.getConnectionInfo().getUserName());
+        dataMapDefaults.getCurrentPreference().put(PASSWORD_PROPERTY, connectWizard.getConnectionInfo().getPassword());
+        dataMapDefaults.getCurrentPreference().put(JDBC_DRIVER_PROPERTY, connectWizard.getConnectionInfo().getJdbcDriver());
+    }
+
+    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;
+    }
+
+    public void setDraggableTreePanel(DraggableTreePanel draggableTreePanel) {
+        this.draggableTreePanel = draggableTreePanel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java
index 3ec5279..6ce3a6c 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java
@@ -78,9 +78,14 @@ public class MigrateAction extends DBWizardAction<DbActionOptionsDialog> {
 
     @Override
     protected DbActionOptionsDialog createDialog(Collection<String> catalogs, Collection<String> schemas,
-                                                 String currentCatalog, String currentSchema) {
+                                                 String currentCatalog, String currentSchema, int command) {
         dialogShown = true;
-        return new DbActionOptionsDialog(Application.getFrame(), "Migrate DB Schema: Select Catalog and Schema",
-                catalogs, schemas, currentCatalog, currentSchema);
+        switch (command) {
+            case DbActionOptionsDialog.SELECT:
+                return new DbActionOptionsDialog(Application.getFrame(), "Migrate DB Schema: Select Catalog and Schema",
+                    catalogs, schemas, currentCatalog, currentSchema);
+            default:
+                return null;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveImportNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveImportNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveImportNodeAction.java
new file mode 100644
index 0000000..525f6ab
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveImportNodeAction.java
@@ -0,0 +1,235 @@
+/*****************************************************************
+ *   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.action;
+
+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.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.editor.DbImportTree;
+import org.apache.cayenne.modeler.editor.DbImportView;
+import org.apache.cayenne.modeler.editor.DraggableTreePanel;
+import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
+import org.apache.cayenne.modeler.util.CayenneAction;
+
+import javax.swing.tree.TreePath;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+
+/**
+ * @since 4.1
+ */
+public class MoveImportNodeAction extends CayenneAction {
+
+    private static final String ICON_NAME = "icon-backward.png";
+    private static final String ACTION_NAME = "Include";
+    private static final String EMPTY_NAME = "";
+
+    private DbImportTree sourceTree;
+    private DbImportTree targetTree;
+    private DraggableTreePanel panel;
+    protected boolean moveInverted;
+    private Map<Class, Class> classMap;
+
+    MoveImportNodeAction(Application application) {
+        super(ACTION_NAME, application);
+    }
+
+    MoveImportNodeAction(String actionName, Application application) {
+        super(actionName, application);
+        initMap();
+    }
+
+    private void initMap() {
+        classMap = new HashMap<>();
+        classMap.put(IncludeTable.class, ExcludeTable.class);
+        classMap.put(IncludeColumn.class, ExcludeColumn.class);
+        classMap.put(IncludeProcedure.class, ExcludeProcedure.class);
+        classMap.put(Schema.class, Schema.class);
+        classMap.put(Catalog.class, Catalog.class);
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    private boolean canInsert(TreePath path, DbImportTreeNode foundNode) {
+        DbImportTreeNode sourceElement = (DbImportTreeNode) path.getLastPathComponent();
+        DbImportTreeNode selectedElement;
+        if (foundNode == null) {
+            if (targetTree.getSelectionPath() != null) {
+                DbImportTreeNode node = targetTree.getSelectedNode();
+                if ((node.getUserObject().getClass() == Catalog.class)
+                        || (node.getUserObject().getClass() == Schema.class)
+                        || (node.getUserObject().getClass() == ReverseEngineering.class)) {
+                    selectedElement = targetTree.getSelectedNode();
+                } else {
+                    selectedElement = (DbImportTreeNode) targetTree.getSelectionPath().
+                            getParentPath().getLastPathComponent();
+                }
+            } else {
+                selectedElement = targetTree.getRootNode();
+            }
+        } else {
+            selectedElement = foundNode;
+        }
+        if ((nodeClassesIsSameTypes(sourceElement, selectedElement))
+                && (sourceElement.getSimpleNodeName().equals(selectedElement.getSimpleNodeName()))) {
+            return false;
+        }
+        int childCount = selectedElement.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            DbImportTreeNode child = (DbImportTreeNode) selectedElement.getChildAt(i);
+            if ((nodeClassesIsSameTypes(sourceElement, child))
+                && (sourceElement.getSimpleNodeName().equals(child.getSimpleNodeName()))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        TreePath[] paths = sourceTree.getSelectionPaths();
+        TreeManipulationAction action = null;
+        String insertableName = EMPTY_NAME;
+        DbImportView rootParent = (DbImportView) panel.getParent().getParent();
+        rootParent.getReverseEngineeringProgress().setVisible(true);
+        if (paths != null) {
+            boolean isChanged = false;
+            ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(targetTree.getReverseEngineering());
+            try {
+                for (TreePath path : paths) {
+                    DbImportTreeNode selectedElement = (DbImportTreeNode) path.getLastPathComponent();
+                    DbImportTreeNode previousNode;
+                    DbImportTreeNode foundNode = targetTree.findNodeByParentsChain(
+                            targetTree.getRootNode(), selectedElement, 0
+                    );
+                    // If parent nodes from db schema doesn't exist, create it
+                    if (foundNode == null) {
+                        for (int i = selectedElement.getParents().size() - 2; i >= 0; i--) {
+                            DbImportTreeNode insertedNode = selectedElement.getParents().get(i);
+                            previousNode = targetTree.findNodeByParentsChain(targetTree.getRootNode(), insertedNode, 0);
+                            TreeManipulationAction manipulationAction = panel.getActionByNodeType(
+                                    insertedNode.getUserObject().getClass()
+                            );
+                            if (canInsert(new TreePath(insertedNode.getPath()), previousNode)) {
+                                manipulationAction.setFoundNode(previousNode);
+                                manipulationAction.setInsertableNodeName(insertedNode.getSimpleNodeName());
+                                manipulationAction.setTree(targetTree);
+                                manipulationAction.setMovedFromDbSchema(true);
+                                manipulationAction.actionPerformed(e);
+                                manipulationAction.setFoundNode(null);
+                                manipulationAction.setMultipleAction(false);
+                            }
+                        }
+                    }
+                    // Again find node where we insert our node
+                    foundNode = targetTree.findNodeByParentsChain(targetTree.getRootNode(), selectedElement, 0);
+                    if (!moveInverted) {
+                        action = panel.getActionByNodeType(selectedElement.getUserObject().getClass());
+                    } else {
+                        action = panel.getActionByNodeType(classMap.get(selectedElement.getUserObject().getClass()));
+                    }
+                    if (action != null) {
+                        if (paths.length > 1) {
+                            action.setMultipleAction(true);
+                        } else {
+                            action.setMultipleAction(false);
+                        }
+                        if (canInsert(path, foundNode)) {
+                            insertableName = selectedElement.getSimpleNodeName();
+                            action.setFoundNode(foundNode);
+                            action.setInsertableNodeName(Matcher.quoteReplacement(insertableName));
+                            action.setTree(targetTree);
+                            action.setMovedFromDbSchema(true);
+                            action.actionPerformed(e);
+                            action.setFoundNode(null);
+                            action.resetActionFlags();
+                            isChanged = true;
+                            sourceTree.setSelectionRow(-1);
+                            panel.getMoveButton().setEnabled(false);
+                            panel.getMoveInvertButton().setEnabled(false);
+                        }
+                    }
+                }
+                if ((paths.length > 1) && (targetTree.getSelectionPath() != null)) {
+                    getProjectController().setDirty(true);
+                    ArrayList<DbImportTreeNode> expandList = targetTree.getTreeExpandList();
+                    targetTree.translateReverseEngineeringToTree(targetTree.getReverseEngineering(), false);
+                    targetTree.expandTree(expandList);
+                }
+                if ((isChanged) && (!insertableName.equals(EMPTY_NAME))) {
+                    ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(targetTree.getReverseEngineering());
+                    DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
+                            reverseEngineeringOldCopy, reverseEngineeringNewCopy, targetTree, getProjectController()
+                    );
+                    getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
+                }
+            } finally {
+                rootParent.getReverseEngineeringProgress().setVisible(false);
+                if (action != null) {
+                    action.resetActionFlags();
+                }
+            }
+        }
+    }
+
+    private boolean nodeClassesIsSameTypes(DbImportTreeNode sourceElement, DbImportTreeNode selectedElement) {
+        if (sourceElement.getUserObject().getClass() == selectedElement.getUserObject().getClass()) {
+            return true;
+        }
+        if (sourceElement.getUserObject().getClass() == IncludeTable.class) {
+            if ((selectedElement.getUserObject().getClass() == IncludeTable.class)
+                || (selectedElement.getUserObject().getClass() == ExcludeTable.class)) {
+                return true;
+            }
+        }
+        if (sourceElement.getUserObject().getClass() == IncludeProcedure.class) {
+            if ((selectedElement.getUserObject().getClass() == IncludeProcedure.class)
+                    || (selectedElement.getUserObject().getClass() == ExcludeProcedure.class)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void setSourceTree(DbImportTree sourceTree) {
+        this.sourceTree = sourceTree;
+    }
+
+    public void setTargetTree(DbImportTree targetTree) {
+        this.targetTree = targetTree;
+    }
+
+    public void setPanel(DraggableTreePanel panel) {
+        this.panel = panel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveInvertNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveInvertNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveInvertNodeAction.java
new file mode 100644
index 0000000..653cc91
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MoveInvertNodeAction.java
@@ -0,0 +1,35 @@
+/*****************************************************************
+ *   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.action;
+
+import org.apache.cayenne.modeler.Application;
+
+/**
+ * @since 4.1
+ */
+public class MoveInvertNodeAction extends MoveImportNodeAction {
+
+    private static final String ACTION_NAME = "Exclude";
+
+    MoveInvertNodeAction(Application application) {
+        super(ACTION_NAME, application);
+        moveInverted = true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java
index a7d700f..3bb3a16 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java
@@ -21,9 +21,12 @@ package org.apache.cayenne.modeler.action;
 
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.dialog.db.DataSourceWizard;
+import org.apache.cayenne.modeler.dialog.db.DbActionOptionsDialog;
 import org.apache.cayenne.modeler.dialog.db.load.DbLoaderContext;
-import org.apache.cayenne.modeler.dialog.db.load.DbLoaderOptionsDialog;
 import org.apache.cayenne.modeler.dialog.db.load.LoadDataMapTask;
+import org.apache.cayenne.modeler.editor.DbImportView;
+import org.apache.cayenne.modeler.pref.DBConnectionInfo;
+import org.apache.cayenne.modeler.pref.DataMapDefaults;
 
 import java.awt.event.ActionEvent;
 import java.sql.SQLException;
@@ -31,17 +34,33 @@ import java.util.Collection;
 import javax.swing.SwingUtilities;
 import javax.swing.JOptionPane;
 
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.DB_ADAPTER_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.URL_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.USER_NAME_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.PASSWORD_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.JDBC_DRIVER_PROPERTY;
+
 /**
  * Action that imports database structure into a DataMap.
  */
-public class ReverseEngineeringAction extends DBWizardAction<DbLoaderOptionsDialog> {
+public class ReverseEngineeringAction extends DBWizardAction<DbActionOptionsDialog> {
+
+    private static final String ACTION_NAME = "Reengineer Database Schema";
+    private static final String ICON_NAME = "icon-dbi-runImport.png";
+    private static final String DIALOG_TITLE = "Reengineer DB Schema: Connect to Database";
+
+    private DbImportView view;
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
 
     ReverseEngineeringAction(Application application) {
         super(getActionName(), application);
     }
 
     public static String getActionName() {
-        return "Reengineer Database Schema";
+        return ACTION_NAME;
     }
 
     /**
@@ -49,15 +68,21 @@ public class ReverseEngineeringAction extends DBWizardAction<DbLoaderOptionsDial
      */
     @Override
     public void performAction(ActionEvent event) {
-        final DbLoaderContext context = new DbLoaderContext();
-        final DataSourceWizard connectWizard = dataSourceWizardDialog("Reengineer DB Schema: Connect to Database");
-        if(connectWizard == null) {
-            return;
+        final DbLoaderContext context = new DbLoaderContext(application.getMetaData());
+        DBConnectionInfo connectionInfo;
+        if (!datamapPreferencesExist()) {
+            final DataSourceWizard connectWizard = dataSourceWizardDialog(DIALOG_TITLE);
+            if (connectWizard == null) {
+                return;
+            }
+            connectionInfo = connectWizard.getConnectionInfo();
+            saveConnectionInfo(connectWizard);
+        } else {
+            connectionInfo = getConnectionInfoFromPreferences();
         }
-
         context.setProjectController(getProjectController());
         try {
-            context.setConnection(connectWizard.getDataSource().getConnection());
+            context.setConnection(connectionInfo.makeDataSource(getApplication().getClassLoadingService()).getConnection());
         } catch (SQLException ex) {
             JOptionPane.showMessageDialog(
                     Application.getFrame(),
@@ -66,9 +91,7 @@ public class ReverseEngineeringAction extends DBWizardAction<DbLoaderOptionsDial
                     JOptionPane.ERROR_MESSAGE);
             return;
         }
-
-        final DbLoaderOptionsDialog loaderOptionsDialog = loaderOptionDialog(connectWizard);
-        if(!context.buildConfig(connectWizard, loaderOptionsDialog)) {
+        if(!context.buildConfig(connectionInfo, view)) {
             try {
                 context.getConnection().close();
             } catch (SQLException ignored) {}
@@ -86,6 +109,34 @@ public class ReverseEngineeringAction extends DBWizardAction<DbLoaderOptionsDial
         });
     }
 
+    private DBConnectionInfo getConnectionInfoFromPreferences() {
+        DBConnectionInfo connectionInfo = new DBConnectionInfo();
+        DataMapDefaults dataMapDefaults = getProjectController().
+                getDataMapPreferences(getProjectController().getCurrentDataMap());
+        connectionInfo.setDbAdapter(dataMapDefaults.getCurrentPreference().get(DB_ADAPTER_PROPERTY, null));
+        connectionInfo.setUrl(dataMapDefaults.getCurrentPreference().get(URL_PROPERTY, null));
+        connectionInfo.setUserName(dataMapDefaults.getCurrentPreference().get(USER_NAME_PROPERTY, null));
+        connectionInfo.setPassword(dataMapDefaults.getCurrentPreference().get(PASSWORD_PROPERTY, null));
+        connectionInfo.setJdbcDriver(dataMapDefaults.getCurrentPreference().get(JDBC_DRIVER_PROPERTY, null));
+        return connectionInfo;
+    }
+
+    private void saveConnectionInfo(DataSourceWizard connectWizard) {
+        DataMapDefaults dataMapDefaults = getProjectController().
+                getDataMapPreferences(getProjectController().getCurrentDataMap());
+        dataMapDefaults.getCurrentPreference().put(DB_ADAPTER_PROPERTY, connectWizard.getConnectionInfo().getDbAdapter());
+        dataMapDefaults.getCurrentPreference().put(URL_PROPERTY, connectWizard.getConnectionInfo().getUrl());
+        dataMapDefaults.getCurrentPreference().put(USER_NAME_PROPERTY, connectWizard.getConnectionInfo().getUserName());
+        dataMapDefaults.getCurrentPreference().put(PASSWORD_PROPERTY, connectWizard.getConnectionInfo().getPassword());
+        dataMapDefaults.getCurrentPreference().put(JDBC_DRIVER_PROPERTY, connectWizard.getConnectionInfo().getJdbcDriver());
+    }
+
+    private boolean datamapPreferencesExist() {
+        DataMapDefaults dataMapDefaults = getProjectController().
+                getDataMapPreferences(getProjectController().getCurrentDataMap());
+        return dataMapDefaults.getCurrentPreference().get(DB_ADAPTER_PROPERTY, null) != null;
+    }
+
     private void runLoaderInThread(final DbLoaderContext context, final Runnable callback) {
         Thread th = new Thread(new Runnable() {
             public void run() {
@@ -98,8 +149,13 @@ public class ReverseEngineeringAction extends DBWizardAction<DbLoaderOptionsDial
     }
 
     @Override
-    protected DbLoaderOptionsDialog createDialog(Collection<String> catalogs, Collection<String> schemas,
-                                                 String currentCatalog, String currentSchema) {
-        return new DbLoaderOptionsDialog(catalogs, schemas, currentCatalog, currentSchema);
+    protected DbActionOptionsDialog createDialog(Collection<String> catalogs, Collection<String> schemas,
+                                                 String currentCatalog, String currentSchema, int command) {
+        // NOOP
+        return null;
+    }
+
+    public void setView(DbImportView view) {
+        this.view = view;
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/TreeManipulationAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/TreeManipulationAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/TreeManipulationAction.java
new file mode 100644
index 0000000..6b38f34
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/TreeManipulationAction.java
@@ -0,0 +1,197 @@
+/*****************************************************************
+ *   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.action;
+
+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.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.editor.DbImportModel;
+import org.apache.cayenne.modeler.editor.DbImportTree;
+import org.apache.cayenne.modeler.util.CayenneAction;
+
+import javax.swing.JTree;
+import javax.swing.tree.TreePath;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @since 4.1
+ */
+public abstract class TreeManipulationAction extends CayenneAction {
+
+    static final String EMPTY_NAME = "";
+
+    protected DbImportTree tree;
+    protected DbImportTreeNode selectedElement;
+    DbImportTreeNode parentElement;
+    DbImportTreeNode foundNode;
+    String insertableNodeName;
+    Class insertableNodeClass;
+    boolean isMultipleAction;
+    private boolean movedFromDbSchema;
+    private Map<Class, List<Class>> levels;
+
+    public TreeManipulationAction(String name, Application application) {
+        super(name, application);
+        initLevels();
+    }
+
+    boolean reverseEngineeringIsEmpty() {
+        ReverseEngineering reverseEngineering = tree.getReverseEngineering();
+        return ((reverseEngineering.getCatalogs().size() == 0) && (reverseEngineering.getSchemas().size() == 0)
+                && (reverseEngineering.getIncludeTables().size() == 0) && (reverseEngineering.getExcludeTables().size() == 0)
+                && (reverseEngineering.getIncludeColumns().size() == 0) && (reverseEngineering.getExcludeColumns().size() == 0)
+                && (reverseEngineering.getIncludeProcedures().size() == 0) && (reverseEngineering.getExcludeProcedures().size() == 0));
+    }
+
+    private void initLevels() {
+        levels = new HashMap<>();
+
+        List<Class> rootChilds = new ArrayList<>();
+        rootChilds.add(Schema.class);
+        rootChilds.add(IncludeTable.class);
+        rootChilds.add(ExcludeTable.class);
+        rootChilds.add(IncludeColumn.class);
+        rootChilds.add(ExcludeColumn.class);
+        rootChilds.add(IncludeProcedure.class);
+        rootChilds.add(ExcludeProcedure.class);
+        levels.put(ReverseEngineering.class, rootChilds);
+
+        List<Class> catalogChilds = new ArrayList<>();
+        catalogChilds.add(Schema.class);
+        catalogChilds.add(IncludeTable.class);
+        catalogChilds.add(ExcludeTable.class);
+        catalogChilds.add(IncludeColumn.class);
+        catalogChilds.add(ExcludeColumn.class);
+        catalogChilds.add(IncludeProcedure.class);
+        catalogChilds.add(ExcludeProcedure.class);
+        levels.put(Catalog.class, catalogChilds);
+
+        List<Class> schemaChilds = new ArrayList<>();
+        schemaChilds.add(IncludeTable.class);
+        schemaChilds.add(ExcludeTable.class);
+        schemaChilds.add(IncludeColumn.class);
+        schemaChilds.add(ExcludeColumn.class);
+        schemaChilds.add(IncludeProcedure.class);
+        schemaChilds.add(ExcludeProcedure.class);
+        levels.put(Schema.class, schemaChilds);
+
+        List<Class> includeTableChilds = new ArrayList<>();
+        includeTableChilds.add(IncludeColumn.class);
+        includeTableChilds.add(ExcludeColumn.class);
+        levels.put(IncludeTable.class, includeTableChilds);
+        levels.put(ExcludeTable.class, null);
+        levels.put(IncludeColumn.class, null);
+        levels.put(ExcludeColumn.class, null);
+        levels.put(IncludeProcedure.class, null);
+        levels.put(ExcludeProcedure.class, null);
+    }
+
+    public void setTree(DbImportTree tree) {
+        this.tree = tree;
+    }
+
+    public JTree getTree() {
+        return tree;
+    }
+
+    boolean canBeInserted(DbImportTreeNode node) {
+        if (node == null) {
+            return false;
+        }
+        Class selectedObjectClass = node.getUserObject().getClass();
+        List<Class> childs = levels.get(selectedObjectClass);
+        return childs != null && childs.contains(insertableNodeClass);
+    }
+
+    boolean canInsert() {
+        if (selectedElement == null) {
+            return true;
+        }
+        if (parentElement != null) {
+            for (int i = 0; i < parentElement.getChildCount(); i++) {
+                DbImportTreeNode child = (DbImportTreeNode) parentElement.getChildAt(i);
+                if (child.getSimpleNodeName().equals(insertableNodeName)
+                        && (child.getUserObject().getClass() == insertableNodeClass)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    protected void updateModel(boolean updateSelected) {
+        insertableNodeName = null;
+        DbImportModel model = (DbImportModel) tree.getModel();
+        getProjectController().setDirty(true);
+        TreePath savedPath = null;
+        if (!updateSelected) {
+            savedPath = new TreePath(parentElement.getPath());
+        }
+        model.reload(updateSelected ? selectedElement : parentElement);
+        if ((savedPath != null) && (parentElement.getUserObject().getClass() != ReverseEngineering.class)) {
+            tree.setSelectionPath(savedPath);
+        }
+    }
+
+    void updateAfterInsert(boolean updateSelected) {
+        updateModel(updateSelected);
+        if (!movedFromDbSchema) {
+            if (updateSelected) {
+                tree.startEditingAtPath(new TreePath(((DbImportTreeNode) selectedElement.getLastChild()).getPath()));
+            } else {
+                tree.startEditingAtPath(new TreePath(((DbImportTreeNode) parentElement.getLastChild()).getPath()));
+            }
+        }
+        resetActionFlags();
+    }
+
+    public void resetActionFlags() {
+        movedFromDbSchema = false;
+        isMultipleAction = false;
+        insertableNodeName = "";
+    }
+
+    void setInsertableNodeName(String nodeName) {
+        this.insertableNodeName = nodeName;
+    }
+
+    void setMultipleAction(boolean multipleAction) {
+        isMultipleAction = multipleAction;
+    }
+
+    void setMovedFromDbSchema(boolean movedFromDbSchema) {
+        this.movedFromDbSchema = movedFromDbSchema;
+    }
+
+    void setFoundNode(DbImportTreeNode node) {
+        this.foundNode = node;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizard.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizard.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizard.java
index 814f589..0ecb849 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizard.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizard.java
@@ -21,24 +21,34 @@ package org.apache.cayenne.modeler.dialog.db;
 
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.modeler.ClassLoadingService;
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.action.GetDbConnectionAction;
 import org.apache.cayenne.modeler.dialog.pref.GeneralPreferences;
 import org.apache.cayenne.modeler.dialog.pref.PreferenceDialog;
 import org.apache.cayenne.modeler.event.DataSourceModificationEvent;
 import org.apache.cayenne.modeler.event.DataSourceModificationListener;
 import org.apache.cayenne.modeler.pref.DBConnectionInfo;
+import org.apache.cayenne.modeler.pref.DataMapDefaults;
 import org.apache.cayenne.modeler.util.CayenneController;
 import org.apache.cayenne.swing.BindingBuilder;
 import org.apache.cayenne.swing.ObjectBinding;
 
 import javax.sql.DataSource;
-import javax.swing.*;
-import java.awt.*;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.WindowConstants;
+import java.awt.Component;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.Arrays;
 import java.util.Map;
 import java.util.prefs.Preferences;
 
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.DB_ADAPTER_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.JDBC_DRIVER_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.PASSWORD_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.URL_PROPERTY;
+import static org.apache.cayenne.modeler.pref.DBConnectionInfo.USER_NAME_PROPERTY;
+
 /**
  * A subclass of ConnectionWizard that tests configured DataSource, but does not
  * keep an open connection.
@@ -50,6 +60,7 @@ public class DataSourceWizard extends CayenneController {
 	private ObjectBinding dataSourceBinding;
 	private Map<String, DBConnectionInfo> dataSources;
 	private String dataSourceKey;
+	private ProjectController projectController;
 
 	// this object is a clone of an object selected from the dropdown, as we
 	// need to allow
@@ -66,7 +77,7 @@ public class DataSourceWizard extends CayenneController {
 	public DataSourceWizard(CayenneController parent, String title) {
 		super(parent);
 
-		this.view = createView();
+		this.view = createView(title);
 		this.view.setTitle(title);
 		this.connectionInfo = new DBConnectionInfo();
 
@@ -74,11 +85,22 @@ public class DataSourceWizard extends CayenneController {
 		initDataSourceListener();
 	}
 
+	private String[] getLabelsForDialog(String viewTitle) {
+		switch (viewTitle) {
+			case GetDbConnectionAction.DIALOG_TITLE: {
+				return new String[]{"Save", "Cancel"};
+			}
+			default:
+				return new String[]{"Continue", "Cancel"};
+		}
+	}
+
 	/**
 	 * Creates swing dialog for this wizard
 	 */
-	private DataSourceWizardView createView() {
-		return new DataSourceWizardView(this);
+	private DataSourceWizardView createView(String viewTitle) {
+		String[] labels = getLabelsForDialog(viewTitle);
+		return new DataSourceWizardView(this, labels);
 	}
 
 	protected void initBindings() {
@@ -120,6 +142,18 @@ public class DataSourceWizard extends CayenneController {
 				.removeDataSourceModificationListener(dataSourceListener);
 	}
 
+	private DBConnectionInfo getConnectionInfoFromPreferences() {
+		DBConnectionInfo connectionInfo = new DBConnectionInfo();
+		DataMapDefaults dataMapDefaults = projectController.
+				getDataMapPreferences(projectController.getCurrentDataMap());
+		connectionInfo.setDbAdapter(dataMapDefaults.getCurrentPreference().get(DB_ADAPTER_PROPERTY, null));
+		connectionInfo.setUrl(dataMapDefaults.getCurrentPreference().get(URL_PROPERTY, null));
+		connectionInfo.setUserName(dataMapDefaults.getCurrentPreference().get(USER_NAME_PROPERTY, null));
+		connectionInfo.setPassword(dataMapDefaults.getCurrentPreference().get(PASSWORD_PROPERTY, null));
+		connectionInfo.setJdbcDriver(dataMapDefaults.getCurrentPreference().get(JDBC_DRIVER_PROPERTY, null));
+		return connectionInfo;
+	}
+
 	public String getDataSourceKey() {
 		return dataSourceKey;
 	}
@@ -134,7 +168,6 @@ public class DataSourceWizard extends CayenneController {
 		} else {
 			connectionInfo = new DBConnectionInfo();
 		}
-
 		view.getConnectionInfo().setConnectionInfo(connectionInfo);
 	}
 
@@ -144,13 +177,18 @@ public class DataSourceWizard extends CayenneController {
 	 */
 	public boolean startupAction() {
 		this.canceled = true;
-
 		refreshDataSources();
 		initFavouriteDataSource();
 
+		DataMapDefaults dataMapDefaults = projectController.
+				getDataMapPreferences(projectController.getCurrentDataMap());
+		if (dataMapDefaults.getCurrentPreference().get(DB_ADAPTER_PROPERTY, null) != null) {
+			getConnectionInfoFromPreferences().copyTo(connectionInfo);
+		}
 		view.pack();
 		view.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
 		view.setModal(true);
+		view.connectionInfo.setConnectionInfo(connectionInfo);
 		makeCloseableOnEscape();
 		centerView();
 		view.setVisible(true);
@@ -253,4 +291,8 @@ public class DataSourceWizard extends CayenneController {
 	public DbAdapter getAdapter() {
 		return adapter;
 	}
+
+	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/DataSourceWizardView.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizardView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizardView.java
index 7f2222d..553b2ab 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizardView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizardView.java
@@ -33,21 +33,24 @@ import java.awt.*;
  */
 public class DataSourceWizardView extends JDialog {
 
+    private static final byte OK_BUTTON_INDEX = 0;
+    private static final byte CANCEL_BUTTON_INDEX = 1;
+
     protected JComboBox<String> dataSources;
     protected JButton configButton;
     protected JButton okButton;
     protected JButton cancelButton;
     protected DBConnectionInfoEditor connectionInfo;
 
-    public DataSourceWizardView(CayenneController controller) {
+    public DataSourceWizardView(CayenneController controller, String[] labels) {
         super(Application.getFrame());
         
         this.dataSources = new JComboBox<>();
 
         this.configButton = new JButton("...");
         this.configButton.setToolTipText("configure local DataSource");
-        this.okButton = new JButton("Continue");
-        this.cancelButton = new JButton("Cancel");
+        this.okButton = new JButton(labels[OK_BUTTON_INDEX]);
+        this.cancelButton = new JButton(labels[CANCEL_BUTTON_INDEX]);
         this.connectionInfo = new DBConnectionInfoEditor(controller);
 
         CellConstraints cc = new CellConstraints();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbActionOptionsDialog.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbActionOptionsDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbActionOptionsDialog.java
index 20eb185..0a59335 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbActionOptionsDialog.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbActionOptionsDialog.java
@@ -43,17 +43,17 @@ import org.apache.cayenne.modeler.util.CayenneDialog;
  */
 public class DbActionOptionsDialog extends CayenneDialog {
 
-    protected static final String WILDCARD_PATTERN = ".*";
     public static final int CANCEL = 0;
     public static final int SELECT = 1;
 
-    private int choice;
+    protected int choice;
     private JLabel schemaLabel;
     private JLabel catalogLabel;
     private JComboBox<String> catalogSelector;
     private JComboBox<String> schemaSelector;
     private JButton selectButton;
     private JButton cancelButton;
+    protected JPanel buttons;
 
     public DbActionOptionsDialog(Frame owner, String title, Collection<String> catalogs, Collection<String> schemas,
                                  String currentCatalog, String currentSchema) throws HeadlessException {
@@ -81,9 +81,8 @@ public class DbActionOptionsDialog extends CayenneDialog {
         DefaultFormBuilder builder = new DefaultFormBuilder(layout);
         builder.setDefaultDialogBorder();
 
+        buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT));
         initForm(builder);
-
-        JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT));
         buttons.add(selectButton);
         buttons.add(cancelButton);
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/CatalogPopUpMenu.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/CatalogPopUpMenu.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/CatalogPopUpMenu.java
new file mode 100644
index 0000000..ff12ba9
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/CatalogPopUpMenu.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 CatalogPopUpMenu extends RootPopUpMenu {
+
+    public CatalogPopUpMenu() {
+        delete.setVisible(true);
+        rename.setVisible(true);
+        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/DbImportTreeNode.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbImportTreeNode.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbImportTreeNode.java
new file mode 100644
index 0000000..20b46bc
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbImportTreeNode.java
@@ -0,0 +1,194 @@
+/*****************************************************************
+ *   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.ExcludeProcedure;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeTable;
+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 javax.swing.tree.DefaultMutableTreeNode;
+import java.util.ArrayList;
+
+
+/**
+ * @since 4.1
+ */
+public class DbImportTreeNode extends DefaultMutableTreeNode {
+
+    private boolean isColorized;
+
+    public DbImportTreeNode() {
+        this(null);
+    }
+
+    private DbImportTreeNode(Object userObject, boolean allowsChildren) {
+        super();
+        this.userObject = userObject;
+        this.allowsChildren = allowsChildren;
+        parent = null;
+    }
+
+    public boolean isIncludeTable() {
+        return (getUserObject().getClass() == IncludeTable.class);
+    }
+
+    public boolean isExcludeTable() {
+        return (getUserObject().getClass() == ExcludeTable.class);
+    }
+
+    public boolean isExcludeProcedure() {
+        return (getUserObject().getClass() == ExcludeProcedure.class);
+    }
+
+    public boolean isIncludeProcedure() {
+        return (getUserObject().getClass() == IncludeProcedure.class);
+    }
+
+    public boolean isLabel() {
+        return (getUserObject().getClass() == String.class);
+    }
+
+    public boolean isSchema() {
+        return (getUserObject().getClass() == Schema.class);
+    }
+
+    public boolean isCatalog() {
+        return (getUserObject().getClass() == Catalog.class);
+    }
+
+    public boolean isReverseEngineering() {
+        return (getUserObject().getClass() == ReverseEngineering.class);
+    }
+
+    public DbImportTreeNode(Object userObject) {
+        this(userObject, true);
+    }
+
+    // Compare parents chain
+    public boolean parentsIsEqual(DbImportTreeNode reverseEngineeringNode) {
+        ArrayList<DbImportTreeNode> reverseEngineeringNodeParents;
+        if (reverseEngineeringNode == null) {
+                reverseEngineeringNodeParents = new ArrayList<>();
+        } else {
+             reverseEngineeringNodeParents = reverseEngineeringNode.getParents();
+        }
+        ArrayList<DbImportTreeNode> dbNodeParents = getParents();
+        for (DbImportTreeNode node : reverseEngineeringNodeParents) {
+            int deleteIndex = -1;
+            for (int i = 0; i < dbNodeParents.size(); i++) {
+                if (node.getSimpleNodeName().equals(dbNodeParents.get(i).getSimpleNodeName())) {
+                    deleteIndex = i;
+                    break;
+                }
+            }
+            if (deleteIndex != -1) {
+                dbNodeParents.remove(deleteIndex);
+            } else {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    // Create parents chain
+    public ArrayList<DbImportTreeNode> getParents() {
+        ArrayList<DbImportTreeNode> parents = new ArrayList<>();
+        DbImportTreeNode tmpNode = this;
+        while (tmpNode.getParent() != null) {
+            parents.add((DbImportTreeNode) tmpNode.getParent());
+            tmpNode = (DbImportTreeNode) tmpNode.getParent();
+        }
+        return parents;
+    }
+
+    protected String getFormattedName(String className, String nodeName) {
+        if (nodeName == null) {
+            return className;
+        } else {
+            return String.format("%s", nodeName);
+        }
+    }
+
+    protected String getNodeName() {
+        if (userObject instanceof FilterContainer) {
+            return getFormattedName(userObject.getClass().getSimpleName(), ((FilterContainer) userObject).getName());
+        } else if (userObject instanceof PatternParam) {
+            return getFormattedName(userObject.getClass().getSimpleName(), ((PatternParam) userObject).getPattern());
+        } else if (userObject != null) {
+            return userObject.toString();
+        }
+        return "";
+    }
+
+    public String getSimpleNodeName() {
+        if (userObject instanceof ReverseEngineering) {
+            return "";
+        } else if (userObject instanceof FilterContainer) {
+            return ((FilterContainer) userObject).getName();
+        } else if (userObject instanceof PatternParam) {
+            return ((PatternParam) userObject).getPattern();
+        }
+        return "";
+    }
+
+    public String toString() {
+        if (userObject == null) {
+            return "";
+        } else if (userObject instanceof ReverseEngineering) {
+            return "Reverse Engineering Configuration:";
+        } else {
+            return getNodeName();
+        }
+    }
+
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (this.getClass() != obj.getClass()) {
+            return false;
+        }
+        DbImportTreeNode objNode = (DbImportTreeNode) obj;
+        if (!objNode.getSimpleNodeName().equals(this.getSimpleNodeName())) {
+            return false;
+        }
+        if (objNode.getUserObject().getClass() != this.getUserObject().getClass()) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean isColorized() {
+        return isColorized;
+    }
+
+    public void setColorized(boolean colorized) {
+        isColorized = colorized;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoadResultDialog.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoadResultDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoadResultDialog.java
new file mode 100644
index 0000000..648219c
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoadResultDialog.java
@@ -0,0 +1,105 @@
+/*****************************************************************
+ *   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 com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.table.DefaultTableModel;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @since 4.1
+ */
+public class DbLoadResultDialog extends JDialog {
+
+    private static int TABLE_ROW_HIGH = 24;
+    private static int TABLE_ROW_MARGIN = 3;
+
+    private DefaultTableModel tableModel;
+    private JTable table;
+    private JButton okButton;
+    private String title;
+
+    DbLoadResultDialog(String title) {
+        super();
+        this.title = title;
+        initElements();
+        buildElements();
+        configureDialog();
+    }
+
+    private void configureDialog() {
+        this.setResizable(false);
+        this.setTitle(title);
+        this.pack();
+        this.setLocationRelativeTo(null);
+        this.setModal(false);
+        this.setAlwaysOnTop(true);
+    }
+
+    private void initElements() {
+        tableModel = new DefaultTableModel() {
+            @Override
+            public boolean isCellEditable(int row, int col) {
+                return false;
+            }
+        };
+        table = new JTable(tableModel);
+        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        table.setRowHeight(TABLE_ROW_HIGH);
+        table.setRowMargin(TABLE_ROW_MARGIN);
+        tableModel.addColumn("");
+        okButton = new JButton("OK");
+        okButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                DbLoadResultDialog.this.setVisible(false);
+            }
+        });
+    }
+
+    private void buildElements() {
+        FormLayout layout = new FormLayout("fill:200dlu");
+        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+        builder.append(new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
+        JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+        panel.add(okButton);
+        builder.append(panel);
+        this.add(builder.getPanel());
+    }
+
+    public void addRowToOutput(String output) {
+        tableModel.addRow(new Object[]{output});
+    }
+
+    public int getTableRowCount() {
+        return tableModel.getRowCount();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java
index 88c2042..9f499f7 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java
@@ -25,20 +25,16 @@ import javax.swing.JOptionPane;
 import javax.swing.SwingUtilities;
 
 import org.apache.cayenne.configuration.ConfigurationNode;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.dbsync.naming.NameBuilder;
-import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
 import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfiguration;
-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.dbsync.reverse.dbload.DbLoaderDelegate;
 import org.apache.cayenne.dbsync.reverse.filters.FiltersConfigBuilder;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
-import org.apache.cayenne.modeler.dialog.db.DataSourceWizard;
+import org.apache.cayenne.modeler.editor.DbImportView;
 import org.apache.cayenne.modeler.pref.DBConnectionInfo;
 import org.apache.cayenne.util.Util;
 import org.slf4j.Logger;
@@ -59,7 +55,10 @@ public class DbLoaderContext {
     private boolean stopping;
     private String loadStatusNote;
 
-    public DbLoaderContext() {
+    private DataChannelMetaData metaData;
+
+    public DbLoaderContext(DataChannelMetaData metaData) {
+        this.metaData = metaData;
     }
 
     DataMap getDataMap() {
@@ -98,6 +97,10 @@ public class DbLoaderContext {
         return stopping;
     }
 
+    public DataChannelMetaData getMetaData() {
+        return metaData;
+    }
+
     void setStopping(boolean stopping) {
         this.stopping = stopping;
     }
@@ -110,23 +113,27 @@ public class DbLoaderContext {
         this.loadStatusNote = loadStatusNote;
     }
 
-    public boolean buildConfig(DataSourceWizard connectionWizard, DbLoaderOptionsDialog dialog) {
-        if (dialog == null || connectionWizard == null) {
-            return false;
-        }
+    private void fillReverseEngineeringFromView(ReverseEngineering reverseEngineering, DbImportView view) {
+        reverseEngineering.setUsePrimitives(view.isUsePrimitives());
+        reverseEngineering.setUseJava7Types(view.isUseJava7Typed());
+        reverseEngineering.setForceDataMapCatalog(view.isForceDataMapCatalog());
+        reverseEngineering.setForceDataMapSchema(view.isForceDataMapSchema());
+        reverseEngineering.setSkipRelationshipsLoading(view.isSkipRelationshipsLoading());
+        reverseEngineering.setSkipPrimaryKeyLoading(view.isSkipPrimaryKeyLoading());
+        reverseEngineering.setMeaningfulPkTables(view.getMeaningfulPk());
+        reverseEngineering.setNamingStrategy(view.getNamingStrategy());
+        reverseEngineering.setStripFromTableNames(view.getStripFromTableNames());
+    }
 
-        // Build filters
-        ReverseEngineering reverseEngineering = new ReverseEngineering();
-        reverseEngineering.addCatalog(new Catalog(dialog.getSelectedCatalog()));
-        reverseEngineering.addSchema(new Schema(dialog.getSelectedSchema()));
-        reverseEngineering.addIncludeTable(new IncludeTable(dialog.getTableIncludePattern()));
-        if(dialog.getTableExcludePattern() != null) {
-            reverseEngineering.addExcludeTable(new ExcludeTable(dialog.getTableExcludePattern()));
+    public boolean buildConfig(DBConnectionInfo connectionInfo, DbImportView view) {
+        if (connectionInfo == null) {
+            return false;
         }
-        // Add here auto_pk_support table
-        reverseEngineering.addExcludeTable(new ExcludeTable("auto_pk_support|AUTO_PK_SUPPORT"));
-        reverseEngineering.addIncludeProcedure(new IncludeProcedure(dialog.getProcedureNamePattern()));
-        FiltersConfigBuilder filtersConfigBuilder = new FiltersConfigBuilder(reverseEngineering);
+        // Build reverse engineering from metadata and dialog values
+        ReverseEngineering metaReverseEngineering = metaData.get(getProjectController().getCurrentDataMap(), ReverseEngineering.class);
+        fillReverseEngineeringFromView(metaReverseEngineering, view);
+        // Create copy of metaReverseEngineering
+        ReverseEngineering reverseEngineering = new ReverseEngineering(metaReverseEngineering);
 
         DbImportConfiguration config = new DbImportConfiguration() {
             @Override
@@ -134,24 +141,35 @@ public class DbLoaderContext {
                 return new LoaderDelegate(DbLoaderContext.this);
             }
         };
+        fillConfig(config, connectionInfo, reverseEngineering);
+        setConfig(config);
+
+        prepareDataMap();
 
-        // Build config
-        DBConnectionInfo connectionInfo = connectionWizard.getConnectionInfo();
-        config.setAdapter(connectionWizard.getAdapter().getClass().getName());
+        return true;
+    }
+
+    // Fill config from metadata reverseEngineering
+    private void fillConfig(DbImportConfiguration config, DBConnectionInfo connectionInfo,
+                            ReverseEngineering reverseEngineering) {
+        FiltersConfigBuilder filtersConfigBuilder = new FiltersConfigBuilder(reverseEngineering);
+        config.setAdapter(connectionInfo.getDbAdapter());
         config.setUsername(connectionInfo.getUserName());
         config.setPassword(connectionInfo.getPassword());
         config.setDriver(connectionInfo.getJdbcDriver());
         config.setUrl(connectionInfo.getUrl());
         config.getDbLoaderConfig().setFiltersConfig(filtersConfigBuilder.build());
-        config.setMeaningfulPkTables(dialog.getMeaningfulPk());
-        config.setNamingStrategy(dialog.getNamingStrategy());
-        config.setUsePrimitives(dialog.isUsePrimitives());
-        config.setUseJava7Types(dialog.isUseJava7Typed());
-        setConfig(config);
-
-        prepareDataMap();
-
-        return true;
+        config.setMeaningfulPkTables(reverseEngineering.getMeaningfulPkTables());
+        config.setNamingStrategy(reverseEngineering.getNamingStrategy());
+        config.setDefaultPackage(reverseEngineering.getDefaultPackage());
+        config.setStripFromTableNames(reverseEngineering.getStripFromTableNames());
+        config.setUsePrimitives(reverseEngineering.isUsePrimitives());
+        config.setUseJava7Types(reverseEngineering.isUseJava7Types());
+        config.setForceDataMapCatalog(reverseEngineering.isForceDataMapCatalog());
+        config.setForceDataMapSchema(reverseEngineering.isForceDataMapSchema());
+        config.setSkipRelationshipsLoading(reverseEngineering.getSkipRelationshipsLoading());
+        config.setSkipPrimaryKeyLoading(reverseEngineering.getSkipPrimaryKeyLoading());
+        config.setTableTypes(new String[] {"TABLE", "VIEW", "SYSTEM TABLE"});
     }
 
     private void prepareDataMap() {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderOptionsDialog.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderOptionsDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderOptionsDialog.java
deleted file mode 100644
index f42c359..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderOptionsDialog.java
+++ /dev/null
@@ -1,139 +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.dialog.db.load;
-
-import com.jgoodies.forms.builder.DefaultFormBuilder;
-import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.dialog.db.DbActionOptionsDialog;
-import org.apache.cayenne.modeler.util.NameGeneratorPreferences;
-
-import java.util.Collection;
-import java.util.Vector;
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JCheckBox;
-import javax.swing.JComboBox;
-import javax.swing.JTextField;
-
-/**
- * Dialog for selecting database reverse-engineering parameters.
- */
-public class DbLoaderOptionsDialog extends DbActionOptionsDialog {
-
-    private JTextField tableIncludePatternField;
-    private JTextField tableExcludePatternField;
-    private JTextField meaningfulPk;
-    private JTextField procNamePatternField;
-    private JComboBox<String> strategyCombo;
-    protected String strategy;
-    private JCheckBox usePrimitives;
-    private JCheckBox useJava7Types;
-
-    /**
-     * Creates and initializes new ChooseSchemaDialog.
-     */
-    public DbLoaderOptionsDialog(Collection<String> catalogs, Collection<String> schemas,
-                                 String dbCatalog, String currentSchema) {
-        super(Application.getFrame(), "Reengineer DB Schema: Select Options",
-                catalogs, schemas, dbCatalog, currentSchema);
-    }
-
-    @Override
-    protected void initForm(DefaultFormBuilder builder) {
-        super.initForm(builder);
-        tableIncludePatternField = new JTextField();
-        tableIncludePatternField.setToolTipText("<html>Regular expression to filter table names.<br>" +
-                "Default expression <b>.*</b> includes all tables.</html>");
-        tableExcludePatternField = new JTextField();
-        tableExcludePatternField.setToolTipText("<html>Regular expression to filter table names.<br>" +
-                "Empty by default excludes nothing.</html>");
-        procNamePatternField = new JTextField();
-        procNamePatternField.setToolTipText("<html>Regular expression to filter stored procedures names.<br>" +
-                "Default expression <b>.*</b> includes all stored procedures.</html>");
-        meaningfulPk = new JTextField();
-        meaningfulPk.setToolTipText("<html>Regular expression to filter tables with meaningful primary keys.<br>" +
-                "Multiple expressions divided by comma can be used.<br>" +
-                "Example: <b>^table1|^table2|^prefix.*|table_name</b></html>");
-        strategyCombo = new JComboBox<>();
-        strategyCombo.setEditable(true);
-
-        usePrimitives = new JCheckBox();
-        usePrimitives.setSelected(true);
-        usePrimitives.setToolTipText("<html>Use primitive types (e.g. int) or Object types (e.g. java.lang.Integer)</html>");
-
-        useJava7Types = new JCheckBox();
-        useJava7Types.setSelected(false);
-        useJava7Types.setToolTipText("<html>Use <b>java.util.Date</b> for all columns with <i>DATE/TIME/TIMESTAMP</i> types.<br>" +
-                "By default <b>java.time.*</b> types will be used.</html>");
-
-        builder.append("Table Name Include Pattern:", tableIncludePatternField);
-        builder.append("Table Name Exclude Pattern:", tableExcludePatternField);
-        builder.append("Procedure Name Pattern:", procNamePatternField);
-        builder.append("Naming Strategy:", strategyCombo);
-        builder.append("Tables with Meaningful PK Pattern:", meaningfulPk);
-        builder.append("Use Java primitive types:", usePrimitives);
-        builder.append("Use old java.util.Date type:", useJava7Types);
-    }
-
-    protected void initFromModel(Collection<String> catalogs, Collection<String> schemas, String currentCatalog, String currentSchema) {
-        super.initFromModel(catalogs, schemas, currentCatalog, currentSchema);
-
-        this.tableIncludePatternField.setText(WILDCARD_PATTERN);
-        this.procNamePatternField.setText(WILDCARD_PATTERN);
-
-        Vector<String> arr = NameGeneratorPreferences
-                .getInstance()
-                .getLastUsedStrategies();
-        strategyCombo.setModel(new DefaultComboBoxModel<>(arr));
-    }
-
-    String getTableIncludePattern() {
-        return "".equals(tableIncludePatternField.getText()) ?
-                null :
-                tableIncludePatternField.getText();
-    }
-
-    String getTableExcludePattern() {
-        return "".equals(tableExcludePatternField.getText()) ?
-                null :
-                tableExcludePatternField.getText();
-    }
-
-    String getMeaningfulPk() {
-        return "".equals(meaningfulPk.getText()) ? null : meaningfulPk
-                .getText();
-    }
-
-    String getProcedureNamePattern() {
-        return "".equals(procNamePatternField.getText()) ? null : procNamePatternField
-                .getText();
-    }
-
-    boolean isUsePrimitives() {
-        return usePrimitives.isSelected();
-    }
-
-    boolean isUseJava7Typed() {
-        return useJava7Types.isSelected();
-    }
-
-    String getNamingStrategy() {
-        return (String) strategyCombo.getSelectedItem();
-    }
-}


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

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/TreeManipulationAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/TreeManipulationAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/TreeManipulationAction.java
deleted file mode 100644
index 6b38f34..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/TreeManipulationAction.java
+++ /dev/null
@@ -1,197 +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.action;
-
-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.Application;
-import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
-import org.apache.cayenne.modeler.editor.DbImportModel;
-import org.apache.cayenne.modeler.editor.DbImportTree;
-import org.apache.cayenne.modeler.util.CayenneAction;
-
-import javax.swing.JTree;
-import javax.swing.tree.TreePath;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @since 4.1
- */
-public abstract class TreeManipulationAction extends CayenneAction {
-
-    static final String EMPTY_NAME = "";
-
-    protected DbImportTree tree;
-    protected DbImportTreeNode selectedElement;
-    DbImportTreeNode parentElement;
-    DbImportTreeNode foundNode;
-    String insertableNodeName;
-    Class insertableNodeClass;
-    boolean isMultipleAction;
-    private boolean movedFromDbSchema;
-    private Map<Class, List<Class>> levels;
-
-    public TreeManipulationAction(String name, Application application) {
-        super(name, application);
-        initLevels();
-    }
-
-    boolean reverseEngineeringIsEmpty() {
-        ReverseEngineering reverseEngineering = tree.getReverseEngineering();
-        return ((reverseEngineering.getCatalogs().size() == 0) && (reverseEngineering.getSchemas().size() == 0)
-                && (reverseEngineering.getIncludeTables().size() == 0) && (reverseEngineering.getExcludeTables().size() == 0)
-                && (reverseEngineering.getIncludeColumns().size() == 0) && (reverseEngineering.getExcludeColumns().size() == 0)
-                && (reverseEngineering.getIncludeProcedures().size() == 0) && (reverseEngineering.getExcludeProcedures().size() == 0));
-    }
-
-    private void initLevels() {
-        levels = new HashMap<>();
-
-        List<Class> rootChilds = new ArrayList<>();
-        rootChilds.add(Schema.class);
-        rootChilds.add(IncludeTable.class);
-        rootChilds.add(ExcludeTable.class);
-        rootChilds.add(IncludeColumn.class);
-        rootChilds.add(ExcludeColumn.class);
-        rootChilds.add(IncludeProcedure.class);
-        rootChilds.add(ExcludeProcedure.class);
-        levels.put(ReverseEngineering.class, rootChilds);
-
-        List<Class> catalogChilds = new ArrayList<>();
-        catalogChilds.add(Schema.class);
-        catalogChilds.add(IncludeTable.class);
-        catalogChilds.add(ExcludeTable.class);
-        catalogChilds.add(IncludeColumn.class);
-        catalogChilds.add(ExcludeColumn.class);
-        catalogChilds.add(IncludeProcedure.class);
-        catalogChilds.add(ExcludeProcedure.class);
-        levels.put(Catalog.class, catalogChilds);
-
-        List<Class> schemaChilds = new ArrayList<>();
-        schemaChilds.add(IncludeTable.class);
-        schemaChilds.add(ExcludeTable.class);
-        schemaChilds.add(IncludeColumn.class);
-        schemaChilds.add(ExcludeColumn.class);
-        schemaChilds.add(IncludeProcedure.class);
-        schemaChilds.add(ExcludeProcedure.class);
-        levels.put(Schema.class, schemaChilds);
-
-        List<Class> includeTableChilds = new ArrayList<>();
-        includeTableChilds.add(IncludeColumn.class);
-        includeTableChilds.add(ExcludeColumn.class);
-        levels.put(IncludeTable.class, includeTableChilds);
-        levels.put(ExcludeTable.class, null);
-        levels.put(IncludeColumn.class, null);
-        levels.put(ExcludeColumn.class, null);
-        levels.put(IncludeProcedure.class, null);
-        levels.put(ExcludeProcedure.class, null);
-    }
-
-    public void setTree(DbImportTree tree) {
-        this.tree = tree;
-    }
-
-    public JTree getTree() {
-        return tree;
-    }
-
-    boolean canBeInserted(DbImportTreeNode node) {
-        if (node == null) {
-            return false;
-        }
-        Class selectedObjectClass = node.getUserObject().getClass();
-        List<Class> childs = levels.get(selectedObjectClass);
-        return childs != null && childs.contains(insertableNodeClass);
-    }
-
-    boolean canInsert() {
-        if (selectedElement == null) {
-            return true;
-        }
-        if (parentElement != null) {
-            for (int i = 0; i < parentElement.getChildCount(); i++) {
-                DbImportTreeNode child = (DbImportTreeNode) parentElement.getChildAt(i);
-                if (child.getSimpleNodeName().equals(insertableNodeName)
-                        && (child.getUserObject().getClass() == insertableNodeClass)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    protected void updateModel(boolean updateSelected) {
-        insertableNodeName = null;
-        DbImportModel model = (DbImportModel) tree.getModel();
-        getProjectController().setDirty(true);
-        TreePath savedPath = null;
-        if (!updateSelected) {
-            savedPath = new TreePath(parentElement.getPath());
-        }
-        model.reload(updateSelected ? selectedElement : parentElement);
-        if ((savedPath != null) && (parentElement.getUserObject().getClass() != ReverseEngineering.class)) {
-            tree.setSelectionPath(savedPath);
-        }
-    }
-
-    void updateAfterInsert(boolean updateSelected) {
-        updateModel(updateSelected);
-        if (!movedFromDbSchema) {
-            if (updateSelected) {
-                tree.startEditingAtPath(new TreePath(((DbImportTreeNode) selectedElement.getLastChild()).getPath()));
-            } else {
-                tree.startEditingAtPath(new TreePath(((DbImportTreeNode) parentElement.getLastChild()).getPath()));
-            }
-        }
-        resetActionFlags();
-    }
-
-    public void resetActionFlags() {
-        movedFromDbSchema = false;
-        isMultipleAction = false;
-        insertableNodeName = "";
-    }
-
-    void setInsertableNodeName(String nodeName) {
-        this.insertableNodeName = nodeName;
-    }
-
-    void setMultipleAction(boolean multipleAction) {
-        isMultipleAction = multipleAction;
-    }
-
-    void setMovedFromDbSchema(boolean movedFromDbSchema) {
-        this.movedFromDbSchema = movedFromDbSchema;
-    }
-
-    void setFoundNode(DbImportTreeNode node) {
-        this.foundNode = node;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddCatalogAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddCatalogAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddCatalogAction.java
new file mode 100644
index 0000000..5ea7cc6
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddCatalogAction.java
@@ -0,0 +1,61 @@
+/*****************************************************************
+ *   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.action.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+
+import java.awt.event.ActionEvent;
+
+/**
+ * @since 4.1
+ */
+public class AddCatalogAction extends TreeManipulationAction {
+
+    private static final String ACTION_NAME = "Add Catalog";
+    private static final String ICON_NAME = "icon-dbi-catalog.png";
+
+    public AddCatalogAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = Catalog.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        ReverseEngineering reverseEngineeringOld = prepareElements();
+        Catalog newCatalog = new Catalog(name);
+        if (canBeInserted(selectedElement)) {
+            ((ReverseEngineering) selectedElement.getUserObject()).addCatalog(newCatalog);
+            selectedElement.add(new DbImportTreeNode(newCatalog));
+            updateSelected = true;
+        } else if (canInsert()) {
+            ((ReverseEngineering) parentElement.getUserObject()).addCatalog(newCatalog);
+            parentElement.add(new DbImportTreeNode(newCatalog));
+            updateSelected = false;
+        }
+        completeInserting(reverseEngineeringOld);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddExcludeColumnAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddExcludeColumnAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddExcludeColumnAction.java
new file mode 100644
index 0000000..ee1435d
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddExcludeColumnAction.java
@@ -0,0 +1,41 @@
+/*****************************************************************
+ *   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.action.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeColumn;
+import org.apache.cayenne.modeler.Application;
+
+/**
+ * @since 4.1
+ */
+public class AddExcludeColumnAction extends AddPatternParamAction {
+
+    private static final String ACTION_NAME = "Add Exclude Column";
+    private static final String ICON_NAME = "icon-dbi-excludeColumn.png";
+
+    public AddExcludeColumnAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = ExcludeColumn.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddExcludeProcedureAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddExcludeProcedureAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddExcludeProcedureAction.java
new file mode 100644
index 0000000..ef844ba
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddExcludeProcedureAction.java
@@ -0,0 +1,41 @@
+/*****************************************************************
+ *   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.action.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeProcedure;
+import org.apache.cayenne.modeler.Application;
+
+/**
+ * @since 4.1
+ */
+public class AddExcludeProcedureAction extends AddPatternParamAction {
+
+    private static final String ACTION_NAME = "Add Exclude Procedure";
+    private static final String ICON_NAME = "icon-dbi-excludeProcedure.png";
+
+    public AddExcludeProcedureAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = ExcludeProcedure.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddExcludeTableAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddExcludeTableAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddExcludeTableAction.java
new file mode 100644
index 0000000..b8dbeb8
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddExcludeTableAction.java
@@ -0,0 +1,41 @@
+/*****************************************************************
+ *   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.action.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeTable;
+import org.apache.cayenne.modeler.Application;
+
+/**
+ * @since 4.1
+ */
+public class AddExcludeTableAction extends AddPatternParamAction {
+
+    private static final String ACTION_NAME = "Add Exclude Table";
+    private static final String ICON_NAME = "icon-dbi-excludeTable.png";
+
+    public AddExcludeTableAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = ExcludeTable.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddIncludeColumnAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddIncludeColumnAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddIncludeColumnAction.java
new file mode 100644
index 0000000..ea5c5ef
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddIncludeColumnAction.java
@@ -0,0 +1,41 @@
+/*****************************************************************
+ *   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.action.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeColumn;
+import org.apache.cayenne.modeler.Application;
+
+/**
+ * @since 4.1
+ */
+public class AddIncludeColumnAction extends AddPatternParamAction {
+
+    private static final String ACTION_NAME = "Add Include Column";
+    private static final String ICON_NAME = "icon-dbi-includeColumn.png";
+
+    public AddIncludeColumnAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = IncludeColumn.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddIncludeProcedureAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddIncludeProcedureAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddIncludeProcedureAction.java
new file mode 100644
index 0000000..ca567b7
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddIncludeProcedureAction.java
@@ -0,0 +1,41 @@
+/*****************************************************************
+ *   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.action.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
+import org.apache.cayenne.modeler.Application;
+
+/**
+ * @since 4.1
+ */
+public class AddIncludeProcedureAction extends AddPatternParamAction {
+
+    private static final String ACTION_NAME = "Add Include Procedure";
+    private static final String ICON_NAME = "icon-dbi-includeProcedure.png";
+
+    public AddIncludeProcedureAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = IncludeProcedure.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddIncludeTableAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddIncludeTableAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddIncludeTableAction.java
new file mode 100644
index 0000000..3d7c197
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddIncludeTableAction.java
@@ -0,0 +1,69 @@
+/*****************************************************************
+ *   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.action.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.FilterContainer;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+
+import javax.swing.tree.TreePath;
+import java.awt.event.ActionEvent;
+
+/**
+ * @since 4.1
+ */
+public class AddIncludeTableAction extends TreeManipulationAction {
+
+    private static final String ACTION_NAME = "Add Include Table";
+    private static final String ICON_NAME = "icon-dbi-includeTable.png";
+
+    public AddIncludeTableAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = IncludeTable.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        ReverseEngineering reverseEngineeringOldCopy = prepareElements();
+        if (reverseEngineeringIsEmpty()) {
+            tree.getRootNode().removeAllChildren();
+        }
+        IncludeTable newTable = new IncludeTable(name);
+        if (canBeInserted(selectedElement)) {
+            ((FilterContainer) selectedElement.getUserObject()).addIncludeTable(newTable);
+            selectedElement.add(new DbImportTreeNode(newTable));
+            updateSelected = true;
+        } else {
+            if (parentElement == null) {
+                parentElement = tree.getRootNode();
+            }
+            ((FilterContainer) parentElement.getUserObject()).addIncludeTable(newTable);
+            parentElement.add(new DbImportTreeNode(newTable));
+            updateSelected = false;
+        }
+        completeInserting(reverseEngineeringOldCopy);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddPatternParamAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddPatternParamAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddPatternParamAction.java
new file mode 100644
index 0000000..640ffd8
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddPatternParamAction.java
@@ -0,0 +1,117 @@
+/*****************************************************************
+ *   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.action.dbimport;
+
+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.FilterContainer;
+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.PatternParam;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+
+import javax.swing.tree.TreePath;
+import java.awt.event.ActionEvent;
+
+/**
+ * @since 4.1
+ */
+public abstract class AddPatternParamAction extends TreeManipulationAction {
+
+    private Class paramClass;
+
+    AddPatternParamAction(String name, Application application) {
+        super(name, application);
+    }
+
+    private void addPatternParamToContainer(Class paramClass, Object selectedObject, String name, DbImportTreeNode node) {
+        FilterContainer container = (FilterContainer) selectedObject;
+        PatternParam element = null;
+        if (paramClass == ExcludeTable.class) {
+            element = new ExcludeTable(name);
+            container.addExcludeTable((ExcludeTable) element);
+        } else if (paramClass == IncludeColumn.class) {
+            element = new IncludeColumn(name);
+            container.addIncludeColumn((IncludeColumn) element);
+        } else if (paramClass == ExcludeColumn.class) {
+            element = new ExcludeColumn(name);
+            container.addExcludeColumn((ExcludeColumn) element);
+        } else if (paramClass == IncludeProcedure.class) {
+            element = new IncludeProcedure(name);
+            container.addIncludeProcedure((IncludeProcedure) element);
+        } else if (paramClass == ExcludeProcedure.class) {
+            element = new ExcludeProcedure(name);
+            container.addExcludeProcedure((ExcludeProcedure) element);
+        }
+        node.add(new DbImportTreeNode(element));
+    }
+
+    private void addPatternParamToIncludeTable(Class paramClass, Object selectedObject, String name, DbImportTreeNode node) {
+        IncludeTable includeTable = (IncludeTable) selectedObject;
+        PatternParam element = null;
+        if (paramClass == IncludeColumn.class) {
+            element = new IncludeColumn(name);
+            includeTable.addIncludeColumn((IncludeColumn) element);
+
+        } else if (paramClass == ExcludeColumn.class) {
+            element = new ExcludeColumn(name);
+            includeTable.addExcludeColumn((ExcludeColumn) element);
+        }
+        node.add(new DbImportTreeNode(element));
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        ReverseEngineering reverseEngineeringOldCopy = prepareElements();
+        Object selectedObject;
+        if (reverseEngineeringIsEmpty()) {
+            tree.getRootNode().removeAllChildren();
+        }
+        if (canBeInserted(selectedElement)) {
+            selectedObject = selectedElement.getUserObject();
+            if (selectedObject instanceof FilterContainer) {
+                addPatternParamToContainer(paramClass, selectedObject, name, selectedElement);
+            } else if (selectedObject instanceof IncludeTable) {
+                addPatternParamToIncludeTable(paramClass, selectedObject, name, selectedElement);
+            }
+            updateSelected = true;
+        } else {
+            if (parentElement == null) {
+                parentElement = tree.getRootNode();
+            }
+            selectedObject = parentElement.getUserObject();
+            if (selectedObject instanceof FilterContainer) {
+                addPatternParamToContainer(paramClass, selectedObject, name, parentElement);
+            } else if (selectedObject instanceof IncludeTable) {
+                addPatternParamToIncludeTable(paramClass, selectedObject, name, parentElement);
+            }
+            updateSelected = false;
+        }
+        completeInserting(reverseEngineeringOldCopy);
+    }
+
+    public void setParamClass(Class paramClass) {
+        this.paramClass = paramClass;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddSchemaAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddSchemaAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddSchemaAction.java
new file mode 100644
index 0000000..fa9562c
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/AddSchemaAction.java
@@ -0,0 +1,67 @@
+/*****************************************************************
+ *   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.action.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.dbsync.reverse.dbimport.SchemaContainer;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+
+import java.awt.event.ActionEvent;
+
+/**
+ * @since 4.1
+ */
+public class AddSchemaAction extends TreeManipulationAction {
+
+    private static final String ACTION_NAME = "Add Schema";
+    private static final String ICON_NAME = "icon-dbi-schema.png";
+
+    public AddSchemaAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = Schema.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        ReverseEngineering reverseEngineeringOldCopy = prepareElements();
+        Schema newSchema = new Schema(name);
+        if (canBeInserted(selectedElement)) {
+            ((SchemaContainer) selectedElement.getUserObject()).addSchema(newSchema);
+            selectedElement.add(new DbImportTreeNode(newSchema));
+            updateSelected = true;
+        } else if (canInsert()) {
+            if (parentElement.isReverseEngineering()) {
+                ((ReverseEngineering) parentElement.getUserObject()).addSchema(newSchema);
+            } else {
+                ((Catalog) parentElement.getUserObject()).addSchema(newSchema);
+            }
+            parentElement.add(new DbImportTreeNode(newSchema));
+            updateSelected = false;
+        }
+        completeInserting(reverseEngineeringOldCopy);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/DeleteNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/DeleteNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/DeleteNodeAction.java
new file mode 100644
index 0000000..94779d1
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/DeleteNodeAction.java
@@ -0,0 +1,170 @@
+/*****************************************************************
+ *   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.action.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.FilterContainer;
+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.PatternParam;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportModel;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportView;
+import org.apache.cayenne.modeler.editor.dbimport.DraggableTreePanel;
+
+import javax.swing.tree.TreePath;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+
+/**
+ * @since 4.1
+ */
+public class DeleteNodeAction extends TreeManipulationAction {
+
+    private static final String ACTION_NAME = "Delete";
+    private static final String ICON_NAME = "icon-trash.png";
+
+    private DraggableTreePanel panel;
+
+    public DeleteNodeAction(Application application) {
+        super(ACTION_NAME, application);
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    private void removePatternParams(FilterContainer container, Object selectedObject) {
+        container.getExcludeTables().remove(selectedObject);
+        container.getIncludeColumns().remove(selectedObject);
+        container.getExcludeColumns().remove(selectedObject);
+        container.getIncludeProcedures().remove(selectedObject);
+        container.getExcludeProcedures().remove(selectedObject);
+    }
+
+    private void deleteChilds(Catalog catalog) {
+        Object selectedObject = this.selectedElement.getUserObject();
+        if (selectedObject instanceof Schema) {
+            catalog.getSchemas().remove(selectedObject);
+        } else if (selectedObject instanceof IncludeTable) {
+            catalog.getIncludeTables().remove(selectedObject);
+        } else if (selectedObject instanceof PatternParam) {
+            removePatternParams(catalog, selectedObject);
+        }
+    }
+
+    private void deleteChilds(Schema schema) {
+        Object selectedObject = this.selectedElement.getUserObject();
+        if (selectedObject instanceof IncludeTable) {
+            schema.getIncludeTables().remove(selectedObject);
+        } else if (selectedObject instanceof PatternParam) {
+            removePatternParams(schema, selectedObject);
+        }
+    }
+
+    private void deleteChilds(IncludeTable includeTable) {
+        Object selectedObject = this.selectedElement.getUserObject();
+        includeTable.getIncludeColumns().remove(selectedObject);
+        includeTable.getExcludeColumns().remove(selectedObject);
+    }
+
+    private void deleteChilds(ReverseEngineering reverseEngineering) {
+        Object selectedObject = this.selectedElement.getUserObject();
+        if (selectedObject instanceof Catalog) {
+            reverseEngineering.getCatalogs().remove(selectedObject);
+        } else if (selectedObject instanceof Schema) {
+            reverseEngineering.getSchemas().remove(selectedObject);
+        } else if (selectedObject instanceof IncludeTable) {
+            reverseEngineering.getIncludeTables().remove(selectedObject);
+        } else if (selectedObject instanceof ExcludeTable) {
+            reverseEngineering.getExcludeTables().remove(selectedObject);
+        } else if (selectedObject instanceof IncludeColumn) {
+            reverseEngineering.getIncludeColumns().remove(selectedObject);
+        } else if (selectedObject instanceof ExcludeColumn) {
+            reverseEngineering.getExcludeColumns().remove(selectedObject);
+        } else if (selectedObject instanceof IncludeProcedure) {
+            reverseEngineering.getIncludeProcedures().remove(selectedObject);
+        } else if (selectedObject instanceof ExcludeProcedure) {
+            reverseEngineering.getExcludeProcedures().remove(selectedObject);
+        }
+    }
+
+    private void updateParentChilds() {
+        DbImportModel model = (DbImportModel) tree.getModel();
+        model.removeNodeFromParent(selectedElement);
+        getProjectController().setDirty(true);
+        model.reload(parentElement);
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        tree.stopEditing();
+        final TreePath[] paths = tree.getSelectionPaths();
+        final DbImportView rootParent = ((DbImportView) panel.getParent().getParent());
+        rootParent.getLoadDbSchemaButton().setEnabled(false);
+        rootParent.getReverseEngineeringProgress().setVisible(true);
+        if (paths != null) {
+            ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
+            rootParent.lockToolbarButtons();
+            for (TreePath path : paths) {
+                selectedElement = (DbImportTreeNode) path.getLastPathComponent();
+                parentElement = (DbImportTreeNode) selectedElement.getParent();
+                if (parentElement != null) {
+                    Object parentUserObject = parentElement.getUserObject();
+                    if (parentUserObject instanceof ReverseEngineering) {
+                        ReverseEngineering reverseEngineering = (ReverseEngineering) parentUserObject;
+                        deleteChilds(reverseEngineering);
+                    } else if (parentUserObject instanceof Catalog) {
+                        Catalog catalog = (Catalog) parentUserObject;
+                        deleteChilds(catalog);
+                    } else if (parentUserObject instanceof Schema) {
+                        Schema schema = (Schema) parentUserObject;
+                        deleteChilds(schema);
+                    } else if (parentUserObject instanceof IncludeTable) {
+                        IncludeTable includeTable = (IncludeTable) parentUserObject;
+                        deleteChilds(includeTable);
+                    }
+                }
+            }
+            if (paths.length > 1) {
+                getProjectController().setDirty(true);
+                ArrayList<DbImportTreeNode> expandList = tree.getTreeExpandList();
+                tree.translateReverseEngineeringToTree(tree.getReverseEngineering(), false);
+                tree.expandTree(expandList);
+            } else {
+                updateParentChilds();
+            }
+            putReverseEngineeringToUndoManager(reverseEngineeringOldCopy);
+            rootParent.getLoadDbSchemaButton().setEnabled(true);
+            rootParent.getReverseEngineeringProgress().setVisible(false);
+        }
+    }
+
+    public void setPanel(DraggableTreePanel panel) {
+        this.panel = panel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/EditNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/EditNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/EditNodeAction.java
new file mode 100644
index 0000000..5ae0591
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/EditNodeAction.java
@@ -0,0 +1,88 @@
+/*****************************************************************
+ *   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.action.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.FilterContainer;
+import org.apache.cayenne.dbsync.reverse.dbimport.PatternParam;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.util.Util;
+
+import java.awt.event.ActionEvent;
+
+/**
+ * @since 4.1
+ */
+public class EditNodeAction extends TreeManipulationAction {
+
+    private static final String ACTION_NAME = "Rename";
+    private static final String ICON_NAME = "icon-edit.png";
+
+    private String actionName;
+
+    public EditNodeAction(Application application) {
+        super(ACTION_NAME, application);
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        if (tree.isEditing()) {
+            return;
+        }
+        if (e != null) {
+            if (tree.getSelectionPath() != null) {
+                tree.startEditingAtPath(tree.getSelectionPath());
+            }
+        }
+        if (actionName == null) {
+            return;
+        }
+        if (tree.getSelectionPath() != null) {
+            selectedElement = tree.getSelectedNode();
+            parentElement = (DbImportTreeNode) selectedElement.getParent();
+            if (parentElement != null) {
+                Object selectedObject = selectedElement.getUserObject();
+                ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
+                if (!Util.isEmptyString(actionName)) {
+                    if (selectedObject instanceof FilterContainer) {
+                        ((FilterContainer) selectedObject).setName(actionName);
+                    } else if (selectedObject instanceof PatternParam) {
+                        ((PatternParam) selectedObject).setPattern(actionName);
+                    }
+                    updateModel(true);
+                    selectedElement = null;
+                }
+                if (!actionName.equals(EMPTY_NAME)) {
+                    putReverseEngineeringToUndoManager(reverseEngineeringOldCopy);
+                }
+            }
+        }
+    }
+
+    public void setActionName(String name) {
+        this.actionName = name;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/MoveImportNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/MoveImportNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/MoveImportNodeAction.java
new file mode 100644
index 0000000..cf8f44e
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/MoveImportNodeAction.java
@@ -0,0 +1,238 @@
+/*****************************************************************
+ *   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.action.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.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportTree;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportView;
+import org.apache.cayenne.modeler.editor.dbimport.DraggableTreePanel;
+import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
+import org.apache.cayenne.modeler.util.CayenneAction;
+
+import javax.swing.tree.TreePath;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+
+/**
+ * @since 4.1
+ */
+public class MoveImportNodeAction extends CayenneAction {
+
+    private static final String ICON_NAME = "icon-backward.png";
+    private static final String ACTION_NAME = "Include";
+    private static final String EMPTY_NAME = "";
+
+    private DbImportTree sourceTree;
+    private DbImportTree targetTree;
+    private DraggableTreePanel panel;
+    protected boolean moveInverted;
+    private Map<Class, Class> classMap;
+
+    public MoveImportNodeAction(Application application) {
+        super(ACTION_NAME, application);
+    }
+
+    MoveImportNodeAction(String actionName, Application application) {
+        super(actionName, application);
+        initMap();
+    }
+
+    private void initMap() {
+        classMap = new HashMap<>();
+        classMap.put(IncludeTable.class, ExcludeTable.class);
+        classMap.put(IncludeColumn.class, ExcludeColumn.class);
+        classMap.put(IncludeProcedure.class, ExcludeProcedure.class);
+        classMap.put(Schema.class, Schema.class);
+        classMap.put(Catalog.class, Catalog.class);
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    private boolean canInsert(TreePath path, DbImportTreeNode foundNode) {
+        DbImportTreeNode sourceElement = (DbImportTreeNode) path.getLastPathComponent();
+        DbImportTreeNode selectedElement;
+        if (foundNode == null) {
+            if (targetTree.getSelectionPath() != null) {
+                DbImportTreeNode node = targetTree.getSelectedNode();
+                if ((node.getUserObject().getClass() == Catalog.class)
+                        || (node.getUserObject().getClass() == Schema.class)
+                        || (node.getUserObject().getClass() == ReverseEngineering.class)) {
+                    selectedElement = targetTree.getSelectedNode();
+                } else {
+                    selectedElement = (DbImportTreeNode) targetTree.getSelectionPath().
+                            getParentPath().getLastPathComponent();
+                }
+            } else {
+                selectedElement = targetTree.getRootNode();
+            }
+        } else {
+            selectedElement = foundNode;
+        }
+        if ((nodeClassesIsSameTypes(sourceElement, selectedElement))
+                && (sourceElement.getSimpleNodeName().equals(selectedElement.getSimpleNodeName()))) {
+            return false;
+        }
+        int childCount = selectedElement.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            DbImportTreeNode child = (DbImportTreeNode) selectedElement.getChildAt(i);
+            if ((nodeClassesIsSameTypes(sourceElement, child))
+                && (sourceElement.getSimpleNodeName().equals(child.getSimpleNodeName()))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        TreePath[] paths = sourceTree.getSelectionPaths();
+        TreeManipulationAction action = null;
+        String insertableName = EMPTY_NAME;
+        DbImportView rootParent = (DbImportView) panel.getParent().getParent();
+        rootParent.getReverseEngineeringProgress().setVisible(true);
+        if (paths != null) {
+            boolean isChanged = false;
+            ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(targetTree.getReverseEngineering());
+            try {
+                for (TreePath path : paths) {
+                    DbImportTreeNode selectedElement = (DbImportTreeNode) path.getLastPathComponent();
+                    DbImportTreeNode previousNode;
+                    DbImportTreeNode foundNode = targetTree.findNodeByParentsChain(
+                            targetTree.getRootNode(), selectedElement, 0
+                    );
+                    // If parent nodes from db schema doesn't exist, create it
+                    if (foundNode == null) {
+                        for (int i = selectedElement.getParents().size() - 2; i >= 0; i--) {
+                            DbImportTreeNode insertedNode = selectedElement.getParents().get(i);
+                            previousNode = targetTree.findNodeByParentsChain(targetTree.getRootNode(), insertedNode, 0);
+                            if (previousNode == null) {
+                                previousNode = targetTree.getRootNode();
+                            }
+                            TreeManipulationAction manipulationAction = panel.getActionByNodeType(
+                                    insertedNode.getUserObject().getClass()
+                            );
+                            if (canInsert(new TreePath(insertedNode.getPath()), previousNode)) {
+                                manipulationAction.setFoundNode(previousNode);
+                                manipulationAction.setInsertableNodeName(insertedNode.getSimpleNodeName());
+                                manipulationAction.setTree(targetTree);
+                                manipulationAction.setMovedFromDbSchema(true);
+                                manipulationAction.actionPerformed(e);
+                                manipulationAction.setFoundNode(null);
+                                manipulationAction.setMultipleAction(false);
+                            }
+                        }
+                    }
+                    // Again find node where we insert our node
+                    foundNode = targetTree.findNodeByParentsChain(targetTree.getRootNode(), selectedElement, 0);
+                    if (!moveInverted) {
+                        action = panel.getActionByNodeType(selectedElement.getUserObject().getClass());
+                    } else {
+                        action = panel.getActionByNodeType(classMap.get(selectedElement.getUserObject().getClass()));
+                    }
+                    if (action != null) {
+                        if (paths.length > 1) {
+                            action.setMultipleAction(true);
+                        } else {
+                            action.setMultipleAction(false);
+                        }
+                        if (canInsert(path, foundNode)) {
+                            insertableName = selectedElement.getSimpleNodeName();
+                            action.setFoundNode(foundNode);
+                            action.setInsertableNodeName(Matcher.quoteReplacement(insertableName));
+                            action.setTree(targetTree);
+                            action.setMovedFromDbSchema(true);
+                            action.actionPerformed(e);
+                            action.setFoundNode(null);
+                            action.resetActionFlags();
+                            isChanged = true;
+                            sourceTree.setSelectionRow(-1);
+                            panel.getMoveButton().setEnabled(false);
+                            panel.getMoveInvertButton().setEnabled(false);
+                        }
+                    }
+                }
+                if ((paths.length > 1) && (targetTree.getSelectionPath() != null)) {
+                    getProjectController().setDirty(true);
+                    ArrayList<DbImportTreeNode> expandList = targetTree.getTreeExpandList();
+                    targetTree.translateReverseEngineeringToTree(targetTree.getReverseEngineering(), false);
+                    targetTree.expandTree(expandList);
+                }
+                if ((isChanged) && (!insertableName.equals(EMPTY_NAME))) {
+                    ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(targetTree.getReverseEngineering());
+                    DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
+                            reverseEngineeringOldCopy, reverseEngineeringNewCopy, targetTree, getProjectController()
+                    );
+                    getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
+                }
+            } finally {
+                rootParent.getReverseEngineeringProgress().setVisible(false);
+                if (action != null) {
+                    action.resetActionFlags();
+                }
+            }
+        }
+    }
+
+    private boolean nodeClassesIsSameTypes(DbImportTreeNode sourceElement, DbImportTreeNode selectedElement) {
+        if (sourceElement.getUserObject().getClass() == selectedElement.getUserObject().getClass()) {
+            return true;
+        }
+        if (sourceElement.getUserObject().getClass() == IncludeTable.class) {
+            if ((selectedElement.getUserObject().getClass() == IncludeTable.class)
+                || (selectedElement.getUserObject().getClass() == ExcludeTable.class)) {
+                return true;
+            }
+        }
+        if (sourceElement.getUserObject().getClass() == IncludeProcedure.class) {
+            if ((selectedElement.getUserObject().getClass() == IncludeProcedure.class)
+                    || (selectedElement.getUserObject().getClass() == ExcludeProcedure.class)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void setSourceTree(DbImportTree sourceTree) {
+        this.sourceTree = sourceTree;
+    }
+
+    public void setTargetTree(DbImportTree targetTree) {
+        this.targetTree = targetTree;
+    }
+
+    public void setPanel(DraggableTreePanel panel) {
+        this.panel = panel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/MoveInvertNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/MoveInvertNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/MoveInvertNodeAction.java
new file mode 100644
index 0000000..dd7da10
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/MoveInvertNodeAction.java
@@ -0,0 +1,35 @@
+/*****************************************************************
+ *   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.action.dbimport;
+
+import org.apache.cayenne.modeler.Application;
+
+/**
+ * @since 4.1
+ */
+public class MoveInvertNodeAction extends MoveImportNodeAction {
+
+    private static final String ACTION_NAME = "Exclude";
+
+    public MoveInvertNodeAction(Application application) {
+        super(ACTION_NAME, application);
+        moveInverted = true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/TreeManipulationAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/TreeManipulationAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/TreeManipulationAction.java
new file mode 100644
index 0000000..23e6c65
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/TreeManipulationAction.java
@@ -0,0 +1,243 @@
+/*****************************************************************
+ *   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.action.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.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportModel;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportTree;
+import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
+import org.apache.cayenne.modeler.util.CayenneAction;
+
+import javax.swing.JTree;
+import javax.swing.tree.TreePath;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @since 4.1
+ */
+public abstract class TreeManipulationAction extends CayenneAction {
+
+    static final String EMPTY_NAME = "";
+
+    protected DbImportTree tree;
+    protected DbImportTreeNode selectedElement;
+    DbImportTreeNode parentElement;
+    DbImportTreeNode foundNode;
+    String insertableNodeName;
+    Class insertableNodeClass;
+    boolean isMultipleAction;
+    private boolean movedFromDbSchema;
+    private Map<Class, List<Class>> levels;
+    protected String name;
+    protected boolean updateSelected;
+
+    public TreeManipulationAction(String name, Application application) {
+        super(name, application);
+        initLevels();
+    }
+
+    void completeInserting(ReverseEngineering reverseEngineeringOldCopy) {
+        if (!isMultipleAction) {
+            updateAfterInsert();
+        }
+        if ((!isMultipleAction) && (!insertableNodeName.equals(EMPTY_NAME))) {
+            putReverseEngineeringToUndoManager(reverseEngineeringOldCopy);
+        }
+    }
+
+    private String getNodeName() {
+        return insertableNodeName != null ? insertableNodeName : EMPTY_NAME;
+    }
+
+    protected ReverseEngineering prepareElements() {
+        name = getNodeName();
+        tree.stopEditing();
+        if (tree.getSelectionPath() == null) {
+            TreePath root = new TreePath(tree.getRootNode());
+            tree.setSelectionPath(root);
+        }
+        if (foundNode == null) {
+            selectedElement = tree.getSelectedNode();
+        } else {
+            selectedElement = foundNode;
+        }
+        parentElement = (DbImportTreeNode) selectedElement.getParent();
+        if (parentElement == null) {
+            parentElement = selectedElement;
+        }
+        if (reverseEngineeringIsEmpty()) {
+            tree.getRootNode().removeAllChildren();
+        }
+        return new ReverseEngineering(tree.getReverseEngineering());
+    }
+
+    protected void putReverseEngineeringToUndoManager(ReverseEngineering reverseEngineeringOldCopy) {
+        ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
+        DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
+                reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController()
+        );
+        getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
+    }
+
+    boolean reverseEngineeringIsEmpty() {
+        ReverseEngineering reverseEngineering = tree.getReverseEngineering();
+        return ((reverseEngineering.getCatalogs().size() == 0) && (reverseEngineering.getSchemas().size() == 0)
+                && (reverseEngineering.getIncludeTables().size() == 0) && (reverseEngineering.getExcludeTables().size() == 0)
+                && (reverseEngineering.getIncludeColumns().size() == 0) && (reverseEngineering.getExcludeColumns().size() == 0)
+                && (reverseEngineering.getIncludeProcedures().size() == 0) && (reverseEngineering.getExcludeProcedures().size() == 0));
+    }
+
+    private void initLevels() {
+        levels = new HashMap<>();
+
+        List<Class> rootChilds = new ArrayList<>();
+        rootChilds.add(Schema.class);
+        rootChilds.add(IncludeTable.class);
+        rootChilds.add(ExcludeTable.class);
+        rootChilds.add(IncludeColumn.class);
+        rootChilds.add(ExcludeColumn.class);
+        rootChilds.add(IncludeProcedure.class);
+        rootChilds.add(ExcludeProcedure.class);
+        levels.put(ReverseEngineering.class, rootChilds);
+
+        List<Class> catalogChilds = new ArrayList<>();
+        catalogChilds.add(Schema.class);
+        catalogChilds.add(IncludeTable.class);
+        catalogChilds.add(ExcludeTable.class);
+        catalogChilds.add(IncludeColumn.class);
+        catalogChilds.add(ExcludeColumn.class);
+        catalogChilds.add(IncludeProcedure.class);
+        catalogChilds.add(ExcludeProcedure.class);
+        levels.put(Catalog.class, catalogChilds);
+
+        List<Class> schemaChilds = new ArrayList<>();
+        schemaChilds.add(IncludeTable.class);
+        schemaChilds.add(ExcludeTable.class);
+        schemaChilds.add(IncludeColumn.class);
+        schemaChilds.add(ExcludeColumn.class);
+        schemaChilds.add(IncludeProcedure.class);
+        schemaChilds.add(ExcludeProcedure.class);
+        levels.put(Schema.class, schemaChilds);
+
+        List<Class> includeTableChilds = new ArrayList<>();
+        includeTableChilds.add(IncludeColumn.class);
+        includeTableChilds.add(ExcludeColumn.class);
+        levels.put(IncludeTable.class, includeTableChilds);
+        levels.put(ExcludeTable.class, null);
+        levels.put(IncludeColumn.class, null);
+        levels.put(ExcludeColumn.class, null);
+        levels.put(IncludeProcedure.class, null);
+        levels.put(ExcludeProcedure.class, null);
+    }
+
+    public void setTree(DbImportTree tree) {
+        this.tree = tree;
+    }
+
+    public JTree getTree() {
+        return tree;
+    }
+
+    boolean canBeInserted(DbImportTreeNode node) {
+        if (node == null) {
+            return false;
+        }
+        Class selectedObjectClass = node.getUserObject().getClass();
+        List<Class> childs = levels.get(selectedObjectClass);
+        return childs != null && childs.contains(insertableNodeClass);
+    }
+
+    boolean canInsert() {
+        if (selectedElement == null) {
+            return true;
+        }
+        if (parentElement != null) {
+            for (int i = 0; i < parentElement.getChildCount(); i++) {
+                DbImportTreeNode child = (DbImportTreeNode) parentElement.getChildAt(i);
+                if (child.getSimpleNodeName().equals(insertableNodeName)
+                        && (child.getUserObject().getClass() == insertableNodeClass)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    protected void updateModel(boolean updateSelected) {
+        insertableNodeName = null;
+        DbImportModel model = (DbImportModel) tree.getModel();
+        getProjectController().setDirty(true);
+        TreePath savedPath = null;
+        if (!updateSelected) {
+            savedPath = new TreePath(parentElement.getPath());
+        }
+        model.reload(updateSelected ? selectedElement : parentElement);
+        if ((savedPath != null) && (parentElement.getUserObject().getClass() != ReverseEngineering.class)) {
+            tree.setSelectionPath(savedPath);
+        }
+    }
+
+    void updateAfterInsert() {
+        updateModel(updateSelected);
+        if (!movedFromDbSchema) {
+            if (updateSelected) {
+                tree.startEditingAtPath(new TreePath(((DbImportTreeNode) selectedElement.getLastChild()).getPath()));
+            } else {
+                tree.startEditingAtPath(new TreePath(((DbImportTreeNode) parentElement.getLastChild()).getPath()));
+            }
+        }
+        resetActionFlags();
+    }
+
+    public void resetActionFlags() {
+        movedFromDbSchema = false;
+        isMultipleAction = false;
+        insertableNodeName = "";
+    }
+
+    void setInsertableNodeName(String nodeName) {
+        this.insertableNodeName = nodeName;
+    }
+
+    void setMultipleAction(boolean multipleAction) {
+        isMultipleAction = multipleAction;
+    }
+
+    void setMovedFromDbSchema(boolean movedFromDbSchema) {
+        this.movedFromDbSchema = movedFromDbSchema;
+    }
+
+    void setFoundNode(DbImportTreeNode node) {
+        this.foundNode = node;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java
index 9f499f7..4f22c77 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java
@@ -34,7 +34,7 @@ import org.apache.cayenne.dbsync.reverse.filters.FiltersConfigBuilder;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
-import org.apache.cayenne.modeler.editor.DbImportView;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportView;
 import org.apache.cayenne.modeler.pref.DBConnectionInfo;
 import org.apache.cayenne.util.Util;
 import org.slf4j.Logger;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/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
index 8fa7ae1..8603337 100644
--- 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
@@ -20,8 +20,8 @@
 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 org.apache.cayenne.modeler.action.dbimport.DeleteNodeAction;
+import org.apache.cayenne.modeler.action.dbimport.EditNodeAction;
 
 import javax.swing.JMenuItem;
 import javax.swing.JPopupMenu;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/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 1109753..22924ac 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
@@ -26,11 +26,8 @@ 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;
@@ -88,43 +85,25 @@ public class ModelerDbImportAction extends DefaultDbImportAction {
     }
 
     @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;
-            }
+    protected void addMessageToLogs(String message, List<String> messages) {
+        String formattedMessage = String.format("    %-20s", message);
+        messages.add(formattedMessage);
+        resultDialog.addRowToOutput(formattedMessage);
+        isNothingChanged = false;
+    }
 
-            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)) {
+    @Override
+    protected void logMessages(List<String> messages) {
+        super.logMessages(messages);
+        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);
+        } else if (!resultDialog.isVisible()) {
+            resultDialog.setVisible(true);
         }
-        return hasChanges;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/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
index 0e3ef1d..f32030b 100644
--- 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
@@ -19,14 +19,14 @@
 
 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 org.apache.cayenne.modeler.action.dbimport.AddCatalogAction;
+import org.apache.cayenne.modeler.action.dbimport.AddExcludeColumnAction;
+import org.apache.cayenne.modeler.action.dbimport.AddExcludeProcedureAction;
+import org.apache.cayenne.modeler.action.dbimport.AddExcludeTableAction;
+import org.apache.cayenne.modeler.action.dbimport.AddIncludeColumnAction;
+import org.apache.cayenne.modeler.action.dbimport.AddIncludeProcedureAction;
+import org.apache.cayenne.modeler.action.dbimport.AddIncludeTableAction;
+import org.apache.cayenne.modeler.action.dbimport.AddSchemaAction;
 
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/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
deleted file mode 100644
index da0d474..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ColorTreeRenderer.java
+++ /dev/null
@@ -1,146 +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.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/51289d1c/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 5aa2544..ed1b6f1 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
@@ -22,6 +22,7 @@ import javax.swing.JScrollPane;
 import javax.swing.JTabbedPane;
 
 import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportView;
 
 
 /**


[12/14] cayenne git commit: Modeler: fix ComboBox style

Posted by nt...@apache.org.
Modeler: fix ComboBox style


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/da66ff90
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/da66ff90
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/da66ff90

Branch: refs/heads/master
Commit: da66ff90e834ddf4335fc90ccc9a0d78ee3b83ed
Parents: e158372
Author: Nikita Timofeev <st...@gmail.com>
Authored: Wed Mar 28 13:57:32 2018 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Wed Mar 28 13:57:32 2018 +0300

----------------------------------------------------------------------
 .../modeler/osx/OSXPlatformInitializer.java     | 31 +++++++++++---------
 1 file changed, 17 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/da66ff90/modeler/cayenne-modeler-mac-ext/src/main/java/org/apache/cayenne/modeler/osx/OSXPlatformInitializer.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler-mac-ext/src/main/java/org/apache/cayenne/modeler/osx/OSXPlatformInitializer.java b/modeler/cayenne-modeler-mac-ext/src/main/java/org/apache/cayenne/modeler/osx/OSXPlatformInitializer.java
index 159f09c..0578b9d 100644
--- a/modeler/cayenne-modeler-mac-ext/src/main/java/org/apache/cayenne/modeler/osx/OSXPlatformInitializer.java
+++ b/modeler/cayenne-modeler-mac-ext/src/main/java/org/apache/cayenne/modeler/osx/OSXPlatformInitializer.java
@@ -76,21 +76,24 @@ public class OSXPlatformInitializer implements PlatformInitializer {
         Color darkGrey  = new Color(225, 225, 225);
         Border darkBorder = BorderFactory.createLineBorder(darkGrey);
 
-        UIManager.put("ToolBarSeparatorUI",          OSXToolBarSeparatorUI.class.getName());
-        UIManager.put("PanelUI",                     OSXPanelUI.class.getName());
+        UIManager.put("ToolBarSeparatorUI",           OSXToolBarSeparatorUI.class.getName());
+        UIManager.put("PanelUI",                      OSXPanelUI.class.getName());
         // next two is custom made for Cayenne's MainToolBar
-        UIManager.put("MainToolBar.background",      UIManager.get("ToolBar.background"));
-        UIManager.put("MainToolBar.border",          BorderFactory.createEmptyBorder(0, 7, 0, 7));
-        UIManager.put("ToolBar.background",          lightGrey);
-        UIManager.put("ToolBar.border",              darkBorder);
-        UIManager.put("ScrollPane.border",           darkBorder);
-        UIManager.put("Table.scrollPaneBorder",      darkBorder);
-        UIManager.put("SplitPane.border",            BorderFactory.createEmptyBorder());
-        UIManager.put("SplitPane.background",        darkGrey);
-        UIManager.put("Tree.rendererFillBackground", Boolean.TRUE);
-        UIManager.put("Tree.selectionForeground",    Color.BLACK);
-        UIManager.put("Tree.selectionBackground",    lightGrey);
-        UIManager.put("Tree.selectionBorderColor",   lightGrey);
+        UIManager.put("MainToolBar.background",       UIManager.get("ToolBar.background"));
+        UIManager.put("MainToolBar.border",           BorderFactory.createEmptyBorder(0, 7, 0, 7));
+        UIManager.put("ToolBar.background",           lightGrey);
+        UIManager.put("ToolBar.border",               darkBorder);
+        UIManager.put("ScrollPane.border",            darkBorder);
+        UIManager.put("Table.scrollPaneBorder",       darkBorder);
+        UIManager.put("SplitPane.border",             BorderFactory.createEmptyBorder());
+        UIManager.put("SplitPane.background",         darkGrey);
+        UIManager.put("Tree.rendererFillBackground",  Boolean.TRUE);
+        UIManager.put("ComboBox.background",          Color.WHITE);
+        UIManager.put("ComboBox.selectionBackground", darkGrey);
+        UIManager.put("ComboBox.selectionForeground", Color.BLACK);
+        UIManager.put("Tree.selectionForeground",     Color.BLACK);
+        UIManager.put("Tree.selectionBackground",     lightGrey);
+        UIManager.put("Tree.selectionBorderColor",    lightGrey);
 
         Border backgroundPainter = new AbstractBorder() {
             @Override


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

Posted by nt...@apache.org.
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;
+    }
+}


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

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DraggableTreePanel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DraggableTreePanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DraggableTreePanel.java
new file mode 100644
index 0000000..9605e54
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DraggableTreePanel.java
@@ -0,0 +1,449 @@
+/*****************************************************************
+ *   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.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.action.dbimport.AddCatalogAction;
+import org.apache.cayenne.modeler.action.dbimport.AddExcludeColumnAction;
+import org.apache.cayenne.modeler.action.dbimport.AddExcludeProcedureAction;
+import org.apache.cayenne.modeler.action.dbimport.AddExcludeTableAction;
+import org.apache.cayenne.modeler.action.dbimport.AddIncludeColumnAction;
+import org.apache.cayenne.modeler.action.dbimport.AddIncludeProcedureAction;
+import org.apache.cayenne.modeler.action.dbimport.AddIncludeTableAction;
+import org.apache.cayenne.modeler.action.dbimport.AddSchemaAction;
+import org.apache.cayenne.modeler.action.dbimport.MoveImportNodeAction;
+import org.apache.cayenne.modeler.action.dbimport.MoveInvertNodeAction;
+import org.apache.cayenne.modeler.action.dbimport.TreeManipulationAction;
+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.DropMode;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.TransferHandler;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.TreePath;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @since 4.1
+ */
+public class DraggableTreePanel extends JScrollPane {
+
+    private static final int ROOT_LEVEL = 14;
+    private static final int FIRST_LEVEL = 11;
+    private static final int SECOND_LEVEL = 8;
+    private static final int THIRD_LEVEL = 5;
+    private static final int FOURTH_LEVEL = 2;
+    private static final int FIFTH_LEVEL = 3;
+    private static final String MOVE_BUTTON_LABEL = "Include";
+    private static final String MOVE_INV_BUTTON_LABEL = "Exclude";
+
+    private DbImportTree sourceTree;
+    private DbImportTree targetTree;
+    private CayenneAction.CayenneToolbarButton moveButton;
+    private CayenneAction.CayenneToolbarButton moveInvertButton;
+    private Map<DataMap, ReverseEngineering> databaseStructures;
+
+    private ProjectController projectController;
+    private Map<Class, Integer> levels;
+    private Map<Class, List<Class>> insertableLevels;
+    private Map<Class, Class> actions;
+
+    public DraggableTreePanel(ProjectController projectController, DbImportTree sourceTree, DbImportTree targetTree) {
+        super(sourceTree);
+        this.targetTree = targetTree;
+        this.sourceTree = sourceTree;
+        this.projectController = projectController;
+        this.databaseStructures = new HashMap<>();
+        initLevels();
+        initElement();
+        initActions();
+        initListeners();
+    }
+
+    private void initActions() {
+        actions = new HashMap<>();
+        actions.put(Catalog.class, AddCatalogAction.class);
+        actions.put(Schema.class, AddSchemaAction.class);
+        actions.put(IncludeTable.class, AddIncludeTableAction.class);
+        actions.put(ExcludeTable.class, AddExcludeTableAction.class);
+        actions.put(IncludeColumn.class, AddIncludeColumnAction.class);
+        actions.put(ExcludeColumn.class, AddExcludeColumnAction.class);
+        actions.put(IncludeProcedure.class, AddIncludeProcedureAction.class);
+        actions.put(ExcludeProcedure.class, AddExcludeProcedureAction.class);
+    }
+
+    public void updateTree(DataMap dataMap) {
+        DbImportModel model = (DbImportModel) sourceTree.getModel();
+        model.reload();
+        if (databaseStructures.get(dataMap) != null) {
+            sourceTree.setReverseEngineering(databaseStructures.get(dataMap));
+            sourceTree.translateReverseEngineeringToTree(databaseStructures.get(dataMap), true);
+            sourceTree.setEnabled(true);
+        } else {
+            sourceTree.setEnabled(false);
+        }
+    }
+
+    private void initListeners() {
+        sourceTree.addKeyListener(new SourceTreeKeyListener());
+        targetTree.addKeyListener(new TargetTreeKeyListener());
+        targetTree.addTreeSelectionListener(new TargetTreeSelectionListener());
+        targetTree.setTransferHandler(new TargetTreeTransferHandler());
+        sourceTree.setTransferHandler(new SourceTreeTransferHandler());
+        sourceTree.addTreeSelectionListener(new SourceTreeSelectionListener());
+        sourceTree.addMouseListener(new ResetFocusMouseAdapter());
+        targetTree.setDragEnabled(true);
+    }
+
+    private boolean canBeInverted() {
+        if (sourceTree.getSelectionPath() != null) {
+            DbImportTreeNode selectedElement = sourceTree.getSelectedNode();
+            if (selectedElement == null) {
+                return false;
+            }
+            if (levels.get(selectedElement.getUserObject().getClass()) < SECOND_LEVEL) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void initElement() {
+        sourceTree.setDragEnabled(true);
+        sourceTree.setCellRenderer(new ColorTreeRenderer());
+        sourceTree.setDropMode(DropMode.INSERT);
+
+        MoveImportNodeAction action = projectController.getApplication().
+                getActionManager().getAction(MoveImportNodeAction.class);
+        action.setPanel(this);
+        action.setSourceTree(sourceTree);
+        action.setTargetTree(targetTree);
+        moveButton = (CayenneAction.CayenneToolbarButton) action.buildButton();
+        moveButton.setShowingText(true);
+        moveButton.setText(MOVE_BUTTON_LABEL);
+        MoveInvertNodeAction actionInv = projectController.getApplication().
+                getActionManager().getAction(MoveInvertNodeAction.class);
+        actionInv.setPanel(this);
+        actionInv.setSourceTree(sourceTree);
+        actionInv.setTargetTree(targetTree);
+        moveInvertButton = (CayenneAction.CayenneToolbarButton) actionInv.buildButton();
+        moveInvertButton.setShowingText(true);
+        moveInvertButton.setText(MOVE_INV_BUTTON_LABEL);
+
+
+        DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) sourceTree.getCellRenderer();
+        renderer.setLeafIcon(null);
+        renderer.setClosedIcon(null);
+        renderer.setOpenIcon(null);
+    }
+
+    private void initLevels() {
+        levels = new HashMap<>();
+        levels.put(ReverseEngineering.class, ROOT_LEVEL);
+        levels.put(Catalog.class, FIRST_LEVEL);
+        levels.put(Schema.class, SECOND_LEVEL);
+        levels.put(IncludeTable.class, THIRD_LEVEL);
+        levels.put(IncludeColumn.class, FOURTH_LEVEL);
+        levels.put(ExcludeColumn.class, FOURTH_LEVEL);
+        levels.put(ExcludeTable.class, FIFTH_LEVEL);
+        levels.put(IncludeProcedure.class, FIFTH_LEVEL);
+        levels.put(ExcludeProcedure.class, FIFTH_LEVEL);
+
+        insertableLevels = new HashMap<>();
+        List<Class> rootLevelClasses = new ArrayList<>();
+        rootLevelClasses.add(Catalog.class);
+        rootLevelClasses.add(Schema.class);
+        rootLevelClasses.add(IncludeTable.class);
+        rootLevelClasses.add(ExcludeTable.class);
+        rootLevelClasses.add(IncludeColumn.class);
+        rootLevelClasses.add(ExcludeColumn.class);
+        rootLevelClasses.add(IncludeProcedure.class);
+        rootLevelClasses.add(ExcludeProcedure.class);
+
+        List<Class> catalogLevelClasses = new ArrayList<>();
+        catalogLevelClasses.add(Schema.class);
+        catalogLevelClasses.add(IncludeTable.class);
+        catalogLevelClasses.add(ExcludeTable.class);
+        catalogLevelClasses.add(IncludeColumn.class);
+        catalogLevelClasses.add(ExcludeColumn.class);
+        catalogLevelClasses.add(IncludeProcedure.class);
+        catalogLevelClasses.add(ExcludeProcedure.class);
+
+        List<Class> schemaLevelClasses = new ArrayList<>();
+        schemaLevelClasses.add(IncludeTable.class);
+        schemaLevelClasses.add(ExcludeTable.class);
+        schemaLevelClasses.add(IncludeColumn.class);
+        schemaLevelClasses.add(ExcludeColumn.class);
+        schemaLevelClasses.add(IncludeProcedure.class);
+        schemaLevelClasses.add(ExcludeProcedure.class);
+
+        List<Class> includeTableLevelClasses = new ArrayList<>();
+        includeTableLevelClasses.add(IncludeColumn.class);
+        includeTableLevelClasses.add(ExcludeColumn.class);
+
+        insertableLevels.put(ReverseEngineering.class, rootLevelClasses);
+        insertableLevels.put(Catalog.class, catalogLevelClasses);
+        insertableLevels.put(Schema.class, schemaLevelClasses);
+        insertableLevels.put(IncludeTable.class, includeTableLevelClasses);
+    }
+
+    private boolean canBeMoved() {
+        if (sourceTree.getSelectionPath() != null) {
+            DbImportTreeNode selectedElement = sourceTree.getSelectedNode();
+            if (selectedElement == null) {
+                return false;
+            }
+            Class draggableElementClass = selectedElement.getUserObject().getClass();
+            Class reverseEngineeringElementClass;
+            if (targetTree.getSelectionPath() != null) {
+                selectedElement = targetTree.getSelectedNode();
+                DbImportTreeNode parent = (DbImportTreeNode) selectedElement.getParent();
+                if (parent != null) {
+                    reverseEngineeringElementClass = parent.getUserObject().getClass();
+                } else {
+                    reverseEngineeringElementClass = selectedElement.getUserObject().getClass();
+                }
+            } else {
+                reverseEngineeringElementClass = ReverseEngineering.class;
+            }
+            List<Class> containsList = insertableLevels.get(reverseEngineeringElementClass);
+            return containsList.contains(draggableElementClass);
+        }
+        return false;
+    }
+
+    public JButton getMoveButton() {
+        return moveButton;
+    }
+
+    public JButton getMoveInvertButton() {
+        return moveInvertButton;
+    }
+
+    public TreeManipulationAction getActionByNodeType(Class nodeType) {
+        Class actionClass = actions.get(nodeType);
+        if (actionClass != null) {
+            TreeManipulationAction action = (TreeManipulationAction) projectController.getApplication().
+                    getActionManager().getAction(actionClass);
+            return action;
+        }
+        return null;
+    }
+
+    public void bindReverseEngineeringToDatamap(DataMap dataMap, ReverseEngineering reverseEngineering) {
+        databaseStructures.put(dataMap, reverseEngineering);
+    }
+
+    public DbImportTree getSourceTree() {
+        return sourceTree;
+    }
+
+    private static class SourceTreeTransferHandler extends TransferHandler {
+
+        @Override
+        public int getSourceActions(JComponent c) {
+            return COPY;
+        }
+
+        @Override
+        public Transferable createTransferable(JComponent c) {
+            JTree tree = (JTree) c;
+            TreePath[] paths = tree.getSelectionPaths();
+            DbImportTreeNode[] nodes = new DbImportTreeNode[paths.length];
+            for (int i = 0; i < paths.length; i++) {
+                nodes[i] = (DbImportTreeNode) paths[i].getLastPathComponent();
+            }
+            return new Transferable() {
+                @Override
+                public DataFlavor[] getTransferDataFlavors() {
+                    return TransferableNode.flavors;
+                }
+
+                @Override
+                public boolean isDataFlavorSupported(DataFlavor flavor) {
+                    return true;
+                }
+
+                @Override
+                public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+                    return nodes;
+                }
+            };
+        }
+    }
+
+    private class SourceTreeKeyListener implements KeyListener {
+        @Override
+        public void keyTyped(KeyEvent e) {}
+
+        @Override
+        public void keyPressed(KeyEvent e) {
+            if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                sourceTree.setSelectionRow(-1);
+                moveButton.setEnabled(false);
+                moveInvertButton.setEnabled(false);
+            }
+        }
+
+        @Override
+        public void keyReleased(KeyEvent e) {}
+    }
+
+    private class TargetTreeKeyListener implements KeyListener {
+        @Override
+        public void keyTyped(KeyEvent e) {}
+
+        @Override
+        public void keyPressed(KeyEvent e) {
+            if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                targetTree.setSelectionRow(-1);
+            }
+        }
+
+        @Override
+        public void keyReleased(KeyEvent e) {}
+    }
+
+    private class TargetTreeSelectionListener implements TreeSelectionListener {
+        @Override
+        public void valueChanged(TreeSelectionEvent e) {
+            DbImportModel model = (DbImportModel) sourceTree.getModel();
+            DbImportTreeNode root = (DbImportTreeNode) model.getRoot();
+            sourceTree.repaint();
+            if (root.getChildCount() > 0) {
+                model.nodesChanged(root, new int[]{root.getChildCount() - 1});
+            }
+            if (canBeMoved()) {
+                moveButton.setEnabled(true);
+                if (canBeInverted()) {
+                    moveInvertButton.setEnabled(true);
+                } else {
+                    moveInvertButton.setEnabled(false);
+                }
+            } else {
+                moveButton.setEnabled(false);
+                moveInvertButton.setEnabled(false);
+            }
+        }
+    }
+
+    private class TargetTreeTransferHandler extends TransferHandler {
+
+        @Override
+        public int getSourceActions(JComponent c) {
+            return COPY_OR_MOVE;
+        }
+
+        @Override
+        public boolean canImport(TransferSupport support) {
+            if (!support.isDrop()) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public boolean importData(TransferSupport support) {
+            if (!canImport(support)) {
+                return false;
+            }
+            if (!canBeMoved()) {
+                return false;
+            }
+            Transferable transferable = support.getTransferable();
+            DbImportTreeNode[] transferData = null;
+            try {
+                for (DataFlavor dataFlavor : transferable.getTransferDataFlavors()) {
+                    transferData = (DbImportTreeNode[]) transferable.getTransferData(dataFlavor);
+                }
+            } catch (IOException | UnsupportedFlavorException e) {
+                return false;
+            }
+            if (transferData != null) {
+                MoveImportNodeAction action = projectController.getApplication().
+                        getActionManager().getAction(MoveImportNodeAction.class);
+                action.setSourceTree(sourceTree);
+                action.setTargetTree(targetTree);
+                action.setPanel(DraggableTreePanel.this);
+                action.performAction(null);
+                return true;
+            }
+            return false;
+        }
+    }
+
+    private class SourceTreeSelectionListener implements TreeSelectionListener {
+        @Override
+        public void valueChanged(TreeSelectionEvent e) {
+            if (sourceTree.getLastSelectedPathComponent() != null) {
+                if (canBeMoved()) {
+                    moveButton.setEnabled(true);
+                    if (canBeInverted()) {
+                        moveInvertButton.setEnabled(true);
+                    } else {
+                        moveInvertButton.setEnabled(false);
+                    }
+                } else {
+                    moveInvertButton.setEnabled(false);
+                    moveButton.setEnabled(false);
+                }
+            }
+        }
+    }
+
+    private class ResetFocusMouseAdapter extends MouseAdapter {
+        @Override
+        public void mouseClicked(MouseEvent e) {
+            if (sourceTree.getRowForLocation(e.getX(),e.getY()) == -1) {
+                sourceTree.setSelectionRow(-1);
+                moveInvertButton.setEnabled(false);
+                moveButton.setEnabled(false);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ReverseEngineeringConfigPanel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ReverseEngineeringConfigPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ReverseEngineeringConfigPanel.java
new file mode 100644
index 0000000..8f3993a
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ReverseEngineeringConfigPanel.java
@@ -0,0 +1,221 @@
+/*****************************************************************
+ *   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.util.NameGeneratorPreferences;
+import org.apache.cayenne.modeler.util.TextAdapter;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import java.util.Vector;
+
+/**
+ * @since 4.1
+ */
+public class ReverseEngineeringConfigPanel extends JPanel {
+
+    private static final String DATA_FIELDS_LAYOUT = "right:pref, 3dlu, fill:235dlu";
+
+    private JComboBox<String> strategyCombo;
+    private TextAdapter meaningfulPk;
+    private TextAdapter stripFromTableNames;
+    private JCheckBox skipRelationshipsLoading;
+    private JCheckBox skipPrimaryKeyLoading;
+    private JCheckBox forceDataMapCatalog;
+    private JCheckBox forceDataMapSchema;
+    private JCheckBox usePrimitives;
+    private JCheckBox useJava7Types;
+
+    private ProjectController projectController;
+
+    ReverseEngineeringConfigPanel(ProjectController projectController) {
+        this.projectController = projectController;
+        initFormElements();
+        initListeners();
+        buildView();
+    }
+
+    private void buildView() {
+        FormLayout panelLayout = new FormLayout(DATA_FIELDS_LAYOUT);
+        DefaultFormBuilder panelBuilder = new DefaultFormBuilder(panelLayout);
+        panelBuilder.setDefaultDialogBorder();
+
+        panelBuilder.append("Tables with Meaningful PK Pattern:", meaningfulPk.getComponent());
+        panelBuilder.append("Strip from table names:", stripFromTableNames.getComponent());
+        panelBuilder.append("Skip relationships loading:", skipRelationshipsLoading);
+        panelBuilder.append("Skip primary key loading:", skipPrimaryKeyLoading);
+        panelBuilder.append("Force datamap catalog:", forceDataMapCatalog);
+        panelBuilder.append("Force datamap schema:", forceDataMapSchema);
+        panelBuilder.append("Use Java primitive types:", usePrimitives);
+        panelBuilder.append("Use java.util.Date type:", useJava7Types);
+        panelBuilder.append(strategyCombo);
+
+        add(panelBuilder.getPanel());
+    }
+
+    void fillCheckboxes(ReverseEngineering reverseEngineering) {
+        skipRelationshipsLoading.setSelected(reverseEngineering.getSkipRelationshipsLoading());
+        skipPrimaryKeyLoading.setSelected(reverseEngineering.getSkipPrimaryKeyLoading());
+        forceDataMapCatalog.setSelected(reverseEngineering.isForceDataMapCatalog());
+        forceDataMapSchema.setSelected(reverseEngineering.isForceDataMapSchema());
+        usePrimitives.setSelected(reverseEngineering.isUsePrimitives());
+        useJava7Types.setSelected(reverseEngineering.isUseJava7Types());
+    }
+
+    void initializeTextFields(ReverseEngineering reverseEngineering) {
+        meaningfulPk.setText(reverseEngineering.getMeaningfulPkTables());
+        stripFromTableNames.setText(reverseEngineering.getStripFromTableNames());
+    }
+
+    private ReverseEngineering getReverseEngineeringBySelectedMap() {
+        DataMap dataMap = projectController.getCurrentDataMap();
+        return projectController.getApplication().getMetaData().get(dataMap, ReverseEngineering.class);
+    }
+
+    private void initStrategy() {
+        Vector<String> arr = NameGeneratorPreferences
+                .getInstance()
+                .getLastUsedStrategies();
+        strategyCombo.setModel(new DefaultComboBoxModel<>(arr));
+    }
+
+    private void initFormElements() {
+        strategyCombo = new JComboBox<>();
+        strategyCombo.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setNamingStrategy(
+                    (String) ReverseEngineeringConfigPanel.this.getStrategyCombo().getSelectedItem()
+            );
+            projectController.setDirty(true);
+        });
+        strategyCombo.setVisible(false);
+
+        JTextField meaningfulPkField = new JTextField();
+        meaningfulPkField.setToolTipText("<html>Regular expression to filter tables with meaningful primary keys.<br>" +
+                "Multiple expressions divided by comma can be used.<br>" +
+                "Example: <b>^table1|^table2|^prefix.*|table_name</b></html>");
+        meaningfulPk = new TextAdapter(meaningfulPkField) {
+            protected void updateModel(String text) {
+                getReverseEngineeringBySelectedMap().setMeaningfulPkTables(text);
+                projectController.setDirty(true);
+            }
+        };
+
+        JTextField stripFromTableNamesField = new JTextField();
+        stripFromTableNamesField.setToolTipText("<html>Regex that matches the part of the table name that needs to be stripped off " +
+                "when generating ObjEntity name</html>");
+        stripFromTableNames = new TextAdapter(stripFromTableNamesField) {
+            protected void updateModel(String text) {
+                getReverseEngineeringBySelectedMap().setStripFromTableNames(text);
+                projectController.setDirty(true);
+            }
+        };
+
+        skipRelationshipsLoading = new JCheckBox();
+        skipRelationshipsLoading.setToolTipText("<html>Whether to load relationships.</html>");
+        skipPrimaryKeyLoading = new JCheckBox();
+        skipPrimaryKeyLoading.setToolTipText("<html>Whether to load primary keys.</html>");
+        forceDataMapCatalog = new JCheckBox();
+        forceDataMapCatalog.setToolTipText("<html>Automatically tagging each DbEntity with the actual DB catalog/schema" +
+                "(default behavior) may sometimes be undesirable.<br>  If this is the case then setting <b>forceDataMapCatalog</b> " +
+                "to <b>true</b> will set DbEntity catalog to one in the DataMap.</html>");
+        forceDataMapSchema = new JCheckBox();
+        forceDataMapSchema.setToolTipText("<html>Automatically tagging each DbEntity with the actual DB catalog/schema " +
+                "(default behavior) may sometimes be undesirable.<br> If this is the case then setting <b>forceDataMapSchema</b> " +
+                "to <b>true</b> will set DbEntity schema to one in the DataMap.</html>");
+        useJava7Types = new JCheckBox();
+        useJava7Types.setToolTipText("<html>Use <b>java.util.Date</b> for all columns with <i>DATE/TIME/TIMESTAMP</i> types.<br>" +
+                "By default <b>java.time.*</b> types will be used.</html>");
+        usePrimitives = new JCheckBox();
+        usePrimitives.setToolTipText("<html>Use primitive types (e.g. int) or Object types (e.g. java.lang.Integer)</html>");
+        initStrategy();
+    }
+
+    private void initListeners() {
+        skipRelationshipsLoading.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setSkipRelationshipsLoading(skipRelationshipsLoading.isSelected());
+            projectController.setDirty(true);
+        });
+        skipPrimaryKeyLoading.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setSkipPrimaryKeyLoading(skipPrimaryKeyLoading.isSelected());
+            projectController.setDirty(true);
+        });
+        forceDataMapCatalog.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setForceDataMapCatalog(forceDataMapCatalog.isSelected());
+            projectController.setDirty(true);
+        });
+        forceDataMapSchema.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setForceDataMapSchema(forceDataMapSchema.isSelected());
+            projectController.setDirty(true);
+        });
+        usePrimitives.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setUsePrimitives(usePrimitives.isSelected());
+            projectController.setDirty(true);
+        });
+        useJava7Types.addActionListener(e -> {
+            getReverseEngineeringBySelectedMap().setUseJava7Types(useJava7Types.isSelected());
+            projectController.setDirty(true);
+        });
+    }
+
+    JComboBox<String> getStrategyCombo() {
+        return strategyCombo;
+    }
+
+    TextAdapter getMeaningfulPk() {
+        return meaningfulPk;
+    }
+
+    TextAdapter getStripFromTableNames() {
+        return stripFromTableNames;
+    }
+
+    JCheckBox getSkipRelationshipsLoading() {
+        return skipRelationshipsLoading;
+    }
+
+    JCheckBox getSkipPrimaryKeyLoading() {
+        return skipPrimaryKeyLoading;
+    }
+
+    JCheckBox getForceDataMapCatalog() {
+        return forceDataMapCatalog;
+    }
+
+    JCheckBox getForceDataMapSchema() {
+        return forceDataMapSchema;
+    }
+
+    JCheckBox getUsePrimitives() {
+        return usePrimitives;
+    }
+
+    JCheckBox getUseJava7Types() {
+        return useJava7Types;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ReverseEngineeringTreePanel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ReverseEngineeringTreePanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ReverseEngineeringTreePanel.java
new file mode 100644
index 0000000..5fefdd2
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ReverseEngineeringTreePanel.java
@@ -0,0 +1,173 @@
+/*****************************************************************
+ *   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.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.dialog.db.load.CatalogPopUpMenu;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.dialog.db.load.DefaultPopUpMenu;
+import org.apache.cayenne.modeler.dialog.db.load.IncludeTablePopUpMenu;
+import org.apache.cayenne.modeler.dialog.db.load.RootPopUpMenu;
+import org.apache.cayenne.modeler.dialog.db.load.SchemaPopUpMenu;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportTree;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportTreeCellEditor;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportTreeCellRenderer;
+import org.apache.cayenne.modeler.editor.dbimport.DraggableTreePanel;
+import org.apache.cayenne.modeler.editor.dbimport.TreeToolbarPanel;
+
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.SwingUtilities;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.TreePath;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @since 4.1
+ */
+class ReverseEngineeringTreePanel extends JScrollPane {
+
+    private DbImportTree reverseEngineeringTree;
+    private DbImportTree dbSchemaTree;
+
+    private ProjectController projectController;
+    private TreeToolbarPanel treeToolbar;
+    private Map<Class, DefaultPopUpMenu> popups;
+
+    ReverseEngineeringTreePanel(ProjectController projectController, DbImportTree reverseEngineeringTree,
+                                DbImportTree dbSchemaTree) {
+        super(reverseEngineeringTree);
+        this.projectController = projectController;
+        this.reverseEngineeringTree = reverseEngineeringTree;
+        this.dbSchemaTree = dbSchemaTree;
+        reverseEngineeringTree.setEditable(true);
+        reverseEngineeringTree.setCellRenderer(new DbImportTreeCellRenderer());
+        DbImportTreeCellEditor editor = new DbImportTreeCellEditor(reverseEngineeringTree,
+                (DefaultTreeCellRenderer) reverseEngineeringTree.getCellRenderer());
+        editor.setProjectController(projectController);
+        reverseEngineeringTree.setCellEditor(editor);
+        initListeners();
+        initPopupMenus();
+        changeIcons();
+    }
+
+    void updateTree() {
+        reverseEngineeringTree.translateReverseEngineeringToTree(getReverseEngineeringBySelectedMap(), false);
+    }
+
+    private void initPopupMenus() {
+        popups = new HashMap<>();
+        popups.put(Catalog.class, new CatalogPopUpMenu());
+        popups.put(Schema.class, new SchemaPopUpMenu());
+        popups.put(ReverseEngineering.class, new RootPopUpMenu());
+        popups.put(String.class, new RootPopUpMenu());
+        popups.put(IncludeTable.class, new IncludeTablePopUpMenu());
+        popups.put(ExcludeTable.class, new DefaultPopUpMenu());
+        popups.put(IncludeColumn.class, new DefaultPopUpMenu());
+        popups.put(ExcludeColumn.class, new DefaultPopUpMenu());
+        popups.put(IncludeProcedure.class, new DefaultPopUpMenu());
+        popups.put(ExcludeProcedure.class, new DefaultPopUpMenu());
+    }
+
+    private void initListeners() {
+        reverseEngineeringTree.addTreeSelectionListener(e -> treeToolbar.lockButtons());
+        reverseEngineeringTree.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mouseClicked(MouseEvent e) {
+                if (reverseEngineeringTree.getRowForLocation(e.getX(), e.getY()) == -1) {
+                    reverseEngineeringTree.setSelectionRow(-1);
+                }
+
+                if (SwingUtilities.isRightMouseButton(e)) {
+                    if (reverseEngineeringTree.isEditing()) {
+                        return;
+                    }
+                    int row = reverseEngineeringTree.getClosestRowForLocation(e.getX(), e.getY());
+                    reverseEngineeringTree.setSelectionRow(row);
+                    DefaultPopUpMenu popupMenu;
+                    DbImportTreeNode selectedElement;
+                    if (reverseEngineeringTree.getSelectionPath() != null) {
+                        selectedElement = reverseEngineeringTree.getSelectedNode();
+                        popupMenu = popups.get(selectedElement.getUserObject().getClass());
+                    } else {
+                        selectedElement = reverseEngineeringTree.getRootNode();
+                        popupMenu = popups.get(ReverseEngineering.class);
+                    }
+                    if (popupMenu != null) {
+                        popupMenu.setProjectController(projectController);
+                        popupMenu.setSelectedElement(selectedElement);
+                        popupMenu.setParentElement((DbImportTreeNode) selectedElement.getParent());
+                        popupMenu.setTree(reverseEngineeringTree);
+                        popupMenu.show(e.getComponent(), e.getX(), e.getY());
+                    }
+                } else if (reverseEngineeringTree.getSelectionPath() != null) {
+                    DbImportTreeNode findedNode = dbSchemaTree.findNode(
+                            dbSchemaTree.getRootNode(), reverseEngineeringTree.getSelectedNode(), 0
+                    );
+                    if (findedNode != null) {
+                        dbSchemaTree.expandPath(new TreePath(((DbImportTreeNode) findedNode.getParent()).getPath()));
+                        scrollToNode(dbSchemaTree, findedNode);
+                    }
+                }
+            }
+        });
+    }
+
+    private void scrollToNode(JTree tree, DbImportTreeNode node) {
+        TreePath path = new TreePath(node.getPath());
+        tree.scrollPathToVisible(path);
+        DraggableTreePanel parentPanel = ((DraggableTreePanel) dbSchemaTree.getParent().getParent());
+        parentPanel.getHorizontalScrollBar().setValue(0);
+    }
+
+    private ReverseEngineering getReverseEngineeringBySelectedMap() {
+        DataMap dataMap = projectController.getCurrentDataMap();
+        return projectController.getApplication().getMetaData().get(dataMap, ReverseEngineering.class);
+    }
+
+    private void changeIcons() {
+        // Deleting standard tree icons
+        DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) reverseEngineeringTree.getCellRenderer();
+        renderer.setLeafIcon(null);
+        renderer.setClosedIcon(null);
+        renderer.setOpenIcon(null);
+    }
+
+    public DbImportTree getReverseEngineeringTree() {
+        return reverseEngineeringTree;
+    }
+
+    void setTreeToolbar(TreeToolbarPanel treeToolbar) {
+        this.treeToolbar = treeToolbar;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/TreeToolbarPanel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/TreeToolbarPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/TreeToolbarPanel.java
new file mode 100644
index 0000000..cb1ee9b
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/TreeToolbarPanel.java
@@ -0,0 +1,231 @@
+/*****************************************************************
+ *   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.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.modeler.ProjectController;
+import org.apache.cayenne.modeler.action.dbimport.AddCatalogAction;
+import org.apache.cayenne.modeler.action.dbimport.AddExcludeColumnAction;
+import org.apache.cayenne.modeler.action.dbimport.AddExcludeProcedureAction;
+import org.apache.cayenne.modeler.action.dbimport.AddExcludeTableAction;
+import org.apache.cayenne.modeler.action.dbimport.AddIncludeColumnAction;
+import org.apache.cayenne.modeler.action.dbimport.AddIncludeProcedureAction;
+import org.apache.cayenne.modeler.action.dbimport.AddIncludeTableAction;
+import org.apache.cayenne.modeler.action.dbimport.AddPatternParamAction;
+import org.apache.cayenne.modeler.action.dbimport.AddSchemaAction;
+import org.apache.cayenne.modeler.action.dbimport.DeleteNodeAction;
+import org.apache.cayenne.modeler.action.dbimport.EditNodeAction;
+import org.apache.cayenne.modeler.action.GetDbConnectionAction;
+import org.apache.cayenne.modeler.action.dbimport.TreeManipulationAction;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportTree;
+import org.apache.cayenne.modeler.editor.dbimport.DraggableTreePanel;
+
+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/graph/extension/GraphHandler.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/extension/GraphHandler.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/extension/GraphHandler.java
index 1efdd60..0870ef7 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/extension/GraphHandler.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/extension/GraphHandler.java
@@ -23,8 +23,6 @@ import java.util.Map;
 
 import javax.swing.undo.UndoableEdit;
 
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.xml.DataChannelLoaderListener;
 import org.apache.cayenne.configuration.xml.NamespaceAwareNestedTagHandler;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.graph.GraphBuilder;
@@ -37,10 +35,6 @@ import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
-import javax.swing.undo.UndoableEdit;
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * Class to load graph from XML
  */

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java
index 9e7c81e..cd99859 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java
@@ -22,7 +22,7 @@ package org.apache.cayenne.modeler.undo;
 import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
-import org.apache.cayenne.modeler.editor.DbImportTree;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportTree;
 
 import javax.swing.undo.AbstractUndoableEdit;
 import javax.swing.undo.CannotRedoException;


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

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/DbImportSaverDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/DbImportSaverDelegate.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/DbImportSaverDelegate.java
new file mode 100644
index 0000000..dceb3ee
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/DbImportSaverDelegate.java
@@ -0,0 +1,46 @@
+/*****************************************************************
+ *   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.dbsync.xml;
+
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.project.extension.BaseSaverDelegate;
+
+/**
+ * @since 4.1
+ */
+class DbImportSaverDelegate extends BaseSaverDelegate {
+
+    private DataChannelMetaData metaData;
+
+    DbImportSaverDelegate(DataChannelMetaData metaData) {
+        this.metaData = metaData;
+    }
+
+    @Override
+    public Void visitDataMap(DataMap dataMap) {
+        ReverseEngineering reverseEngineering = metaData.get(dataMap, ReverseEngineering.class);
+        if(reverseEngineering != null) {
+            encoder.nested(reverseEngineering, getParentDelegate());
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/IncludeTableHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/IncludeTableHandler.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/IncludeTableHandler.java
new file mode 100644
index 0000000..edac2b8
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/IncludeTableHandler.java
@@ -0,0 +1,112 @@
+/*****************************************************************
+ *   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.dbsync.xml;
+
+import org.apache.cayenne.configuration.xml.NamespaceAwareNestedTagHandler;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeColumn;
+import org.apache.cayenne.dbsync.reverse.dbimport.FilterContainer;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeColumn;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+class IncludeTableHandler extends NamespaceAwareNestedTagHandler {
+
+    private static final String INCLUDE_TABLE_TAG = "includeTable";
+    private static final String INCLUDE_TABLE_NAME_TAG = "name";
+    private static final String INCLUDE_COLUMN_TAG = "includeColumn";
+    private static final String EXCLUDE_COLUMN_TAG = "excludeColumn";
+
+    private IncludeTable includeTable;
+
+    private FilterContainer entity;
+
+    IncludeTableHandler(NamespaceAwareNestedTagHandler parentHandler,FilterContainer entity) {
+        super(parentHandler);
+        this.entity = entity;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        switch (localName) {
+            case INCLUDE_TABLE_TAG:
+                return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    protected void processCharData(String localName, String data) {
+        switch (localName) {
+            case INCLUDE_TABLE_NAME_TAG:
+                createIncludeTableName(data);
+                break;
+            case INCLUDE_COLUMN_TAG:
+                createIncludeColumn(data);
+                break;
+            case EXCLUDE_COLUMN_TAG:
+                createExcludeColumn(data);
+                break;
+        }
+    }
+
+    private void createExcludeColumn(String excludeColumn) {
+        if (excludeColumn.trim().length() == 0) {
+            return;
+        }
+
+        if (includeTable != null) {
+            includeTable.addExcludeColumn(new ExcludeColumn(excludeColumn));
+        }
+    }
+
+    private void createIncludeColumn(String includeColumn) {
+        if (includeColumn.trim().length() == 0) {
+            return;
+        }
+
+        if (includeTable != null) {
+            includeTable.addIncludeColumn(new IncludeColumn(includeColumn));
+        }
+    }
+
+    private void createIncludeTableName(String includeTableName) {
+        if (includeTableName.trim().length() == 0) {
+            return;
+        }
+
+        if (includeTable == null) {
+            createIncludeTable();
+        }
+
+        if (includeTable != null) {
+            includeTable.setName(includeTableName);
+        }
+    }
+
+    private void createIncludeTable() {
+        includeTable = new IncludeTable();
+        entity.addIncludeTable(includeTable);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/SchemaHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/SchemaHandler.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/SchemaHandler.java
new file mode 100644
index 0000000..7476789
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/SchemaHandler.java
@@ -0,0 +1,186 @@
+/*****************************************************************
+ *   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.dbsync.xml;
+
+import org.apache.cayenne.configuration.xml.NamespaceAwareNestedTagHandler;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeProcedure;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.dbsync.reverse.dbimport.SchemaContainer;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeColumn;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeColumn;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+class SchemaHandler extends NamespaceAwareNestedTagHandler {
+
+    private static final String SCHEMA_TAG = "schema";
+    private static final String SCHEMA_NAME_TAG = "name";
+    private static final String INCLUDE_TABLE_TAG = "includeTable";
+    private static final String EXCLUDE_TABLE_TAG = "excludeTable";
+    private static final String INCLUDE_COLUMN_TAG = "includeColumn";
+    private static final String EXCLUDE_COLUMN_TAG = "excludeColumn";
+    private static final String INCLUDE_PROCEDURE_TAG = "includeProcedure";
+    private static final String EXCLUDE_PROCEDURE_TAG = "excludeProcedure";
+
+    private SchemaContainer entity;
+
+    private Schema schema;
+
+    SchemaHandler(NamespaceAwareNestedTagHandler parentHandler, SchemaContainer entity) {
+        super(parentHandler);
+        this.entity = entity;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        switch (localName) {
+            case SCHEMA_TAG:
+                createSchema();
+                return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    protected ContentHandler createChildTagHandler(String namespaceURI, String localName,
+                                                   String qName, Attributes attributes) {
+
+        if (namespaceURI.equals(targetNamespace)) {
+            switch (localName) {
+                case INCLUDE_TABLE_TAG:
+                    return new IncludeTableHandler(this, schema);
+            }
+        }
+
+        return super.createChildTagHandler(namespaceURI, localName, qName, attributes);
+    }
+
+    @Override
+    protected void processCharData(String localName, String data) {
+        switch (localName) {
+            case INCLUDE_TABLE_TAG:
+                createIncludeTable(data);
+                break;
+            case SCHEMA_NAME_TAG:
+                createSchemaName(data);
+                break;
+            case EXCLUDE_TABLE_TAG:
+                createExcludeTable(data);
+                break;
+            case INCLUDE_COLUMN_TAG:
+                createIncludeColumn(data);
+                break;
+            case EXCLUDE_COLUMN_TAG:
+                createExcludeColumn(data);
+                break;
+            case INCLUDE_PROCEDURE_TAG:
+                createIncludeProcedure(data);
+                break;
+            case EXCLUDE_PROCEDURE_TAG:
+                createExcludeProcedure(data);
+                break;
+        }
+    }
+
+    private void createIncludeTable(String includeTableData) {
+        if (includeTableData.trim().length() == 0) {
+            return;
+        }
+
+        if (schema != null) {
+            IncludeTable includeTable = new IncludeTable();
+            includeTable.setName(includeTableData);
+            schema.addIncludeTable(includeTable);
+        }
+    }
+
+    private void createExcludeProcedure(String excludeProcedure) {
+        if (excludeProcedure.trim().length() == 0) {
+            return;
+        }
+
+        if (schema != null) {
+            schema.addExcludeProcedure(new ExcludeProcedure(excludeProcedure));
+        }
+    }
+
+    private void createIncludeProcedure(String includeProcedure) {
+        if (includeProcedure.trim().length() == 0) {
+            return;
+        }
+
+        if (schema != null) {
+            schema.addIncludeProcedure(new IncludeProcedure(includeProcedure));
+        }
+    }
+
+    private void createExcludeColumn(String excludeColumn) {
+        if (excludeColumn.trim().length() == 0) {
+            return;
+        }
+
+        if (schema != null) {
+            schema.addExcludeColumn(new ExcludeColumn(excludeColumn));
+        }
+    }
+
+    private void createIncludeColumn(String includeColumn) {
+        if (includeColumn.trim().length() == 0) {
+            return;
+        }
+
+        if (schema != null) {
+            schema.addIncludeColumn(new IncludeColumn(includeColumn));
+        }
+    }
+
+    private void createExcludeTable(String excludeTable) {
+        if (excludeTable.trim().length() == 0) {
+            return;
+        }
+
+        if (schema != null) {
+            schema.addExcludeTable(new ExcludeTable(excludeTable));
+        }
+    }
+
+    private void createSchemaName(String schemaName) {
+        if (schemaName.trim().length() == 0) {
+            return;
+        }
+
+        if (schema != null) {
+            schema.setName(schemaName);
+        }
+    }
+
+    private void createSchema() {
+        schema = new Schema();
+        entity.addSchema(schema);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java
index 094a904..5acb389 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java
@@ -100,7 +100,7 @@ public class DbAttributeBuilder extends DefaultBuilder<DbAttribute> {
 
     @Override
     public DbAttribute build() {
-        if (Util.isEmptyString(obj.getName())) {
+        if (Util.isEmptyString((obj.getName()))) {
             name();
         }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
index 364f770..910a8e0 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 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.dba.DbAdapter;
 import org.apache.cayenne.dbsync.DbSyncModule;
 import org.apache.cayenne.dbsync.filter.NamePatternMatcher;
@@ -297,13 +298,13 @@ public class DefaultDbImportActionTest {
         DataSourceFactory dataSourceFactory = mock(DataSourceFactory.class);
         DataSource mock = mock(DataSource.class);
         when(dataSourceFactory.getDataSource((DataNodeDescriptor)any())).thenReturn(mock);
-
+        DataChannelMetaData metaData = mock(DataChannelMetaData.class);
         MergerTokenFactoryProvider mergerTokenFactoryProvider = mock(MergerTokenFactoryProvider.class);
         when(mergerTokenFactoryProvider.get((DbAdapter)any())).thenReturn(new DefaultMergerTokenFactory());
 
         DataChannelDescriptorLoader dataChannelDescriptorLoader = mock(DataChannelDescriptorLoader.class);
 
-        return new DefaultDbImportAction(log, projectSaver, dataSourceFactory, adapterFactory, mapLoader, mergerTokenFactoryProvider, dataChannelDescriptorLoader) {
+        return new DefaultDbImportAction(log, projectSaver, dataSourceFactory, adapterFactory, mapLoader, mergerTokenFactoryProvider, dataChannelDescriptorLoader, metaData) {
 
             protected DbLoader createDbLoader(DbAdapter adapter,
                                                Connection connection,

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilderTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilderTest.java
index 4ce8ef3..6aba638 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilderTest.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilderTest.java
@@ -54,7 +54,8 @@ public class FiltersConfigBuilderTest {
                 "      IncludeTable: table2\n" +
                 "        IncludeColumn: includeColumn\n" +
                 "      IncludeTable: table3\n" +
-                "        IncludeColumn: includeColumn\n", engineering.toString());
+                "        IncludeColumn: includeColumn\n\n" +
+                "  Use primitives", engineering.toString());
     }
 
     @Test
@@ -81,7 +82,8 @@ public class FiltersConfigBuilderTest {
                 "    Schema: schemaName02\n" +
                 "      IncludeTable: table1\n" +
                 "        IncludeColumn: includeColumn\n" +
-                "      ExcludeTable: table2\n", engineering.toString());
+                "      ExcludeTable: table2\n\n"+
+                "  Use primitives", engineering.toString());
     }
 
     @Test
@@ -106,7 +108,8 @@ public class FiltersConfigBuilderTest {
                 "    Schema: null\n" +
                 "      IncludeTable: null\n" +
                 "        ExcludeColumn: calculated_.*\n" +
-                "      ExcludeTable: SYS_.*\n", engineering.toString());
+                "      ExcludeTable: SYS_.*\n\n" +
+                "  Use primitives", engineering.toString());
     }
 
     @Test
@@ -120,7 +123,8 @@ public class FiltersConfigBuilderTest {
                 "ReverseEngineering: \n" +
                 "  Catalog: null\n" +
                 "    Schema: s\n" +
-                "      IncludeTable: null\n", engineering.toString());
+                "      IncludeTable: null\n\n" +
+                "  Use primitives", engineering.toString());
     }
 
     @Test
@@ -203,7 +207,8 @@ public class FiltersConfigBuilderTest {
                 "    IncludeColumn: c_xxx1\n" +
                 "    ExcludeColumn: c_xxx2\n" +
                 "    IncludeProcedure: p7\n" +
-                "    ExcludeProcedure: p8\n", engineering.toString());
+                "    ExcludeProcedure: p8\n\n" +
+                "  Use primitives", engineering.toString());
 
 
         builder.compact();
@@ -259,7 +264,8 @@ public class FiltersConfigBuilderTest {
                         "      IncludeProcedure: p5\n" +
                         "      IncludeProcedure: p7\n" +
                         "      ExcludeProcedure: p6\n" +
-                        "      ExcludeProcedure: p8\n", engineering.toString());
+                        "      ExcludeProcedure: p8\n\n" +
+                        "  Use primitives", engineering.toString());
     }
 
     protected IncludeTable includeTable(String name, String incCol, String excCol) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-di/src/main/java/org/apache/cayenne/di/BindingBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-di/src/main/java/org/apache/cayenne/di/BindingBuilder.java b/cayenne-di/src/main/java/org/apache/cayenne/di/BindingBuilder.java
index 49edbe0..4aa2c59 100644
--- a/cayenne-di/src/main/java/org/apache/cayenne/di/BindingBuilder.java
+++ b/cayenne-di/src/main/java/org/apache/cayenne/di/BindingBuilder.java
@@ -18,9 +18,6 @@
  ****************************************************************/
 package org.apache.cayenne.di;
 
-import org.apache.cayenne.di.DIRuntimeException;
-
-
 /**
  * A binding builder that helps with fluent binding creation.
  * 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java
----------------------------------------------------------------------
diff --git a/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java b/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java
index e5a9bd1..d4e50a4 100644
--- a/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java
+++ b/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java
@@ -82,8 +82,8 @@ public class DbImportTask extends BaseCayenneTask {
         DbImportConfiguration config = createConfig();
 
         Injector injector = DIBootstrap.createInjector(new DbSyncModule(), new ToolsModule(getLogger()), new DbImportModule());
-
         DbImportConfigurationValidator validator = new DbImportConfigurationValidator(reverseEngineering, config, injector);
+
         try {
             validator.validate();
         } catch (Exception ex) {
@@ -109,25 +109,27 @@ public class DbImportTask extends BaseCayenneTask {
     DbImportConfiguration createConfig() {
 
         reverseEngineering = config.toReverseEngineering();
-
         DbImportConfiguration config = new DbImportConfiguration();
+        if (reverseEngineering.getCatalogs().size() == 0 && reverseEngineering.isEmptyContainer()) {
+            config.setUseDataMapReverseEngineering(true);
+        }
         config.setAdapter(adapter);
-        config.setDefaultPackage(reverseEngineering.getDefaultPackage());
         config.setDriver(dataSource.getDriver());
-        config.setFiltersConfig(new FiltersConfigBuilder(reverseEngineering).build());
-        config.setForceDataMapCatalog(reverseEngineering.isForceDataMapCatalog());
-        config.setForceDataMapSchema(reverseEngineering.isForceDataMapSchema());
         config.setLogger(getLogger());
-        config.setMeaningfulPkTables(reverseEngineering.getMeaningfulPkTables());
-        config.setNamingStrategy(reverseEngineering.getNamingStrategy());
         config.setPassword(dataSource.getPassword());
+        config.setTargetDataMap(getDataMapFile());
+        config.setUrl(dataSource.getUrl());
+        config.setUsername(dataSource.getUsername());
         config.setSkipRelationshipsLoading(reverseEngineering.getSkipRelationshipsLoading());
         config.setSkipPrimaryKeyLoading(reverseEngineering.getSkipPrimaryKeyLoading());
         config.setStripFromTableNames(reverseEngineering.getStripFromTableNames());
         config.setTableTypes(reverseEngineering.getTableTypes());
-        config.setTargetDataMap(getDataMapFile());
-        config.setUrl(dataSource.getUrl());
-        config.setUsername(dataSource.getUsername());
+        config.setMeaningfulPkTables(reverseEngineering.getMeaningfulPkTables());
+        config.setNamingStrategy(reverseEngineering.getNamingStrategy());
+        config.setFiltersConfig(new FiltersConfigBuilder(reverseEngineering).build());
+        config.setForceDataMapCatalog(reverseEngineering.isForceDataMapCatalog());
+        config.setForceDataMapSchema(reverseEngineering.isForceDataMapSchema());
+        config.setDefaultPackage(reverseEngineering.getDefaultPackage());
         config.setUsePrimitives(reverseEngineering.isUsePrimitives());
         config.setUseJava7Types(reverseEngineering.isUseJava7Types());
         config.setCayenneProject(cayenneProject);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-server/src/main/java/org/apache/cayenne/CayenneDataObject.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/CayenneDataObject.java b/cayenne-server/src/main/java/org/apache/cayenne/CayenneDataObject.java
index 3cad849..512f712 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/CayenneDataObject.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/CayenneDataObject.java
@@ -47,6 +47,8 @@ public class CayenneDataObject extends BaseDataObject {
 
 	private static final long serialVersionUID = -313743913882350400L;
 
+	protected long snapshotVersion = DEFAULT_VERSION;
+
 	protected Map<String, Object> values = new HashMap<>();
 
 	@Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java b/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
index e6422c5..7da60af 100644
--- a/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
+++ b/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
@@ -122,6 +122,9 @@ public class DbImporterMojo extends AbstractMojo {
     DbImportConfiguration createConfig(Logger logger) {
 
         DbImportConfiguration config = new DbImportConfiguration();
+        if (dbImportConfig.getCatalogs().size() == 0 && dbImportConfig.isEmptyContainer()) {
+            config.setUseDataMapReverseEngineering(true);
+        }
         config.setAdapter(adapter);
         config.setDefaultPackage(dbImportConfig.getDefaultPackage());
         config.setDriver(dataSource.getDriver());

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/CayenneGeneratorMojoTest.java
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/CayenneGeneratorMojoTest.java b/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/CayenneGeneratorMojoTest.java
index 734e93c..40338fb 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/CayenneGeneratorMojoTest.java
+++ b/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/CayenneGeneratorMojoTest.java
@@ -31,31 +31,22 @@ public class CayenneGeneratorMojoTest extends AbstractMojoTestCase {
         assertNotNull(pom);
         assertTrue(pom.exists());
 
-        CayenneGeneratorMojo myMojo = (CayenneGeneratorMojo) lookupMojo("cgen",
-                pom);
+        CayenneGeneratorMojo myMojo = (CayenneGeneratorMojo) lookupMojo("cgen", pom);
         assertNotNull(myMojo);
         myMojo.execute();
 
-        File superTestEntity = new File(
-                "target/cayenneGeneratedClasses/superPkg/_TestEntity.txt");
-        File testEntity = new File(
-                "target/cayenneGeneratedClasses/pack/TestEntity.txt");
+        File superTestEntity = new File("target/cayenneGeneratedClasses/superPkg/_TestEntity.txt");
+        File testEntity = new File("target/cayenneGeneratedClasses/pack/TestEntity.txt");
 
-        File superEmbeddable = new File(
-                "target/cayenneGeneratedClasses/superPkg/_Embeddable.txt");
-        File embeddable = new File(
-                "target/cayenneGeneratedClasses/pack/Embeddable.txt");
+        File superEmbeddable = new File("target/cayenneGeneratedClasses/superPkg/_Embeddable.txt");
+        File embeddable = new File("target/cayenneGeneratedClasses/pack/Embeddable.txt");
 
-        File superNotIncludedEntity = new File(
-                "target/cayenneGeneratedClasses/pack/_NotIncludedEntity.txt");
+        File superNotIncludedEntity = new File("target/cayenneGeneratedClasses/pack/_NotIncludedEntity.txt");
 
-        File notIncludedEntity = new File(
-                "target/cayenneGeneratedClasses/pack/NotIncludedEntity.txt");
+        File notIncludedEntity = new File("target/cayenneGeneratedClasses/pack/NotIncludedEntity.txt");
 
-        File superExcludedEntity = new File(
-                "target/cayenneGeneratedClasses/pack/_TestExcludedEntity.txt");
-        File excludedEntity = new File(
-                "target/cayenneGeneratedClasses/pack/TestExcludedEntity.txt");
+        File superExcludedEntity = new File("target/cayenneGeneratedClasses/pack/_TestExcludedEntity.txt");
+        File excludedEntity = new File("target/cayenneGeneratedClasses/pack/TestExcludedEntity.txt");
 
         assertTrue(superTestEntity.exists());
         assertTrue(testEntity.exists());
@@ -73,6 +64,5 @@ public class CayenneGeneratorMojoTest extends AbstractMojoTestCase {
         assertTrue(content.contains("public static final Property<List<TestRelEntity>> ADDITIONAL_REL = Property.create(\"additionalRel\", List.class);"));
         assertTrue(content.contains("public void addToAdditionalRel(TestRelEntity obj)"));
         assertTrue(content.contains("public void removeFromAdditionalRel(TestRelEntity obj)"));
-
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges-pom.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges-pom.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges-pom.xml
index 69831e9..56995b3 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges-pom.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges-pom.xml
@@ -21,7 +21,7 @@
 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
 	http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
-	<name>DbImporterMojo Test1</name>	
+	<name>DbImporterMojo Test1</name>
 
 	<build>
 		<plugins>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance-pom.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance-pom.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance-pom.xml
index 37c18d4..27fca57 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance-pom.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance-pom.xml
@@ -21,7 +21,7 @@
 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
 	http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
-	<name>DbImporterMojo Test1</name>	
+	<name>DbImporterMojo Test1</name>
 
 	<build>
 		<plugins>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimporter-pom1.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimporter-pom1.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimporter-pom1.xml
index 3bb6207..76bd257 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimporter-pom1.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimporter-pom1.xml
@@ -21,7 +21,7 @@
 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
 	http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
-	<name>DbImporterMojo Test1</name>	
+	<name>DbImporterMojo Test1</name>
 
 	<build>
 		<plugins>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimporter-pom3.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimporter-pom3.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimporter-pom3.xml
index be64020..04bc4ff 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimporter-pom3.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimporter-pom3.xml
@@ -21,7 +21,7 @@
 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
 	http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
-	<name>DbImporterMojo Test1</name>	
+	<name>DbImporterMojo Test1</name>
 
 	<build>
 		<plugins>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/pom.xml
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/pom.xml b/modeler/cayenne-modeler/pom.xml
index ef96ba8..794ebd3 100644
--- a/modeler/cayenne-modeler/pom.xml
+++ b/modeler/cayenne-modeler/pom.xml
@@ -20,8 +20,20 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
 	<modelVersion>4.0.0</modelVersion>
-
-	<parent>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <parent>
 		<groupId>org.apache.cayenne.modeler</groupId>
 		<artifactId>cayenne-modeler-parent</artifactId>
 		<version>4.1.M2-SNAPSHOT</version>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/CayenneModelerFrame.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/CayenneModelerFrame.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/CayenneModelerFrame.java
index 52cfcd3..ffc02fa 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/CayenneModelerFrame.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/CayenneModelerFrame.java
@@ -232,7 +232,6 @@ public class CayenneModelerFrame extends JFrame implements DataNodeDisplayListen
         projectMenu.addSeparator();
         projectMenu.add(getAction(RemoveAction.class).buildMenu());
 
-        toolMenu.add(getAction(ReverseEngineeringAction.class).buildMenu());
         toolMenu.add(getAction(InferRelationshipsAction.class).buildMenu());
         toolMenu.add(getAction(ImportEOModelAction.class).buildMenu());
         toolMenu.addSeparator();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddCatalogAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddCatalogAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddCatalogAction.java
new file mode 100644
index 0000000..50ebe74
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddCatalogAction.java
@@ -0,0 +1,91 @@
+/*****************************************************************
+ *   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.action;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
+
+import javax.swing.tree.TreePath;
+import java.awt.event.ActionEvent;
+
+/**
+ * @since 4.1
+ */
+public class AddCatalogAction extends TreeManipulationAction {
+
+    private static final String ACTION_NAME = "Add Catalog";
+    private static final String ICON_NAME = "icon-dbi-catalog.png";
+
+    AddCatalogAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = Catalog.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        boolean updateSelected = false;
+        tree.stopEditing();
+        String name = insertableNodeName != null ? insertableNodeName : EMPTY_NAME;
+        if (tree.getSelectionPath() == null) {
+            TreePath root = new TreePath(tree.getRootNode());
+            tree.setSelectionPath(root);
+        }
+        if (foundNode == null) {
+            selectedElement = tree.getSelectedNode();
+        } else {
+            selectedElement = foundNode;
+        }
+        parentElement = (DbImportTreeNode) selectedElement.getParent();
+        if (parentElement == null) {
+            parentElement = selectedElement;
+        }
+        Catalog newCatalog = new Catalog(name);
+        ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
+        if (reverseEngineeringIsEmpty()) {
+            tree.getRootNode().removeAllChildren();
+        }
+        if (canBeInserted(selectedElement)) {
+            ((ReverseEngineering) selectedElement.getUserObject()).addCatalog(newCatalog);
+            selectedElement.add(new DbImportTreeNode(newCatalog));
+            updateSelected = true;
+        } else if (canInsert()) {
+            ((ReverseEngineering) parentElement.getUserObject()).addCatalog(newCatalog);
+            parentElement.add(new DbImportTreeNode(newCatalog));
+            updateSelected = false;
+        }
+        if (!isMultipleAction) {
+            updateAfterInsert(updateSelected);
+        }
+        ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
+        if ((!isMultipleAction) && (!insertableNodeName.equals(EMPTY_NAME))) {
+            DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
+                    reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController()
+            );
+            getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeColumnAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeColumnAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeColumnAction.java
new file mode 100644
index 0000000..d36c7e2
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeColumnAction.java
@@ -0,0 +1,41 @@
+/*****************************************************************
+ *   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.action;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeColumn;
+import org.apache.cayenne.modeler.Application;
+
+/**
+ * @since 4.1
+ */
+public class AddExcludeColumnAction extends AddPatternParamAction {
+
+    private static final String ACTION_NAME = "Add Exclude Column";
+    private static final String ICON_NAME = "icon-dbi-excludeColumn.png";
+
+    public AddExcludeColumnAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = ExcludeColumn.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeProcedureAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeProcedureAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeProcedureAction.java
new file mode 100644
index 0000000..09ec188
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeProcedureAction.java
@@ -0,0 +1,41 @@
+/*****************************************************************
+ *   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.action;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeProcedure;
+import org.apache.cayenne.modeler.Application;
+
+/**
+ * @since 4.1
+ */
+public class AddExcludeProcedureAction extends AddPatternParamAction {
+
+    private static final String ACTION_NAME = "Add Exclude Procedure";
+    private static final String ICON_NAME = "icon-dbi-excludeProcedure.png";
+
+    public AddExcludeProcedureAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = ExcludeProcedure.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeTableAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeTableAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeTableAction.java
new file mode 100644
index 0000000..58baef2
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddExcludeTableAction.java
@@ -0,0 +1,41 @@
+/*****************************************************************
+ *   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.action;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeTable;
+import org.apache.cayenne.modeler.Application;
+
+/**
+ * @since 4.1
+ */
+public class AddExcludeTableAction extends AddPatternParamAction {
+
+    private static final String ACTION_NAME = "Add Exclude Table";
+    private static final String ICON_NAME = "icon-dbi-excludeTable.png";
+
+    public AddExcludeTableAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = ExcludeTable.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeColumnAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeColumnAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeColumnAction.java
new file mode 100644
index 0000000..e2b27b1
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeColumnAction.java
@@ -0,0 +1,41 @@
+/*****************************************************************
+ *   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.action;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeColumn;
+import org.apache.cayenne.modeler.Application;
+
+/**
+ * @since 4.1
+ */
+public class AddIncludeColumnAction extends AddPatternParamAction {
+
+    private static final String ACTION_NAME = "Add Include Column";
+    private static final String ICON_NAME = "icon-dbi-includeColumn.png";
+
+    public AddIncludeColumnAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = IncludeColumn.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeProcedureAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeProcedureAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeProcedureAction.java
new file mode 100644
index 0000000..6a04a63
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeProcedureAction.java
@@ -0,0 +1,41 @@
+/*****************************************************************
+ *   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.action;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
+import org.apache.cayenne.modeler.Application;
+
+/**
+ * @since 4.1
+ */
+public class AddIncludeProcedureAction extends AddPatternParamAction {
+
+    private static final String ACTION_NAME = "Add Include Procedure";
+    private static final String ICON_NAME = "icon-dbi-includeProcedure.png";
+
+    public AddIncludeProcedureAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = IncludeProcedure.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeTableAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeTableAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeTableAction.java
new file mode 100644
index 0000000..136a166
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddIncludeTableAction.java
@@ -0,0 +1,92 @@
+/*****************************************************************
+ *   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.action;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.FilterContainer;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
+
+import javax.swing.tree.TreePath;
+import java.awt.event.ActionEvent;
+
+/**
+ * @since 4.1
+ */
+public class AddIncludeTableAction extends TreeManipulationAction {
+
+    private static final String ACTION_NAME = "Add Include Table";
+    private static final String ICON_NAME = "icon-dbi-includeTable.png";
+
+    AddIncludeTableAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = IncludeTable.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        boolean updateSelected = false;
+        tree.stopEditing();
+        String name = insertableNodeName != null ? insertableNodeName : EMPTY_NAME;
+        if (tree.getSelectionPath() == null) {
+            TreePath root = new TreePath(tree.getRootNode());
+            tree.setSelectionPath(root);
+        }
+        if (foundNode == null) {
+            selectedElement = tree.getSelectedNode();
+        } else {
+            selectedElement = foundNode;
+        }
+        parentElement = (DbImportTreeNode) selectedElement.getParent();
+        ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
+        IncludeTable newTable = new IncludeTable(name);
+        if (reverseEngineeringIsEmpty()) {
+            tree.getRootNode().removeAllChildren();
+        }
+        if (canBeInserted(selectedElement)) {
+            ((FilterContainer) selectedElement.getUserObject()).addIncludeTable(newTable);
+            selectedElement.add(new DbImportTreeNode(newTable));
+            updateSelected = true;
+        } else {
+            if (parentElement == null) {
+                parentElement = tree.getRootNode();
+            }
+            ((FilterContainer) parentElement.getUserObject()).addIncludeTable(newTable);
+            parentElement.add(new DbImportTreeNode(newTable));
+            updateSelected = false;
+        }
+        if (!isMultipleAction) {
+            updateAfterInsert(updateSelected);
+        }
+        ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
+        if ((!isMultipleAction) && (!insertableNodeName.equals(EMPTY_NAME))) {
+            DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
+                    reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController()
+            );
+            getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddPatternParamAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddPatternParamAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddPatternParamAction.java
new file mode 100644
index 0000000..78479fc
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddPatternParamAction.java
@@ -0,0 +1,140 @@
+/*****************************************************************
+ *   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.action;
+
+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.FilterContainer;
+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.PatternParam;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
+
+import javax.swing.tree.TreePath;
+import java.awt.event.ActionEvent;
+
+/**
+ * @since 4.1
+ */
+public abstract class AddPatternParamAction extends TreeManipulationAction {
+
+    private Class paramClass;
+
+    AddPatternParamAction(String name, Application application) {
+        super(name, application);
+    }
+
+    private void addPatternParamToContainer(Class paramClass, Object selectedObject, String name, DbImportTreeNode node) {
+        FilterContainer container = (FilterContainer) selectedObject;
+        PatternParam element = null;
+        if (paramClass == ExcludeTable.class) {
+            element = new ExcludeTable(name);
+            container.addExcludeTable((ExcludeTable) element);
+        } else if (paramClass == IncludeColumn.class) {
+            element = new IncludeColumn(name);
+            container.addIncludeColumn((IncludeColumn) element);
+        } else if (paramClass == ExcludeColumn.class) {
+            element = new ExcludeColumn(name);
+            container.addExcludeColumn((ExcludeColumn) element);
+        } else if (paramClass == IncludeProcedure.class) {
+            element = new IncludeProcedure(name);
+            container.addIncludeProcedure((IncludeProcedure) element);
+        } else if (paramClass == ExcludeProcedure.class) {
+            element = new ExcludeProcedure(name);
+            container.addExcludeProcedure((ExcludeProcedure) element);
+        }
+        node.add(new DbImportTreeNode(element));
+    }
+
+    private void addPatternParamToIncludeTable(Class paramClass, Object selectedObject, String name, DbImportTreeNode node) {
+        IncludeTable includeTable = (IncludeTable) selectedObject;
+        PatternParam element = null;
+        if (paramClass == IncludeColumn.class) {
+            element = new IncludeColumn(name);
+            includeTable.addIncludeColumn((IncludeColumn) element);
+
+        } else if (paramClass == ExcludeColumn.class) {
+            element = new ExcludeColumn(name);
+            includeTable.addExcludeColumn((ExcludeColumn) element);
+        }
+        node.add(new DbImportTreeNode(element));
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        tree.stopEditing();
+        String name = insertableNodeName != null ? insertableNodeName : EMPTY_NAME;
+        boolean updateSelected;
+        if (tree.getSelectionPath() == null) {
+            TreePath root = new TreePath(tree.getRootNode());
+            tree.setSelectionPath(root);
+        }
+        if (foundNode == null) {
+            selectedElement = tree.getSelectedNode();
+        } else {
+            selectedElement = foundNode;
+        }
+        parentElement = (DbImportTreeNode) selectedElement.getParent();
+        Object selectedObject;
+        ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
+        if (reverseEngineeringIsEmpty()) {
+            tree.getRootNode().removeAllChildren();
+        }
+        if (canBeInserted(selectedElement)) {
+            selectedObject = selectedElement.getUserObject();
+            if (selectedObject instanceof FilterContainer) {
+                addPatternParamToContainer(paramClass, selectedObject, name, selectedElement);
+            } else if (selectedObject instanceof IncludeTable) {
+                addPatternParamToIncludeTable(paramClass, selectedObject, name, selectedElement);
+            }
+            updateSelected = true;
+        } else {
+            if (parentElement == null) {
+                parentElement = tree.getRootNode();
+            }
+            selectedObject = parentElement.getUserObject();
+            if (selectedObject instanceof FilterContainer) {
+                addPatternParamToContainer(paramClass, selectedObject, name, parentElement);
+            } else if (selectedObject instanceof IncludeTable) {
+                addPatternParamToIncludeTable(paramClass, selectedObject, name, parentElement);
+            }
+            updateSelected = false;
+        }
+        if (!isMultipleAction) {
+            updateAfterInsert(updateSelected);
+        }
+        ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
+        if ((!isMultipleAction) && (!insertableNodeName.equals(EMPTY_NAME))) {
+            DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
+                    reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController()
+            );
+            getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
+        }
+    }
+
+    public void setParamClass(Class paramClass) {
+        this.paramClass = paramClass;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddSchemaAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddSchemaAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddSchemaAction.java
new file mode 100644
index 0000000..817b17c
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/AddSchemaAction.java
@@ -0,0 +1,97 @@
+/*****************************************************************
+ *   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.action;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.dbsync.reverse.dbimport.SchemaContainer;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
+
+import javax.swing.tree.TreePath;
+import java.awt.event.ActionEvent;
+
+/**
+ * @since 4.1
+ */
+public class AddSchemaAction extends TreeManipulationAction {
+
+    private static final String ACTION_NAME = "Add Schema";
+    private static final String ICON_NAME = "icon-dbi-schema.png";
+
+    AddSchemaAction(Application application) {
+        super(ACTION_NAME, application);
+        insertableNodeClass = Schema.class;
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        boolean updateSelected = false;
+        tree.stopEditing();
+        String name = insertableNodeName != null ? insertableNodeName : EMPTY_NAME;
+        if (tree.getSelectionPath() == null) {
+            TreePath root = new TreePath(tree.getRootNode());
+            tree.setSelectionPath(root);
+        }
+        if (foundNode == null) {
+            selectedElement = tree.getSelectedNode();
+        } else {
+            selectedElement = foundNode;
+        }
+        parentElement = (DbImportTreeNode) selectedElement.getParent();
+        if (parentElement == null) {
+            parentElement = tree.getRootNode();
+        }
+        Schema newSchema = new Schema(name);
+        ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
+        if (reverseEngineeringIsEmpty()) {
+            tree.getRootNode().removeAllChildren();
+        }
+        if (canBeInserted(selectedElement)) {
+            ((SchemaContainer) selectedElement.getUserObject()).addSchema(newSchema);
+            selectedElement.add(new DbImportTreeNode(newSchema));
+            updateSelected = true;
+        } else if (canInsert()) {
+            if (parentElement.isReverseEngineering()) {
+                ((ReverseEngineering) parentElement.getUserObject()).addSchema(newSchema);
+            } else {
+                ((Catalog) parentElement.getUserObject()).addSchema(newSchema);
+            }
+            parentElement.add(new DbImportTreeNode(newSchema));
+            updateSelected = false;
+        }
+        if (!isMultipleAction) {
+            updateAfterInsert(updateSelected);
+        }
+        ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
+        if ((!isMultipleAction) && (!insertableNodeName.equals(EMPTY_NAME))) {
+            DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
+                    reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController()
+            );
+            getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DBWizardAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DBWizardAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DBWizardAction.java
index cd5de6f..0fbaac3 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DBWizardAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DBWizardAction.java
@@ -25,7 +25,7 @@ import java.util.Collections;
 import java.util.List;
 
 import javax.swing.JOptionPane;
-	
+
 import org.apache.cayenne.dbsync.reverse.dbload.DbLoader;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.dialog.db.DataSourceWizard;
@@ -44,6 +44,7 @@ public abstract class DBWizardAction<T extends DbActionOptionsDialog> extends Ca
     protected DataSourceWizard dataSourceWizardDialog(String title) {
         // connect
         DataSourceWizard connectWizard = new DataSourceWizard(getProjectController(), title);
+        connectWizard.setProjectController(getProjectController());
         if (!connectWizard.startupAction()) {
             return null;
         }
@@ -51,7 +52,7 @@ public abstract class DBWizardAction<T extends DbActionOptionsDialog> extends Ca
         return connectWizard;
     }
 
-    protected abstract T createDialog(Collection<String> catalogs, Collection<String> schemas, String currentCatalog, String currentSchema);
+    protected abstract T createDialog(Collection<String> catalogs, Collection<String> schemas, String currentCatalog, String currentSchema, int command);
 
     protected T loaderOptionDialog(DataSourceWizard connectWizard) {
 
@@ -81,16 +82,24 @@ public abstract class DBWizardAction<T extends DbActionOptionsDialog> extends Ca
                     JOptionPane.ERROR_MESSAGE);
             return null;
         }
-
-        final T optionsDialog = createDialog(catalogs, schemas, currentCatalog, currentSchema);
+        T optionsDialog = getStartDialog(catalogs, schemas, currentCatalog, currentSchema);
         optionsDialog.setVisible(true);
-        if (optionsDialog.getChoice() == DbActionOptionsDialog.SELECT) {
-            return optionsDialog;
+        while ((optionsDialog.getChoice() != DbActionOptionsDialog.CANCEL)) {
+            if (optionsDialog.getChoice() == DbActionOptionsDialog.SELECT) {
+                return optionsDialog;
+            }
+            optionsDialog = createDialog(catalogs, schemas, currentCatalog, currentSchema, optionsDialog.getChoice());
+            optionsDialog.setVisible(true);
         }
 
         return null;
     }
 
+    private T getStartDialog(List<String> catalogs, List<String> schemas, String currentCatalog, String currentSchema) {
+        int command = DbActionOptionsDialog.SELECT;
+        return createDialog(catalogs, schemas, currentCatalog, currentSchema, command);
+    }
+
     @SuppressWarnings("unchecked")
     private List<String> getCatalogs(DataSourceWizard connectWizard, Connection connection) throws Exception {
         if(!connectWizard.getAdapter().supportsCatalogsOnReverseEngineering()) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntityCounterpartAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntityCounterpartAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntityCounterpartAction.java
index 700b951..b3755cd 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntityCounterpartAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntityCounterpartAction.java
@@ -21,6 +21,9 @@ package org.apache.cayenne.modeler.action;
 
 import java.util.Iterator;
 
+import javax.swing.tree.TreePath;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.ObjEntity;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java
index fa427f8..a626365 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java
@@ -98,6 +98,20 @@ public class DefaultActionManager implements ActionManager {
         registerAction(new ImportEOModelAction(application));
         registerAction(new GenerateDBAction(application));
         registerAction(new MigrateAction(application));
+        registerAction(new AddSchemaAction(application)).setAlwaysOn(true);
+        registerAction(new AddCatalogAction(application)).setAlwaysOn(true);
+        registerAction(new AddIncludeTableAction(application)).setAlwaysOn(true);
+        registerAction(new AddExcludeTableAction(application)).setAlwaysOn(true);
+        registerAction(new AddIncludeColumnAction(application)).setAlwaysOn(true);
+        registerAction(new AddExcludeColumnAction(application)).setAlwaysOn(true);
+        registerAction(new AddIncludeProcedureAction(application)).setAlwaysOn(true);
+        registerAction(new AddExcludeProcedureAction(application)).setAlwaysOn(true);
+        registerAction(new GetDbConnectionAction(application)).setAlwaysOn(true);
+        registerAction(new EditNodeAction(application)).setAlwaysOn(true);
+        registerAction(new DeleteNodeAction(application)).setAlwaysOn(true);
+        registerAction(new MoveImportNodeAction(application)).setAlwaysOn(true);
+        registerAction(new LoadDbSchemaAction(application)).setAlwaysOn(true);
+        registerAction(new MoveInvertNodeAction(application)).setAlwaysOn(true);
         registerAction(new AboutAction(application)).setAlwaysOn(true);
         registerAction(new DocumentationAction(application)).setAlwaysOn(true);
         registerAction(new ConfigurePreferencesAction(application)).setAlwaysOn(true);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DeleteNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DeleteNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DeleteNodeAction.java
new file mode 100644
index 0000000..4645ee7
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DeleteNodeAction.java
@@ -0,0 +1,175 @@
+/*****************************************************************
+ *   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.action;
+
+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.FilterContainer;
+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.PatternParam;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.editor.DbImportModel;
+import org.apache.cayenne.modeler.editor.DbImportView;
+import org.apache.cayenne.modeler.editor.DraggableTreePanel;
+import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
+
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreePath;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+
+/**
+ * @since 4.1
+ */
+public class DeleteNodeAction extends TreeManipulationAction {
+
+    private static final String ACTION_NAME = "Delete";
+    private static final String ICON_NAME = "icon-trash.png";
+
+    private DraggableTreePanel panel;
+
+    DeleteNodeAction(Application application) {
+        super(ACTION_NAME, application);
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    private void removePatternParams(FilterContainer container, Object selectedObject) {
+        container.getExcludeTables().remove(selectedObject);
+        container.getIncludeColumns().remove(selectedObject);
+        container.getExcludeColumns().remove(selectedObject);
+        container.getIncludeProcedures().remove(selectedObject);
+        container.getExcludeProcedures().remove(selectedObject);
+    }
+
+    private void deleteChilds(Catalog catalog) {
+        Object selectedObject = this.selectedElement.getUserObject();
+        if (selectedObject instanceof Schema) {
+            catalog.getSchemas().remove(selectedObject);
+        } else if (selectedObject instanceof IncludeTable) {
+            catalog.getIncludeTables().remove(selectedObject);
+        } else if (selectedObject instanceof PatternParam) {
+            removePatternParams(catalog, selectedObject);
+        }
+    }
+
+    private void deleteChilds(Schema schema) {
+        Object selectedObject = this.selectedElement.getUserObject();
+        if (selectedObject instanceof IncludeTable) {
+            schema.getIncludeTables().remove(selectedObject);
+        } else if (selectedObject instanceof PatternParam) {
+            removePatternParams(schema, selectedObject);
+        }
+    }
+
+    private void deleteChilds(IncludeTable includeTable) {
+        Object selectedObject = this.selectedElement.getUserObject();
+        includeTable.getIncludeColumns().remove(selectedObject);
+        includeTable.getExcludeColumns().remove(selectedObject);
+    }
+
+    private void deleteChilds(ReverseEngineering reverseEngineering) {
+        Object selectedObject = this.selectedElement.getUserObject();
+        if (selectedObject instanceof Catalog) {
+            reverseEngineering.getCatalogs().remove(selectedObject);
+        } else if (selectedObject instanceof Schema) {
+            reverseEngineering.getSchemas().remove(selectedObject);
+        } else if (selectedObject instanceof IncludeTable) {
+            reverseEngineering.getIncludeTables().remove(selectedObject);
+        } else if (selectedObject instanceof ExcludeTable) {
+            reverseEngineering.getExcludeTables().remove(selectedObject);
+        } else if (selectedObject instanceof IncludeColumn) {
+            reverseEngineering.getIncludeColumns().remove(selectedObject);
+        } else if (selectedObject instanceof ExcludeColumn) {
+            reverseEngineering.getExcludeColumns().remove(selectedObject);
+        } else if (selectedObject instanceof IncludeProcedure) {
+            reverseEngineering.getIncludeProcedures().remove(selectedObject);
+        } else if (selectedObject instanceof ExcludeProcedure) {
+            reverseEngineering.getExcludeProcedures().remove(selectedObject);
+        }
+    }
+
+    private void updateParentChilds() {
+        DbImportModel model = (DbImportModel) tree.getModel();
+        model.removeNodeFromParent(selectedElement);
+        getProjectController().setDirty(true);
+        model.reload(parentElement);
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        tree.stopEditing();
+        final TreePath[] paths = tree.getSelectionPaths();
+        final DbImportView rootParent = ((DbImportView) panel.getParent().getParent());
+        rootParent.getLoadDbSchemaButton().setEnabled(false);
+        rootParent.getReverseEngineeringProgress().setVisible(true);
+        if (paths != null) {
+            ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
+            rootParent.lockToolbarButtons();
+            for (TreePath path : paths) {
+                selectedElement = (DbImportTreeNode) path.getLastPathComponent();
+                parentElement = (DbImportTreeNode) selectedElement.getParent();
+                if (parentElement != null) {
+                    Object parentUserObject = parentElement.getUserObject();
+                    if (parentUserObject instanceof ReverseEngineering) {
+                        ReverseEngineering reverseEngineering = (ReverseEngineering) parentUserObject;
+                        deleteChilds(reverseEngineering);
+                    } else if (parentUserObject instanceof Catalog) {
+                        Catalog catalog = (Catalog) parentUserObject;
+                        deleteChilds(catalog);
+                    } else if (parentUserObject instanceof Schema) {
+                        Schema schema = (Schema) parentUserObject;
+                        deleteChilds(schema);
+                    } else if (parentUserObject instanceof IncludeTable) {
+                        IncludeTable includeTable = (IncludeTable) parentUserObject;
+                        deleteChilds(includeTable);
+                    }
+                }
+            }
+            if (paths.length > 1) {
+                getProjectController().setDirty(true);
+                ArrayList<DbImportTreeNode> expandList = tree.getTreeExpandList();
+                tree.translateReverseEngineeringToTree(tree.getReverseEngineering(), false);
+                tree.expandTree(expandList);
+            } else {
+                updateParentChilds();
+            }
+            ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
+            getProjectController().getApplication().getUndoManager().addEdit(
+                    new DbImportTreeUndoableEdit(reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController())
+            );
+            rootParent.getLoadDbSchemaButton().setEnabled(true);
+            rootParent.getReverseEngineeringProgress().setVisible(false);
+        }
+    }
+
+    public void setPanel(DraggableTreePanel panel) {
+        this.panel = panel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/EditNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/EditNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/EditNodeAction.java
new file mode 100644
index 0000000..ac0fa46
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/EditNodeAction.java
@@ -0,0 +1,93 @@
+/*****************************************************************
+ *   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.action;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.FilterContainer;
+import org.apache.cayenne.dbsync.reverse.dbimport.PatternParam;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.undo.DbImportTreeUndoableEdit;
+import org.apache.cayenne.util.Util;
+
+import java.awt.event.ActionEvent;
+
+/**
+ * @since 4.1
+ */
+public class EditNodeAction extends TreeManipulationAction {
+
+    private static final String ACTION_NAME = "Rename";
+    private static final String ICON_NAME = "icon-edit.png";
+
+    private String actionName;
+
+    EditNodeAction(Application application) {
+        super(ACTION_NAME, application);
+    }
+
+    public String getIconName() {
+        return ICON_NAME;
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        if (tree.isEditing()) {
+            return;
+        }
+        if (e != null) {
+            if (tree.getSelectionPath() != null) {
+                tree.startEditingAtPath(tree.getSelectionPath());
+            }
+        }
+        if (actionName == null) {
+            return;
+        }
+        if (tree.getSelectionPath() != null) {
+            selectedElement = tree.getSelectedNode();
+            parentElement = (DbImportTreeNode) selectedElement.getParent();
+            if (parentElement != null) {
+                Object selectedObject = selectedElement.getUserObject();
+                ReverseEngineering reverseEngineeringOldCopy = new ReverseEngineering(tree.getReverseEngineering());
+                if (!Util.isEmptyString(actionName)) {
+                    if (selectedObject instanceof FilterContainer) {
+                        ((FilterContainer) selectedObject).setName(actionName);
+                    } else if (selectedObject instanceof PatternParam) {
+                        ((PatternParam) selectedObject).setPattern(actionName);
+                    }
+                    updateModel(true);
+                    selectedElement = null;
+                }
+                ReverseEngineering reverseEngineeringNewCopy = new ReverseEngineering(tree.getReverseEngineering());
+                if (!actionName.equals(EMPTY_NAME)) {
+                    DbImportTreeUndoableEdit undoableEdit = new DbImportTreeUndoableEdit(
+                            reverseEngineeringOldCopy, reverseEngineeringNewCopy, tree, getProjectController()
+                    );
+                    getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
+                }
+            }
+        }
+    }
+
+    public void setActionName(String name) {
+        this.actionName = name;
+    }
+
+}


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

Posted by nt...@apache.org.
CAY-2337 Save reverse engineering configuration with datamap XML


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/2ead78b6
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/2ead78b6
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/2ead78b6

Branch: refs/heads/master
Commit: 2ead78b63c8ad1701f09b3a8d3b6e5ca39a20d5b
Parents: 2373263
Author: Maxim Petrusevich <ma...@gmail.com>
Authored: Mon Mar 26 16:31:04 2018 +0300
Committer: Maxim Petrusevich <ma...@gmail.com>
Committed: Mon Mar 26 16:31:05 2018 +0300

----------------------------------------------------------------------
 RELEASE-NOTES.txt                               |  72 ++--
 .../main/resources/assemblies/assembly-mac.xml  |  13 +
 .../apache/cayenne/tools/DbImporterTask.java    |   3 +
 .../cayenne/tools/DbImporterTaskTest.java       |  41 +-
 cayenne-dbsync/pom.xml                          |   5 +
 .../reverse/configuration/ToolsModule.java      |   3 +-
 .../dbsync/reverse/dbimport/Catalog.java        |  24 +-
 .../reverse/dbimport/DbImportConfiguration.java |   9 +
 .../dbsync/reverse/dbimport/DbImportModule.java |   3 +-
 .../reverse/dbimport/DefaultDbImportAction.java |  42 +-
 .../dbsync/reverse/dbimport/ExcludeColumn.java  |  15 +-
 .../reverse/dbimport/ExcludeProcedure.java      |  15 +-
 .../dbsync/reverse/dbimport/ExcludeTable.java   |  15 +-
 .../reverse/dbimport/FilterContainer.java       |  25 ++
 .../dbsync/reverse/dbimport/IncludeColumn.java  |  15 +-
 .../reverse/dbimport/IncludeProcedure.java      |  15 +-
 .../dbsync/reverse/dbimport/IncludeTable.java   |  25 +-
 .../dbsync/reverse/dbimport/PatternParam.java   |  19 +
 .../reverse/dbimport/ReverseEngineering.java    |  85 +++-
 .../cayenne/dbsync/reverse/dbimport/Schema.java |  23 +-
 .../reverse/dbimport/SchemaContainer.java       |  12 +-
 .../cayenne/dbsync/reverse/dbload/DbLoader.java |   8 +-
 .../dbsync/reverse/filters/PatternFilter.java   |   4 +
 .../dbsync/reverse/filters/TableFilter.java     |   4 +
 .../cayenne/dbsync/xml/CatalogHandler.java      | 183 ++++++++
 .../cayenne/dbsync/xml/ConfigHandler.java       | 350 +++++++++++++++
 .../cayenne/dbsync/xml/DbImportExtension.java   |  56 +++
 .../dbsync/xml/DbImportLoaderDelegate.java      |  49 +++
 .../dbsync/xml/DbImportSaverDelegate.java       |  46 ++
 .../cayenne/dbsync/xml/IncludeTableHandler.java | 112 +++++
 .../cayenne/dbsync/xml/SchemaHandler.java       | 186 ++++++++
 .../merge/builders/DbAttributeBuilder.java      |   2 +-
 .../dbimport/DefaultDbImportActionTest.java     |   5 +-
 .../filters/FiltersConfigBuilderTest.java       |  18 +-
 .../org/apache/cayenne/di/BindingBuilder.java   |   3 -
 .../org/apache/cayenne/tools/DbImportTask.java  |  24 +-
 .../org/apache/cayenne/CayenneDataObject.java   |   2 +
 .../apache/cayenne/tools/DbImporterMojo.java    |   3 +
 .../cayenne/tools/CayenneGeneratorMojoTest.java |  28 +-
 .../dbimport/testImportWithoutChanges-pom.xml   |   2 +-
 .../tools/dbimport/testInheritance-pom.xml      |   2 +-
 .../apache/cayenne/tools/dbimporter-pom1.xml    |   2 +-
 .../apache/cayenne/tools/dbimporter-pom3.xml    |   2 +-
 modeler/cayenne-modeler/pom.xml                 |  16 +-
 .../cayenne/modeler/CayenneModelerFrame.java    |   1 -
 .../modeler/action/AddCatalogAction.java        |  91 ++++
 .../modeler/action/AddExcludeColumnAction.java  |  41 ++
 .../action/AddExcludeProcedureAction.java       |  41 ++
 .../modeler/action/AddExcludeTableAction.java   |  41 ++
 .../modeler/action/AddIncludeColumnAction.java  |  41 ++
 .../action/AddIncludeProcedureAction.java       |  41 ++
 .../modeler/action/AddIncludeTableAction.java   |  92 ++++
 .../modeler/action/AddPatternParamAction.java   | 140 ++++++
 .../cayenne/modeler/action/AddSchemaAction.java |  97 +++++
 .../cayenne/modeler/action/DBWizardAction.java  |  21 +-
 .../action/DbEntityCounterpartAction.java       |   3 +
 .../modeler/action/DefaultActionManager.java    |  14 +
 .../modeler/action/DeleteNodeAction.java        | 175 ++++++++
 .../cayenne/modeler/action/EditNodeAction.java  |  93 ++++
 .../modeler/action/GetDbConnectionAction.java   |  75 ++++
 .../modeler/action/LoadDbSchemaAction.java      | 292 +++++++++++++
 .../cayenne/modeler/action/MigrateAction.java   |  11 +-
 .../modeler/action/MoveImportNodeAction.java    | 235 ++++++++++
 .../modeler/action/MoveInvertNodeAction.java    |  35 ++
 .../action/ReverseEngineeringAction.java        |  88 +++-
 .../modeler/action/TreeManipulationAction.java  | 197 +++++++++
 .../modeler/dialog/db/DataSourceWizard.java     |  56 ++-
 .../modeler/dialog/db/DataSourceWizardView.java |   9 +-
 .../dialog/db/DbActionOptionsDialog.java        |   7 +-
 .../dialog/db/load/CatalogPopUpMenu.java        |  33 ++
 .../dialog/db/load/DbImportTreeNode.java        | 194 +++++++++
 .../dialog/db/load/DbLoadResultDialog.java      | 105 +++++
 .../modeler/dialog/db/load/DbLoaderContext.java |  86 ++--
 .../dialog/db/load/DbLoaderOptionsDialog.java   | 139 ------
 .../dialog/db/load/DefaultPopUpMenu.java        |  86 ++++
 .../dialog/db/load/IncludeTablePopUpMenu.java   |  37 ++
 .../dialog/db/load/ModelerDbImportAction.java   |  82 +++-
 .../modeler/dialog/db/load/RootPopUpMenu.java   | 133 ++++++
 .../modeler/dialog/db/load/SchemaPopUpMenu.java |  33 ++
 .../dialog/db/load/TransferableNode.java        |  74 ++++
 .../dialog/pref/DBConnectionInfoEditorView.java |   2 +-
 .../modeler/editor/ColorTreeRenderer.java       | 146 +++++++
 .../modeler/editor/DataMapTabbedView.java       |   3 +-
 .../cayenne/modeler/editor/DataMapView.java     |   6 +-
 .../cayenne/modeler/editor/DbImportModel.java   |  75 ++++
 .../modeler/editor/DbImportNodeHandler.java     | 341 +++++++++++++++
 .../cayenne/modeler/editor/DbImportTree.java    | 207 +++++++++
 .../modeler/editor/DbImportTreeCellEditor.java  | 154 +++++++
 .../editor/DbImportTreeCellRenderer.java        |  96 +++++
 .../cayenne/modeler/editor/DbImportView.java    | 236 ++++++++++
 .../modeler/editor/DraggableTreePanel.java      | 428 +++++++++++++++++++
 .../editor/ReverseEngineeringConfigPanel.java   | 223 ++++++++++
 .../editor/ReverseEngineeringTreePanel.java     | 169 ++++++++
 .../modeler/editor/TreeToolbarPanel.java        | 229 ++++++++++
 .../modeler/graph/extension/GraphHandler.java   |   7 +
 .../modeler/init/CayenneModelerModule.java      |   4 +-
 .../modeler/undo/DbImportTreeUndoableEdit.java  |  76 ++++
 .../components/image/FilteredIconFactory.java   |   1 +
 .../cayenne/modeler/images/icon-dbi-catalog.png | Bin 0 -> 288 bytes
 .../cayenne/modeler/images/icon-dbi-config.png  | Bin 0 -> 635 bytes
 .../modeler/images/icon-dbi-excludeColumn.png   | Bin 0 -> 289 bytes
 .../images/icon-dbi-excludeProcedure.png        | Bin 0 -> 365 bytes
 .../modeler/images/icon-dbi-excludeTable.png    | Bin 0 -> 258 bytes
 .../modeler/images/icon-dbi-includeColumn.png   | Bin 0 -> 307 bytes
 .../images/icon-dbi-includeProcedure.png        | Bin 0 -> 386 bytes
 .../modeler/images/icon-dbi-includeTable.png    | Bin 0 -> 288 bytes
 .../cayenne/modeler/images/icon-dbi-refresh.png | Bin 0 -> 547 bytes
 .../modeler/images/icon-dbi-runImport.png       | Bin 0 -> 577 bytes
 .../cayenne/modeler/images/icon-dbi-schema.png  | Bin 0 -> 316 bytes
 109 files changed, 6587 insertions(+), 341 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 5228c96..57f2ea9 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -14,6 +14,7 @@ Date:
 Changes/New Features:
 
 CAY-2334 cgen: option to force run from maven/gradle
+CAY-2337 Save reverse engineering configuration with datamap XML
 CAY-2372 Extract new modules from cayenne-server
 CAY-2377 Cleanup deprecated code.
 CAY-2391 cdbimport: add option to skip user-defined relationships
@@ -96,7 +97,7 @@ CAY-1873 Move DataDomain cache configuration from the Modeler and into DI
 CAY-1891 Modeler: Add To-Many Warning
 CAY-1892 Modeler: Add Relationship Data Type Warning
 CAY-2057 Modeler: Clean up OS X version
-CAY-2109 cayenne-crypto: add value authentication (HMAC) 
+CAY-2109 cayenne-crypto: add value authentication (HMAC)
 CAY-2210 Query cache: incorrect cache key for queries with custom value objects
 CAY-2255 ObjectSelect improvement: columns as full entities
 CAY-2258 DI: type-safe binding of List and Map
@@ -318,16 +319,16 @@ CAY-1267 Some changes to LogDialog
 CAY-1826 Merge Entity Attributes and Relationships tabs together with one toolbar.
 CAY-1839 Allow to link DataMaps to DataNodes from DataNode editor.
 CAY-1841 Filters for Left-hand project navigator
-CAY-1842 Remove Listeners support from the Modeler 
+CAY-1842 Remove Listeners support from the Modeler
 CAY-1843 DataMap v7: Stop saving listeners in DataMap, add upgrade handler
-CAY-1845 Upgrade javadoc plugin to 2.9.1 
+CAY-1845 Upgrade javadoc plugin to 2.9.1
 CAY-1846 Reworking of callback mapping
 CAY-1847 Make ConverterFactory extensible
-CAY-1848 New method: ObjectContext.selectOne(Select query) 
+CAY-1848 New method: ObjectContext.selectOne(Select query)
 CAY-1851 Generate default serialVersionUID for generated java classes to avoid eclipse warnings
-CAY-1852 Straighten thread model and synchronization in the Modeler 
-CAY-1855 Iterated and paginated queries must print result counts 
-CAY-1856 Expression.expWithParameters does not work when parameters are placed in the inline collection 
+CAY-1852 Straighten thread model and synchronization in the Modeler
+CAY-1855 Iterated and paginated queries must print result counts
+CAY-1856 Expression.expWithParameters does not work when parameters are placed in the inline collection
 CAY-1860 In-memory matching of DataObjects against ObjectId or int
 CAY-1861 Remove runtime relationships
 CAY-1870 cgen - smarter default for 'superPkg' and 'destDir'
@@ -377,7 +378,7 @@ CAY-1966 SQLTemplate/SQLSelect positional parameter binding
 CAY-1967 Deprecate SQLTemplate parameter batches
 CAY-1968 SQLSelect cleanup and omissions
 CAY-1971 Variants of Property.like(..) : contains(..), startsWith(..), endsWith(..)
-CAY-1972 A property to override DataSources of multi-module projects 
+CAY-1972 A property to override DataSources of multi-module projects
 CAY-1981 Add support of JDBC 4.0 N-types (nchar, nvarchar, longnvarchar, nclob)
 CAY-1984 cdbimport doesn't flatten many to many relationships
 
@@ -385,7 +386,7 @@ Bug Fixes:
 
 CAy-1988 ServerRuntimeBuilder: synthetic DataNode does not have domain's DataMaps linked
 CAY-1480 Implement cross-db functional expressions
-CAY-1695 Unexpected null value in bidirectional one-to-one prefetch 
+CAY-1695 Unexpected null value in bidirectional one-to-one prefetch
 CAY-1736 IllegalArgumentException when synchronizing entities in the Modeler
 CAY-1795 "Invisible" ObjAttribute in subclass
 CAY-1796 ROP: All entity's to-many relationships getting faulted from database when using it as a parameter in qualifier expression
@@ -393,13 +394,13 @@ CAY-1797 NPE importing DataMap
 CAY-1798 ROP: Reverse relationships of prefetched entity objects are not filled during server to client objects conversion
 CAY-1799 ROP: Server can't deserialize LIKE expression with pattern already compiled
 CAY-1818 Fix copyright year in the Modeler "about" panel
-CAY-1834 Exception: ToManyList cannot be cast to DataObject 
-CAY-1857 Problem with hotkeys 
-CAY-1859 NullPointerException when importing EOModel 
+CAY-1834 Exception: ToManyList cannot be cast to DataObject
+CAY-1857 Problem with hotkeys
+CAY-1859 NullPointerException when importing EOModel
 CAY-1863 Make determining whether a particular database type supports length adapter-specific not universal
 CAY-1866 Change in General Modeler Preferences reverts old settings to default value
-CAY-1868 Select contention with multiple contexts 
-CAY-1869 ResultIterator from cayenne-client dependency is subclassed from org.apache.cayenne.access.ResultIterator which is present only in cayenne-server dependency 
+CAY-1868 Select contention with multiple contexts
+CAY-1869 ResultIterator from cayenne-client dependency is subclassed from org.apache.cayenne.access.ResultIterator which is present only in cayenne-server dependency
 CAY-1874 DB2 Procedure action ignores the first result set
 CAY-1877 In-memory evaluation of expression may fail with UnsupportedOpeartionException depending on order of nodes
 CAY-1880 objectStore snapshots never cleared from RefreshQuery when "use shared cache" unchecked
@@ -434,10 +435,10 @@ CAY-1753 remove light-superclass.vm class template
 CAY-1754 Modeler suggested URL for SQLServer should start with 'jdbc:sqlserver:' instead of 'jdbc:microsoft:sqlserver:'
 CAY-1758 cdbimport improvements
 CAY-1759 cdbimport improvements: add 'catalog', rename 'schemaName' to 'schema'
-CAY-1760 cdbimport improvements: Default adapter (if none specified) must be AutoAdapter, not JdbcAdapter 
-CAY-1761 cdbimport improvements: DbLoader must reverse engineer PK auto-increment state. 
-CAY-1762 cdbimport improvements: Support for "defaultPackage" parameter, as the new DataMaps ends up placing entities in the root package 
-CAY-1763 cdbimport improvements: specified "schema" should become the default schema of the generated DataMap 
+CAY-1760 cdbimport improvements: Default adapter (if none specified) must be AutoAdapter, not JdbcAdapter
+CAY-1761 cdbimport improvements: DbLoader must reverse engineer PK auto-increment state.
+CAY-1762 cdbimport improvements: Support for "defaultPackage" parameter, as the new DataMaps ends up placing entities in the root package
+CAY-1763 cdbimport improvements: specified "schema" should become the default schema of the generated DataMap
 CAY-1764 cdbimport improvements: "overwrite" flag
 CAY-1765 cdbimport improvements: add excludeTables/includeTables parameters
 CAY-1766 Deprecating DataPort ant task
@@ -445,25 +446,25 @@ CAY-1768 cdbimport improvements: DataMap "project-version" attribute is skipped
 CAY-1769 cdbimport improvements: meaningfulPk flag must be turned into a pattern
 CAY-1771 cdbimport improvements: "usePrimitives" flag
 CAY-1772 Real support for DbEntity catalogs
-CAY-1778 TransactionManager to simplify user-managed transactions 
-CAY-1779 Flatten object entities for many to many relationships on reverse engineering 
+CAY-1778 TransactionManager to simplify user-managed transactions
+CAY-1779 Flatten object entities for many to many relationships on reverse engineering
 CAY-1781 Add StatelessContextRequestHandler as an alternative to the Session-based one
 CAY-1785 SelectQuery<T> for DataRows
-CAY-1789 Lock-free EntityResolver 
-CAY-1792 [PATCH] Supply additional factory methods for generic SelectQueries 
-CAY-1803 Optimize Expression conversion to String and EJBQL 
+CAY-1789 Lock-free EntityResolver
+CAY-1792 [PATCH] Supply additional factory methods for generic SelectQueries
+CAY-1803 Optimize Expression conversion to String and EJBQL
 CAY-1809 Remove 'final' modifier from Cayenne, HessianUtil, PropertyComparator, ConversionUtil, and LinkedDeque
 CAY-1813 Missing ObjEntity Attribute Validation with Duplicate DbEntity Columns
-CAY-1814 Support Property.nin 
-CAY-1819 When adding a filter, auto-register it as a listener 
-CAY-1820 DataDomain.addListener(Object) - a shortcut for adding annotated listeners 
+CAY-1814 Support Property.nin
+CAY-1819 When adding a filter, auto-register it as a listener
+CAY-1820 DataDomain.addListener(Object) - a shortcut for adding annotated listeners
 CAY-1821 AuditableFilter and friends should explicitly work with Persistent instead of Object
-CAY-1822 Make DataMap editor fields wider 
-CAY-1823 remove ":sync w/DbEntity" button from ObjEntity - it is redundant and already present on the entity toolbar. 
+CAY-1822 Make DataMap editor fields wider
+CAY-1823 remove ":sync w/DbEntity" button from ObjEntity - it is redundant and already present on the entity toolbar.
 CAY-1825 Simplify API for setting up query caching
 CAY-1828 SQLSelect - generics friendly fluent selecting sql query
 CAY-1829 Make ResultIterator implement Iterable<T>, create ObjectContext.iterate method
-CAY-1836 Firebird Adapter 
+CAY-1836 Firebird Adapter
 CAY-1838 Deprecate EntityResolver.indexedByClassProperty
 CAY-1840 Conditionally log slow / long-running queries
 CAY-1844 Configuration for maximum time to wait for an available DB connection
@@ -476,7 +477,7 @@ CAY-1522 EJBQL query don't support quotes
 CAY-1677 Modeler: text fields discard input unless you press enter
 CAY-1701 Modeler cannot undo pasting of obj (db) entity
 CAY-1708 Modeler error when pasting datamap with EJBQL query
-CAY-1714 ROP: Cayenne tries to build a query for non committed object when using more than 2 nested contexts 
+CAY-1714 ROP: Cayenne tries to build a query for non committed object when using more than 2 nested contexts
 CAY-1721 Writing blobs fails (Oracle)
 CAY-1725 NullPointerException from call to removeToManyTarget
 CAY-1719 Modeler - Obj Attribute Java Type editor won't focus sometimes
@@ -488,15 +489,14 @@ CAY-1742 ObjRelationship inspector says "ObjAttribute Inspector"
 CAY-1744 Unexpected read-only relationships in vertical inheritance mapping
 CAY-1749 NPE on simple nested context commit
 CAY-1755 FaultFailureException resolving relationships to UNIQUE non-PK columns
-CAY-1757 ROP: Faulting entity relationship resets uncommitted modifications made to its reverse relationship 
+CAY-1757 ROP: Faulting entity relationship resets uncommitted modifications made to its reverse relationship
 CAY-1774 EhCacheQueryCache.get(QueryMetadata, QueryCacheEntryFactory) returns null if EhCache instance for group is not present
 CAY-1780 cdbimport do not create xml file in resource folder
 CAY-1782 Deadlock when performing many concurrent inserts
 CAY-1783 JdbcPkGenerator.longPkFromDatabase would throw an exception if the PK value exceeds a range of Java int
 CAY-1794 Duplicate attributes in discriminator columns of PersistentDescriptor
-CAY-1804 Serialisation of long[] type was not working correctly. 
-CAY-1806 Error importing eomodel 
-CAY-1817 NPE during Validate Project 
+CAY-1804 Serialisation of long[] type was not working correctly.
+CAY-1806 Error importing eomodel
+CAY-1817 NPE during Validate Project
 CAY-1827 EhCache region corresponding to a cache group loses its settings after 'removeGroup'
-CAY-1832 Exception when modifying objects in postLoad callback
-
+CAY-1832 Exception when modifying objects in postLoad callback
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/assembly/src/main/resources/assemblies/assembly-mac.xml
----------------------------------------------------------------------
diff --git a/assembly/src/main/resources/assemblies/assembly-mac.xml b/assembly/src/main/resources/assemblies/assembly-mac.xml
index 6ff90db..a6bd5a9 100644
--- a/assembly/src/main/resources/assemblies/assembly-mac.xml
+++ b/assembly/src/main/resources/assemblies/assembly-mac.xml
@@ -61,6 +61,19 @@
 				<include>KEYS</include>
 			</includes>
 		</fileSet>
+		<fileSet>
+			<directory>target/doc-staging</directory>
+			<outputDirectory>cayenne-${project.version}-macosx/doc</outputDirectory>
+		</fileSet>
+		<fileSet>
+			<directory>../</directory>
+			<outputDirectory>cayenne-${project.version}-macosx/</outputDirectory>
+			<includes>
+				<include>RELEASE-NOTES.txt</include>
+				<include>UPGRADE.txt</include>
+				<include>KEYS</include>
+			</includes>
+		</fileSet>
 	</fileSets>
 
 	<dependencySets>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
----------------------------------------------------------------------
diff --git a/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java b/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
index 0d97213..a241e8c 100644
--- a/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
+++ b/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
@@ -115,6 +115,9 @@ public class DbImporterTask extends Task {
 
     @Override
     public void execute() {
+        if (reverseEngineering.getCatalogs().size() == 0 && reverseEngineering.isEmptyContainer()) {
+            config.setUseDataMapReverseEngineering(true);
+        }
         config.setFiltersConfig(new FiltersConfigBuilder(reverseEngineering).build());
         validateAttributes();
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-ant/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
----------------------------------------------------------------------
diff --git a/cayenne-ant/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java b/cayenne-ant/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
index 43745e7..7e88a1b 100644
--- a/cayenne-ant/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
+++ b/cayenne-ant/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
@@ -39,11 +39,16 @@ import java.io.IOException;
 import java.net.URL;
 import java.sql.Connection;
 import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.List;
 
 import static org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineeringUtils.*;
-import static org.junit.Assert.*;
+import static org.apache.cayenne.util.Util.isBlank;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 // TODO: we are only testing on Derby. We may need to dynamically switch between DBs 
 // based on "cayenneTestConnection", like we do in cayenne-server, etc.
@@ -104,11 +109,6 @@ public class DbImporterTaskTest {
         test("build-include-table.xml");
     }
 
-    @Test
-    public void testExcludeRelationshipFirst() throws Exception {
-        test("testExcludeRelationshipFirst.xml");
-    }
-
     private DbImporterTask getCdbImport(String buildFile) {
         Project project = new Project();
 
@@ -149,9 +149,32 @@ public class DbImporterTaskTest {
         try {
             cdbImport.execute();
             verifyResult(mapFile, mapFileCopy);
+        } finally {
+            cleanDb(cdbImport.toParameters());
         }
-        catch (Exception ex){
-            fail();
+    }
+
+    private void cleanDb(DbImportConfiguration dbImportConfiguration) throws ClassNotFoundException,
+            IllegalAccessException, InstantiationException, SQLException {
+        Class.forName(dbImportConfiguration.getDriver()).newInstance();
+        // Get a connection
+        Connection connection = DriverManager.getConnection(dbImportConfiguration.getUrl());
+        Statement stmt = connection.createStatement();
+
+        ResultSet tables = connection.getMetaData().getTables(null, null, null, new String[]{"TABLE"});
+        while (tables.next()) {
+            String schema = tables.getString("TABLE_SCHEM");
+            System.out.println("DROP TABLE " + (isBlank(schema) ? "" : schema + ".") + tables.getString("TABLE_NAME"));
+            stmt.execute("DROP TABLE " + (isBlank(schema) ? "" : schema + ".") + tables.getString("TABLE_NAME"));
+        }
+
+        ResultSet schemas = connection.getMetaData().getSchemas();
+        while (schemas.next()) {
+            String schem = schemas.getString("TABLE_SCHEM");
+            if (schem.startsWith("SCHEMA")) {
+                System.out.println("DROP SCHEMA " + schem);
+                stmt.execute("DROP SCHEMA " + schem + " RESTRICT");
+            }
         }
     }
 
@@ -208,4 +231,6 @@ public class DbImporterTaskTest {
         }
     }
 
+
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/pom.xml b/cayenne-dbsync/pom.xml
index 5c68b4d..fa5809e 100644
--- a/cayenne-dbsync/pom.xml
+++ b/cayenne-dbsync/pom.xml
@@ -86,6 +86,11 @@
 			<version>${project.version}</version>
 			<scope>test</scope>
 		</dependency>
+		<dependency>
+			<groupId>org.apache.cayenne</groupId>
+			<artifactId>cayenne-di</artifactId>
+			<version>4.1.M2-SNAPSHOT</version>
+		</dependency>
 	</dependencies>
 
 	<build>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
index ceb1e11..0ca291d 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -65,6 +65,7 @@ import org.apache.cayenne.log.Slf4jJdbcEventLogger;
 import org.apache.cayenne.log.JdbcEventLogger;
 import org.apache.cayenne.project.ProjectModule;
 import org.apache.cayenne.project.extension.ExtensionAwareHandlerFactory;
+import org.apache.cayenne.project.extension.info.InfoExtension;
 import org.apache.cayenne.resource.ClassLoaderResourceLocator;
 import org.apache.cayenne.resource.ResourceLocator;
 import org.slf4j.Logger;
@@ -121,7 +122,7 @@ public class ToolsModule implements Module {
         binder.bind(DataChannelMetaData.class).to(DefaultDataChannelMetaData.class);
         binder.bind(XMLReader.class).toProviderInstance(new XMLReaderProvider(true)).withoutScope();
 
-        ProjectModule.contributeExtensions(binder);
+        ProjectModule.contributeExtensions(binder).add(InfoExtension.class);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/Catalog.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/Catalog.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/Catalog.java
index 3ed8755..5fbb659 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/Catalog.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/Catalog.java
@@ -19,10 +19,14 @@
 
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.util.XMLEncoder;
+import org.apache.cayenne.util.XMLSerializable;
+
 /**
  * @since 4.0.
  */
-public class Catalog extends SchemaContainer {
+public class Catalog extends SchemaContainer implements XMLSerializable {
 
     public Catalog() {
     }
@@ -31,9 +35,27 @@ public class Catalog extends SchemaContainer {
         setName(name);
     }
 
+    public Catalog(Catalog original) {
+        super(original);
+    }
+
     @Override
     public StringBuilder toString(StringBuilder res, String prefix) {
         res.append(prefix).append("Catalog: ").append(getName()).append("\n");
         return super.toString(res, prefix + "  ");
     }
+
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("catalog")
+            .nested(this.getIncludeTables(), delegate)
+            .nested(this.getExcludeTables(), delegate)
+            .nested(this.getIncludeColumns(), delegate)
+            .nested(this.getExcludeColumns(), delegate)
+            .nested(this.getIncludeProcedures(), delegate)
+            .nested(this.getExcludeProcedures(), delegate)
+            .simpleTag("name", this.getName())
+            .nested(this.getSchemas(), delegate)
+        .end();
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java
index 06b04f0..87d249f 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java
@@ -61,6 +61,7 @@ public class DbImportConfiguration {
     private String stripFromTableNames;
     private boolean forceDataMapCatalog;
     private boolean forceDataMapSchema;
+    private boolean useDataMapReverseEngineering;
     private File cayenneProject;
 
     public DbImportConfiguration() {
@@ -317,4 +318,12 @@ public class DbImportConfiguration {
     public boolean isForceDataMapSchema() {
         return forceDataMapSchema;
     }
+
+    public boolean isUseDataMapReverseEngineering() {
+        return useDataMapReverseEngineering;
+    }
+
+    public void setUseDataMapReverseEngineering(boolean useDataMapReverseEngineering) {
+        this.useDataMapReverseEngineering = useDataMapReverseEngineering;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java
index 7cb227c..02d4fc3 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java
@@ -27,6 +27,7 @@ import org.apache.cayenne.configuration.xml.DefaultDataChannelMetaData;
 import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
 import org.apache.cayenne.configuration.xml.HandlerFactory;
 import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
+import org.apache.cayenne.dbsync.xml.DbImportExtension;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.Module;
 import org.apache.cayenne.project.FileProjectSaver;
@@ -51,7 +52,7 @@ public class DbImportModule implements Module {
         binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
         binder.bind(DataChannelMetaData.class).to(DefaultDataChannelMetaData.class);
         binder.bind(HandlerFactory.class).to(ExtensionAwareHandlerFactory.class);
-        ProjectModule.contributeExtensions(binder);
+        ProjectModule.contributeExtensions(binder).add(DbImportExtension.class);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
index 37d895e..2c8f6b2 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
@@ -16,6 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
+
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
 import org.apache.cayenne.CayenneRuntimeException;
@@ -27,6 +28,7 @@ import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 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.dba.DbAdapter;
 import org.apache.cayenne.dbsync.merge.token.model.AbstractToModelToken;
 import org.apache.cayenne.dbsync.merge.DataMapMerger;
@@ -41,6 +43,7 @@ import org.apache.cayenne.dbsync.reverse.dbload.DbLoader;
 import org.apache.cayenne.dbsync.reverse.dbload.DbLoaderConfiguration;
 import org.apache.cayenne.dbsync.reverse.filters.CatalogFilter;
 import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfigBuilder;
 import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.DataMap;
@@ -78,12 +81,13 @@ import static org.apache.cayenne.util.Util.isBlank;
 public class DefaultDbImportAction implements DbImportAction {
 
     private final ProjectSaver projectSaver;
-    private final Logger logger;
+    protected final Logger logger;
     private final DataSourceFactory dataSourceFactory;
     private final DbAdapterFactory adapterFactory;
     private final DataMapLoader mapLoader;
     private final MergerTokenFactoryProvider mergerTokenFactoryProvider;
     private final DataChannelDescriptorLoader dataChannelDescriptorLoader;
+    private final DataChannelMetaData metaData;
 
     public DefaultDbImportAction(@Inject Logger logger,
                                  @Inject ProjectSaver projectSaver,
@@ -91,13 +95,15 @@ public class DefaultDbImportAction implements DbImportAction {
                                  @Inject DbAdapterFactory adapterFactory,
                                  @Inject DataMapLoader mapLoader,
                                  @Inject MergerTokenFactoryProvider mergerTokenFactoryProvider,
-                                 @Inject DataChannelDescriptorLoader dataChannelDescriptorLoader) {
+                                 @Inject DataChannelDescriptorLoader dataChannelDescriptorLoader,
+                                 @Inject DataChannelMetaData metaData) {
         this.logger = logger;
         this.projectSaver = projectSaver;
         this.dataSourceFactory = dataSourceFactory;
         this.adapterFactory = adapterFactory;
         this.mapLoader = mapLoader;
         this.mergerTokenFactoryProvider = mergerTokenFactoryProvider;
+        this.metaData = metaData;
         this.dataChannelDescriptorLoader = dataChannelDescriptorLoader;
     }
 
@@ -146,11 +152,23 @@ public class DefaultDbImportAction implements DbImportAction {
         DbAdapter adapter = adapterFactory.createAdapter(dataNodeDescriptor, dataSource);
 
         DataMap sourceDataMap;
+        DataMap targetDataMap = existingTargetMap(config);
+
+        ReverseEngineering dataMapReverseEngineering = metaData.get(targetDataMap, ReverseEngineering.class);
+        if ((config.isUseDataMapReverseEngineering()) && (dataMapReverseEngineering != null)) {
+            putReverseEngineeringToConfig(dataMapReverseEngineering, config);
+        }
+        if ((dataMapReverseEngineering != null) && (!config.isUseDataMapReverseEngineering())) {
+            logger.warn("Found several dbimport configs. Configuration selected from 'build.gradle' file.");
+        }
+        if ((dataMapReverseEngineering == null) && (config.isUseDataMapReverseEngineering())) {
+            logger.warn("Missing dbimport config. Database is imported completely.");
+        }
+
         try (Connection connection = dataSource.getConnection()) {
             sourceDataMap = load(config, adapter, connection);
         }
 
-        DataMap targetDataMap = existingTargetMap(config);
         if (targetDataMap == null) {
 
             String path = config.getTargetDataMap() == null ? "null" : config.getTargetDataMap().getAbsolutePath() + "'";
@@ -184,6 +202,20 @@ public class DefaultDbImportAction implements DbImportAction {
             saveLoaded(targetDataMap, config);
         }
     }
+    private void putReverseEngineeringToConfig(ReverseEngineering reverseEngineering, DbImportConfiguration config) {
+        config.setSkipRelationshipsLoading(reverseEngineering.getSkipRelationshipsLoading());
+        config.setSkipPrimaryKeyLoading(reverseEngineering.getSkipPrimaryKeyLoading());
+        config.setStripFromTableNames(reverseEngineering.getStripFromTableNames());
+        config.setTableTypes(reverseEngineering.getTableTypes());
+        config.setMeaningfulPkTables(reverseEngineering.getMeaningfulPkTables());
+        config.setNamingStrategy(reverseEngineering.getNamingStrategy());
+        config.setFiltersConfig(new FiltersConfigBuilder(reverseEngineering).build());
+        config.setForceDataMapCatalog(reverseEngineering.isForceDataMapCatalog());
+        config.setForceDataMapSchema(reverseEngineering.isForceDataMapSchema());
+        config.setDefaultPackage(reverseEngineering.getDefaultPackage());
+        config.setUsePrimitives(reverseEngineering.isUsePrimitives());
+        config.setUseJava7Types(reverseEngineering.isUseJava7Types());
+    }
 
     protected void transformSourceBeforeMerge(DataMap sourceDataMap, DataMap targetDataMap, DbImportConfiguration configuration) {
         if (configuration.isForceDataMapCatalog()) {
@@ -228,7 +260,7 @@ public class DefaultDbImportAction implements DbImportAction {
         }
     }
 
-    private Collection<MergerToken> log(List<MergerToken> tokens) {
+    protected Collection<MergerToken> log(List<MergerToken> tokens) {
         logger.info("");
         if (tokens.isEmpty()) {
             logger.info("Detected changes: No changes to import.");
@@ -365,7 +397,7 @@ public class DefaultDbImportAction implements DbImportAction {
         return true;
     }
 
-    private boolean syncProcedures(DataMap targetDataMap, DataMap loadedDataMap, FiltersConfig filters) {
+    protected boolean syncProcedures(DataMap targetDataMap, DataMap loadedDataMap, FiltersConfig filters) {
         Collection<Procedure> procedures = loadedDataMap.getProcedures();
         if (procedures.isEmpty()) {
             return false;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeColumn.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeColumn.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeColumn.java
index a57400a..58fd551 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeColumn.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeColumn.java
@@ -19,14 +19,27 @@
 
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.util.XMLEncoder;
+import org.apache.cayenne.util.XMLSerializable;
+
 /**
  * @since 4.0.
  */
-public class ExcludeColumn extends PatternParam {
+public class ExcludeColumn extends PatternParam implements XMLSerializable {
     public ExcludeColumn() {
     }
 
     public ExcludeColumn(String pattern) {
         super(pattern);
     }
+
+    public ExcludeColumn(ExcludeColumn original) {
+        super(original);
+    }
+
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.simpleTag("excludeColumn", this.getPattern());
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeProcedure.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeProcedure.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeProcedure.java
index a42aa23..c629468 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeProcedure.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeProcedure.java
@@ -19,14 +19,27 @@
 
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.util.XMLEncoder;
+import org.apache.cayenne.util.XMLSerializable;
+
 /**
  * @since 4.0.
  */
-public class ExcludeProcedure extends PatternParam {
+public class ExcludeProcedure extends PatternParam implements XMLSerializable {
     public ExcludeProcedure() {
     }
 
     public ExcludeProcedure(String pattern) {
         super(pattern);
     }
+
+    public ExcludeProcedure(ExcludeProcedure original) {
+        super(original);
+    }
+
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.simpleTag("excludeProcedure", this.getPattern());
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeTable.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeTable.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeTable.java
index c55a5c4..61a4e9f 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeTable.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeTable.java
@@ -19,14 +19,27 @@
 
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.util.XMLEncoder;
+import org.apache.cayenne.util.XMLSerializable;
+
 /**
  * @since 4.0.
  */
-public class ExcludeTable extends PatternParam {
+public class ExcludeTable extends PatternParam implements XMLSerializable {
     public ExcludeTable() {
     }
 
     public ExcludeTable(String pattern) {
         super(pattern);
     }
+
+    public ExcludeTable(ExcludeTable original) {
+        super(original);
+    }
+
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.simpleTag("excludeTable", this.getPattern());
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/FilterContainer.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/FilterContainer.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/FilterContainer.java
index 7090522..3914439 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/FilterContainer.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/FilterContainer.java
@@ -46,6 +46,31 @@ public abstract class FilterContainer {
 
     private final Collection<ExcludeRelationship> excludeRelationshipCollection = new LinkedList<>();
 
+    public FilterContainer() {
+    }
+
+    public FilterContainer(FilterContainer original) {
+        this.setName(original.getName());
+        for (IncludeTable includeTable : original.getIncludeTables()) {
+            this.addIncludeTable(new IncludeTable(includeTable));
+        }
+        for (ExcludeTable excludeTable : original.getExcludeTables()) {
+            this.addExcludeTable(new ExcludeTable(excludeTable));
+        }
+        for (IncludeColumn includeColumn : original.getIncludeColumns()) {
+            this.addIncludeColumn(new IncludeColumn(includeColumn));
+        }
+        for (ExcludeColumn excludeColumn : original.getExcludeColumns()) {
+            this.addExcludeColumn(new ExcludeColumn(excludeColumn));
+        }
+        for (IncludeProcedure includeProcedure : original.getIncludeProcedures()) {
+            this.addIncludeProcedure(new IncludeProcedure(includeProcedure));
+        }
+        for (ExcludeProcedure excludeProcedure : original.getExcludeProcedures()) {
+            this.addExcludeProcedure(new ExcludeProcedure(excludeProcedure));
+        }
+    }
+
     public Collection<IncludeTable> getIncludeTables() {
         return includeTableCollection;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeColumn.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeColumn.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeColumn.java
index 780eb86..db54b07 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeColumn.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeColumn.java
@@ -19,14 +19,27 @@
 
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.util.XMLEncoder;
+import org.apache.cayenne.util.XMLSerializable;
+
 /**
  * @since 4.0.
  */
-public class IncludeColumn extends PatternParam {
+public class IncludeColumn extends PatternParam implements XMLSerializable {
     public IncludeColumn() {
     }
 
     public IncludeColumn(String pattern) {
         super(pattern);
     }
+
+    public IncludeColumn(IncludeColumn original) {
+        super(original);
+    }
+
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.simpleTag("includeColumn", this.getPattern());
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeProcedure.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeProcedure.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeProcedure.java
index f3b9040..d6140ea 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeProcedure.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeProcedure.java
@@ -19,14 +19,27 @@
 
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.util.XMLEncoder;
+import org.apache.cayenne.util.XMLSerializable;
+
 /**
  * @since 4.0.
  */
-public class IncludeProcedure extends PatternParam {
+public class IncludeProcedure extends PatternParam implements XMLSerializable {
     public IncludeProcedure() {
     }
 
     public IncludeProcedure(String pattern) {
         super(pattern);
     }
+
+    public IncludeProcedure(IncludeProcedure original) {
+        super(original);
+    }
+
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.simpleTag("includeProcedure", this.getPattern());
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeTable.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeTable.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeTable.java
index defa595..ff2ed59 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeTable.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeTable.java
@@ -19,13 +19,17 @@
 
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.util.XMLEncoder;
+import org.apache.cayenne.util.XMLSerializable;
+
 import java.util.Collection;
 import java.util.LinkedList;
 
 /**
  * @since 4.0.
  */
-public class IncludeTable extends PatternParam {
+public class IncludeTable extends PatternParam implements XMLSerializable {
 
     private final Collection<IncludeColumn> includeColumns = new LinkedList<>();
 
@@ -40,6 +44,16 @@ public class IncludeTable extends PatternParam {
         super(pattern);
     }
 
+    public IncludeTable(IncludeTable original) {
+        super(original);
+        for (IncludeColumn includeColumn : original.getIncludeColumns()) {
+            this.addIncludeColumn(new IncludeColumn(includeColumn));
+        }
+        for (ExcludeColumn excludeColumn : original.getExcludeColumns()) {
+            this.addExcludeColumn(new ExcludeColumn(excludeColumn));
+        }
+    }
+
     public Collection<IncludeColumn> getIncludeColumns() {
         return includeColumns;
     }
@@ -86,6 +100,15 @@ public class IncludeTable extends PatternParam {
     }
 
     @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("includeTable")
+            .simpleTag("name", this.getPattern())
+            .nested(this.getIncludeColumns(), delegate)
+            .nested(this.getExcludeColumns(), delegate)
+        .end();
+    }
+
+    @Override
     public StringBuilder toString(StringBuilder res, String s) {
         super.toString(res, s);
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/PatternParam.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/PatternParam.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/PatternParam.java
index bef2d5e..b875234 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/PatternParam.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/PatternParam.java
@@ -35,6 +35,10 @@ public class PatternParam {
         this.pattern = pattern;
     }
 
+    public PatternParam(PatternParam original) {
+        this.setPattern(original.getPattern());
+    }
+
     public String getPattern() {
         return pattern;
     }
@@ -82,4 +86,19 @@ public class PatternParam {
         res.append(s).append(getClass().getSimpleName()).append(": ").append(pattern).append("\n");
         return res;
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (obj.getClass() != this.getClass()) {
+            return false;
+        }
+        PatternParam patternParam = (PatternParam) obj;
+        return patternParam.getPattern().equals(pattern);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineering.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineering.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineering.java
index 082f65a..4e0321d 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineering.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineering.java
@@ -16,20 +16,28 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
+
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.dbsync.xml.DbImportExtension;
+import org.apache.cayenne.util.Util;
+import org.apache.cayenne.util.XMLEncoder;
+import org.apache.cayenne.util.XMLSerializable;
+
 import java.io.Serializable;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.LinkedList;
 
 /**
  * @since 4.0
  */
-public class ReverseEngineering extends SchemaContainer implements Serializable {
+public class ReverseEngineering extends SchemaContainer implements Serializable, XMLSerializable {
 
-    private Boolean skipRelationshipsLoading;
+    private boolean skipRelationshipsLoading;
 
-    private Boolean skipPrimaryKeyLoading;
+    private boolean skipPrimaryKeyLoading;
 
     /*
      * <p>
@@ -118,6 +126,25 @@ public class ReverseEngineering extends SchemaContainer implements Serializable
     public ReverseEngineering() {
     }
 
+    public ReverseEngineering(ReverseEngineering original) {
+        super(original);
+        this.setDefaultPackage(original.getDefaultPackage());
+        this.setStripFromTableNames(original.getStripFromTableNames());
+        this.setNamingStrategy(original.getNamingStrategy());
+        this.setMeaningfulPkTables(original.getMeaningfulPkTables());
+        this.setSkipPrimaryKeyLoading(original.getSkipPrimaryKeyLoading());
+        this.setSkipRelationshipsLoading(original.getSkipRelationshipsLoading());
+        this.setForceDataMapSchema(original.isForceDataMapSchema());
+        this.setForceDataMapCatalog(original.isForceDataMapCatalog());
+        this.setUseJava7Types(original.isUseJava7Types());
+        this.setUsePrimitives(original.isUsePrimitives());
+        this.setTableTypes(Arrays.asList(original.getTableTypes()));
+        this.setName(original.getName());
+        for (Catalog catalog : original.getCatalogs()) {
+            this.addCatalog(new Catalog(catalog));
+        }
+    }
+
     public Boolean getSkipRelationshipsLoading() {
         return skipRelationshipsLoading;
     }
@@ -175,14 +202,27 @@ public class ReverseEngineering extends SchemaContainer implements Serializable
             }
         }
 
-        if (skipRelationshipsLoading != null && skipRelationshipsLoading) {
-            res.append("\n        Skip Relationships Loading");
+        super.toString(res, "  ");
+
+        if (skipRelationshipsLoading) {
+            res.append("\n  Skip Relationships Loading");
         }
-        if (skipPrimaryKeyLoading != null && skipPrimaryKeyLoading) {
-            res.append("\n        Skip PrimaryKey Loading");
+        if (skipPrimaryKeyLoading) {
+            res.append("\n  Skip PrimaryKey Loading");
         }
-
-        return super.toString(res, "  ").toString();
+        if (forceDataMapCatalog) {
+            res.append("\n  Force DataMap catalog");
+        }
+        if (forceDataMapSchema) {
+            res.append("\n  Force DataMap schema");
+        }
+        if (usePrimitives) {
+            res.append("\n  Use primitives");
+        }
+        if (useJava7Types) {
+            res.append("\n  Use Java 7 types");
+        }
+        return res.toString();
     }
 
     public String getDefaultPackage() {
@@ -248,4 +288,31 @@ public class ReverseEngineering extends SchemaContainer implements Serializable
     public void setUseJava7Types(boolean useJava7Types) {
         this.useJava7Types = useJava7Types;
     }
+
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("config")
+                .attribute("xmlns", DbImportExtension.NAMESPACE)
+                .nested(this.getIncludeTables(), delegate)
+                .nested(this.getExcludeTables(), delegate)
+                .nested(this.getIncludeColumns(), delegate)
+                .nested(this.getExcludeColumns(), delegate)
+                .nested(this.getIncludeProcedures(), delegate)
+                .nested(this.getExcludeProcedures(), delegate)
+                .nested(this.getCatalogs(), delegate)
+                .nested(this.getSchemas(), delegate)
+                .simpleTag("db-type", Util.join(Arrays.asList(this.getTableTypes()), ","))
+                .simpleTag("defaultPackage", this.getDefaultPackage())
+                .simpleTag("forceDataMapCatalog", Boolean.toString(this.isForceDataMapCatalog()))
+                .simpleTag("forceDataMapSchema", Boolean.toString(this.isForceDataMapSchema()))
+                .simpleTag("meaningfulPkTables", this.getMeaningfulPkTables())
+                .simpleTag("namingStrategy", this.getNamingStrategy())
+                .simpleTag("skipPrimaryKeyLoading", this.getSkipPrimaryKeyLoading().toString())
+                .simpleTag("skipRelationshipsLoading", this.getSkipRelationshipsLoading().toString())
+                .simpleTag("stripFromTableNames", this.getStripFromTableNames())
+                .simpleTag("useJava7Types", Boolean.toString(this.isUseJava7Types()))
+                .simpleTag("usePrimitives", Boolean.toString(this.isUsePrimitives()))
+                .end();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/Schema.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/Schema.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/Schema.java
index 7e7d273..6e6033f 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/Schema.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/Schema.java
@@ -19,10 +19,14 @@
 
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.util.XMLEncoder;
+import org.apache.cayenne.util.XMLSerializable;
+
 /**
  * @since 4.0.
  */
-public class Schema extends FilterContainer {
+public class Schema extends FilterContainer implements XMLSerializable {
 
     public Schema() {
     }
@@ -31,9 +35,26 @@ public class Schema extends FilterContainer {
         setName(name);
     }
 
+    public Schema(Schema original) {
+        super(original);
+    }
+
     @Override
     public StringBuilder toString(StringBuilder res, String prefix) {
         res.append(prefix).append("Schema: ").append(getName()).append("\n");
         return super.toString(res, prefix + "  ");
     }
+
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("schema")
+            .nested(this.getIncludeTables(), delegate)
+            .nested(this.getExcludeTables(), delegate)
+            .nested(this.getIncludeColumns(), delegate)
+            .nested(this.getExcludeColumns(), delegate)
+            .nested(this.getIncludeProcedures(), delegate)
+            .nested(this.getExcludeProcedures(), delegate)
+            .simpleTag("name", this.getName())
+        .end();
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/SchemaContainer.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/SchemaContainer.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/SchemaContainer.java
index 7b4a849..e7a9391 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/SchemaContainer.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/SchemaContainer.java
@@ -25,7 +25,7 @@ import java.util.LinkedList;
 /**
  * @since 4.0
  */
-abstract class SchemaContainer extends FilterContainer {
+public abstract class SchemaContainer extends FilterContainer implements Cloneable {
 
     private final Collection<Schema> schemaCollection = new LinkedList<>();
 
@@ -37,6 +37,16 @@ abstract class SchemaContainer extends FilterContainer {
         this.schemaCollection.add(schema);
     }
 
+    public SchemaContainer(){
+    }
+
+    public SchemaContainer(SchemaContainer original) {
+        super(original);
+        for (Schema schema : original.getSchemas()) {
+            this.addSchema(new Schema(schema));
+        }
+    }
+
     @Override
     public boolean isEmptyContainer() {
         if (!super.isEmptyContainer()) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoader.java
index f0da783..dd0851a 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoader.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoader.java
@@ -93,7 +93,7 @@ public class DbLoader {
      */
     public static List<String> loadCatalogs(Connection connection) throws SQLException {
         try (ResultSet rs = connection.getMetaData().getCatalogs()) {
-            return getStrings(rs);
+            return getStrings(rs, 1);
         }
     }
 
@@ -104,14 +104,14 @@ public class DbLoader {
      */
     public static List<String> loadSchemas(Connection connection) throws SQLException {
         try (ResultSet rs = connection.getMetaData().getSchemas()) {
-            return getStrings(rs);
+            return getStrings(rs, 1);
         }
     }
 
-    private static List<String> getStrings(ResultSet rs) throws SQLException {
+    private static List<String> getStrings(ResultSet rs, int columnIndex) throws SQLException {
         List<String> strings = new ArrayList<>();
         while (rs.next()) {
-            strings.add(rs.getString(1));
+            strings.add(rs.getString(columnIndex));
         }
         return strings;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java
index feb90de..54eb641 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java
@@ -75,6 +75,10 @@ public class PatternFilter {
         this.excludes = new TreeSet<>(PATTERN_COMPARATOR);
     }
 
+    public SortedSet<Pattern> getIncludes() {
+        return includes;
+    }
+
     public PatternFilter include(Pattern p) {
         includes.add(p);
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java
index ebc2358..ecf6dc3 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java
@@ -84,6 +84,10 @@ public class TableFilter {
         return include.columnsFilter;
     }
 
+    public SortedSet<IncludeTableFilter> getIncludes() {
+        return includes;
+    }
+
     public static TableFilter include(String tablePattern) {
         TreeSet<IncludeTableFilter> includes = new TreeSet<IncludeTableFilter>();
         includes.add(new IncludeTableFilter(tablePattern == null ? null : tablePattern.replaceAll("%", ".*")));

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/CatalogHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/CatalogHandler.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/CatalogHandler.java
new file mode 100644
index 0000000..dd71840
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/CatalogHandler.java
@@ -0,0 +1,183 @@
+/*****************************************************************
+ *   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.dbsync.xml;
+
+import org.apache.cayenne.configuration.xml.NamespaceAwareNestedTagHandler;
+import org.apache.cayenne.dbsync.reverse.dbimport.*;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+class CatalogHandler extends NamespaceAwareNestedTagHandler {
+
+    private static final String CATALOG_TAG = "catalog";
+    private static final String CATALOG_NAME_TAG = "name";
+    private static final String SCHEMA_TAG = "schema";
+    private static final String INCLUDE_TABLE_TAG = "includeTable";
+    private static final String EXCLUDE_TABLE_TAG = "excludeTable";
+    private static final String INCLUDE_COLUMN_TAG = "includeColumn";
+    private static final String EXCLUDE_COLUMN_TAG = "excludeColumn";
+    private static final String INCLUDE_PROCEDURE_TAG = "includeProcedure";
+    private static final String EXCLUDE_PROCEDURE_TAG = "excludeProcedure";
+
+    private ReverseEngineering configuration;
+
+    private Catalog catalog;
+
+    CatalogHandler(NamespaceAwareNestedTagHandler parentHandler, ReverseEngineering configuration) {
+        super(parentHandler);
+        this.configuration = configuration;
+    }
+
+    @Override
+    protected ContentHandler createChildTagHandler(String namespaceURI, String localName,
+                                                   String qName, Attributes attributes) {
+
+        if (namespaceURI.equals(targetNamespace)) {
+            switch (localName) {
+                case SCHEMA_TAG:
+                    return new SchemaHandler(this, catalog);
+                case INCLUDE_TABLE_TAG:
+                    return new IncludeTableHandler(this, catalog);
+            }
+        }
+
+        return super.createChildTagHandler(namespaceURI, localName, qName, attributes);
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        switch (localName) {
+            case CATALOG_TAG:
+                createCatalog();
+                return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    protected void processCharData(String localName, String data) {
+        switch (localName) {
+            case INCLUDE_TABLE_TAG:
+                createIncludeTable(data);
+                break;
+            case CATALOG_NAME_TAG:
+                createCatalogName(data);
+                break;
+            case EXCLUDE_TABLE_TAG:
+                createExcludeTable(data);
+                break;
+            case INCLUDE_COLUMN_TAG:
+                createIncludeColumn(data);
+                break;
+            case EXCLUDE_COLUMN_TAG:
+                createExcludeColumn(data);
+                break;
+            case INCLUDE_PROCEDURE_TAG:
+                createIncludeProcedure(data);
+                break;
+            case EXCLUDE_PROCEDURE_TAG:
+                createExcludeProcedure(data);
+                break;
+        }
+    }
+
+    private void createIncludeTable(String includeTableData) {
+        if (includeTableData.trim().length() == 0) {
+            return;
+        }
+
+        if (catalog != null) {
+            IncludeTable includeTable = new IncludeTable();
+            includeTable.setName(includeTableData);
+            catalog.addIncludeTable(includeTable);
+        }
+    }
+
+    private void createCatalogName(String catalogName) {
+        if (catalogName.trim().length() == 0) {
+            return;
+        }
+
+        if (catalog != null) {
+            catalog.setName(catalogName);
+        }
+    }
+
+    private void createExcludeProcedure(String excludeProcedure) {
+        if (excludeProcedure.trim().length() == 0) {
+            return;
+        }
+
+        if (catalog != null) {
+            catalog.addExcludeProcedure(new ExcludeProcedure(excludeProcedure));
+        }
+    }
+
+    private void createIncludeProcedure(String includeProcedure) {
+        if (includeProcedure.trim().length() == 0) {
+            return;
+        }
+
+        if (catalog != null) {
+            catalog.addIncludeProcedure(new IncludeProcedure(includeProcedure));
+        }
+    }
+
+    private void createExcludeColumn(String excludeColumn) {
+        if (excludeColumn.trim().length() == 0) {
+            return;
+        }
+
+        if (catalog != null) {
+            catalog.addExcludeColumn(new ExcludeColumn(excludeColumn));
+        }
+    }
+
+    private void createIncludeColumn(String includeColumn) {
+        if (includeColumn.trim().length() == 0) {
+            return;
+        }
+
+        if (catalog != null) {
+            catalog.addIncludeColumn(new IncludeColumn(includeColumn));
+        }
+    }
+
+    private void createExcludeTable(String excludeTable) {
+        if (excludeTable.trim().length() == 0) {
+            return;
+        }
+
+        if (catalog != null) {
+            catalog.addExcludeTable(new ExcludeTable(excludeTable));
+        }
+    }
+
+    private void createCatalog() {
+        catalog = new Catalog();
+        configuration.addCatalog(catalog);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/ConfigHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/ConfigHandler.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/ConfigHandler.java
new file mode 100644
index 0000000..e522d89
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/ConfigHandler.java
@@ -0,0 +1,350 @@
+/*****************************************************************
+ *   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.dbsync.xml;
+
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DataMapLoaderListener;
+import org.apache.cayenne.configuration.xml.NamespaceAwareNestedTagHandler;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeColumn;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeProcedure;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeColumn;
+import org.apache.cayenne.map.DataMap;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+class ConfigHandler extends NamespaceAwareNestedTagHandler {
+
+    public static final String CONFIG_TAG = "config";
+
+    private static final String CATALOG_TAG = "catalog";
+    private static final String SCHEMA_TAG = "schema";
+    private static final String TABLE_TYPE_TAG = "tableType";
+    private static final String DEFAULT_PACKAGE_TAG = "defaultPackage";
+    private static final String FORCE_DATAMAP_CATALOG_TAG = "forceDataMapCatalog";
+    private static final String FORCE_DATAMAP_SCHEMA_TAG = "forceDataMapSchema";
+    private static final String MEANINGFUL_PK_TABLES_TAG = "meaningfulPkTables";
+    private static final String NAMING_STRATEGY_TAG = "namingStrategy";
+    private static final String SKIP_PK_LOADING_TAG = "skipPrimaryKeyLoading";
+    private static final String SKIP_RELATIONSHIPS_LOADING_TAG = "skipRelationshipsLoading";
+    private static final String STRIP_FROM_TABLE_NAMES_TAG = "stripFromTableNames";
+    private static final String USE_JAVA7_TYPES_TAG = "useJava7Types";
+    private static final String USE_PRIMITIVES_TAG = "usePrimitives";
+    private static final String INCLUDE_TABLE_TAG = "includeTable";
+    private static final String EXCLUDE_TABLE_TAG = "excludeTable";
+    private static final String INCLUDE_COLUMN_TAG = "includeColumn";
+    private static final String EXCLUDE_COLUMN_TAG = "excludeColumn";
+    private static final String INCLUDE_PROCEDURE_TAG = "includeProcedure";
+    private static final String EXCLUDE_PROCEDURE_TAG = "excludeProcedure";
+
+    private static final String TRUE = "true";
+
+    private ReverseEngineering configuration;
+    private DataChannelMetaData metaData;
+
+    ConfigHandler(NamespaceAwareNestedTagHandler parentHandler, DataChannelMetaData metaData) {
+        super(parentHandler);
+        this.metaData = metaData;
+        this.targetNamespace = DbImportExtension.NAMESPACE;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        switch (localName) {
+            case CONFIG_TAG:
+                createConfig();
+                return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    protected ContentHandler createChildTagHandler(String namespaceURI, String localName,
+                                                   String qName, Attributes attributes) {
+
+        if (namespaceURI.equals(targetNamespace)) {
+            switch (localName) {
+                case CATALOG_TAG:
+                    return new CatalogHandler(this, configuration);
+                case SCHEMA_TAG:
+                    return new SchemaHandler(this, configuration);
+                case INCLUDE_TABLE_TAG:
+                    return new IncludeTableHandler(this , configuration);
+            }
+        }
+
+        return super.createChildTagHandler(namespaceURI, localName, qName, attributes);
+    }
+
+    @Override
+    protected void processCharData(String localName, String data) {
+        switch (localName) {
+            case TABLE_TYPE_TAG:
+                createTableType(data);
+                break;
+            case DEFAULT_PACKAGE_TAG:
+                createDefaultPackage(data);
+                break;
+            case FORCE_DATAMAP_CATALOG_TAG:
+                createForceDatamapCatalog(data);
+                break;
+            case FORCE_DATAMAP_SCHEMA_TAG:
+                createForceDatamapSchema(data);
+                break;
+            case MEANINGFUL_PK_TABLES_TAG:
+                createMeaningfulPkTables(data);
+                break;
+            case NAMING_STRATEGY_TAG:
+                createNamingStrategy(data);
+                break;
+            case SKIP_PK_LOADING_TAG:
+                createSkipPkLoading(data);
+                break;
+            case SKIP_RELATIONSHIPS_LOADING_TAG:
+                createSkipRelationshipsLoading(data);
+                break;
+            case STRIP_FROM_TABLE_NAMES_TAG:
+                createStripFromTableNames(data);
+                break;
+            case USE_JAVA7_TYPES_TAG:
+                createUseJava7Types(data);
+                break;
+            case USE_PRIMITIVES_TAG:
+                createUsePrimitives(data);
+                break;
+            case EXCLUDE_TABLE_TAG:
+                createExcludeTable(data);
+                break;
+            case INCLUDE_COLUMN_TAG:
+                createIncludeColumn(data);
+                break;
+            case EXCLUDE_COLUMN_TAG:
+                createExcludeColumn(data);
+                break;
+            case INCLUDE_PROCEDURE_TAG:
+                createIncludeProcedure(data);
+                break;
+            case EXCLUDE_PROCEDURE_TAG:
+                createExcludeProcedure(data);
+                break;
+        }
+    }
+
+    private void createExcludeProcedure(String excludeProcedure) {
+        if (excludeProcedure.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            configuration.addExcludeProcedure(new ExcludeProcedure(excludeProcedure));
+        }
+    }
+
+    private void createIncludeProcedure(String includeProcedure) {
+        if (includeProcedure.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            configuration.addIncludeProcedure(new IncludeProcedure(includeProcedure));
+        }
+    }
+
+    private void createExcludeColumn(String excludeColumn) {
+        if (excludeColumn.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            configuration.addExcludeColumn(new ExcludeColumn(excludeColumn));
+        }
+    }
+
+    private void createIncludeColumn(String includeColumn) {
+        if (includeColumn.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            configuration.addIncludeColumn(new IncludeColumn(includeColumn));
+        }
+    }
+
+    private void createExcludeTable(String excludeTable) {
+        if (excludeTable.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            configuration.addExcludeTable(new ExcludeTable(excludeTable));
+        }
+    }
+
+    private void createUsePrimitives(String usePrimitives) {
+        if (usePrimitives.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            if (usePrimitives.equals(TRUE)) {
+                configuration.setUsePrimitives(true);
+            } else {
+                configuration.setUsePrimitives(false);
+            }
+        }
+    }
+
+    private void createUseJava7Types(String useJava7Types) {
+        if (useJava7Types.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            if (useJava7Types.equals(TRUE)) {
+                configuration.setUseJava7Types(true);
+            } else {
+                configuration.setUseJava7Types(false);
+            }
+        }
+    }
+
+    private void createStripFromTableNames(String stripFromTableNames) {
+        if (stripFromTableNames.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            configuration.setStripFromTableNames(stripFromTableNames);
+        }
+    }
+
+    private void createSkipRelationshipsLoading(String skipRelationshipsLoading) {
+        if (skipRelationshipsLoading.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            if (skipRelationshipsLoading.equals(TRUE)) {
+                configuration.setSkipRelationshipsLoading(true);
+            } else {
+                configuration.setSkipRelationshipsLoading(false);
+            }
+        }
+    }
+
+    private void createSkipPkLoading(String skipPkLoading) {
+        if (skipPkLoading.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            if (skipPkLoading.equals(TRUE)) {
+                configuration.setSkipPrimaryKeyLoading(true);
+            } else {
+                configuration.setSkipPrimaryKeyLoading(false);
+            }
+        }
+    }
+
+    private void createNamingStrategy(String namingStrategy) {
+        if (namingStrategy.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            configuration.setNamingStrategy(namingStrategy);
+        }
+    }
+
+    private void createMeaningfulPkTables(String meaningfulPkTables) {
+        if (meaningfulPkTables.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            configuration.setMeaningfulPkTables(meaningfulPkTables);
+        }
+    }
+
+    private void createForceDatamapSchema(String forceDatamapSchema) {
+        if (forceDatamapSchema.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            if (forceDatamapSchema.equals(TRUE)) {
+                configuration.setForceDataMapSchema(true);
+            } else {
+                configuration.setForceDataMapSchema(false);
+            }
+        }
+    }
+
+    private void createForceDatamapCatalog(String forceDatamapCatalog) {
+        if (forceDatamapCatalog.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            if (forceDatamapCatalog.equals(TRUE)) {
+                configuration.setForceDataMapCatalog(true);
+            } else {
+                configuration.setForceDataMapCatalog(false);
+            }
+        }
+    }
+
+    private void createDefaultPackage(String defaultPackage) {
+        if (defaultPackage.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            configuration.setDefaultPackage(defaultPackage);
+        }
+    }
+
+    private void createTableType(String tableType) {
+        if (tableType.trim().length() == 0) {
+            return;
+        }
+
+        if (configuration != null) {
+            configuration.addTableType(tableType);
+        }
+    }
+
+    private void createConfig() {
+        configuration = new ReverseEngineering();
+        loaderContext.addDataMapListener(new DataMapLoaderListener() {
+            @Override
+            public void onDataMapLoaded(DataMap dataMap) {
+                ConfigHandler.this.metaData.add(dataMap, configuration);
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/DbImportExtension.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/DbImportExtension.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/DbImportExtension.java
new file mode 100644
index 0000000..120826d
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/DbImportExtension.java
@@ -0,0 +1,56 @@
+/*****************************************************************
+ *   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.dbsync.xml;
+
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.project.Project;
+import org.apache.cayenne.project.extension.BaseNamingDelegate;
+import org.apache.cayenne.project.extension.LoaderDelegate;
+import org.apache.cayenne.project.extension.ProjectExtension;
+import org.apache.cayenne.project.extension.SaverDelegate;
+
+/**
+ * @since 4.1
+ */
+public class DbImportExtension implements ProjectExtension {
+
+    public static final String NAMESPACE = "http://cayenne.apache.org/schema/" + Project.VERSION + "/dbimport";
+
+    @Inject
+    private DataChannelMetaData metaData;
+
+    @Override
+    public LoaderDelegate createLoaderDelegate() {
+        return new DbImportLoaderDelegate(metaData);
+    }
+
+    @Override
+    public SaverDelegate createSaverDelegate() {
+        return new DbImportSaverDelegate(metaData);
+    }
+
+    @Override
+    public ConfigurationNodeVisitor<String> createNamingDelegate() {
+        return new BaseNamingDelegate();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/DbImportLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/DbImportLoaderDelegate.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/DbImportLoaderDelegate.java
new file mode 100644
index 0000000..e777665
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/DbImportLoaderDelegate.java
@@ -0,0 +1,49 @@
+/*****************************************************************
+ *   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.dbsync.xml;
+
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.NamespaceAwareNestedTagHandler;
+import org.apache.cayenne.project.extension.LoaderDelegate;
+
+/**
+ * @since 4.1
+ */
+class DbImportLoaderDelegate implements LoaderDelegate {
+
+    private DataChannelMetaData metaData;
+
+    DbImportLoaderDelegate(DataChannelMetaData metaData) {
+        this.metaData = metaData;
+    }
+
+    @Override
+    public String getTargetNamespace() {
+        return DbImportExtension.NAMESPACE;
+    }
+
+    @Override
+    public NamespaceAwareNestedTagHandler createHandler(NamespaceAwareNestedTagHandler parent, String tag) {
+        if(ConfigHandler.CONFIG_TAG.equals(tag)) {
+            return new ConfigHandler(parent, metaData);
+        }
+        return null;
+    }
+}
\ No newline at end of file


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

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/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
deleted file mode 100644
index 749ffb0..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportModel.java
+++ /dev/null
@@ -1,75 +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.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/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
deleted file mode 100644
index 3b33ad7..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportNodeHandler.java
+++ /dev/null
@@ -1,341 +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.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/51289d1c/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
deleted file mode 100644
index 6862c82..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTree.java
+++ /dev/null
@@ -1,207 +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.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/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
deleted file mode 100644
index 6c96e31..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTreeCellEditor.java
+++ /dev/null
@@ -1,154 +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.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/51289d1c/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
deleted file mode 100644
index 82a1cd5..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportTreeCellRenderer.java
+++ /dev/null
@@ -1,96 +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.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/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
deleted file mode 100644
index 453ce00..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DbImportView.java
+++ /dev/null
@@ -1,236 +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 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;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DraggableTreePanel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DraggableTreePanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DraggableTreePanel.java
deleted file mode 100644
index 5418f0f..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DraggableTreePanel.java
+++ /dev/null
@@ -1,428 +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.map.DataMap;
-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.AddSchemaAction;
-import org.apache.cayenne.modeler.action.MoveImportNodeAction;
-import org.apache.cayenne.modeler.action.MoveInvertNodeAction;
-import org.apache.cayenne.modeler.action.TreeManipulationAction;
-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.DropMode;
-import javax.swing.JButton;
-import javax.swing.JComponent;
-import javax.swing.JScrollPane;
-import javax.swing.JTree;
-import javax.swing.TransferHandler;
-import javax.swing.tree.DefaultTreeCellRenderer;
-import javax.swing.tree.TreePath;
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
-import java.awt.datatransfer.UnsupportedFlavorException;
-import java.awt.event.KeyEvent;
-import java.awt.event.KeyListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @since 4.1
- */
-public class DraggableTreePanel extends JScrollPane {
-
-    private static final int ROOT_LEVEL = 14;
-    private static final int FIRST_LEVEL = 11;
-    private static final int SECOND_LEVEL = 8;
-    private static final int THIRD_LEVEL = 5;
-    private static final int FOURTH_LEVEL = 2;
-    private static final int FIFTH_LEVEL = 3;
-    private static final String MOVE_BUTTON_LABEL = "Include";
-    private static final String MOVE_INV_BUTTON_LABEL = "Exclude";
-
-    private DbImportTree sourceTree;
-    private DbImportTree targetTree;
-    private CayenneAction.CayenneToolbarButton moveButton;
-    private CayenneAction.CayenneToolbarButton moveInvertButton;
-    private Map<DataMap, ReverseEngineering> databaseStructures;
-
-    private ProjectController projectController;
-    private Map<Class, Integer> levels;
-    private Map<Class, List<Class>> insertableLevels;
-    private Map<Class, Class> actions;
-
-    public DraggableTreePanel(ProjectController projectController, DbImportTree sourceTree, DbImportTree targetTree) {
-        super(sourceTree);
-        this.targetTree = targetTree;
-        this.sourceTree = sourceTree;
-        this.projectController = projectController;
-        this.databaseStructures = new HashMap<>();
-        initLevels();
-        initElement();
-        initActions();
-        initListeners();
-    }
-
-    private void initActions() {
-        actions = new HashMap<>();
-        actions.put(Catalog.class, AddCatalogAction.class);
-        actions.put(Schema.class, AddSchemaAction.class);
-        actions.put(IncludeTable.class, AddIncludeTableAction.class);
-        actions.put(ExcludeTable.class, AddExcludeTableAction.class);
-        actions.put(IncludeColumn.class, AddIncludeColumnAction.class);
-        actions.put(ExcludeColumn.class, AddExcludeColumnAction.class);
-        actions.put(IncludeProcedure.class, AddIncludeProcedureAction.class);
-        actions.put(ExcludeProcedure.class, AddExcludeProcedureAction.class);
-    }
-
-    public void updateTree(DataMap dataMap) {
-        DbImportModel model = (DbImportModel) sourceTree.getModel();
-        model.reload();
-        if (databaseStructures.get(dataMap) != null) {
-            sourceTree.setReverseEngineering(databaseStructures.get(dataMap));
-            sourceTree.translateReverseEngineeringToTree(databaseStructures.get(dataMap), true);
-            sourceTree.setEnabled(true);
-        } else {
-            sourceTree.setEnabled(false);
-        }
-    }
-
-    private void initListeners() {
-        sourceTree.addKeyListener(new KeyListener() {
-            @Override
-            public void keyTyped(KeyEvent e) {}
-
-            @Override
-            public void keyPressed(KeyEvent e) {
-                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
-                    sourceTree.setSelectionRow(-1);
-                    moveButton.setEnabled(false);
-                    moveInvertButton.setEnabled(false);
-                }
-            }
-
-            @Override
-            public void keyReleased(KeyEvent e) {}
-        });
-        targetTree.addKeyListener(new KeyListener() {
-            @Override
-            public void keyTyped(KeyEvent e) {}
-
-            @Override
-            public void keyPressed(KeyEvent e) {
-                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
-                    targetTree.setSelectionRow(-1);
-                }
-            }
-
-            @Override
-            public void keyReleased(KeyEvent e) {}
-        });
-        targetTree.addTreeSelectionListener(e -> {
-            DbImportModel model = (DbImportModel) sourceTree.getModel();
-            DbImportTreeNode root = (DbImportTreeNode) model.getRoot();
-            sourceTree.repaint();
-            if (root.getChildCount() > 0) {
-                model.nodesChanged(root, new int[]{root.getChildCount() - 1});
-            }
-            if (canBeMoved()) {
-                moveButton.setEnabled(true);
-                if (canBeInverted()) {
-                    moveInvertButton.setEnabled(true);
-                } else {
-                    moveInvertButton.setEnabled(false);
-                }
-            } else {
-                moveButton.setEnabled(false);
-                moveInvertButton.setEnabled(false);
-            }
-        });
-        targetTree.setDragEnabled(true);
-        targetTree.setTransferHandler(new TransferHandler() {
-
-            @Override
-            public int getSourceActions(JComponent c) {
-                return COPY_OR_MOVE;
-            }
-
-            @Override
-            public boolean canImport(TransferSupport support) {
-                if (!support.isDrop()) {
-                    return false;
-                }
-                return true;
-            }
-
-            @Override
-            public boolean importData(TransferSupport support) {
-                if (!canImport(support)) {
-                    return false;
-                }
-                if (!canBeMoved()) {
-                    return false;
-                }
-                Transferable transferable = support.getTransferable();
-                DbImportTreeNode[] transferData = null;
-                try {
-                    for (DataFlavor dataFlavor : transferable.getTransferDataFlavors()) {
-                        transferData = (DbImportTreeNode[]) transferable.getTransferData(dataFlavor);
-                    }
-                } catch (IOException | UnsupportedFlavorException e) {
-                    return false;
-                }
-                if (transferData != null) {
-                    MoveImportNodeAction action = projectController.getApplication().
-                            getActionManager().getAction(MoveImportNodeAction.class);
-                    action.setSourceTree(sourceTree);
-                    action.setTargetTree(targetTree);
-                    action.setPanel(DraggableTreePanel.this);
-                    action.performAction(null);
-                    return true;
-                }
-                return false;
-            }
-        });
-    }
-
-    private boolean canBeInverted() {
-        if (sourceTree.getSelectionPath() != null) {
-            DbImportTreeNode selectedElement = sourceTree.getSelectedNode();
-            if (selectedElement == null) {
-                return false;
-            }
-            if (levels.get(selectedElement.getUserObject().getClass()) < SECOND_LEVEL) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void initElement() {
-        sourceTree.setDragEnabled(true);
-        sourceTree.setCellRenderer(new ColorTreeRenderer());
-        sourceTree.setDropMode(DropMode.INSERT);
-        sourceTree.setTransferHandler(new TransferHandler() {
-
-            @Override
-            public int getSourceActions(JComponent c) {
-                return COPY;
-            }
-
-            @Override
-            public Transferable createTransferable(JComponent c) {
-                JTree tree = (JTree) c;
-                TreePath[] paths = tree.getSelectionPaths();
-                DbImportTreeNode[] nodes = new DbImportTreeNode[paths.length];
-                for (int i = 0; i < paths.length; i++) {
-                    nodes[i] = (DbImportTreeNode) paths[i].getLastPathComponent();
-                }
-                return new Transferable() {
-                    @Override
-                    public DataFlavor[] getTransferDataFlavors() {
-                        return TransferableNode.flavors;
-                    }
-
-                    @Override
-                    public boolean isDataFlavorSupported(DataFlavor flavor) {
-                        return true;
-                    }
-
-                    @Override
-                    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
-                        return nodes;
-                    }
-                };
-            }
-        });
-        sourceTree.addTreeSelectionListener(e -> {
-            if (sourceTree.getLastSelectedPathComponent() != null) {
-                if (canBeMoved()) {
-                    moveButton.setEnabled(true);
-                    if (canBeInverted()) {
-                        moveInvertButton.setEnabled(true);
-                    } else {
-                        moveInvertButton.setEnabled(false);
-                    }
-                } else {
-                    moveInvertButton.setEnabled(false);
-                    moveButton.setEnabled(false);
-                }
-            }
-        });
-
-        sourceTree.addMouseListener(new MouseAdapter() {
-            @Override
-            public void mouseClicked(MouseEvent e) {
-                if (sourceTree.getRowForLocation(e.getX(),e.getY()) == -1) {
-                    sourceTree.setSelectionRow(-1);
-                    moveInvertButton.setEnabled(false);
-                    moveButton.setEnabled(false);
-                }
-            }
-        });
-
-        MoveImportNodeAction action = projectController.getApplication().
-                getActionManager().getAction(MoveImportNodeAction.class);
-        action.setPanel(this);
-        action.setSourceTree(sourceTree);
-        action.setTargetTree(targetTree);
-        moveButton = (CayenneAction.CayenneToolbarButton) action.buildButton();
-        moveButton.setShowingText(true);
-        moveButton.setText(MOVE_BUTTON_LABEL);
-        MoveInvertNodeAction actionInv = projectController.getApplication().
-                getActionManager().getAction(MoveInvertNodeAction.class);
-        actionInv.setPanel(this);
-        actionInv.setSourceTree(sourceTree);
-        actionInv.setTargetTree(targetTree);
-        moveInvertButton = (CayenneAction.CayenneToolbarButton) actionInv.buildButton();
-        moveInvertButton.setShowingText(true);
-        moveInvertButton.setText(MOVE_INV_BUTTON_LABEL);
-
-
-        DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) sourceTree.getCellRenderer();
-        renderer.setLeafIcon(null);
-        renderer.setClosedIcon(null);
-        renderer.setOpenIcon(null);
-    }
-
-    private void initLevels() {
-        levels = new HashMap<>();
-        levels.put(ReverseEngineering.class, ROOT_LEVEL);
-        levels.put(Catalog.class, FIRST_LEVEL);
-        levels.put(Schema.class, SECOND_LEVEL);
-        levels.put(IncludeTable.class, THIRD_LEVEL);
-        levels.put(IncludeColumn.class, FOURTH_LEVEL);
-        levels.put(ExcludeColumn.class, FOURTH_LEVEL);
-        levels.put(ExcludeTable.class, FIFTH_LEVEL);
-        levels.put(IncludeProcedure.class, FIFTH_LEVEL);
-        levels.put(ExcludeProcedure.class, FIFTH_LEVEL);
-
-        insertableLevels = new HashMap<>();
-        List<Class> rootLevelClasses = new ArrayList<>();
-        rootLevelClasses.add(Catalog.class);
-        rootLevelClasses.add(Schema.class);
-        rootLevelClasses.add(IncludeTable.class);
-        rootLevelClasses.add(ExcludeTable.class);
-        rootLevelClasses.add(IncludeColumn.class);
-        rootLevelClasses.add(ExcludeColumn.class);
-        rootLevelClasses.add(IncludeProcedure.class);
-        rootLevelClasses.add(ExcludeProcedure.class);
-
-        List<Class> catalogLevelClasses = new ArrayList<>();
-        catalogLevelClasses.add(Schema.class);
-        catalogLevelClasses.add(IncludeTable.class);
-        catalogLevelClasses.add(ExcludeTable.class);
-        catalogLevelClasses.add(IncludeColumn.class);
-        catalogLevelClasses.add(ExcludeColumn.class);
-        catalogLevelClasses.add(IncludeProcedure.class);
-        catalogLevelClasses.add(ExcludeProcedure.class);
-
-        List<Class> schemaLevelClasses = new ArrayList<>();
-        schemaLevelClasses.add(IncludeTable.class);
-        schemaLevelClasses.add(ExcludeTable.class);
-        schemaLevelClasses.add(IncludeColumn.class);
-        schemaLevelClasses.add(ExcludeColumn.class);
-        schemaLevelClasses.add(IncludeProcedure.class);
-        schemaLevelClasses.add(ExcludeProcedure.class);
-
-        List<Class> includeTableLevelClasses = new ArrayList<>();
-        includeTableLevelClasses.add(IncludeColumn.class);
-        includeTableLevelClasses.add(ExcludeColumn.class);
-
-        insertableLevels.put(ReverseEngineering.class, rootLevelClasses);
-        insertableLevels.put(Catalog.class, catalogLevelClasses);
-        insertableLevels.put(Schema.class, schemaLevelClasses);
-        insertableLevels.put(IncludeTable.class, includeTableLevelClasses);
-    }
-
-    private boolean canBeMoved() {
-        if (sourceTree.getSelectionPath() != null) {
-            DbImportTreeNode selectedElement = sourceTree.getSelectedNode();
-            if (selectedElement == null) {
-                return false;
-            }
-            Class draggableElementClass = selectedElement.getUserObject().getClass();
-            Class reverseEngineeringElementClass;
-            if (targetTree.getSelectionPath() != null) {
-                selectedElement = targetTree.getSelectedNode();
-                DbImportTreeNode parent = (DbImportTreeNode) selectedElement.getParent();
-                if (parent != null) {
-                    reverseEngineeringElementClass = parent.getUserObject().getClass();
-                } else {
-                    reverseEngineeringElementClass = selectedElement.getUserObject().getClass();
-                }
-            } else {
-                reverseEngineeringElementClass = ReverseEngineering.class;
-            }
-            List<Class> containsList = insertableLevels.get(reverseEngineeringElementClass);
-            return containsList.contains(draggableElementClass);
-        }
-        return false;
-    }
-
-    public JButton getMoveButton() {
-        return moveButton;
-    }
-
-    public JButton getMoveInvertButton() {
-        return moveInvertButton;
-    }
-
-    public TreeManipulationAction getActionByNodeType(Class nodeType) {
-        Class actionClass = actions.get(nodeType);
-        if (actionClass != null) {
-            TreeManipulationAction action = (TreeManipulationAction) projectController.getApplication().
-                    getActionManager().getAction(actionClass);
-            return action;
-        }
-        return null;
-    }
-
-    public void bindReverseEngineeringToDatamap(DataMap dataMap, ReverseEngineering reverseEngineering) {
-        databaseStructures.put(dataMap, reverseEngineering);
-    }
-
-    public DbImportTree getSourceTree() {
-        return sourceTree;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringConfigPanel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringConfigPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringConfigPanel.java
deleted file mode 100644
index 65c9282..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringConfigPanel.java
+++ /dev/null
@@ -1,223 +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 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.util.NameGeneratorPreferences;
-import org.apache.cayenne.modeler.util.TextAdapter;
-
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JCheckBox;
-import javax.swing.JComboBox;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.Vector;
-
-/**
- * @since 4.1
- */
-public class ReverseEngineeringConfigPanel extends JPanel {
-
-    private static final String DATA_FIELDS_LAYOUT = "right:pref, 3dlu, fill:235dlu";
-
-    private JComboBox<String> strategyCombo;
-    private TextAdapter meaningfulPk;
-    private TextAdapter stripFromTableNames;
-    private JCheckBox skipRelationshipsLoading;
-    private JCheckBox skipPrimaryKeyLoading;
-    private JCheckBox forceDataMapCatalog;
-    private JCheckBox forceDataMapSchema;
-    private JCheckBox usePrimitives;
-    private JCheckBox useJava7Types;
-
-    private ProjectController projectController;
-
-    ReverseEngineeringConfigPanel(ProjectController projectController) {
-        this.projectController = projectController;
-        initFormElements();
-        initListeners();
-        buildView();
-    }
-
-    private void buildView() {
-        FormLayout panelLayout = new FormLayout(DATA_FIELDS_LAYOUT);
-        DefaultFormBuilder panelBuilder = new DefaultFormBuilder(panelLayout);
-        panelBuilder.setDefaultDialogBorder();
-
-        panelBuilder.append("Tables with Meaningful PK Pattern:", meaningfulPk.getComponent());
-        panelBuilder.append("Strip from table names:", stripFromTableNames.getComponent());
-        panelBuilder.append("Skip relationships loading:", skipRelationshipsLoading);
-        panelBuilder.append("Skip primary key loading:", skipPrimaryKeyLoading);
-        panelBuilder.append("Force datamap catalog:", forceDataMapCatalog);
-        panelBuilder.append("Force datamap schema:", forceDataMapSchema);
-        panelBuilder.append("Use Java primitive types:", usePrimitives);
-        panelBuilder.append("Use java.util.Date type:", useJava7Types);
-        panelBuilder.append(strategyCombo);
-
-        add(panelBuilder.getPanel());
-    }
-
-    void fillCheckboxes(ReverseEngineering reverseEngineering) {
-        skipRelationshipsLoading.setSelected(reverseEngineering.getSkipRelationshipsLoading());
-        skipPrimaryKeyLoading.setSelected(reverseEngineering.getSkipPrimaryKeyLoading());
-        forceDataMapCatalog.setSelected(reverseEngineering.isForceDataMapCatalog());
-        forceDataMapSchema.setSelected(reverseEngineering.isForceDataMapSchema());
-        usePrimitives.setSelected(reverseEngineering.isUsePrimitives());
-        useJava7Types.setSelected(reverseEngineering.isUseJava7Types());
-    }
-
-    void initializeTextFields(ReverseEngineering reverseEngineering) {
-        meaningfulPk.setText(reverseEngineering.getMeaningfulPkTables());
-        stripFromTableNames.setText(reverseEngineering.getStripFromTableNames());
-    }
-
-    private ReverseEngineering getReverseEngineeringBySelectedMap() {
-        DataMap dataMap = projectController.getCurrentDataMap();
-        return projectController.getApplication().getMetaData().get(dataMap, ReverseEngineering.class);
-    }
-
-    private void initStrategy() {
-        Vector<String> arr = NameGeneratorPreferences
-                .getInstance()
-                .getLastUsedStrategies();
-        strategyCombo.setModel(new DefaultComboBoxModel<>(arr));
-    }
-
-    private void initFormElements() {
-        strategyCombo = new JComboBox<>();
-        strategyCombo.addActionListener(e -> {
-            getReverseEngineeringBySelectedMap().setNamingStrategy(
-                    (String) ReverseEngineeringConfigPanel.this.getStrategyCombo().getSelectedItem()
-            );
-            projectController.setDirty(true);
-        });
-        strategyCombo.setVisible(false);
-
-        JTextField meaningfulPkField = new JTextField();
-        meaningfulPkField.setToolTipText("<html>Regular expression to filter tables with meaningful primary keys.<br>" +
-                "Multiple expressions divided by comma can be used.<br>" +
-                "Example: <b>^table1|^table2|^prefix.*|table_name</b></html>");
-        meaningfulPk = new TextAdapter(meaningfulPkField) {
-            protected void updateModel(String text) {
-                getReverseEngineeringBySelectedMap().setMeaningfulPkTables(text);
-                projectController.setDirty(true);
-            }
-        };
-
-        JTextField stripFromTableNamesField = new JTextField();
-        stripFromTableNamesField.setToolTipText("<html>Regex that matches the part of the table name that needs to be stripped off " +
-                "when generating ObjEntity name</html>");
-        stripFromTableNames = new TextAdapter(stripFromTableNamesField) {
-            protected void updateModel(String text) {
-                getReverseEngineeringBySelectedMap().setStripFromTableNames(text);
-                projectController.setDirty(true);
-            }
-        };
-
-        skipRelationshipsLoading = new JCheckBox();
-        skipRelationshipsLoading.setToolTipText("<html>Whether to load relationships.</html>");
-        skipPrimaryKeyLoading = new JCheckBox();
-        skipPrimaryKeyLoading.setToolTipText("<html>Whether to load primary keys.</html>");
-        forceDataMapCatalog = new JCheckBox();
-        forceDataMapCatalog.setToolTipText("<html>Automatically tagging each DbEntity with the actual DB catalog/schema" +
-                "(default behavior) may sometimes be undesirable.<br>  If this is the case then setting <b>forceDataMapCatalog</b> " +
-                "to <b>true</b> will set DbEntity catalog to one in the DataMap.</html>");
-        forceDataMapSchema = new JCheckBox();
-        forceDataMapSchema.setToolTipText("<html>Automatically tagging each DbEntity with the actual DB catalog/schema " +
-                "(default behavior) may sometimes be undesirable.<br> If this is the case then setting <b>forceDataMapSchema</b> " +
-                "to <b>true</b> will set DbEntity schema to one in the DataMap.</html>");
-        useJava7Types = new JCheckBox();
-        useJava7Types.setToolTipText("<html>Use <b>java.util.Date</b> for all columns with <i>DATE/TIME/TIMESTAMP</i> types.<br>" +
-                "By default <b>java.time.*</b> types will be used.</html>");
-        usePrimitives = new JCheckBox();
-        usePrimitives.setToolTipText("<html>Use primitive types (e.g. int) or Object types (e.g. java.lang.Integer)</html>");
-        initStrategy();
-    }
-
-    private void initListeners() {
-        skipRelationshipsLoading.addActionListener(e -> {
-            getReverseEngineeringBySelectedMap().setSkipRelationshipsLoading(skipRelationshipsLoading.isSelected());
-            projectController.setDirty(true);
-        });
-        skipPrimaryKeyLoading.addActionListener(e -> {
-            getReverseEngineeringBySelectedMap().setSkipPrimaryKeyLoading(skipPrimaryKeyLoading.isSelected());
-            projectController.setDirty(true);
-        });
-        forceDataMapCatalog.addActionListener(e -> {
-            getReverseEngineeringBySelectedMap().setForceDataMapCatalog(forceDataMapCatalog.isSelected());
-            projectController.setDirty(true);
-        });
-        forceDataMapSchema.addActionListener(e -> {
-            getReverseEngineeringBySelectedMap().setForceDataMapSchema(forceDataMapSchema.isSelected());
-            projectController.setDirty(true);
-        });
-        usePrimitives.addActionListener(e -> {
-            getReverseEngineeringBySelectedMap().setUsePrimitives(usePrimitives.isSelected());
-            projectController.setDirty(true);
-        });
-        useJava7Types.addActionListener(e -> {
-            getReverseEngineeringBySelectedMap().setUseJava7Types(useJava7Types.isSelected());
-            projectController.setDirty(true);
-        });
-    }
-
-    JComboBox<String> getStrategyCombo() {
-        return strategyCombo;
-    }
-
-    TextAdapter getMeaningfulPk() {
-        return meaningfulPk;
-    }
-
-    TextAdapter getStripFromTableNames() {
-        return stripFromTableNames;
-    }
-
-    JCheckBox getSkipRelationshipsLoading() {
-        return skipRelationshipsLoading;
-    }
-
-    JCheckBox getSkipPrimaryKeyLoading() {
-        return skipPrimaryKeyLoading;
-    }
-
-    JCheckBox getForceDataMapCatalog() {
-        return forceDataMapCatalog;
-    }
-
-    JCheckBox getForceDataMapSchema() {
-        return forceDataMapSchema;
-    }
-
-    JCheckBox getUsePrimitives() {
-        return usePrimitives;
-    }
-
-    JCheckBox getUseJava7Types() {
-        return useJava7Types;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/51289d1c/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringTreePanel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringTreePanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringTreePanel.java
deleted file mode 100644
index 8c50c1e..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ReverseEngineeringTreePanel.java
+++ /dev/null
@@ -1,169 +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.map.DataMap;
-import org.apache.cayenne.modeler.ProjectController;
-import org.apache.cayenne.modeler.dialog.db.load.CatalogPopUpMenu;
-import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
-import org.apache.cayenne.modeler.dialog.db.load.DefaultPopUpMenu;
-import org.apache.cayenne.modeler.dialog.db.load.IncludeTablePopUpMenu;
-import org.apache.cayenne.modeler.dialog.db.load.RootPopUpMenu;
-import org.apache.cayenne.modeler.dialog.db.load.SchemaPopUpMenu;
-
-import javax.swing.JScrollPane;
-import javax.swing.JTree;
-import javax.swing.SwingUtilities;
-import javax.swing.tree.DefaultTreeCellRenderer;
-import javax.swing.tree.TreePath;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @since 4.1
- */
-class ReverseEngineeringTreePanel extends JScrollPane {
-
-    private DbImportTree reverseEngineeringTree;
-    private DbImportTree dbSchemaTree;
-
-    private ProjectController projectController;
-    private TreeToolbarPanel treeToolbar;
-    private Map<Class, DefaultPopUpMenu> popups;
-
-    ReverseEngineeringTreePanel(ProjectController projectController, DbImportTree reverseEngineeringTree,
-                                DbImportTree dbSchemaTree) {
-        super(reverseEngineeringTree);
-        this.projectController = projectController;
-        this.reverseEngineeringTree = reverseEngineeringTree;
-        this.dbSchemaTree = dbSchemaTree;
-        reverseEngineeringTree.setEditable(true);
-        reverseEngineeringTree.setCellRenderer(new DbImportTreeCellRenderer());
-        DbImportTreeCellEditor editor = new DbImportTreeCellEditor(reverseEngineeringTree,
-                (DefaultTreeCellRenderer) reverseEngineeringTree.getCellRenderer());
-        editor.setProjectController(projectController);
-        reverseEngineeringTree.setCellEditor(editor);
-        initListeners();
-        initPopupMenus();
-        changeIcons();
-    }
-
-    void updateTree() {
-        reverseEngineeringTree.translateReverseEngineeringToTree(getReverseEngineeringBySelectedMap(), false);
-    }
-
-    private void initPopupMenus() {
-        popups = new HashMap<>();
-        popups.put(Catalog.class, new CatalogPopUpMenu());
-        popups.put(Schema.class, new SchemaPopUpMenu());
-        popups.put(ReverseEngineering.class, new RootPopUpMenu());
-        popups.put(String.class, new RootPopUpMenu());
-        popups.put(IncludeTable.class, new IncludeTablePopUpMenu());
-        popups.put(ExcludeTable.class, new DefaultPopUpMenu());
-        popups.put(IncludeColumn.class, new DefaultPopUpMenu());
-        popups.put(ExcludeColumn.class, new DefaultPopUpMenu());
-        popups.put(IncludeProcedure.class, new DefaultPopUpMenu());
-        popups.put(ExcludeProcedure.class, new DefaultPopUpMenu());
-    }
-
-    private void initListeners() {
-        reverseEngineeringTree.addTreeSelectionListener(e -> treeToolbar.lockButtons());
-        reverseEngineeringTree.addMouseListener(new MouseAdapter() {
-            @Override
-            public void mouseClicked(MouseEvent e) {
-                if (reverseEngineeringTree.getRowForLocation(e.getX(), e.getY()) == -1) {
-                    reverseEngineeringTree.setSelectionRow(-1);
-                }
-
-                if (SwingUtilities.isRightMouseButton(e)) {
-                    if (reverseEngineeringTree.isEditing()) {
-                        return;
-                    }
-                    int row = reverseEngineeringTree.getClosestRowForLocation(e.getX(), e.getY());
-                    reverseEngineeringTree.setSelectionRow(row);
-                    DefaultPopUpMenu popupMenu;
-                    DbImportTreeNode selectedElement;
-                    if (reverseEngineeringTree.getSelectionPath() != null) {
-                        selectedElement = reverseEngineeringTree.getSelectedNode();
-                        popupMenu = popups.get(selectedElement.getUserObject().getClass());
-                    } else {
-                        selectedElement = reverseEngineeringTree.getRootNode();
-                        popupMenu = popups.get(ReverseEngineering.class);
-                    }
-                    if (popupMenu != null) {
-                        popupMenu.setProjectController(projectController);
-                        popupMenu.setSelectedElement(selectedElement);
-                        popupMenu.setParentElement((DbImportTreeNode) selectedElement.getParent());
-                        popupMenu.setTree(reverseEngineeringTree);
-                        popupMenu.show(e.getComponent(), e.getX(), e.getY());
-                    }
-                } else if (reverseEngineeringTree.getSelectionPath() != null) {
-                    DbImportTreeNode findedNode = dbSchemaTree.findNode(
-                            dbSchemaTree.getRootNode(), reverseEngineeringTree.getSelectedNode(), 0
-                    );
-                    if (findedNode != null) {
-                        dbSchemaTree.expandPath(new TreePath(((DbImportTreeNode) findedNode.getParent()).getPath()));
-                        scrollToNode(dbSchemaTree, findedNode);
-                    }
-                }
-            }
-        });
-    }
-
-    private void scrollToNode(JTree tree, DbImportTreeNode node) {
-        TreePath path = new TreePath(node.getPath());
-        tree.scrollPathToVisible(path);
-        DraggableTreePanel parentPanel = ((DraggableTreePanel) dbSchemaTree.getParent().getParent());
-        parentPanel.getHorizontalScrollBar().setValue(0);
-    }
-
-    private ReverseEngineering getReverseEngineeringBySelectedMap() {
-        DataMap dataMap = projectController.getCurrentDataMap();
-        return projectController.getApplication().getMetaData().get(dataMap, ReverseEngineering.class);
-    }
-
-    private void changeIcons() {
-        // Deleting standard tree icons
-        DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) reverseEngineeringTree.getCellRenderer();
-        renderer.setLeafIcon(null);
-        renderer.setClosedIcon(null);
-        renderer.setOpenIcon(null);
-    }
-
-    public DbImportTree getReverseEngineeringTree() {
-        return reverseEngineeringTree;
-    }
-
-    void setTreeToolbar(TreeToolbarPanel treeToolbar) {
-        this.treeToolbar = treeToolbar;
-    }
-}


[13/14] cayenne git commit: Modeler: minor code cleanup

Posted by nt...@apache.org.
Modeler: minor code cleanup


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/dbee2d15
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/dbee2d15
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/dbee2d15

Branch: refs/heads/master
Commit: dbee2d15c48ac176e804e160a1ebacb28f2b5575
Parents: da66ff9
Author: Nikita Timofeev <st...@gmail.com>
Authored: Wed Mar 28 13:57:51 2018 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Wed Mar 28 13:57:51 2018 +0300

----------------------------------------------------------------------
 .../dialog/pref/DataSourcePreferences.java      |  9 ++--
 .../dialog/pref/DataSourcePreferencesView.java  |  6 +--
 .../modeler/dialog/pref/GeneralPreferences.java |  7 +--
 .../modeler/dialog/pref/PreferenceDialog.java   | 57 +++++++-------------
 .../dialog/pref/PreferenceDialogView.java       |  4 +-
 5 files changed, 30 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/dbee2d15/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DataSourcePreferences.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DataSourcePreferences.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DataSourcePreferences.java
index 149fb8d..4dd8d8f 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DataSourcePreferences.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DataSourcePreferences.java
@@ -77,7 +77,7 @@ public class DataSourcePreferences extends CayenneController {
 
 		Object[] keys = dataSources.keySet().toArray();
 		Arrays.sort(keys);
-		DefaultComboBoxModel dataSourceModel = new DefaultComboBoxModel(keys);
+		DefaultComboBoxModel<Object> dataSourceModel = new DefaultComboBoxModel<>(keys);
 		view.getDataSources().setModel(dataSourceModel);
 
 		initBindings();
@@ -124,7 +124,6 @@ public class DataSourcePreferences extends CayenneController {
 	 * Shows a dialog to create new local DataSource configuration.
 	 */
 	public void newDataSourceAction() {
-
 		DataSourceCreator creatorWizard = new DataSourceCreator(this);
 		DBConnectionInfo dataSource = creatorWizard.startupAction();
 
@@ -134,7 +133,7 @@ public class DataSourcePreferences extends CayenneController {
 
 			Object[] keys = dataSources.keySet().toArray();
 			Arrays.sort(keys);
-			view.getDataSources().setModel(new DefaultComboBoxModel(keys));
+			view.getDataSources().setModel(new DefaultComboBoxModel<>(keys));
 			view.getDataSources().setSelectedItem(creatorWizard.getName());
 			editDataSourceAction();
 			fireEvent(creatorWizard.getName(), MapEvent.ADD);
@@ -156,7 +155,7 @@ public class DataSourcePreferences extends CayenneController {
 
 				Object[] keys = dataSources.keySet().toArray();
 				Arrays.sort(keys);
-				view.getDataSources().setModel(new DefaultComboBoxModel(keys));
+				view.getDataSources().setModel(new DefaultComboBoxModel<>(keys));
 				view.getDataSources().setSelectedItem(wizard.getName());
 				editDataSourceAction();
 				fireEvent(wizard.getName(), MapEvent.ADD);
@@ -175,7 +174,7 @@ public class DataSourcePreferences extends CayenneController {
 			dataSources = dataSourcePreferences.getChildrenPreferences();
 			Object[] keys = dataSources.keySet().toArray();
 			Arrays.sort(keys);
-			view.getDataSources().setModel(new DefaultComboBoxModel(keys));
+			view.getDataSources().setModel(new DefaultComboBoxModel<>(keys));
 			editDataSourceAction(keys.length > 0 ? keys[0] : null);
 			fireEvent(key, MapEvent.REMOVE);
 		}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dbee2d15/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DataSourcePreferencesView.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DataSourcePreferencesView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DataSourcePreferencesView.java
index 268dfed..f62f95c 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DataSourcePreferencesView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/DataSourcePreferencesView.java
@@ -40,7 +40,7 @@ public class DataSourcePreferencesView extends JPanel {
     protected JButton duplicateDataSource;
     protected JButton removeDataSource;
     protected JButton testDataSource;
-    protected JComboBox dataSources;
+    protected JComboBox<Object> dataSources;
     protected DBConnectionInfoEditor dataSourceEditor;
 
     public DataSourcePreferencesView(CayenneController controller) {
@@ -48,7 +48,7 @@ public class DataSourcePreferencesView extends JPanel {
         this.duplicateDataSource = new JButton("Duplicate...");
         this.removeDataSource = new JButton("Delete");
         this.testDataSource = new JButton("Test...");
-        this.dataSources = new JComboBox();
+        this.dataSources = new JComboBox<>();
         this.dataSourceEditor = new DBConnectionInfoEditor(controller);
 
         // assemble
@@ -74,7 +74,7 @@ public class DataSourcePreferencesView extends JPanel {
         return dataSourceEditor;
     }
 
-    public JComboBox getDataSources() {
+    public JComboBox<Object> getDataSources() {
         return dataSources;
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dbee2d15/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/GeneralPreferences.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/GeneralPreferences.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/GeneralPreferences.java
index f1af77e..288b278 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/GeneralPreferences.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/GeneralPreferences.java
@@ -82,7 +82,6 @@ public class GeneralPreferences extends CayenneController {
 		preferences = application.getPreferencesNode(GeneralPreferences.class, "");
 
 		this.encoding = preferences.get(ENCODING_PREFERENCE, null);
-
 		this.autoLoadProjectPreference = preferences.getBoolean(AUTO_LOAD_PROJECT_PREFERENCE, false);
 		this.deletePromptPreference = preferences.getBoolean(DELETE_PROMPT_PREFERENCE, false);
 
@@ -91,12 +90,8 @@ public class GeneralPreferences extends CayenneController {
 
 		// create bindings...
 		BindingBuilder builder = new BindingBuilder(getApplication().getBindingFactory(), this);
-
-		this.encodingBinding = builder.bindToProperty(encodingSelector, "encoding",
-				EncodingSelector.ENCODING_PROPERTY_BINDING);
-
+		this.encodingBinding = builder.bindToProperty(encodingSelector, "encoding", EncodingSelector.ENCODING_PROPERTY_BINDING);
 		this.autoLoadProjectBinding = builder.bindToCheckBox(view.getAutoLoadProject(), "autoLoadProject");
-
 		this.deletePromptBinding = builder.bindToCheckBox(view.getDeletePrompt(), "deletePrompt");
 	}
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dbee2d15/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/PreferenceDialog.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/PreferenceDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/PreferenceDialog.java
index 2c16140..6ade6f9 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/PreferenceDialog.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/PreferenceDialog.java
@@ -53,17 +53,19 @@ public class PreferenceDialog extends CayenneController {
     };
 
     protected PreferenceDialogView view;
-    protected Map detailControllers;
+    protected Map<String, CayenneController> detailControllers;
     protected PreferenceEditor editor;
 
     public PreferenceDialog(CayenneController parent) {
         super(parent);
 
-        Window parentView = parent.getView() instanceof Window ? (Window) parent.getView() : 
-            SwingUtilities.getWindowAncestor(parent.getView());
-        this.view = (parentView instanceof Dialog) ? new PreferenceDialogView(
-                (Dialog) parentView) : new PreferenceDialogView((Frame) parentView);
-        this.detailControllers = new HashMap();
+        Window parentView = parent.getView() instanceof Window
+                ? (Window) parent.getView()
+                : SwingUtilities.getWindowAncestor(parent.getView());
+        this.view = (parentView instanceof Dialog)
+                ? new PreferenceDialogView((Dialog) parentView)
+                : new PreferenceDialogView((Frame) parentView);
+        this.detailControllers = new HashMap<>();
 
         // editor must be configured before startup for "showDetailViewAction()" to work
         this.editor = new CayenneModelerPreferenceEditor(application);
@@ -72,33 +74,19 @@ public class PreferenceDialog extends CayenneController {
     }
 
     protected void initBindings() {
-        final JList list = view.getList();
+        final JList<String> list = view.getList();
         list.setListData(preferenceMenus);
-        list.addListSelectionListener(new ListSelectionListener() {
-
-            public void valueChanged(ListSelectionEvent e) {
-                Object selection = list.getSelectedValue();
-                if (selection != null) {
-                    view.getDetailLayout().show(
-                            view.getDetailPanel(),
-                            selection.toString());
-                }
-            }
-        });
-
-        view.getCancelButton().addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                cancelAction();
-            }
-        });
-
-        view.getSaveButton().addActionListener(new ActionListener() {
-
-            public void actionPerformed(ActionEvent e) {
-                savePreferencesAction();
-            }
-        });
+        list.addListSelectionListener(e -> updateSelection());
+
+        view.getCancelButton().addActionListener(e -> cancelAction());
+        view.getSaveButton().addActionListener(e -> savePreferencesAction());
+    }
+
+    public void updateSelection() {
+        String selection = view.getList().getSelectedValue();
+        if (selection != null) {
+            view.getDetailLayout().show(view.getDetailPanel(), selection);
+        }
     }
 
     public void cancelAction() {
@@ -108,9 +96,6 @@ public class PreferenceDialog extends CayenneController {
 
     public void savePreferencesAction() {
         editor.save();
-
-        // update
-
         view.dispose();
     }
 
@@ -131,7 +116,6 @@ public class PreferenceDialog extends CayenneController {
     }
 
     public void startupAction(String key) {
-
         if (key == null) {
             key = GENERAL_KEY;
         }
@@ -148,7 +132,6 @@ public class PreferenceDialog extends CayenneController {
         registerPanel(CLASS_PATH_KEY, new ClasspathPreferences(this));
         registerPanel(TEMPLATES_KEY, new TemplatePreferences(this));
         view.getDetailLayout().show(view.getDetailPanel(), GENERAL_KEY);
-        // view.getSplit().setDividerLocation(150);
         view.pack();
 
         // show

http://git-wip-us.apache.org/repos/asf/cayenne/blob/dbee2d15/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/PreferenceDialogView.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/PreferenceDialogView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/PreferenceDialogView.java
index 8e28641..f753ebd 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/PreferenceDialogView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/PreferenceDialogView.java
@@ -45,7 +45,7 @@ import javax.swing.JSplitPane;
 public class PreferenceDialogView extends JDialog {
 
     protected JSplitPane split;
-    protected JList<Object> list;
+    protected JList<String> list;
     protected CardLayout detailLayout;
     protected Container detailPanel;
     protected JButton cancelButton;
@@ -102,7 +102,7 @@ public class PreferenceDialogView extends JDialog {
         setTitle("Edit Preferences");
     }
 
-    public JList getList() {
+    public JList<String> getList() {
         return list;
     }