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

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

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ead78b6/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/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();
-    }
-}