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 2017/02/01 09:29:28 UTC

[1/4] cayenne git commit: CAY-2215 move all DbImport code from cayenne-tools and cayenne-server modules to cayenne-dbsync module

Repository: cayenne
Updated Branches:
  refs/heads/master 67bf710b7 -> 660dd4b28


http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DefaultDbImportActionTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DefaultDbImportActionTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DefaultDbImportActionTest.java
deleted file mode 100644
index 42ff6e9..0000000
--- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DefaultDbImportActionTest.java
+++ /dev/null
@@ -1,356 +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.tools.dbimport;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.configuration.server.DataSourceFactory;
-import org.apache.cayenne.configuration.server.DbAdapterFactory;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dbsync.DbSyncModule;
-import org.apache.cayenne.dbsync.filter.NamePatternMatcher;
-import org.apache.cayenne.dbsync.merge.builders.DataMapBuilder;
-import org.apache.cayenne.dbsync.merge.factory.DefaultMergerTokenFactory;
-import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
-import org.apache.cayenne.dbsync.merge.token.MergerToken;
-import org.apache.cayenne.dbsync.merge.token.db.CreateTableToDb;
-import org.apache.cayenne.dbsync.merge.token.model.AddColumnToModel;
-import org.apache.cayenne.dbsync.merge.token.model.AddRelationshipToModel;
-import org.apache.cayenne.dbsync.merge.token.model.CreateTableToModel;
-import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
-import org.apache.cayenne.dbsync.naming.NoStemStemmer;
-import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
-import org.apache.cayenne.dbsync.reverse.dbload.DbLoader;
-import org.apache.cayenne.dbsync.reverse.dbload.DbLoaderConfiguration;
-import org.apache.cayenne.dbsync.reverse.dbload.DbLoaderDelegate;
-import org.apache.cayenne.dbsync.reverse.dbload.DefaultModelMergeDelegate;
-import org.apache.cayenne.di.DIBootstrap;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.MapLoader;
-import org.apache.cayenne.project.FileProjectSaver;
-import org.apache.cayenne.project.Project;
-import org.apache.cayenne.resource.URLResource;
-import org.apache.cayenne.tools.configuration.ToolsModule;
-import org.apache.cayenne.util.Util;
-import org.apache.commons.logging.Log;
-import org.junit.Before;
-import org.junit.Test;
-import org.xml.sax.InputSource;
-
-import javax.sql.DataSource;
-import java.io.File;
-import java.net.URL;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.LinkedList;
-import java.util.List;
-
-import static java.util.Arrays.asList;
-import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbAttr;
-import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbEntity;
-import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.objAttr;
-import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.objEntity;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.stub;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class DefaultDbImportActionTest {
-
-    public static final File FILE_STUB = new File("") {
-        @Override
-        public boolean exists() {
-            return true;
-        }
-
-        @Override
-        public boolean canRead() {
-            return true;
-        }
-    };
-
-    private DbAdapter mockAdapter;
-    private Connection mockConnection;
-    private DbLoaderDelegate mockDelegate;
-    private ObjectNameGenerator mockNameGenerator;
-
-    @Before
-    public void before() {
-        mockAdapter = mock(DbAdapter.class);
-        mockConnection = mock(Connection.class);
-        mockDelegate = mock(DbLoaderDelegate.class);
-        mockNameGenerator = mock(ObjectNameGenerator.class);
-    }
-
-    @Test
-    public void testNewDataMapImport() throws Exception {
-
-        DbImportConfiguration config = mock(DbImportConfiguration.class);
-        when(config.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
-        when(config.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
-        when(config.getTargetDataMap()).thenReturn(new File("xyz.map.xml"));
-        when(config.createNameGenerator()).thenReturn(new DefaultObjectNameGenerator(NoStemStemmer.getInstance()));
-        when(config.createMeaningfulPKFilter()).thenReturn(NamePatternMatcher.EXCLUDE_ALL);
-
-        DbLoader dbLoader = new DbLoader(mockAdapter, mockConnection, config.getDbLoaderConfig(), mockDelegate, mockNameGenerator) {
-            @Override
-            public DataMap load() throws SQLException {
-                DataMap map = new DataMap();
-                new DataMapBuilder(map).withDbEntities(2).build();
-                return map;
-            }
-        };
-
-        final boolean[] haveWeTriedToSave = {false};
-        DefaultDbImportAction action = buildDbImportAction(new FileProjectSaver() {
-            @Override
-            public void save(Project project) {
-                haveWeTriedToSave[0] = true;
-
-                // Validation phase
-                assertTrue(project.getRootNode() instanceof DataMap);
-            }
-        }, null, dbLoader);
-
-        action.execute(config);
-
-        assertTrue("We should try to save.", haveWeTriedToSave[0]);
-    }
-
-    @Test
-    public void testImportWithFieldChanged() throws Exception {
-
-        DbImportConfiguration config = mock(DbImportConfiguration.class);
-
-        when(config.getTargetDataMap()).thenReturn(FILE_STUB);
-        when(config.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
-        when(config.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
-        when(config.createNameGenerator()).thenReturn(new DefaultObjectNameGenerator(NoStemStemmer.getInstance()));
-        when(config.createMeaningfulPKFilter()).thenReturn(NamePatternMatcher.EXCLUDE_ALL);
-
-        DbLoader dbLoader = new DbLoader(mockAdapter, mockConnection, config.getDbLoaderConfig(), mockDelegate, mockNameGenerator) {
-            @Override
-            public DataMap load() throws SQLException {
-                DataMap dataMap = new DataMap();
-                new DataMapBuilder(dataMap).with(
-                        dbEntity("ARTGROUP").attributes(
-                                dbAttr("GROUP_ID").typeInt().primaryKey(),
-                                dbAttr("NAME").typeVarchar(100).mandatory(),
-                                dbAttr("NAME_01").typeVarchar(100).mandatory(),
-                                dbAttr("PARENT_GROUP_ID").typeInt()
-                        )).with(
-                        objEntity("org.apache.cayenne.testdo.testmap", "ArtGroup", "ARTGROUP").attributes(
-                                objAttr("name").type(String.class).dbPath("NAME")
-                        ));
-                return dataMap;
-            }
-        };
-
-        final boolean[] haveWeTriedToSave = {false};
-        DefaultDbImportAction action = buildDbImportAction(
-            new FileProjectSaver() {
-                @Override
-                public void save(Project project) {
-                    haveWeTriedToSave[0] = true;
-
-                    // Validation phase
-                    DataMap rootNode = (DataMap) project.getRootNode();
-                    assertEquals(1, rootNode.getObjEntities().size());
-                    assertEquals(1, rootNode.getDbEntityMap().size());
-
-                    DbEntity entity = rootNode.getDbEntity("ARTGROUP");
-                    assertNotNull(entity);
-                    assertEquals(4, entity.getAttributes().size());
-                    assertNotNull(entity.getAttribute("NAME_01"));
-                }
-            },
-
-            new MapLoader() {
-                @Override
-                public synchronized DataMap loadDataMap(InputSource src) throws CayenneRuntimeException {
-                    return new DataMapBuilder().with(
-                            dbEntity("ARTGROUP").attributes(
-                                    dbAttr("GROUP_ID").typeInt().primaryKey(),
-                                    dbAttr("NAME").typeVarchar(100).mandatory(),
-                                    dbAttr("PARENT_GROUP_ID").typeInt()
-                            )).with(
-                            objEntity("org.apache.cayenne.testdo.testmap", "ArtGroup", "ARTGROUP").attributes(
-                                    objAttr("name").type(String.class).dbPath("NAME")
-                            )).build();
-                }
-            },
-            dbLoader
-        );
-
-        action.execute(config);
-
-        assertTrue("We should try to save.", haveWeTriedToSave[0]);
-    }
-
-    @Test
-    public void testImportWithoutChanges() throws Exception {
-        DbImportConfiguration config = mock(DbImportConfiguration.class);
-        when(config.getTargetDataMap()).thenReturn(FILE_STUB);
-        when(config.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
-        when(config.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
-
-        DbLoader dbLoader = new DbLoader(mockAdapter, mockConnection, config.getDbLoaderConfig(), mockDelegate, mockNameGenerator) {
-            @Override
-            public DataMap load() throws SQLException {
-                DataMap dataMap = new DataMap();
-                new DataMapBuilder(dataMap).with(
-                        dbEntity("ARTGROUP").attributes(
-                                dbAttr("NAME").typeVarchar(100).mandatory()
-                        ));
-                return dataMap;
-            }
-        };
-
-        FileProjectSaver projectSaver = mock(FileProjectSaver.class);
-        doNothing().when(projectSaver).save(any(Project.class));
-
-        MapLoader mapLoader = mock(MapLoader.class);
-        stub(mapLoader.loadDataMap(any(InputSource.class))).toReturn(new DataMapBuilder().with(
-                dbEntity("ARTGROUP").attributes(
-                        dbAttr("NAME").typeVarchar(100).mandatory()
-                )).build());
-
-        DefaultDbImportAction action = buildDbImportAction(projectSaver, mapLoader, dbLoader);
-
-        action.execute(config);
-
-        // no changes - we still
-        verify(projectSaver, never()).save(any(Project.class));
-        verify(mapLoader, times(1)).loadDataMap(any(InputSource.class));
-    }
-
-    @Test
-    public void testImportWithDbError() throws Exception {
-        DbLoader dbLoader = mock(DbLoader.class);
-        doThrow(new SQLException()).when(dbLoader).load();
-
-        DbImportConfiguration params = mock(DbImportConfiguration.class);
-
-        FileProjectSaver projectSaver = mock(FileProjectSaver.class);
-        doNothing().when(projectSaver).save(any(Project.class));
-
-        MapLoader mapLoader = mock(MapLoader.class);
-        when(mapLoader.loadDataMap(any(InputSource.class))).thenReturn(null);
-
-        DefaultDbImportAction action = buildDbImportAction(projectSaver, mapLoader, dbLoader);
-
-        try {
-            action.execute(params);
-            fail();
-        } catch (SQLException e) {
-            // expected
-        }
-
-        verify(projectSaver, never()).save(any(Project.class));
-        verify(mapLoader, never()).loadDataMap(any(InputSource.class));
-    }
-
-    private DefaultDbImportAction buildDbImportAction(FileProjectSaver projectSaver, MapLoader mapLoader, final DbLoader dbLoader)
-            throws Exception {
-
-        Log log = mock(Log.class);
-        when(log.isDebugEnabled()).thenReturn(true);
-        when(log.isInfoEnabled()).thenReturn(true);
-
-        DbAdapter dbAdapter = mock(DbAdapter.class);
-
-        DbAdapterFactory adapterFactory = mock(DbAdapterFactory.class);
-        when(adapterFactory.createAdapter(any(DataNodeDescriptor.class), any(DataSource.class))).thenReturn(dbAdapter);
-
-        DataSourceFactory dataSourceFactory = mock(DataSourceFactory.class);
-        DataSource mock = mock(DataSource.class);
-        when(dataSourceFactory.getDataSource(any(DataNodeDescriptor.class))).thenReturn(mock);
-
-        MergerTokenFactoryProvider mergerTokenFactoryProvider = mock(MergerTokenFactoryProvider.class);
-        when(mergerTokenFactoryProvider.get(any(DbAdapter.class))).thenReturn(new DefaultMergerTokenFactory());
-
-        return new DefaultDbImportAction(log, projectSaver, dataSourceFactory, adapterFactory, mapLoader, mergerTokenFactoryProvider) {
-
-            protected DbLoader createDbLoader(DbAdapter adapter,
-                                               Connection connection,
-                                               DbImportConfiguration config) {
-                return dbLoader;
-            }
-        };
-    }
-
-    @Test
-    public void testSaveLoaded() throws Exception {
-        Log log = mock(Log.class);
-        Injector i = DIBootstrap.createInjector(new DbSyncModule(), new ToolsModule(log), new DbImportModule());
-
-        DefaultDbImportAction action = (DefaultDbImportAction) i.getInstance(DbImportAction.class);
-
-        String packagePath = getClass().getPackage().getName().replace('.', '/');
-        URL packageUrl = getClass().getClassLoader().getResource(packagePath);
-        assertNotNull(packageUrl);
-        URL outUrl = new URL(packageUrl, "dbimport/testSaveLoaded1.map.xml");
-
-        File out = new File(outUrl.toURI());
-        out.delete();
-        assertFalse(out.isFile());
-
-        DataMap map = new DataMap("testSaveLoaded1");
-        map.setConfigurationSource(new URLResource(outUrl));
-
-        action.saveLoaded(map);
-
-        assertTrue(out.isFile());
-
-        String contents = Util.stringFromFile(out);
-        assertTrue("Has no project version saved", contents.contains("project-version=\""));
-    }
-
-    @Test
-    public void testMergeTokensSorting() {
-        LinkedList<MergerToken> tokens = new LinkedList<MergerToken>();
-        tokens.add(new AddColumnToModel(null, null));
-        tokens.add(new AddRelationshipToModel(null, null));
-        tokens.add(new CreateTableToDb(null));
-        tokens.add(new CreateTableToModel(null));
-
-        assertEquals(asList("CreateTableToDb", "CreateTableToModel", "AddColumnToModel", "AddRelationshipToModel"),
-                toClasses(DefaultDbImportAction.sort(tokens)));
-    }
-
-    private List<String> toClasses(List<MergerToken> sort) {
-        LinkedList<String> res = new LinkedList<String>();
-        for (MergerToken mergerToken : sort) {
-            res.add(mergerToken.getClass().getSimpleName());
-        }
-        return res;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntityTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntityTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntityTest.java
deleted file mode 100644
index 297dd14..0000000
--- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntityTest.java
+++ /dev/null
@@ -1,115 +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.tools.dbimport;
-
-import org.apache.cayenne.configuration.ConfigurationNameMapper;
-import org.apache.cayenne.configuration.ConfigurationTree;
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.DataMapLoader;
-import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
-import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader;
-import org.apache.cayenne.configuration.XMLDataMapLoader;
-import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
-import org.apache.cayenne.dbsync.naming.NoStemStemmer;
-import org.apache.cayenne.di.AdhocObjectFactory;
-import org.apache.cayenne.di.Binder;
-import org.apache.cayenne.di.ClassLoaderManager;
-import org.apache.cayenne.di.DIBootstrap;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.di.Module;
-import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
-import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.Relationship;
-import org.apache.cayenne.resource.URLResource;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.net.URL;
-import java.util.ArrayList;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-public class ManyToManyCandidateEntityTest {
-
-    private DataMap map;
-
-    @Before
-    public void setUp() throws Exception {
-        Module testModule = new Module() {
-
-            public void configure(Binder binder) {
-                binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
-                binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
-                binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
-                binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-            }
-        };
-
-        Injector injector = DIBootstrap.createInjector(testModule);
-
-        // create and initialize loader instance to test
-        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
-        injector.injectMembers(loader);
-
-        String testConfigName = "relationship-optimisation";
-        URL url = getClass().getResource("cayenne-" + testConfigName + ".xml");
-
-        ConfigurationTree<DataChannelDescriptor> tree = loader.load(new URLResource(url));
-
-        map = tree.getRootNode().getDataMap(testConfigName);
-    }
-
-    @Test
-    public void testMatchingForManyToManyEntity() throws Exception {
-        ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
-
-        assertNotNull(ManyToManyCandidateEntity.build(manyToManyEntity));
-    }
-
-    @Test
-    public void testMatchingForNotManyToManyEntity() throws Exception {
-        ObjEntity entity = map.getObjEntity("Table1");
-
-        assertNull(ManyToManyCandidateEntity.build(entity));
-    }
-
-    @Test
-    public void testOptimisationForManyToManyEntity() {
-        ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
-
-        ManyToManyCandidateEntity.build(manyToManyEntity).optimizeRelationships(
-                new DefaultObjectNameGenerator(NoStemStemmer.getInstance()));
-
-        ObjEntity table1Entity = map.getObjEntity("Table1");
-        ObjEntity table2Entity = map.getObjEntity("Table2");
-
-        assertEquals(1, table1Entity.getRelationships().size());
-        assertEquals(table2Entity, new ArrayList<Relationship>(table1Entity.getRelationships()).get(0)
-                .getTargetEntity());
-
-        assertEquals(1, table2Entity.getRelationships().size());
-        assertEquals(table1Entity, new ArrayList<Relationship>(table2Entity.getRelationships()).get(0)
-                .getTargetEntity());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/cayenne-relationship-optimisation.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/cayenne-relationship-optimisation.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/cayenne-relationship-optimisation.xml
deleted file mode 100644
index d4fea49..0000000
--- a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/cayenne-relationship-optimisation.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<domain project-version="6">
-	<map name="relationship-optimisation"/>
-</domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/relationship-optimisation.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/relationship-optimisation.map.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/relationship-optimisation.map.xml
deleted file mode 100644
index e68645f..0000000
--- a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/relationship-optimisation.map.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
-	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/3.0/modelMap http://cayenne.apache.org/schema/3.0/modelMap.xsd"
-	 project-version="6">
-	<property name="defaultPackage" value="com.objectstyle"/>
-	<db-entity name="table1" catalog="many_to_many_test">
-		<db-attribute name="id1" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
-		<db-attribute name="table1col" type="VARCHAR" length="45"/>
-	</db-entity>
-	<db-entity name="table1_table2" catalog="many_to_many_test">
-		<db-attribute name="fk1" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
-		<db-attribute name="fk2" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
-	</db-entity>
-	<db-entity name="table2" catalog="many_to_many_test">
-		<db-attribute name="id2" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
-		<db-attribute name="table2col" type="VARCHAR" length="45"/>
-	</db-entity>
-	<obj-entity name="Table1" className="com.objectstyle.Table1" dbEntityName="table1">
-		<obj-attribute name="table1col" type="java.lang.String" db-attribute-path="table1col"/>
-	</obj-entity>
-	<obj-entity name="Table1Table2" className="com.objectstyle.Table1Table2" dbEntityName="table1_table2">
-	</obj-entity>
-	<obj-entity name="Table2" className="com.objectstyle.Table2" dbEntityName="table2">
-		<obj-attribute name="table2col" type="java.lang.String" db-attribute-path="table2col"/>
-	</obj-entity>
-	<db-relationship name="table1Table2Array" source="table1" target="table1_table2" toDependentPK="true" toMany="true">
-		<db-attribute-pair source="id1" target="fk1"/>
-	</db-relationship>
-	<db-relationship name="toTable1" source="table1_table2" target="table1" toMany="false">
-		<db-attribute-pair source="fk1" target="id1"/>
-	</db-relationship>
-	<db-relationship name="toTable2" source="table1_table2" target="table2" toMany="false">
-		<db-attribute-pair source="fk2" target="id2"/>
-	</db-relationship>
-	<db-relationship name="table1Table2Array" source="table2" target="table1_table2" toDependentPK="true" toMany="true">
-		<db-attribute-pair source="id2" target="fk2"/>
-	</db-relationship>
-	<obj-relationship name="table1Table2Array" source="Table1" target="Table1Table2" deleteRule="Deny" db-relationship-path="table1Table2Array"/>
-	<obj-relationship name="toTable1" source="Table1Table2" target="Table1" deleteRule="Nullify" db-relationship-path="toTable1"/>
-	<obj-relationship name="toTable2" source="Table1Table2" target="Table2" deleteRule="Nullify" db-relationship-path="toTable2"/>
-	<obj-relationship name="table1Table2Array" source="Table2" target="Table1Table2" deleteRule="Deny" db-relationship-path="table1Table2Array"/>
-</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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 d11691a..2fb85a0 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,13 +25,14 @@ import javax.swing.JOptionPane;
 import javax.swing.SwingUtilities;
 
 import org.apache.cayenne.configuration.ConfigurationNode;
-import org.apache.cayenne.dbimport.Catalog;
-import org.apache.cayenne.dbimport.ExcludeTable;
-import org.apache.cayenne.dbimport.IncludeProcedure;
-import org.apache.cayenne.dbimport.IncludeTable;
-import org.apache.cayenne.dbimport.ReverseEngineering;
-import org.apache.cayenne.dbimport.Schema;
 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;
@@ -39,7 +40,6 @@ 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.pref.DBConnectionInfo;
-import org.apache.cayenne.tools.dbimport.DbImportConfiguration;
 import org.apache.cayenne.util.Util;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/LoadDataMapTask.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/LoadDataMapTask.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/LoadDataMapTask.java
index d592385..f0576ea 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/LoadDataMapTask.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/LoadDataMapTask.java
@@ -26,9 +26,9 @@ import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.modeler.util.LongRunningTask;
 import org.apache.cayenne.modeler.util.ProjectUtil;
-import org.apache.cayenne.tools.configuration.ToolsModule;
-import org.apache.cayenne.tools.dbimport.DbImportAction;
-import org.apache.cayenne.tools.dbimport.DbImportModule;
+import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportAction;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportModule;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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 34ad1b5..bf74a0c 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
@@ -25,8 +25,8 @@ import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.project.ProjectSaver;
-import org.apache.cayenne.tools.dbimport.DbImportConfiguration;
-import org.apache.cayenne.tools.dbimport.DefaultDbImportAction;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfiguration;
+import org.apache.cayenne.dbsync.reverse.dbimport.DefaultDbImportAction;
 import org.apache.commons.logging.Log;
 
 import java.io.IOException;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerSyncModule.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerSyncModule.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerSyncModule.java
index 24fdfcf..e4a7975 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerSyncModule.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerSyncModule.java
@@ -24,7 +24,7 @@ import org.apache.cayenne.di.Module;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.project.ProjectSaver;
-import org.apache.cayenne.tools.dbimport.DbImportAction;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportAction;
 
 class ModelerSyncModule implements Module {
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/merge/MergerOptions.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/merge/MergerOptions.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/merge/MergerOptions.java
index 26564a3..3bb67f1 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/merge/MergerOptions.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/merge/MergerOptions.java
@@ -22,21 +22,22 @@ package org.apache.cayenne.modeler.dialog.db.merge;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.configuration.event.DataMapEvent;
 import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dbsync.merge.token.db.AbstractToDbToken;
 import org.apache.cayenne.dbsync.merge.DataMapMerger;
-import org.apache.cayenne.dbsync.reverse.dbload.DefaultModelMergeDelegate;
 import org.apache.cayenne.dbsync.merge.context.MergeDirection;
 import org.apache.cayenne.dbsync.merge.context.MergerContext;
-import org.apache.cayenne.dbsync.merge.token.MergerToken;
-import org.apache.cayenne.dbsync.reverse.dbload.ModelMergeDelegate;
-import org.apache.cayenne.dbsync.reverse.dbload.ProxyModelMergeDelegate;
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
+import org.apache.cayenne.dbsync.merge.token.MergerToken;
+import org.apache.cayenne.dbsync.merge.token.db.AbstractToDbToken;
 import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
 import org.apache.cayenne.dbsync.naming.NoStemStemmer;
+import org.apache.cayenne.dbsync.reverse.dbimport.DefaultDbImportAction;
 import org.apache.cayenne.dbsync.reverse.dbload.DbLoader;
 import org.apache.cayenne.dbsync.reverse.dbload.DbLoaderConfiguration;
+import org.apache.cayenne.dbsync.reverse.dbload.DefaultModelMergeDelegate;
 import org.apache.cayenne.dbsync.reverse.dbload.LoggingDbLoaderDelegate;
+import org.apache.cayenne.dbsync.reverse.dbload.ModelMergeDelegate;
+import org.apache.cayenne.dbsync.reverse.dbload.ProxyModelMergeDelegate;
 import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
 import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
 import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
@@ -52,7 +53,6 @@ import org.apache.cayenne.project.Project;
 import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.swing.BindingBuilder;
 import org.apache.cayenne.swing.ObjectBinding;
-import org.apache.cayenne.tools.dbimport.DefaultDbImportAction;
 import org.apache.cayenne.validation.ValidationResult;
 import org.apache.commons.logging.LogFactory;
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/plugins/cayenne-maven-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/cayenne-maven-plugin/pom.xml b/plugins/cayenne-maven-plugin/pom.xml
index 1c2e6ea..eb5c4db 100644
--- a/plugins/cayenne-maven-plugin/pom.xml
+++ b/plugins/cayenne-maven-plugin/pom.xml
@@ -146,7 +146,7 @@
 
 		<dependency>
 			<groupId>org.apache.cayenne</groupId>
-			<artifactId>cayenne-tools</artifactId>
+			<artifactId>cayenne-dbsync</artifactId>
 			<version>${project.version}</version>
 			<scope>test</scope>
 			<type>test-jar</type>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java
----------------------------------------------------------------------
diff --git a/plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java b/plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java
index f951cb5..0ef8a1c 100644
--- a/plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java
+++ b/plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java
@@ -30,7 +30,7 @@ import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.log.NoopJdbcEventLogger;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.MapLoader;
-import org.apache.cayenne.tools.configuration.ToolsModule;
+import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
 import org.apache.cayenne.util.Util;
 import org.apache.commons.logging.Log;
 import org.apache.maven.plugin.AbstractMojo;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
----------------------------------------------------------------------
diff --git a/plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java b/plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
index 9c9cddf..e473c37 100644
--- a/plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
+++ b/plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
@@ -18,15 +18,16 @@
  ****************************************************************/
 package org.apache.cayenne.tools;
 
-import org.apache.cayenne.dbimport.ReverseEngineering;
 import org.apache.cayenne.dbsync.DbSyncModule;
+import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportAction;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfiguration;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfigurationValidator;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportModule;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
 import org.apache.cayenne.dbsync.reverse.filters.FiltersConfigBuilder;
 import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.tools.configuration.ToolsModule;
-import org.apache.cayenne.tools.dbimport.DbImportAction;
-import org.apache.cayenne.tools.dbimport.DbImportConfiguration;
-import org.apache.cayenne.tools.dbimport.DbImportModule;
 import org.apache.cayenne.util.Util;
 import org.apache.commons.logging.Log;
 import org.apache.maven.plugin.AbstractMojo;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java
----------------------------------------------------------------------
diff --git a/plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java b/plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java
index af6219a..e904216 100644
--- a/plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java
+++ b/plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java
@@ -18,13 +18,13 @@
  ****************************************************************/
 package org.apache.cayenne.tools;
 
-import org.apache.cayenne.dbimport.Catalog;
-import org.apache.cayenne.dbimport.Schema;
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfiguration;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
 import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
 import org.apache.cayenne.dbsync.reverse.filters.IncludeTableFilter;
 import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
 import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
-import org.apache.cayenne.tools.dbimport.DbImportConfiguration;
 import org.apache.commons.logging.Log;
 import org.apache.maven.plugin.testing.AbstractMojoTestCase;
 import org.junit.Test;
@@ -34,7 +34,7 @@ import java.util.Map;
 import java.util.TreeSet;
 import java.util.regex.Pattern;
 
-import static org.apache.cayenne.dbimport.ReverseEngineeringUtils.*;
+import static org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineeringUtils.*;
 import static org.mockito.Mockito.mock;
 
 public class DbImporterMojoConfigurationTest extends AbstractMojoTestCase {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
----------------------------------------------------------------------
diff --git a/plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java b/plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
index 7d8cbfe..a99f309 100644
--- a/plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
+++ b/plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
@@ -18,12 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.tools;
 
-import org.apache.cayenne.dbimport.Catalog;
-import org.apache.cayenne.dbimport.IncludeTable;
-import org.apache.cayenne.dbimport.Schema;
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfiguration;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
 import org.apache.cayenne.test.jdbc.SQLReader;
 import org.apache.cayenne.test.resource.ResourceUtil;
-import org.apache.cayenne.tools.dbimport.DbImportConfiguration;
 import org.apache.commons.logging.Log;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.testing.AbstractMojoTestCase;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/plugins/maven-cayenne-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/pom.xml b/plugins/maven-cayenne-plugin/pom.xml
index ccd20ab..d762d0d 100644
--- a/plugins/maven-cayenne-plugin/pom.xml
+++ b/plugins/maven-cayenne-plugin/pom.xml
@@ -124,7 +124,7 @@
 
         <dependency>
             <groupId>org.apache.cayenne</groupId>
-            <artifactId>cayenne-tools</artifactId>
+            <artifactId>cayenne-dbsync</artifactId>
             <version>${project.version}</version>
             <scope>test</scope>
             <type>test-jar</type>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterOldMojoConfigurationTest.java
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterOldMojoConfigurationTest.java b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterOldMojoConfigurationTest.java
index 48549dd..a14a6b3 100644
--- a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterOldMojoConfigurationTest.java
+++ b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterOldMojoConfigurationTest.java
@@ -24,17 +24,17 @@ import java.util.Map;
 import java.util.TreeSet;
 import java.util.regex.Pattern;
 
-import org.apache.cayenne.dbimport.Catalog;
-import org.apache.cayenne.dbimport.Schema;
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfiguration;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
 import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
 import org.apache.cayenne.dbsync.reverse.filters.IncludeTableFilter;
 import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
 import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
-import org.apache.cayenne.tools.dbimport.DbImportConfiguration;
 import org.apache.commons.logging.Log;
 import org.apache.maven.plugin.testing.AbstractMojoTestCase;
 
-import static org.apache.cayenne.dbimport.ReverseEngineeringUtils.*;
+import static org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineeringUtils.*;
 import static org.mockito.Mockito.mock;
 
 public class DbImporterOldMojoConfigurationTest extends AbstractMojoTestCase {


[3/4] cayenne git commit: CAY-2215 move all DbImport code from cayenne-tools and cayenne-server modules to cayenne-dbsync module

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..b42bc80
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineering.java
@@ -0,0 +1,210 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * @since 4.0
+ */
+public class ReverseEngineering extends SchemaContainer implements Serializable {
+
+    private Boolean skipRelationshipsLoading;
+
+    private Boolean skipPrimaryKeyLoading;
+
+    /*
+     * <p>
+     * A default package for ObjEntity Java classes.
+     * </p>
+     * <p>
+     * If not specified, and the existing DataMap already has the default package,
+     * the existing package will be used.
+     * </p>
+     */
+    private String defaultPackage;
+
+    /**
+     * <p>
+     * Automatically tagging each DbEntity with the actual DB catalog/schema (default behavior) may sometimes be undesirable.
+     * If this is the case then setting forceDataMapCatalog to true will set DbEntity catalog to one in the DataMap.
+     * </p>
+     * <p>
+     * Default value is <b>false</b>.
+     * </p>
+     */
+    private boolean forceDataMapCatalog;
+
+    /**
+     * <p>
+     * Automatically tagging each DbEntity with the actual DB catalog/schema (default behavior) may sometimes be undesirable.
+     * If this is the case then setting forceDataMapSchema to true will set DbEntity schema to one in the DataMap.
+     * </p>
+     * <p>
+     * Default value is <b>false</b>.
+     * </p>
+     */
+    private boolean forceDataMapSchema;
+
+    /**
+     * <p>
+     * A comma-separated list of Perl5 patterns that defines which imported tables should have their primary key columns
+     * mapped as ObjAttributes.
+     * </p>
+     * <p><b>"*"</b> would indicate all tables.</p>
+     */
+    private String meaningfulPkTables;
+
+    /**
+     * <p>
+     * Object layer naming generator implementation.
+     * Should be fully qualified Java class name implementing "org.apache.cayenne.dbsync.naming.ObjectNameGenerator".
+     * </p>
+     * <p>
+     * The default is "org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator".
+     * </p>
+     */
+    private String namingStrategy = "org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator";
+
+    /**
+     * A regular expression that should match the part of the table name to strip before generating DB names.
+     */
+    private String stripFromTableNames = "";
+
+    /**
+     * <p>If true, would use primitives instead of numeric and boolean classes.</p>
+     * <p>Default is <b>"true"</b>, i.e. primitives will be used.</p>
+     */
+    private boolean usePrimitives = true;
+
+    /**
+     * Typical types are: <ul>
+     * <li> "TABLE"
+     * <li> "VIEW"
+     * <li> "SYSTEM TABLE"
+     * <li> "GLOBAL TEMPORARY",
+     * <li> "LOCAL TEMPORARY"
+     * <li> "ALIAS"
+     * <li> "SYNONYM"
+     * </ul>
+     */
+    private final Collection<String> tableTypes = new LinkedList<>();
+
+    private final Collection<Catalog> catalogCollection = new LinkedList<>();
+
+    public ReverseEngineering() {
+    }
+
+    public Boolean getSkipRelationshipsLoading() {
+        return skipRelationshipsLoading;
+    }
+
+    public void setSkipRelationshipsLoading(Boolean skipRelationshipsLoading) {
+        this.skipRelationshipsLoading = skipRelationshipsLoading;
+    }
+
+    public Boolean getSkipPrimaryKeyLoading() {
+        return skipPrimaryKeyLoading;
+    }
+
+    public void setSkipPrimaryKeyLoading(Boolean skipPrimaryKeyLoading) {
+        this.skipPrimaryKeyLoading = skipPrimaryKeyLoading;
+    }
+
+    public Collection<Catalog> getCatalogs() {
+        return catalogCollection;
+    }
+
+    public String[] getTableTypes() {
+        return tableTypes.toArray(new String[tableTypes.size()]);
+    }
+
+    /*
+     * Typical types are "TABLE",
+     * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
+     * "LOCAL TEMPORARY", "ALIAS", "SYNONYM"., etc.
+     */
+    public void setTableTypes(Collection<String> tableTypes) {
+        this.tableTypes.addAll(tableTypes);
+    }
+
+    /*
+     * Typical types are "TABLE",
+     * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
+     * "LOCAL TEMPORARY", "ALIAS", "SYNONYM"., etc.
+     */
+    public void addTableType(String type) {
+        this.tableTypes.add(type);
+    }
+
+    public void addCatalog(Catalog catalog) {
+        this.catalogCollection.add(catalog);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder res = new StringBuilder();
+        res.append("ReverseEngineering: ").append("\n");
+
+        if (!isBlank(catalogCollection)) {
+            for (Catalog catalog : catalogCollection) {
+                catalog.toString(res, "  ");
+            }
+        }
+
+        if (skipRelationshipsLoading != null && skipRelationshipsLoading) {
+            res.append("\n        Skip Relationships Loading");
+        }
+        if (skipPrimaryKeyLoading != null && skipPrimaryKeyLoading) {
+            res.append("\n        Skip PrimaryKey Loading");
+        }
+
+        return super.toString(res, "  ").toString();
+    }
+
+    public String getDefaultPackage() {
+        return defaultPackage;
+    }
+
+    public boolean isForceDataMapCatalog() {
+        return forceDataMapCatalog;
+    }
+
+    public boolean isForceDataMapSchema() {
+        return forceDataMapSchema;
+    }
+
+    public String getMeaningfulPkTables() {
+        return meaningfulPkTables;
+    }
+
+    public String getNamingStrategy() {
+        return namingStrategy;
+    }
+
+    public String getStripFromTableNames() {
+        return stripFromTableNames;
+    }
+
+    public boolean isUsePrimitives() {
+        return usePrimitives;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..7e7d273
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/Schema.java
@@ -0,0 +1,39 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+/**
+ * @since 4.0.
+ */
+public class Schema extends FilterContainer {
+
+    public Schema() {
+    }
+
+    public Schema(String name) {
+        setName(name);
+    }
+
+    @Override
+    public StringBuilder toString(StringBuilder res, String prefix) {
+        res.append(prefix).append("Schema: ").append(getName()).append("\n");
+        return super.toString(res, prefix + "  ");
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..7b4a849
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/SchemaContainer.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.dbsync.reverse.dbimport;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * @since 4.0
+ */
+abstract class SchemaContainer extends FilterContainer {
+
+    private final Collection<Schema> schemaCollection = new LinkedList<>();
+
+    public Collection<Schema> getSchemas() {
+        return schemaCollection;
+    }
+
+    public void addSchema(Schema schema) {
+        this.schemaCollection.add(schema);
+    }
+
+    @Override
+    public boolean isEmptyContainer() {
+        if (!super.isEmptyContainer()) {
+            return false;
+        }
+
+        if (schemaCollection.isEmpty()) {
+            return true;
+        }
+
+        for (Schema schema : schemaCollection) {
+            if (!schema.isEmptyContainer()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public StringBuilder toString(StringBuilder res, String prefix) {
+        if (!isBlank(schemaCollection)) {
+            for (Schema schema : schemaCollection) {
+                schema.toString(res, prefix);
+            }
+        }
+
+        return super.toString(res, prefix + "  ");
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/package-info.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/package-info.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/package-info.java
new file mode 100644
index 0000000..12cdd1c
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/package-info.java
@@ -0,0 +1,24 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+
+@XmlSchema(namespace="http://cayenne.apache.org/schema/8/reverseEngineering", elementFormDefault= XmlNsForm.QUALIFIED)
+package org.apache.cayenne.dbsync.reverse.dbimport;
+
+import javax.xml.bind.annotation.XmlNsForm;
+import javax.xml.bind.annotation.XmlSchema;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java
index 7900dde..a93681f 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java
@@ -18,16 +18,16 @@
  */
 package org.apache.cayenne.dbsync.reverse.filters;
 
-import org.apache.cayenne.dbimport.Catalog;
-import org.apache.cayenne.dbimport.ExcludeColumn;
-import org.apache.cayenne.dbimport.ExcludeProcedure;
-import org.apache.cayenne.dbimport.ExcludeTable;
-import org.apache.cayenne.dbimport.IncludeColumn;
-import org.apache.cayenne.dbimport.IncludeProcedure;
-import org.apache.cayenne.dbimport.IncludeTable;
-import org.apache.cayenne.dbimport.PatternParam;
-import org.apache.cayenne.dbimport.ReverseEngineering;
-import org.apache.cayenne.dbimport.Schema;
+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.PatternParam;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
 
 import java.util.Collection;
 import java.util.SortedSet;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModuleTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModuleTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModuleTest.java
new file mode 100644
index 0000000..899b049
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModuleTest.java
@@ -0,0 +1,66 @@
+/*****************************************************************
+ *   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.reverse.configuration;
+
+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.server.DefaultDbAdapterFactory;
+import org.apache.cayenne.dba.AutoAdapter;
+import org.apache.cayenne.di.AdhocObjectFactory;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
+import org.apache.commons.logging.Log;
+import org.junit.Test;
+
+import javax.sql.DataSource;
+
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+public class ToolsModuleTest {
+
+    @Test
+    public void testModuleContents() {
+
+        Log log = mock(Log.class);
+        Injector i = DIBootstrap.createInjector(new ToolsModule(log));
+
+        assertSame(log, i.getInstance(Log.class));
+        assertTrue(i.getInstance(DataSourceFactory.class) instanceof DriverDataSourceFactory);
+        assertTrue(i.getInstance(AdhocObjectFactory.class) instanceof DefaultAdhocObjectFactory);
+        assertTrue(i.getInstance(DbAdapterFactory.class) instanceof DefaultDbAdapterFactory);
+    }
+
+    @Test
+    public void testDbApdater() throws Exception {
+        Log log = mock(Log.class);
+        Injector i = DIBootstrap.createInjector(new ToolsModule(log));
+
+        DbAdapterFactory factory = i.getInstance(DbAdapterFactory.class);
+
+        DataNodeDescriptor nodeDescriptor = mock(DataNodeDescriptor.class);
+        DataSource dataSource = mock(DataSource.class);
+
+        assertTrue(factory.createAdapter(nodeDescriptor, dataSource) instanceof AutoAdapter);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModuleTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModuleTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModuleTest.java
new file mode 100644
index 0000000..d057fda
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModuleTest.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.dbsync.reverse.dbimport;
+
+import org.apache.cayenne.dbsync.DbSyncModule;
+import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
+import org.apache.commons.logging.Log;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+public class DbImportModuleTest {
+
+    @Test
+    public void testModuleContents() {
+
+        Log log = mock(Log.class);
+        Injector i = DIBootstrap.createInjector(new DbSyncModule(), new ToolsModule(log), new DbImportModule());
+        assertTrue(i.getInstance(DbImportAction.class) instanceof DbImportAction);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..aeddd37
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
@@ -0,0 +1,356 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.configuration.server.DataSourceFactory;
+import org.apache.cayenne.configuration.server.DbAdapterFactory;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.DbSyncModule;
+import org.apache.cayenne.dbsync.filter.NamePatternMatcher;
+import org.apache.cayenne.dbsync.merge.builders.DataMapBuilder;
+import org.apache.cayenne.dbsync.merge.factory.DefaultMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
+import org.apache.cayenne.dbsync.merge.token.MergerToken;
+import org.apache.cayenne.dbsync.merge.token.db.CreateTableToDb;
+import org.apache.cayenne.dbsync.merge.token.model.AddColumnToModel;
+import org.apache.cayenne.dbsync.merge.token.model.AddRelationshipToModel;
+import org.apache.cayenne.dbsync.merge.token.model.CreateTableToModel;
+import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
+import org.apache.cayenne.dbsync.naming.NoStemStemmer;
+import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
+import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
+import org.apache.cayenne.dbsync.reverse.dbload.DbLoader;
+import org.apache.cayenne.dbsync.reverse.dbload.DbLoaderConfiguration;
+import org.apache.cayenne.dbsync.reverse.dbload.DbLoaderDelegate;
+import org.apache.cayenne.dbsync.reverse.dbload.DefaultModelMergeDelegate;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.MapLoader;
+import org.apache.cayenne.project.FileProjectSaver;
+import org.apache.cayenne.project.Project;
+import org.apache.cayenne.resource.URLResource;
+import org.apache.cayenne.util.Util;
+import org.apache.commons.logging.Log;
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.InputSource;
+
+import javax.sql.DataSource;
+import java.io.File;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.LinkedList;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbAttr;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbEntity;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.objAttr;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.objEntity;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.stub;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class DefaultDbImportActionTest {
+
+    public static final File FILE_STUB = new File("") {
+        @Override
+        public boolean exists() {
+            return true;
+        }
+
+        @Override
+        public boolean canRead() {
+            return true;
+        }
+    };
+
+    private DbAdapter mockAdapter;
+    private Connection mockConnection;
+    private DbLoaderDelegate mockDelegate;
+    private ObjectNameGenerator mockNameGenerator;
+
+    @Before
+    public void before() {
+        mockAdapter = mock(DbAdapter.class);
+        mockConnection = mock(Connection.class);
+        mockDelegate = mock(DbLoaderDelegate.class);
+        mockNameGenerator = mock(ObjectNameGenerator.class);
+    }
+
+    @Test
+    public void testNewDataMapImport() throws Exception {
+
+        DbImportConfiguration config = mock(DbImportConfiguration.class);
+        when(config.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
+        when(config.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
+        when(config.getTargetDataMap()).thenReturn(new File("xyz.map.xml"));
+        when(config.createNameGenerator()).thenReturn(new DefaultObjectNameGenerator(NoStemStemmer.getInstance()));
+        when(config.createMeaningfulPKFilter()).thenReturn(NamePatternMatcher.EXCLUDE_ALL);
+
+        DbLoader dbLoader = new DbLoader(mockAdapter, mockConnection, config.getDbLoaderConfig(), mockDelegate, mockNameGenerator) {
+            @Override
+            public DataMap load() throws SQLException {
+                DataMap map = new DataMap();
+                new DataMapBuilder(map).withDbEntities(2).build();
+                return map;
+            }
+        };
+
+        final boolean[] haveWeTriedToSave = {false};
+        DefaultDbImportAction action = buildDbImportAction(new FileProjectSaver() {
+            @Override
+            public void save(Project project) {
+                haveWeTriedToSave[0] = true;
+
+                // Validation phase
+                assertTrue(project.getRootNode() instanceof DataMap);
+            }
+        }, null, dbLoader);
+
+        action.execute(config);
+
+        assertTrue("We should try to save.", haveWeTriedToSave[0]);
+    }
+
+    @Test
+    public void testImportWithFieldChanged() throws Exception {
+
+        DbImportConfiguration config = mock(DbImportConfiguration.class);
+
+        when(config.getTargetDataMap()).thenReturn(FILE_STUB);
+        when(config.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
+        when(config.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
+        when(config.createNameGenerator()).thenReturn(new DefaultObjectNameGenerator(NoStemStemmer.getInstance()));
+        when(config.createMeaningfulPKFilter()).thenReturn(NamePatternMatcher.EXCLUDE_ALL);
+
+        DbLoader dbLoader = new DbLoader(mockAdapter, mockConnection, config.getDbLoaderConfig(), mockDelegate, mockNameGenerator) {
+            @Override
+            public DataMap load() throws SQLException {
+                DataMap dataMap = new DataMap();
+                new DataMapBuilder(dataMap).with(
+                        dbEntity("ARTGROUP").attributes(
+                                dbAttr("GROUP_ID").typeInt().primaryKey(),
+                                dbAttr("NAME").typeVarchar(100).mandatory(),
+                                dbAttr("NAME_01").typeVarchar(100).mandatory(),
+                                dbAttr("PARENT_GROUP_ID").typeInt()
+                        )).with(
+                        objEntity("org.apache.cayenne.testdo.testmap", "ArtGroup", "ARTGROUP").attributes(
+                                objAttr("name").type(String.class).dbPath("NAME")
+                        ));
+                return dataMap;
+            }
+        };
+
+        final boolean[] haveWeTriedToSave = {false};
+        DefaultDbImportAction action = buildDbImportAction(
+            new FileProjectSaver() {
+                @Override
+                public void save(Project project) {
+                    haveWeTriedToSave[0] = true;
+
+                    // Validation phase
+                    DataMap rootNode = (DataMap) project.getRootNode();
+                    assertEquals(1, rootNode.getObjEntities().size());
+                    assertEquals(1, rootNode.getDbEntityMap().size());
+
+                    DbEntity entity = rootNode.getDbEntity("ARTGROUP");
+                    assertNotNull(entity);
+                    assertEquals(4, entity.getAttributes().size());
+                    assertNotNull(entity.getAttribute("NAME_01"));
+                }
+            },
+
+            new MapLoader() {
+                @Override
+                public synchronized DataMap loadDataMap(InputSource src) throws CayenneRuntimeException {
+                    return new DataMapBuilder().with(
+                            dbEntity("ARTGROUP").attributes(
+                                    dbAttr("GROUP_ID").typeInt().primaryKey(),
+                                    dbAttr("NAME").typeVarchar(100).mandatory(),
+                                    dbAttr("PARENT_GROUP_ID").typeInt()
+                            )).with(
+                            objEntity("org.apache.cayenne.testdo.testmap", "ArtGroup", "ARTGROUP").attributes(
+                                    objAttr("name").type(String.class).dbPath("NAME")
+                            )).build();
+                }
+            },
+            dbLoader
+        );
+
+        action.execute(config);
+
+        assertTrue("We should try to save.", haveWeTriedToSave[0]);
+    }
+
+    @Test
+    public void testImportWithoutChanges() throws Exception {
+        DbImportConfiguration config = mock(DbImportConfiguration.class);
+        when(config.getTargetDataMap()).thenReturn(FILE_STUB);
+        when(config.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
+        when(config.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
+
+        DbLoader dbLoader = new DbLoader(mockAdapter, mockConnection, config.getDbLoaderConfig(), mockDelegate, mockNameGenerator) {
+            @Override
+            public DataMap load() throws SQLException {
+                DataMap dataMap = new DataMap();
+                new DataMapBuilder(dataMap).with(
+                        dbEntity("ARTGROUP").attributes(
+                                dbAttr("NAME").typeVarchar(100).mandatory()
+                        ));
+                return dataMap;
+            }
+        };
+
+        FileProjectSaver projectSaver = mock(FileProjectSaver.class);
+        doNothing().when(projectSaver).save(any(Project.class));
+
+        MapLoader mapLoader = mock(MapLoader.class);
+        stub(mapLoader.loadDataMap(any(InputSource.class))).toReturn(new DataMapBuilder().with(
+                dbEntity("ARTGROUP").attributes(
+                        dbAttr("NAME").typeVarchar(100).mandatory()
+                )).build());
+
+        DefaultDbImportAction action = buildDbImportAction(projectSaver, mapLoader, dbLoader);
+
+        action.execute(config);
+
+        // no changes - we still
+        verify(projectSaver, never()).save(any(Project.class));
+        verify(mapLoader, times(1)).loadDataMap(any(InputSource.class));
+    }
+
+    @Test
+    public void testImportWithDbError() throws Exception {
+        DbLoader dbLoader = mock(DbLoader.class);
+        doThrow(new SQLException()).when(dbLoader).load();
+
+        DbImportConfiguration params = mock(DbImportConfiguration.class);
+
+        FileProjectSaver projectSaver = mock(FileProjectSaver.class);
+        doNothing().when(projectSaver).save(any(Project.class));
+
+        MapLoader mapLoader = mock(MapLoader.class);
+        when(mapLoader.loadDataMap(any(InputSource.class))).thenReturn(null);
+
+        DefaultDbImportAction action = buildDbImportAction(projectSaver, mapLoader, dbLoader);
+
+        try {
+            action.execute(params);
+            fail();
+        } catch (SQLException e) {
+            // expected
+        }
+
+        verify(projectSaver, never()).save(any(Project.class));
+        verify(mapLoader, never()).loadDataMap(any(InputSource.class));
+    }
+
+    private DefaultDbImportAction buildDbImportAction(FileProjectSaver projectSaver, MapLoader mapLoader, final DbLoader dbLoader)
+            throws Exception {
+
+        Log log = mock(Log.class);
+        when(log.isDebugEnabled()).thenReturn(true);
+        when(log.isInfoEnabled()).thenReturn(true);
+
+        DbAdapter dbAdapter = mock(DbAdapter.class);
+
+        DbAdapterFactory adapterFactory = mock(DbAdapterFactory.class);
+        when(adapterFactory.createAdapter(any(DataNodeDescriptor.class), any(DataSource.class))).thenReturn(dbAdapter);
+
+        DataSourceFactory dataSourceFactory = mock(DataSourceFactory.class);
+        DataSource mock = mock(DataSource.class);
+        when(dataSourceFactory.getDataSource(any(DataNodeDescriptor.class))).thenReturn(mock);
+
+        MergerTokenFactoryProvider mergerTokenFactoryProvider = mock(MergerTokenFactoryProvider.class);
+        when(mergerTokenFactoryProvider.get(any(DbAdapter.class))).thenReturn(new DefaultMergerTokenFactory());
+
+        return new DefaultDbImportAction(log, projectSaver, dataSourceFactory, adapterFactory, mapLoader, mergerTokenFactoryProvider) {
+
+            protected DbLoader createDbLoader(DbAdapter adapter,
+                                               Connection connection,
+                                               DbImportConfiguration config) {
+                return dbLoader;
+            }
+        };
+    }
+
+    @Test
+    public void testSaveLoaded() throws Exception {
+        Log log = mock(Log.class);
+        Injector i = DIBootstrap.createInjector(new DbSyncModule(), new ToolsModule(log), new DbImportModule());
+
+        DefaultDbImportAction action = (DefaultDbImportAction) i.getInstance(DbImportAction.class);
+
+        String packagePath = getClass().getPackage().getName().replace('.', '/');
+        URL packageUrl = getClass().getClassLoader().getResource(packagePath);
+        assertNotNull(packageUrl);
+        URL outUrl = new URL(packageUrl, "dbimport/testSaveLoaded1.map.xml");
+
+        File out = new File(outUrl.toURI());
+        out.delete();
+        assertFalse(out.isFile());
+
+        DataMap map = new DataMap("testSaveLoaded1");
+        map.setConfigurationSource(new URLResource(outUrl));
+
+        action.saveLoaded(map);
+
+        assertTrue(out.isFile());
+
+        String contents = Util.stringFromFile(out);
+        assertTrue("Has no project version saved", contents.contains("project-version=\""));
+    }
+
+    @Test
+    public void testMergeTokensSorting() {
+        LinkedList<MergerToken> tokens = new LinkedList<MergerToken>();
+        tokens.add(new AddColumnToModel(null, null));
+        tokens.add(new AddRelationshipToModel(null, null));
+        tokens.add(new CreateTableToDb(null));
+        tokens.add(new CreateTableToModel(null));
+
+        assertEquals(asList("CreateTableToDb", "CreateTableToModel", "AddColumnToModel", "AddRelationshipToModel"),
+                toClasses(DefaultDbImportAction.sort(tokens)));
+    }
+
+    private List<String> toClasses(List<MergerToken> sort) {
+        LinkedList<String> res = new LinkedList<String>();
+        for (MergerToken mergerToken : sort) {
+            res.add(mergerToken.getClass().getSimpleName());
+        }
+        return res;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java
new file mode 100644
index 0000000..ca255ff
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java
@@ -0,0 +1,116 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+import org.apache.cayenne.configuration.ConfigurationNameMapper;
+import org.apache.cayenne.configuration.ConfigurationTree;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataMapLoader;
+import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
+import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader;
+import org.apache.cayenne.configuration.XMLDataMapLoader;
+import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
+import org.apache.cayenne.dbsync.naming.NoStemStemmer;
+import org.apache.cayenne.di.AdhocObjectFactory;
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.ClassLoaderManager;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
+import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.Relationship;
+import org.apache.cayenne.resource.URLResource;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.URL;
+import java.util.ArrayList;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+public class ManyToManyCandidateEntityTest {
+
+    private DataMap map;
+
+    @Before
+    public void setUp() throws Exception {
+        Module testModule = new Module() {
+
+            public void configure(Binder binder) {
+                binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
+                binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
+                binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
+                binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
+            }
+        };
+
+        Injector injector = DIBootstrap.createInjector(testModule);
+
+        // create and initialize loader instance to test
+        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
+        injector.injectMembers(loader);
+
+        String testConfigName = "relationship-optimisation";
+        URL url = getClass().getResource("cayenne-" + testConfigName + ".xml");
+
+        ConfigurationTree<DataChannelDescriptor> tree = loader.load(new URLResource(url));
+
+        map = tree.getRootNode().getDataMap(testConfigName);
+    }
+
+    @Test
+    public void testMatchingForManyToManyEntity() throws Exception {
+        ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
+
+        assertNotNull(ManyToManyCandidateEntity.build(manyToManyEntity));
+    }
+
+    @Test
+    public void testMatchingForNotManyToManyEntity() throws Exception {
+        ObjEntity entity = map.getObjEntity("Table1");
+
+        assertNull(ManyToManyCandidateEntity.build(entity));
+    }
+
+    @Test
+    public void testOptimisationForManyToManyEntity() {
+        ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
+
+        ManyToManyCandidateEntity.build(manyToManyEntity).optimizeRelationships(
+                new DefaultObjectNameGenerator(NoStemStemmer.getInstance()));
+
+        ObjEntity table1Entity = map.getObjEntity("Table1");
+        ObjEntity table2Entity = map.getObjEntity("Table2");
+
+        assertEquals(1, table1Entity.getRelationships().size());
+        assertEquals(table2Entity, new ArrayList<Relationship>(table1Entity.getRelationships()).get(0)
+                .getTargetEntity());
+
+        assertEquals(1, table2Entity.getRelationships().size());
+        assertEquals(table1Entity, new ArrayList<Relationship>(table2Entity.getRelationships()).get(0)
+                .getTargetEntity());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineeringUtils.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineeringUtils.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineeringUtils.java
new file mode 100644
index 0000000..e3794dd
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineeringUtils.java
@@ -0,0 +1,174 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+import java.util.Iterator;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ReverseEngineeringUtils {
+
+    public static void assertCatalog(ReverseEngineering engineering) {
+        Iterator<Catalog> catalogs = engineering.getCatalogs().iterator();
+        assertEquals("catalog-name-01", catalogs.next().getName());
+        assertEquals("catalog-name-02", catalogs.next().getName());
+
+        assertCatalog(catalogs.next());
+    }
+
+    public static void assertCatalog(Catalog catalog ) {
+        assertEquals("catalog-name-03", catalog.getName());
+
+        Iterator<IncludeTable> includeTables = catalog.getIncludeTables().iterator();
+        assertEquals("includeTable-01", includeTables.next().getPattern());
+        assertEquals("includeTable-02", includeTables.next().getPattern());
+
+        IncludeTable includeTable = includeTables.next();
+        assertEquals("includeTable-03", includeTable.getPattern());
+        assertEquals("includeColumn-01", includeTable.getIncludeColumns().iterator().next().getPattern());
+        assertEquals("excludeColumn-01", includeTable.getExcludeColumns().iterator().next().getPattern());
+
+        Iterator<ExcludeTable> excludeTables = catalog.getExcludeTables().iterator();
+        assertEquals("excludeTable-01", excludeTables.next().getPattern());
+        assertEquals("excludeTable-02", excludeTables.next().getPattern());
+        assertEquals("excludeTable-03", excludeTables.next().getPattern());
+
+        Iterator<ExcludeColumn> excludeColumns = catalog.getExcludeColumns().iterator();
+        assertEquals("excludeColumn-01", excludeColumns.next().getPattern());
+        assertEquals("excludeColumn-02", excludeColumns.next().getPattern());
+        assertEquals("excludeColumn-03", excludeColumns.next().getPattern());
+        Iterator<IncludeColumn> includeColumns = catalog.getIncludeColumns().iterator();
+        assertEquals("includeColumn-01", includeColumns.next().getPattern());
+        assertEquals("includeColumn-02", includeColumns.next().getPattern());
+        assertEquals("includeColumn-03", includeColumns.next().getPattern());
+
+        Iterator<ExcludeProcedure> excludeProcedures = catalog.getExcludeProcedures().iterator();
+        assertEquals("excludeProcedure-01", excludeProcedures.next().getPattern());
+        assertEquals("excludeProcedure-02", excludeProcedures.next().getPattern());
+        assertEquals("excludeProcedure-03", excludeProcedures.next().getPattern());
+        Iterator<IncludeProcedure> includeProcedures = catalog.getIncludeProcedures().iterator();
+        assertEquals("includeProcedure-01", includeProcedures.next().getPattern());
+        assertEquals("includeProcedure-02", includeProcedures.next().getPattern());
+        assertEquals("includeProcedure-03", includeProcedures.next().getPattern());
+    }
+
+    public static void assertSchema(ReverseEngineering engineering) {
+        Iterator<Schema> schemas = engineering.getSchemas().iterator();
+        assertEquals("schema-name-01", schemas.next().getName());
+        assertEquals("schema-name-02", schemas.next().getName());
+
+        Schema schema = schemas.next();
+        assertEquals("schema-name-03", schema.getName());
+
+        assertSchemaContent(schema);
+    }
+
+    public static void assertSchemaContent(Schema schema) {
+        Iterator<IncludeTable> includeTables = schema.getIncludeTables().iterator();
+        assertEquals("includeTable-01", includeTables.next().getPattern());
+        assertEquals("includeTable-02", includeTables.next().getPattern());
+
+        IncludeTable includeTable = includeTables.next();
+        assertEquals("includeTable-03", includeTable.getPattern());
+        assertEquals("includeColumn-01", includeTable.getIncludeColumns().iterator().next().getPattern());
+        assertEquals("excludeColumn-01", includeTable.getExcludeColumns().iterator().next().getPattern());
+
+        Iterator<ExcludeTable> excludeTables = schema.getExcludeTables().iterator();
+        assertEquals("excludeTable-01", excludeTables.next().getPattern());
+        assertEquals("excludeTable-02", excludeTables.next().getPattern());
+        assertEquals("excludeTable-03", excludeTables.next().getPattern());
+
+        Iterator<ExcludeColumn> excludeColumns = schema.getExcludeColumns().iterator();
+        assertEquals("excludeColumn-01", excludeColumns.next().getPattern());
+        assertEquals("excludeColumn-02", excludeColumns.next().getPattern());
+        assertEquals("excludeColumn-03", excludeColumns.next().getPattern());
+        Iterator<IncludeColumn> includeColumns = schema.getIncludeColumns().iterator();
+        assertEquals("includeColumn-01", includeColumns.next().getPattern());
+        assertEquals("includeColumn-02", includeColumns.next().getPattern());
+        assertEquals("includeColumn-03", includeColumns.next().getPattern());
+
+        Iterator<ExcludeProcedure> excludeProcedures = schema.getExcludeProcedures().iterator();
+        assertEquals("excludeProcedure-01", excludeProcedures.next().getPattern());
+        assertEquals("excludeProcedure-02", excludeProcedures.next().getPattern());
+        assertEquals("excludeProcedure-03", excludeProcedures.next().getPattern());
+        Iterator<IncludeProcedure> includeProcedures = schema.getIncludeProcedures().iterator();
+        assertEquals("includeProcedure-01", includeProcedures.next().getPattern());
+        assertEquals("includeProcedure-02", includeProcedures.next().getPattern());
+        assertEquals("includeProcedure-03", includeProcedures.next().getPattern());
+    }
+
+    public static void assertCatalogAndSchema(ReverseEngineering engineering) {
+        Catalog catalog = engineering.getCatalogs().iterator().next();
+        assertEquals("catalog-name", catalog.getName());
+
+        Schema schema = catalog.getSchemas().iterator().next();
+        assertEquals("schema-name", schema.getName());
+
+        assertSchemaContent(schema);
+    }
+
+    public static void assertFlat(ReverseEngineering engineering) {
+        Iterator<IncludeTable> includeTables = engineering.getIncludeTables().iterator();
+        assertEquals("includeTable-01", includeTables.next().getPattern());
+        assertEquals("includeTable-02", includeTables.next().getPattern());
+
+        IncludeTable includeTable = includeTables.next();
+        assertEquals("includeTable-03", includeTable.getPattern());
+        assertEquals("includeColumn-01", includeTable.getIncludeColumns().iterator().next().getPattern());
+        assertEquals("excludeColumn-01", includeTable.getExcludeColumns().iterator().next().getPattern());
+
+        Iterator<ExcludeTable> excludeTables = engineering.getExcludeTables().iterator();
+        assertEquals("excludeTable-01", excludeTables.next().getPattern());
+        assertEquals("excludeTable-02", excludeTables.next().getPattern());
+        assertEquals("excludeTable-03", excludeTables.next().getPattern());
+
+        Iterator<ExcludeColumn> excludeColumns = engineering.getExcludeColumns().iterator();
+        assertEquals("excludeColumn-01", excludeColumns.next().getPattern());
+        assertEquals("excludeColumn-02", excludeColumns.next().getPattern());
+        assertEquals("excludeColumn-03", excludeColumns.next().getPattern());
+        Iterator<IncludeColumn> includeColumns = engineering.getIncludeColumns().iterator();
+        assertEquals("includeColumn-01", includeColumns.next().getPattern());
+        assertEquals("includeColumn-02", includeColumns.next().getPattern());
+        assertEquals("includeColumn-03", includeColumns.next().getPattern());
+
+        Iterator<ExcludeProcedure> excludeProcedures = engineering.getExcludeProcedures().iterator();
+        assertEquals("excludeProcedure-01", excludeProcedures.next().getPattern());
+        assertEquals("excludeProcedure-02", excludeProcedures.next().getPattern());
+        assertEquals("excludeProcedure-03", excludeProcedures.next().getPattern());
+        Iterator<IncludeProcedure> includeProcedures = engineering.getIncludeProcedures().iterator();
+        assertEquals("includeProcedure-01", includeProcedures.next().getPattern());
+        assertEquals("includeProcedure-02", includeProcedures.next().getPattern());
+        assertEquals("includeProcedure-03", includeProcedures.next().getPattern());
+    }
+
+    public static void assertSkipRelationshipsLoading(ReverseEngineering engineering) {
+        assertTrue(engineering.getSkipRelationshipsLoading());
+    }
+
+    public static void assertSkipPrimaryKeyLoading(ReverseEngineering engineering) {
+        assertTrue(engineering.getSkipPrimaryKeyLoading());
+    }
+
+    public static void assertTableTypes(ReverseEngineering engineering) {
+        assertArrayEquals(new String[]{"type1", "type2", "type3"}, engineering.getTableTypes());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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 91d537c..4ce8ef3 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
@@ -19,16 +19,15 @@
 
 package org.apache.cayenne.dbsync.reverse.filters;
 
-import org.apache.cayenne.dbimport.Catalog;
-import org.apache.cayenne.dbimport.ExcludeColumn;
-import org.apache.cayenne.dbimport.ExcludeProcedure;
-import org.apache.cayenne.dbimport.ExcludeTable;
-import org.apache.cayenne.dbimport.IncludeColumn;
-import org.apache.cayenne.dbimport.IncludeProcedure;
-import org.apache.cayenne.dbimport.IncludeTable;
-import org.apache.cayenne.dbimport.ReverseEngineering;
-import org.apache.cayenne.dbimport.Schema;
-import org.apache.cayenne.dbsync.reverse.filters.FiltersConfigBuilder;
+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.junit.Test;
 
 import static org.junit.Assert.assertEquals;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java
index 4ef3c23..f163844 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java
@@ -21,7 +21,6 @@ package org.apache.cayenne.dbsync.reverse.filters;
 import java.util.TreeSet;
 import java.util.regex.Pattern;
 
-import org.apache.cayenne.dbimport.ExcludeTable;
 import org.junit.Test;
 
 import static org.junit.Assert.*;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/cayenne-relationship-optimisation.xml
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/cayenne-relationship-optimisation.xml b/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/cayenne-relationship-optimisation.xml
new file mode 100644
index 0000000..d4fea49
--- /dev/null
+++ b/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/cayenne-relationship-optimisation.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain project-version="6">
+	<map name="relationship-optimisation"/>
+</domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/relationship-optimisation.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/relationship-optimisation.map.xml b/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/relationship-optimisation.map.xml
new file mode 100644
index 0000000..e68645f
--- /dev/null
+++ b/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/relationship-optimisation.map.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/3.0/modelMap http://cayenne.apache.org/schema/3.0/modelMap.xsd"
+	 project-version="6">
+	<property name="defaultPackage" value="com.objectstyle"/>
+	<db-entity name="table1" catalog="many_to_many_test">
+		<db-attribute name="id1" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+		<db-attribute name="table1col" type="VARCHAR" length="45"/>
+	</db-entity>
+	<db-entity name="table1_table2" catalog="many_to_many_test">
+		<db-attribute name="fk1" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+		<db-attribute name="fk2" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+	</db-entity>
+	<db-entity name="table2" catalog="many_to_many_test">
+		<db-attribute name="id2" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+		<db-attribute name="table2col" type="VARCHAR" length="45"/>
+	</db-entity>
+	<obj-entity name="Table1" className="com.objectstyle.Table1" dbEntityName="table1">
+		<obj-attribute name="table1col" type="java.lang.String" db-attribute-path="table1col"/>
+	</obj-entity>
+	<obj-entity name="Table1Table2" className="com.objectstyle.Table1Table2" dbEntityName="table1_table2">
+	</obj-entity>
+	<obj-entity name="Table2" className="com.objectstyle.Table2" dbEntityName="table2">
+		<obj-attribute name="table2col" type="java.lang.String" db-attribute-path="table2col"/>
+	</obj-entity>
+	<db-relationship name="table1Table2Array" source="table1" target="table1_table2" toDependentPK="true" toMany="true">
+		<db-attribute-pair source="id1" target="fk1"/>
+	</db-relationship>
+	<db-relationship name="toTable1" source="table1_table2" target="table1" toMany="false">
+		<db-attribute-pair source="fk1" target="id1"/>
+	</db-relationship>
+	<db-relationship name="toTable2" source="table1_table2" target="table2" toMany="false">
+		<db-attribute-pair source="fk2" target="id2"/>
+	</db-relationship>
+	<db-relationship name="table1Table2Array" source="table2" target="table1_table2" toDependentPK="true" toMany="true">
+		<db-attribute-pair source="id2" target="fk2"/>
+	</db-relationship>
+	<obj-relationship name="table1Table2Array" source="Table1" target="Table1Table2" deleteRule="Deny" db-relationship-path="table1Table2Array"/>
+	<obj-relationship name="toTable1" source="Table1Table2" target="Table1" deleteRule="Nullify" db-relationship-path="toTable1"/>
+	<obj-relationship name="toTable2" source="Table1Table2" target="Table2" deleteRule="Nullify" db-relationship-path="toTable2"/>
+	<obj-relationship name="table1Table2Array" source="Table2" target="Table1Table2" deleteRule="Deny" db-relationship-path="table1Table2Array"/>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/AntNestedElement.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/AntNestedElement.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/AntNestedElement.java
deleted file mode 100644
index f300c02..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/AntNestedElement.java
+++ /dev/null
@@ -1,42 +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.dbimport;
-
-/**
- * Additional class to handle <name> element under <catalog> and <schema>
- *      required for ant configuration
- *
- * @since 4.0.
- */
-public class AntNestedElement {
-
-    private String name;
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public void addText(String str) {
-        name = str;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Catalog.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Catalog.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Catalog.java
deleted file mode 100644
index 9f14dd6..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Catalog.java
+++ /dev/null
@@ -1,38 +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.dbimport;
-
-/**
- * @since 4.0.
- */
-public class Catalog extends SchemaContainer {
-
-    public Catalog() {
-    }
-
-    public Catalog(String name) {
-        setName(name);
-    }
-
-    @Override
-    public StringBuilder toString(StringBuilder res, String prefix) {
-        res.append(prefix).append("Catalog: ").append(getName()).append("\n");
-        return super.toString(res, prefix + "  ");
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeColumn.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeColumn.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeColumn.java
deleted file mode 100644
index ff1e0e3..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeColumn.java
+++ /dev/null
@@ -1,31 +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.dbimport;
-
-/**
- * @since 4.0.
- */
-public class ExcludeColumn extends PatternParam {
-    public ExcludeColumn() {
-    }
-
-    public ExcludeColumn(String pattern) {
-        super(pattern);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeProcedure.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeProcedure.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeProcedure.java
deleted file mode 100644
index e5d7b2d..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeProcedure.java
+++ /dev/null
@@ -1,31 +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.dbimport;
-
-/**
- * @since 4.0.
- */
-public class ExcludeProcedure extends PatternParam {
-    public ExcludeProcedure() {
-    }
-
-    public ExcludeProcedure(String pattern) {
-        super(pattern);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeTable.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeTable.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeTable.java
deleted file mode 100644
index 3cbd8d4..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeTable.java
+++ /dev/null
@@ -1,31 +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.dbimport;
-
-/**
- * @since 4.0.
- */
-public class ExcludeTable extends PatternParam {
-    public ExcludeTable() {
-    }
-
-    public ExcludeTable(String pattern) {
-        super(pattern);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FilterContainer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FilterContainer.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FilterContainer.java
deleted file mode 100644
index 44cfcea..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FilterContainer.java
+++ /dev/null
@@ -1,171 +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.dbimport;
-
-import java.util.Collection;
-import java.util.LinkedList;
-
-/**
- * @since 4.0.
- */
-abstract class FilterContainer {
-
-    private String name;
-
-    private final Collection<IncludeTable> includeTableCollection = new LinkedList<>();
-
-    private final Collection<ExcludeTable> excludeTableCollection = new LinkedList<>();
-
-    private final Collection<IncludeColumn> includeColumnCollection = new LinkedList<>();
-
-    private final Collection<ExcludeColumn> excludeColumnCollection = new LinkedList<>();
-
-    private final Collection<IncludeProcedure> includeProcedureCollection = new LinkedList<>();
-
-    private final Collection<ExcludeProcedure> excludeProcedureCollection = new LinkedList<>();
-
-    public Collection<IncludeTable> getIncludeTables() {
-        return includeTableCollection;
-    }
-
-    public Collection<ExcludeTable> getExcludeTables() {
-        return excludeTableCollection;
-    }
-
-    public Collection<IncludeColumn> getIncludeColumns() {
-        return includeColumnCollection;
-    }
-
-    public Collection<ExcludeColumn> getExcludeColumns() {
-        return excludeColumnCollection;
-    }
-
-    public Collection<IncludeProcedure> getIncludeProcedures() {
-        return includeProcedureCollection;
-    }
-
-    public Collection<ExcludeProcedure> getExcludeProcedures() {
-        return excludeProcedureCollection;
-    }
-
-    public void addIncludeColumn(IncludeColumn includeColumn) {
-        this.includeColumnCollection.add(includeColumn);
-    }
-
-    public void addExcludeColumn(ExcludeColumn excludeColumn) {
-        this.excludeColumnCollection.add(excludeColumn);
-    }
-
-    public void addIncludeTable(IncludeTable includeTable) {
-        this.includeTableCollection.add(includeTable);
-    }
-
-    public void addExcludeTable(ExcludeTable excludeTable) {
-        this.excludeTableCollection.add(excludeTable);
-    }
-
-    public void addIncludeProcedure(IncludeProcedure includeProcedure) {
-        this.includeProcedureCollection.add(includeProcedure);
-    }
-
-    public void addExcludeProcedure(ExcludeProcedure excludeProcedure) {
-        this.excludeProcedureCollection.add(excludeProcedure);
-    }
-
-    public void clearIncludeTables() {
-        includeTableCollection.clear();
-    }
-
-    public void clearExcludeTables() {
-        excludeTableCollection.clear();
-    }
-
-    public void clearIncludeProcedures() {
-        includeProcedureCollection.clear();
-    }
-
-    public void clearExcludeProcedures() {
-        excludeProcedureCollection.clear();
-    }
-
-    public void clearIncludeColumns() {
-        includeColumnCollection.clear();
-    }
-
-    public void clearExcludeColumns() {
-        excludeColumnCollection.clear();
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public void set(String name) {
-        setName(name);
-    }
-
-    public void addConfiguredName(AntNestedElement name) {
-        setName(name.getName());
-    }
-
-    public void addText(String name) {
-        if (name.trim().isEmpty()) {
-            return;
-        }
-        setName(name);
-    }
-
-    public boolean isEmptyContainer() {
-        return includeColumnCollection.isEmpty()    && excludeColumnCollection.isEmpty()
-            && includeTableCollection.isEmpty()     && excludeTableCollection.isEmpty()
-            && includeProcedureCollection.isEmpty() && excludeProcedureCollection.isEmpty();
-    }
-
-    static boolean isBlank(Collection<?> collection) {
-        return collection == null || collection.isEmpty();
-    }
-
-    @Override
-    public String toString() {
-        return toString(new StringBuilder(), "").toString();
-    }
-
-    public StringBuilder toString(StringBuilder res, String prefix) {
-        appendCollection(res, prefix, includeTableCollection);
-        appendCollection(res, prefix, excludeTableCollection);
-        appendCollection(res, prefix, includeColumnCollection);
-        appendCollection(res, prefix, excludeColumnCollection);
-        appendCollection(res, prefix, includeProcedureCollection);
-        appendCollection(res, prefix, excludeProcedureCollection);
-
-        return res;
-    }
-
-    protected void appendCollection(StringBuilder res, String prefix, Collection<? extends PatternParam> collection) {
-        if (!isBlank(collection)) {
-            for (PatternParam item : collection) {
-                item.toString(res, prefix);
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeColumn.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeColumn.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeColumn.java
deleted file mode 100644
index 899e987..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeColumn.java
+++ /dev/null
@@ -1,31 +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.dbimport;
-
-/**
- * @since 4.0.
- */
-public class IncludeColumn extends PatternParam {
-    public IncludeColumn() {
-    }
-
-    public IncludeColumn(String pattern) {
-        super(pattern);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeProcedure.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeProcedure.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeProcedure.java
deleted file mode 100644
index a249385..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeProcedure.java
+++ /dev/null
@@ -1,31 +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.dbimport;
-
-/**
- * @since 4.0.
- */
-public class IncludeProcedure extends PatternParam {
-    public IncludeProcedure() {
-    }
-
-    public IncludeProcedure(String pattern) {
-        super(pattern);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeTable.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeTable.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeTable.java
deleted file mode 100644
index dbd0a18..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeTable.java
+++ /dev/null
@@ -1,83 +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.dbimport;
-
-import java.util.Collection;
-import java.util.LinkedList;
-
-/**
- * @since 4.0.
- */
-public class IncludeTable extends PatternParam {
-
-    private final Collection<IncludeColumn> includeColumns = new LinkedList<>();
-
-    private final Collection<ExcludeColumn> excludeColumns = new LinkedList<>();
-
-    public IncludeTable() {
-    }
-
-    public IncludeTable(String pattern) {
-        super(pattern);
-    }
-
-    public Collection<IncludeColumn> getIncludeColumns() {
-        return includeColumns;
-    }
-
-    public void setIncludeColumns(Collection<IncludeColumn> includeColumns) {
-        this.includeColumns.addAll(includeColumns);
-    }
-
-    public Collection<ExcludeColumn> getExcludeColumns() {
-        return excludeColumns;
-    }
-
-    public void setExcludeColumns(Collection<ExcludeColumn> excludeColumns) {
-        this.excludeColumns.addAll(excludeColumns);
-    }
-
-    public void addIncludeColumn(IncludeColumn includeColumn) {
-        this.includeColumns.add(includeColumn);
-    }
-
-    public void addExcludeColumn(ExcludeColumn excludeColumn) {
-        this.excludeColumns.add(excludeColumn);
-    }
-
-    @Override
-    public StringBuilder toString(StringBuilder res, String s) {
-        super.toString(res, s);
-
-        String prefix = s + "  ";
-        if (includeColumns != null && !includeColumns.isEmpty()) {
-            for (IncludeColumn includeColumn : includeColumns) {
-                includeColumn.toString(res, prefix);
-            }
-        }
-
-        if (excludeColumns != null && !excludeColumns.isEmpty()) {
-            for (ExcludeColumn excludeColumn : excludeColumns) {
-                excludeColumn.toString(res, prefix);
-            }
-        }
-
-        return res;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/PatternParam.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/PatternParam.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/PatternParam.java
deleted file mode 100644
index 240cd5d..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/PatternParam.java
+++ /dev/null
@@ -1,82 +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.dbimport;
-
-/**
- * @since 4.0.
- */
-public class PatternParam {
-
-    private String pattern;
-
-    public PatternParam() {
-    }
-
-    public PatternParam(String pattern) {
-        this.pattern = pattern;
-    }
-
-    public String getPattern() {
-        return pattern;
-    }
-
-    public void setPattern(String pattern) {
-        this.pattern = pattern;
-    }
-
-    public void setName(String name) {
-        setPattern(name);
-    }
-
-    /**
-     * Used by Maven plugin
-     */
-    public void set(String pattern) {
-        setPattern(pattern);
-    }
-
-
-    /**
-     * Used by Ant task
-     */
-    public void addText(String pattern) {
-        if (pattern.trim().isEmpty()) {
-            return;
-        }
-
-        setPattern(pattern);
-    }
-
-    /**
-     * used by Ant?
-     */
-    public void addConfiguredPattern(AntNestedElement pattern) {
-        set(pattern.getName());
-    }
-
-    @Override
-    public String toString() {
-        return toString(new StringBuilder(), "").toString();
-    }
-
-    public StringBuilder toString(StringBuilder res, String s) {
-        res.append(s).append(getClass().getSimpleName()).append(": ").append(pattern).append("\n");
-        return res;
-    }
-}


[2/4] cayenne git commit: CAY-2215 move all DbImport code from cayenne-tools and cayenne-server modules to cayenne-dbsync module

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineering.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineering.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineering.java
deleted file mode 100644
index dd24211..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineering.java
+++ /dev/null
@@ -1,210 +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
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * 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.dbimport;
-
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.LinkedList;
-
-/**
- * @since 4.0
- */
-public class ReverseEngineering extends SchemaContainer implements Serializable {
-
-    private Boolean skipRelationshipsLoading;
-
-    private Boolean skipPrimaryKeyLoading;
-
-    /*
-     * <p>
-     * A default package for ObjEntity Java classes.
-     * </p>
-     * <p>
-     * If not specified, and the existing DataMap already has the default package,
-     * the existing package will be used.
-     * </p>
-     */
-    private String defaultPackage;
-
-    /**
-     * <p>
-     * Automatically tagging each DbEntity with the actual DB catalog/schema (default behavior) may sometimes be undesirable.
-     * If this is the case then setting forceDataMapCatalog to true will set DbEntity catalog to one in the DataMap.
-     * </p>
-     * <p>
-     * Default value is <b>false</b>.
-     * </p>
-     */
-    private boolean forceDataMapCatalog;
-
-    /**
-     * <p>
-     * Automatically tagging each DbEntity with the actual DB catalog/schema (default behavior) may sometimes be undesirable.
-     * If this is the case then setting forceDataMapSchema to true will set DbEntity schema to one in the DataMap.
-     * </p>
-     * <p>
-     * Default value is <b>false</b>.
-     * </p>
-     */
-    private boolean forceDataMapSchema;
-
-    /**
-     * <p>
-     * A comma-separated list of Perl5 patterns that defines which imported tables should have their primary key columns
-     * mapped as ObjAttributes.
-     * </p>
-     * <p><b>"*"</b> would indicate all tables.</p>
-     */
-    private String meaningfulPkTables;
-
-    /**
-     * <p>
-     * Object layer naming generator implementation.
-     * Should be fully qualified Java class name implementing "org.apache.cayenne.dbsync.naming.ObjectNameGenerator".
-     * </p>
-     * <p>
-     * The default is "org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator".
-     * </p>
-     */
-    private String namingStrategy = "org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator";
-
-    /**
-     * A regular expression that should match the part of the table name to strip before generating DB names.
-     */
-    private String stripFromTableNames = "";
-
-    /**
-     * <p>If true, would use primitives instead of numeric and boolean classes.</p>
-     * <p>Default is <b>"true"</b>, i.e. primitives will be used.</p>
-     */
-    private boolean usePrimitives = true;
-
-    /**
-     * Typical types are: <ul>
-     * <li> "TABLE"
-     * <li> "VIEW"
-     * <li> "SYSTEM TABLE"
-     * <li> "GLOBAL TEMPORARY",
-     * <li> "LOCAL TEMPORARY"
-     * <li> "ALIAS"
-     * <li> "SYNONYM"
-     * </ul>
-     */
-    private final Collection<String> tableTypes = new LinkedList<>();
-
-    private final Collection<Catalog> catalogCollection = new LinkedList<>();
-
-    public ReverseEngineering() {
-    }
-
-    public Boolean getSkipRelationshipsLoading() {
-        return skipRelationshipsLoading;
-    }
-
-    public void setSkipRelationshipsLoading(Boolean skipRelationshipsLoading) {
-        this.skipRelationshipsLoading = skipRelationshipsLoading;
-    }
-
-    public Boolean getSkipPrimaryKeyLoading() {
-        return skipPrimaryKeyLoading;
-    }
-
-    public void setSkipPrimaryKeyLoading(Boolean skipPrimaryKeyLoading) {
-        this.skipPrimaryKeyLoading = skipPrimaryKeyLoading;
-    }
-
-    public Collection<Catalog> getCatalogs() {
-        return catalogCollection;
-    }
-
-    public String[] getTableTypes() {
-        return tableTypes.toArray(new String[tableTypes.size()]);
-    }
-
-    /*
-     * Typical types are "TABLE",
-     * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
-     * "LOCAL TEMPORARY", "ALIAS", "SYNONYM"., etc.
-     */
-    public void setTableTypes(Collection<String> tableTypes) {
-        this.tableTypes.addAll(tableTypes);
-    }
-
-    /*
-     * Typical types are "TABLE",
-     * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
-     * "LOCAL TEMPORARY", "ALIAS", "SYNONYM"., etc.
-     */
-    public void addTableType(String type) {
-        this.tableTypes.add(type);
-    }
-
-    public void addCatalog(Catalog catalog) {
-        this.catalogCollection.add(catalog);
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder res = new StringBuilder();
-        res.append("ReverseEngineering: ").append("\n");
-
-        if (!isBlank(catalogCollection)) {
-            for (Catalog catalog : catalogCollection) {
-                catalog.toString(res, "  ");
-            }
-        }
-
-        if (skipRelationshipsLoading != null && skipRelationshipsLoading) {
-            res.append("\n        Skip Relationships Loading");
-        }
-        if (skipPrimaryKeyLoading != null && skipPrimaryKeyLoading) {
-            res.append("\n        Skip PrimaryKey Loading");
-        }
-
-        return super.toString(res, "  ").toString();
-    }
-
-    public String getDefaultPackage() {
-        return defaultPackage;
-    }
-
-    public boolean isForceDataMapCatalog() {
-        return forceDataMapCatalog;
-    }
-
-    public boolean isForceDataMapSchema() {
-        return forceDataMapSchema;
-    }
-
-    public String getMeaningfulPkTables() {
-        return meaningfulPkTables;
-    }
-
-    public String getNamingStrategy() {
-        return namingStrategy;
-    }
-
-    public String getStripFromTableNames() {
-        return stripFromTableNames;
-    }
-
-    public boolean isUsePrimitives() {
-        return usePrimitives;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Schema.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Schema.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Schema.java
deleted file mode 100644
index 5c3592b..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Schema.java
+++ /dev/null
@@ -1,38 +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.dbimport;
-
-/**
- * @since 4.0.
- */
-public class Schema extends FilterContainer {
-
-    public Schema() {
-    }
-
-    public Schema(String name) {
-        setName(name);
-    }
-
-    @Override
-    public StringBuilder toString(StringBuilder res, String prefix) {
-        res.append(prefix).append("Schema: ").append(getName()).append("\n");
-        return super.toString(res, prefix + "  ");
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/SchemaContainer.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/SchemaContainer.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/SchemaContainer.java
deleted file mode 100644
index 935d1e8..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/SchemaContainer.java
+++ /dev/null
@@ -1,67 +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.dbimport;
-
-import java.util.Collection;
-import java.util.LinkedList;
-
-/**
- * @since 4.0
- */
-abstract class SchemaContainer extends FilterContainer {
-
-    private final Collection<Schema> schemaCollection = new LinkedList<>();
-
-    public Collection<Schema> getSchemas() {
-        return schemaCollection;
-    }
-
-    public void addSchema(Schema schema) {
-        this.schemaCollection.add(schema);
-    }
-
-    @Override
-    public boolean isEmptyContainer() {
-        if (!super.isEmptyContainer()) {
-            return false;
-        }
-
-        if (schemaCollection.isEmpty()) {
-            return true;
-        }
-
-        for (Schema schema : schemaCollection) {
-            if (!schema.isEmptyContainer()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public StringBuilder toString(StringBuilder res, String prefix) {
-        if (!isBlank(schemaCollection)) {
-            for (Schema schema : schemaCollection) {
-                schema.toString(res, prefix);
-            }
-        }
-
-        return super.toString(res, prefix + "  ");
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/main/java/org/apache/cayenne/dbimport/package-info.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/package-info.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/package-info.java
deleted file mode 100644
index fba062c..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/package-info.java
+++ /dev/null
@@ -1,24 +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.
- ****************************************************************/
-
-@XmlSchema(namespace="http://cayenne.apache.org/schema/8/reverseEngineering", elementFormDefault= XmlNsForm.QUALIFIED)
-package org.apache.cayenne.dbimport;
-
-import javax.xml.bind.annotation.XmlNsForm;
-import javax.xml.bind.annotation.XmlSchema;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-server/src/test/java/org/apache/cayenne/dbimport/ReverseEngineeringUtils.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/dbimport/ReverseEngineeringUtils.java b/cayenne-server/src/test/java/org/apache/cayenne/dbimport/ReverseEngineeringUtils.java
deleted file mode 100644
index 627ae0f..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/dbimport/ReverseEngineeringUtils.java
+++ /dev/null
@@ -1,173 +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.dbimport;
-
-import java.util.Iterator;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class ReverseEngineeringUtils {
-
-    public static void assertCatalog(ReverseEngineering engineering) {
-        Iterator<Catalog> catalogs = engineering.getCatalogs().iterator();
-        assertEquals("catalog-name-01", catalogs.next().getName());
-        assertEquals("catalog-name-02", catalogs.next().getName());
-
-        assertCatalog(catalogs.next());
-    }
-
-    public static void assertCatalog(Catalog catalog ) {
-        assertEquals("catalog-name-03", catalog.getName());
-
-        Iterator<IncludeTable> includeTables = catalog.getIncludeTables().iterator();
-        assertEquals("includeTable-01", includeTables.next().getPattern());
-        assertEquals("includeTable-02", includeTables.next().getPattern());
-
-        IncludeTable includeTable = includeTables.next();
-        assertEquals("includeTable-03", includeTable.getPattern());
-        assertEquals("includeColumn-01", includeTable.getIncludeColumns().iterator().next().getPattern());
-        assertEquals("excludeColumn-01", includeTable.getExcludeColumns().iterator().next().getPattern());
-
-        Iterator<ExcludeTable> excludeTables = catalog.getExcludeTables().iterator();
-        assertEquals("excludeTable-01", excludeTables.next().getPattern());
-        assertEquals("excludeTable-02", excludeTables.next().getPattern());
-        assertEquals("excludeTable-03", excludeTables.next().getPattern());
-
-        Iterator<ExcludeColumn> excludeColumns = catalog.getExcludeColumns().iterator();
-        assertEquals("excludeColumn-01", excludeColumns.next().getPattern());
-        assertEquals("excludeColumn-02", excludeColumns.next().getPattern());
-        assertEquals("excludeColumn-03", excludeColumns.next().getPattern());
-        Iterator<IncludeColumn> includeColumns = catalog.getIncludeColumns().iterator();
-        assertEquals("includeColumn-01", includeColumns.next().getPattern());
-        assertEquals("includeColumn-02", includeColumns.next().getPattern());
-        assertEquals("includeColumn-03", includeColumns.next().getPattern());
-
-        Iterator<ExcludeProcedure> excludeProcedures = catalog.getExcludeProcedures().iterator();
-        assertEquals("excludeProcedure-01", excludeProcedures.next().getPattern());
-        assertEquals("excludeProcedure-02", excludeProcedures.next().getPattern());
-        assertEquals("excludeProcedure-03", excludeProcedures.next().getPattern());
-        Iterator<IncludeProcedure> includeProcedures = catalog.getIncludeProcedures().iterator();
-        assertEquals("includeProcedure-01", includeProcedures.next().getPattern());
-        assertEquals("includeProcedure-02", includeProcedures.next().getPattern());
-        assertEquals("includeProcedure-03", includeProcedures.next().getPattern());
-    }
-
-    public static void assertSchema(ReverseEngineering engineering) {
-        Iterator<Schema> schemas = engineering.getSchemas().iterator();
-        assertEquals("schema-name-01", schemas.next().getName());
-        assertEquals("schema-name-02", schemas.next().getName());
-
-        Schema schema = schemas.next();
-        assertEquals("schema-name-03", schema.getName());
-
-        assertSchemaContent(schema);
-    }
-
-    public static void assertSchemaContent(Schema schema) {
-        Iterator<IncludeTable> includeTables = schema.getIncludeTables().iterator();
-        assertEquals("includeTable-01", includeTables.next().getPattern());
-        assertEquals("includeTable-02", includeTables.next().getPattern());
-
-        IncludeTable includeTable = includeTables.next();
-        assertEquals("includeTable-03", includeTable.getPattern());
-        assertEquals("includeColumn-01", includeTable.getIncludeColumns().iterator().next().getPattern());
-        assertEquals("excludeColumn-01", includeTable.getExcludeColumns().iterator().next().getPattern());
-
-        Iterator<ExcludeTable> excludeTables = schema.getExcludeTables().iterator();
-        assertEquals("excludeTable-01", excludeTables.next().getPattern());
-        assertEquals("excludeTable-02", excludeTables.next().getPattern());
-        assertEquals("excludeTable-03", excludeTables.next().getPattern());
-
-        Iterator<ExcludeColumn> excludeColumns = schema.getExcludeColumns().iterator();
-        assertEquals("excludeColumn-01", excludeColumns.next().getPattern());
-        assertEquals("excludeColumn-02", excludeColumns.next().getPattern());
-        assertEquals("excludeColumn-03", excludeColumns.next().getPattern());
-        Iterator<IncludeColumn> includeColumns = schema.getIncludeColumns().iterator();
-        assertEquals("includeColumn-01", includeColumns.next().getPattern());
-        assertEquals("includeColumn-02", includeColumns.next().getPattern());
-        assertEquals("includeColumn-03", includeColumns.next().getPattern());
-
-        Iterator<ExcludeProcedure> excludeProcedures = schema.getExcludeProcedures().iterator();
-        assertEquals("excludeProcedure-01", excludeProcedures.next().getPattern());
-        assertEquals("excludeProcedure-02", excludeProcedures.next().getPattern());
-        assertEquals("excludeProcedure-03", excludeProcedures.next().getPattern());
-        Iterator<IncludeProcedure> includeProcedures = schema.getIncludeProcedures().iterator();
-        assertEquals("includeProcedure-01", includeProcedures.next().getPattern());
-        assertEquals("includeProcedure-02", includeProcedures.next().getPattern());
-        assertEquals("includeProcedure-03", includeProcedures.next().getPattern());
-    }
-
-    public static void assertCatalogAndSchema(ReverseEngineering engineering) {
-        Catalog catalog = engineering.getCatalogs().iterator().next();
-        assertEquals("catalog-name", catalog.getName());
-
-        Schema schema = catalog.getSchemas().iterator().next();
-        assertEquals("schema-name", schema.getName());
-
-        assertSchemaContent(schema);
-    }
-
-    public static void assertFlat(ReverseEngineering engineering) {
-        Iterator<IncludeTable> includeTables = engineering.getIncludeTables().iterator();
-        assertEquals("includeTable-01", includeTables.next().getPattern());
-        assertEquals("includeTable-02", includeTables.next().getPattern());
-
-        IncludeTable includeTable = includeTables.next();
-        assertEquals("includeTable-03", includeTable.getPattern());
-        assertEquals("includeColumn-01", includeTable.getIncludeColumns().iterator().next().getPattern());
-        assertEquals("excludeColumn-01", includeTable.getExcludeColumns().iterator().next().getPattern());
-
-        Iterator<ExcludeTable> excludeTables = engineering.getExcludeTables().iterator();
-        assertEquals("excludeTable-01", excludeTables.next().getPattern());
-        assertEquals("excludeTable-02", excludeTables.next().getPattern());
-        assertEquals("excludeTable-03", excludeTables.next().getPattern());
-
-        Iterator<ExcludeColumn> excludeColumns = engineering.getExcludeColumns().iterator();
-        assertEquals("excludeColumn-01", excludeColumns.next().getPattern());
-        assertEquals("excludeColumn-02", excludeColumns.next().getPattern());
-        assertEquals("excludeColumn-03", excludeColumns.next().getPattern());
-        Iterator<IncludeColumn> includeColumns = engineering.getIncludeColumns().iterator();
-        assertEquals("includeColumn-01", includeColumns.next().getPattern());
-        assertEquals("includeColumn-02", includeColumns.next().getPattern());
-        assertEquals("includeColumn-03", includeColumns.next().getPattern());
-
-        Iterator<ExcludeProcedure> excludeProcedures = engineering.getExcludeProcedures().iterator();
-        assertEquals("excludeProcedure-01", excludeProcedures.next().getPattern());
-        assertEquals("excludeProcedure-02", excludeProcedures.next().getPattern());
-        assertEquals("excludeProcedure-03", excludeProcedures.next().getPattern());
-        Iterator<IncludeProcedure> includeProcedures = engineering.getIncludeProcedures().iterator();
-        assertEquals("includeProcedure-01", includeProcedures.next().getPattern());
-        assertEquals("includeProcedure-02", includeProcedures.next().getPattern());
-        assertEquals("includeProcedure-03", includeProcedures.next().getPattern());
-    }
-
-    public static void assertSkipRelationshipsLoading(ReverseEngineering engineering) {
-        assertTrue(engineering.getSkipRelationshipsLoading());
-    }
-
-    public static void assertSkipPrimaryKeyLoading(ReverseEngineering engineering) {
-        assertTrue(engineering.getSkipPrimaryKeyLoading());
-    }
-
-    public static void assertTableTypes(ReverseEngineering engineering) {
-        assertArrayEquals(new String[]{"type1", "type2", "type3"}, engineering.getTableTypes());
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java
index 2319212..ce2e574 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java
@@ -28,7 +28,7 @@ import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.log.NoopJdbcEventLogger;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.tools.configuration.ToolsModule;
+import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
 import org.apache.cayenne.util.Util;
 import org.apache.commons.logging.Log;
 import org.apache.tools.ant.BuildException;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImportConfigurationValidator.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImportConfigurationValidator.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImportConfigurationValidator.java
deleted file mode 100644
index 8a92705..0000000
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImportConfigurationValidator.java
+++ /dev/null
@@ -1,77 +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.tools;
-
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.configuration.server.DataSourceFactory;
-import org.apache.cayenne.configuration.server.DbAdapterFactory;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dbimport.Catalog;
-import org.apache.cayenne.dbimport.ReverseEngineering;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.tools.dbimport.DbImportConfiguration;
-
-import java.util.Collection;
-import javax.sql.DataSource;
-
-class DbImportConfigurationValidator implements Cloneable {
-    private final ReverseEngineering reverseEngineering;
-    private final DbImportConfiguration config;
-    private final Injector injector;
-
-    DbImportConfigurationValidator(ReverseEngineering reverseEngineering, DbImportConfiguration config, Injector injector) {
-        this.reverseEngineering = reverseEngineering;
-        this.config = config;
-        this.injector = injector;
-    }
-
-    void validate() throws Exception {
-        DataNodeDescriptor dataNodeDescriptor = config.createDataNodeDescriptor();
-        DbAdapter adapter;
-
-        try {
-            DataSource dataSource = injector.getInstance(DataSourceFactory.class).getDataSource(dataNodeDescriptor);
-            adapter = injector.getInstance(DbAdapterFactory.class).createAdapter(dataNodeDescriptor, dataSource);
-        } catch (Exception ex) {
-            throw new Exception("Error creating DataSource or DbAdapter for DataNodeDescriptor (" + dataNodeDescriptor + ")", ex);
-        }
-
-        if (adapter != null && !adapter.supportsCatalogsOnReverseEngineering() && !isReverseEngineeringCatalogsEmpty()) {
-            String message = "Your database does not support catalogs on reverse engineering. " +
-                    "It allows to connect to only one at the moment. " +
-                    "Please don't note catalogs in <dbimport> configuration.";
-            throw new Exception(message);
-        }
-    }
-
-    private boolean isReverseEngineeringCatalogsEmpty() {
-        Collection<Catalog> catalogs = reverseEngineering.getCatalogs();
-        if (catalogs == null || catalogs.isEmpty()) {
-            return true;
-        }
-
-        for (Catalog catalog : catalogs) {
-            if (catalog.getName() != null) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
index aa4b631..6c939c1 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
@@ -19,24 +19,25 @@
 package org.apache.cayenne.tools;
 
 import org.apache.cayenne.conn.DataSourceInfo;
-import org.apache.cayenne.dbimport.Catalog;
-import org.apache.cayenne.dbimport.ExcludeColumn;
-import org.apache.cayenne.dbimport.ExcludeProcedure;
-import org.apache.cayenne.dbimport.ExcludeTable;
-import org.apache.cayenne.dbimport.IncludeColumn;
-import org.apache.cayenne.dbimport.IncludeProcedure;
-import org.apache.cayenne.dbimport.IncludeTable;
-import org.apache.cayenne.dbimport.ReverseEngineering;
-import org.apache.cayenne.dbimport.Schema;
 import org.apache.cayenne.dbsync.DbSyncModule;
 import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
+import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportAction;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfigurationValidator;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfiguration;
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportModule;
+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.dbsync.reverse.filters.FiltersConfigBuilder;
 import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.tools.configuration.ToolsModule;
-import org.apache.cayenne.tools.dbimport.DbImportAction;
-import org.apache.cayenne.tools.dbimport.DbImportConfiguration;
-import org.apache.cayenne.tools.dbimport.DbImportModule;
 import org.apache.cayenne.util.Util;
 import org.apache.commons.logging.Log;
 import org.apache.tools.ant.BuildException;
@@ -114,11 +115,8 @@ public class DbImporterTask extends Task {
         config.setSkipPrimaryKeyLoading(reverseEngineering.getSkipPrimaryKeyLoading());
         config.setTableTypes(reverseEngineering.getTableTypes());
 
-        Injector injector = DIBootstrap.createInjector(new DbSyncModule(),
-                new ToolsModule(logger), new DbImportModule());
-
-        DbImportConfigurationValidator validator = new DbImportConfigurationValidator(
-                reverseEngineering, config, injector);
+        Injector injector = DIBootstrap.createInjector(new DbSyncModule(), new ToolsModule(logger), new DbImportModule());
+        DbImportConfigurationValidator validator = new DbImportConfigurationValidator(reverseEngineering, config, injector);
         try {
             validator.validate();
         } catch (Exception ex) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/main/java/org/apache/cayenne/tools/configuration/DriverDataSourceFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/configuration/DriverDataSourceFactory.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/configuration/DriverDataSourceFactory.java
deleted file mode 100644
index c5425d5..0000000
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/configuration/DriverDataSourceFactory.java
+++ /dev/null
@@ -1,53 +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.tools.configuration;
-
-import java.sql.Driver;
-
-import javax.sql.DataSource;
-
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.configuration.server.DataSourceFactory;
-import org.apache.cayenne.conn.DataSourceInfo;
-import org.apache.cayenne.datasource.DriverDataSource;
-import org.apache.cayenne.di.AdhocObjectFactory;
-import org.apache.cayenne.di.Inject;
-
-/**
- * @since 4.0
- */
-public class DriverDataSourceFactory implements DataSourceFactory {
-
-	private AdhocObjectFactory objectFactory;
-
-	public DriverDataSourceFactory(@Inject AdhocObjectFactory objectFactory) {
-		this.objectFactory = objectFactory;
-	}
-
-	public DataSource getDataSource(DataNodeDescriptor nodeDescriptor) throws Exception {
-		DataSourceInfo properties = nodeDescriptor.getDataSourceDescriptor();
-		if (properties == null) {
-			throw new IllegalArgumentException("'nodeDescriptor' contains no datasource descriptor");
-		}
-
-		Driver driver = objectFactory.newInstance(Driver.class, properties.getJdbcDriver());
-		return new DriverDataSource(driver, properties.getDataSourceUrl(), properties.getUserName(),
-				properties.getPassword());
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/main/java/org/apache/cayenne/tools/configuration/ToolsModule.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/configuration/ToolsModule.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/configuration/ToolsModule.java
deleted file mode 100644
index 7abe3b0..0000000
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/configuration/ToolsModule.java
+++ /dev/null
@@ -1,106 +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.tools.configuration;
-
-import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
-import org.apache.cayenne.access.translator.batch.DefaultBatchTranslatorFactory;
-import org.apache.cayenne.configuration.Constants;
-import org.apache.cayenne.configuration.DefaultRuntimeProperties;
-import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.configuration.server.DataSourceFactory;
-import org.apache.cayenne.configuration.server.DbAdapterFactory;
-import org.apache.cayenne.configuration.server.DefaultDbAdapterFactory;
-import org.apache.cayenne.configuration.server.ServerModule;
-import org.apache.cayenne.dba.db2.DB2Sniffer;
-import org.apache.cayenne.dba.derby.DerbySniffer;
-import org.apache.cayenne.dba.firebird.FirebirdSniffer;
-import org.apache.cayenne.dba.frontbase.FrontBaseSniffer;
-import org.apache.cayenne.dba.h2.H2Sniffer;
-import org.apache.cayenne.dba.hsqldb.HSQLDBSniffer;
-import org.apache.cayenne.dba.ingres.IngresSniffer;
-import org.apache.cayenne.dba.mysql.MySQLSniffer;
-import org.apache.cayenne.dba.openbase.OpenBaseSniffer;
-import org.apache.cayenne.dba.oracle.OracleSniffer;
-import org.apache.cayenne.dba.postgres.PostgresSniffer;
-import org.apache.cayenne.dba.sqlite.SQLiteSniffer;
-import org.apache.cayenne.dba.sqlserver.SQLServerSniffer;
-import org.apache.cayenne.dba.sybase.SybaseSniffer;
-import org.apache.cayenne.di.AdhocObjectFactory;
-import org.apache.cayenne.di.Binder;
-import org.apache.cayenne.di.ClassLoaderManager;
-import org.apache.cayenne.di.Key;
-import org.apache.cayenne.di.Module;
-import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
-import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
-import org.apache.cayenne.log.CommonsJdbcEventLogger;
-import org.apache.cayenne.log.JdbcEventLogger;
-import org.apache.cayenne.resource.ClassLoaderResourceLocator;
-import org.apache.cayenne.resource.ResourceLocator;
-import org.apache.commons.logging.Log;
-
-/**
- * A DI module to bootstrap DI container for Cayenne Ant tasks and Maven
- * plugins.
- * 
- * @since 4.0
- */
-public class ToolsModule implements Module {
-
-    private Log logger;
-
-    public ToolsModule(Log logger) {
-
-        if (logger == null) {
-            throw new NullPointerException("Null logger");
-        }
-
-        this.logger = logger;
-    }
-
-    public void configure(Binder binder) {
-
-        binder.bind(Log.class).toInstance(logger);
-
-        // configure empty global stack properties
-        ServerModule.contributeProperties(binder);
-
-        ServerModule.contributeDefaultTypes(binder);
-        ServerModule.contributeUserTypes(binder);
-        ServerModule.contributeTypeFactories(binder);
-
-        binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
-        binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
-        binder.bind(ResourceLocator.class).to(ClassLoaderResourceLocator.class);
-        binder.bind(Key.get(ResourceLocator.class, Constants.SERVER_RESOURCE_LOCATOR)).to(ClassLoaderResourceLocator.class);
-
-        binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
-        binder.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class);
-        binder.bind(JdbcEventLogger.class).to(CommonsJdbcEventLogger.class);
-
-        ServerModule.contributeAdapterDetectors(binder).add(FirebirdSniffer.class).add(OpenBaseSniffer.class)
-                .add(FrontBaseSniffer.class).add(IngresSniffer.class).add(SQLiteSniffer.class).add(DB2Sniffer.class)
-                .add(H2Sniffer.class).add(HSQLDBSniffer.class).add(SybaseSniffer.class).add(DerbySniffer.class)
-                .add(SQLServerSniffer.class).add(OracleSniffer.class).add(PostgresSniffer.class)
-                .add(MySQLSniffer.class);
-
-        binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
-        binder.bind(DataSourceFactory.class).to(DriverDataSourceFactory.class);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
deleted file mode 100644
index 757d5bf..0000000
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
+++ /dev/null
@@ -1,30 +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.tools.dbimport;
-
-/**
- * An API of a strategy that can load DB schema and merge it to a new or an existing DataMap.
- *
- * @since 4.0
- */
-public interface DbImportAction {
-	
-    void execute(DbImportConfiguration config) throws Exception;
-	
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java
deleted file mode 100644
index b7e248b..0000000
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java
+++ /dev/null
@@ -1,302 +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.tools.dbimport;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.conn.DataSourceInfo;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dbsync.filter.NameFilter;
-import org.apache.cayenne.dbsync.filter.NamePatternMatcher;
-import org.apache.cayenne.dbsync.reverse.dbload.DefaultModelMergeDelegate;
-import org.apache.cayenne.dbsync.reverse.dbload.ModelMergeDelegate;
-import org.apache.cayenne.dbsync.naming.DbEntityNameStemmer;
-import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
-import org.apache.cayenne.dbsync.naming.NoStemStemmer;
-import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
-import org.apache.cayenne.dbsync.naming.PatternStemmer;
-import org.apache.cayenne.dbsync.reverse.dbload.DbLoaderConfiguration;
-import org.apache.cayenne.dbsync.reverse.dbload.DbLoaderDelegate;
-import org.apache.cayenne.dbsync.reverse.dbload.DefaultDbLoaderDelegate;
-import org.apache.cayenne.dbsync.reverse.dbload.LoggingDbLoaderDelegate;
-import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
-import org.apache.commons.logging.Log;
-
-import java.io.File;
-import java.util.regex.Pattern;
-
-/**
- * @since 4.0
- */
-public class DbImportConfiguration {
-
-    private static final String DATA_MAP_LOCATION_SUFFIX = ".map.xml";
-
-    private final DataSourceInfo dataSourceInfo;
-    private final DbLoaderConfiguration dbLoaderConfiguration;
-    private File targetDataMap;
-    private String defaultPackage;
-    private String meaningfulPkTables;
-    private String adapter;
-    private boolean usePrimitives;
-    private Log logger;
-    private String namingStrategy;
-    private String stripFromTableNames;
-    private boolean forceDataMapCatalog;
-    private boolean forceDataMapSchema;
-
-    public DbImportConfiguration() {
-        this.dataSourceInfo = new DataSourceInfo();
-        this.dbLoaderConfiguration = new DbLoaderConfiguration();
-    }
-
-    public String getStripFromTableNames() {
-        return stripFromTableNames;
-    }
-
-    public void setStripFromTableNames(String stripFromTableNames) {
-        this.stripFromTableNames = stripFromTableNames;
-    }
-
-    public Log getLogger() {
-        return logger;
-    }
-
-    public void setLogger(Log logger) {
-        this.logger = logger;
-    }
-
-    /**
-     * Returns DataMap XML file representing the target of the DB import operation.
-     */
-    public File getTargetDataMap() {
-        return targetDataMap;
-    }
-
-    public void setTargetDataMap(File map) {
-        this.targetDataMap = map;
-    }
-
-    /**
-     * Returns a default package for ObjEntity Java classes.
-     */
-    public String getDefaultPackage() {
-        return defaultPackage;
-    }
-
-    public void setDefaultPackage(String defaultPackage) {
-        this.defaultPackage = defaultPackage;
-    }
-
-    public String getNamingStrategy() {
-        return namingStrategy;
-    }
-
-    public void setNamingStrategy(String namingStrategy) {
-        this.namingStrategy = namingStrategy;
-    }
-
-    /**
-     * Returns the name of a Java class implementing {@link DbAdapter}. This attribute is optional, the default is
-     * {@link org.apache.cayenne.dba.AutoAdapter}, i.e. Cayenne will try to guess the DB type.
-     */
-    public String getAdapter() {
-        return adapter;
-    }
-
-    public void setAdapter(String adapter) {
-        this.adapter = adapter;
-    }
-
-    /**
-     * Returns a comma-separated list of Perl5 regular expressions that match
-     * table names for which {@link DbImportAction} should include ObjAttribute
-     * for PK.
-     */
-    public String getMeaningfulPkTables() {
-        return meaningfulPkTables;
-    }
-
-    public void setMeaningfulPkTables(String meaningfulPkTables) {
-        this.meaningfulPkTables = meaningfulPkTables;
-    }
-
-    public boolean isUsePrimitives() {
-        return usePrimitives;
-    }
-
-    public void setUsePrimitives(boolean usePrimitives) {
-        this.usePrimitives = usePrimitives;
-    }
-
-    public NameFilter createMeaningfulPKFilter() {
-
-        if (meaningfulPkTables == null) {
-            return NamePatternMatcher.EXCLUDE_ALL;
-        }
-
-        // TODO: this filter can't handle table names with comma in them
-        String[] patternStrings = meaningfulPkTables.split(",");
-        Pattern[] patterns = new Pattern[patternStrings.length];
-        for (int i = 0; i < patterns.length; i++) {
-            patterns[i] = Pattern.compile(patternStrings[i]);
-        }
-
-        return new NamePatternMatcher(patterns, new Pattern[0]);
-    }
-
-    public ObjectNameGenerator createNameGenerator() {
-
-        // TODO: not a singleton; called from different places...
-
-        // custom name generator
-        // TODO: support stemmer in non-standard generators...
-        // TODO: load via DI AdhocObjectFactory
-        String namingStrategy = getNamingStrategy();
-        if (namingStrategy != null && !namingStrategy.equals(DefaultObjectNameGenerator.class.getName())) {
-            try {
-                return (ObjectNameGenerator) Class.forName(namingStrategy).newInstance();
-            } catch (Exception e) {
-                throw new CayenneRuntimeException("Error creating name generator: " + namingStrategy, e);
-            }
-        }
-
-        return new DefaultObjectNameGenerator(createStemmer());
-    }
-
-    protected DbEntityNameStemmer createStemmer() {
-        return (stripFromTableNames == null || stripFromTableNames.length() == 0)
-                ? NoStemStemmer.getInstance()
-                : new PatternStemmer(stripFromTableNames, false);
-    }
-
-    public String getDriver() {
-        return dataSourceInfo.getJdbcDriver();
-    }
-
-    public void setDriver(String jdbcDriver) {
-        dataSourceInfo.setJdbcDriver(jdbcDriver);
-    }
-
-    public String getPassword() {
-        return dataSourceInfo.getPassword();
-    }
-
-    public void setPassword(String password) {
-        dataSourceInfo.setPassword(password);
-    }
-
-    public String getUsername() {
-        return dataSourceInfo.getUserName();
-    }
-
-    public void setUsername(String userName) {
-        dataSourceInfo.setUserName(userName);
-    }
-
-    public String getUrl() {
-        return dataSourceInfo.getDataSourceUrl();
-    }
-
-    public void setUrl(String dataSourceUrl) {
-        dataSourceInfo.setDataSourceUrl(dataSourceUrl);
-    }
-
-    public DataNodeDescriptor createDataNodeDescriptor() {
-        DataNodeDescriptor nodeDescriptor = new DataNodeDescriptor();
-        nodeDescriptor.setAdapterType(getAdapter());
-        nodeDescriptor.setDataSourceDescriptor(dataSourceInfo);
-
-        return nodeDescriptor;
-    }
-
-    public String getDataMapName() {
-        String name = targetDataMap.getName();
-        if (!name.endsWith(DATA_MAP_LOCATION_SUFFIX)) {
-            throw new CayenneRuntimeException("DataMap file name must end with '%s': '%s'", DATA_MAP_LOCATION_SUFFIX,
-                    name);
-        }
-        return name.substring(0, name.length() - DATA_MAP_LOCATION_SUFFIX.length());
-    }
-
-    public ModelMergeDelegate createMergeDelegate() {
-        return new DefaultModelMergeDelegate();
-    }
-
-    public DbLoaderDelegate createLoaderDelegate() {
-        if (getLogger() != null) {
-            return new LoggingDbLoaderDelegate(getLogger());
-        } else {
-            return new DefaultDbLoaderDelegate();
-        }
-    }
-
-    /**
-     * Returns configuration that should be used for DB import stage when the schema is loaded from the database.
-     */
-    public DbLoaderConfiguration getDbLoaderConfig() {
-        return dbLoaderConfiguration;
-    }
-
-    public void setFiltersConfig(FiltersConfig filtersConfig) {
-        dbLoaderConfiguration.setFiltersConfig(filtersConfig);
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder res = new StringBuilder("Importer options:");
-        for (String line : dbLoaderConfiguration.toString().split("\n")) {
-            res.append("    ").append(line).append("\n");
-        }
-
-        return res.toString();
-    }
-
-    public DataSourceInfo getDataSourceInfo() {
-        return dataSourceInfo;
-    }
-
-    public void setSkipRelationshipsLoading(Boolean skipRelationshipsLoading) {
-        this.dbLoaderConfiguration.setSkipRelationshipsLoading(skipRelationshipsLoading);
-    }
-
-    public void setSkipPrimaryKeyLoading(Boolean skipPrimaryKeyLoading) {
-        this.dbLoaderConfiguration.setSkipPrimaryKeyLoading(skipPrimaryKeyLoading);
-    }
-
-    public void setTableTypes(String[] tableTypes) {
-        dbLoaderConfiguration.setTableTypes(tableTypes);
-    }
-
-    public void setForceDataMapCatalog(boolean forceDataMapCatalog) {
-        this.forceDataMapCatalog = forceDataMapCatalog;
-    }
-
-    public boolean isForceDataMapCatalog() {
-        return forceDataMapCatalog;
-    }
-
-    public void setForceDataMapSchema(boolean forceDataMapSchema) {
-        this.forceDataMapSchema = forceDataMapSchema;
-    }
-
-    public boolean isForceDataMapSchema() {
-        return forceDataMapSchema;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportModule.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportModule.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportModule.java
deleted file mode 100644
index 93b5f6b..0000000
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportModule.java
+++ /dev/null
@@ -1,47 +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.tools.dbimport;
-
-import org.apache.cayenne.configuration.ConfigurationNameMapper;
-import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
-import org.apache.cayenne.dbsync.DbSyncModule;
-import org.apache.cayenne.di.Binder;
-import org.apache.cayenne.di.Module;
-import org.apache.cayenne.map.MapLoader;
-import org.apache.cayenne.project.FileProjectSaver;
-import org.apache.cayenne.project.ProjectSaver;
-import org.apache.cayenne.tools.configuration.ToolsModule;
-
-/**
- * A DI module that bootstraps {@link DbImportAction}. Should be used in
- * conjunction with {@link ToolsModule} and {@link DbSyncModule}.
- *
- * @since 4.0
- */
-public class DbImportModule implements Module {
-
-    public void configure(Binder binder) {
-        binder.bind(DbImportAction.class).to(DefaultDbImportAction.class);
-        binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
-        binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-        binder.bind(MapLoader.class).to(MapLoader.class);
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
deleted file mode 100644
index 575b0a4..0000000
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
+++ /dev/null
@@ -1,422 +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.tools.dbimport;
-
-import org.apache.cayenne.configuration.ConfigurationTree;
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.configuration.server.DataSourceFactory;
-import org.apache.cayenne.configuration.server.DbAdapterFactory;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dbsync.filter.NameFilter;
-import org.apache.cayenne.dbsync.merge.token.model.AbstractToModelToken;
-import org.apache.cayenne.dbsync.merge.DataMapMerger;
-import org.apache.cayenne.dbsync.merge.context.MergerContext;
-import org.apache.cayenne.dbsync.merge.token.MergerToken;
-import org.apache.cayenne.dbsync.reverse.dbload.ModelMergeDelegate;
-import org.apache.cayenne.dbsync.reverse.dbload.ProxyModelMergeDelegate;
-import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
-import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
-import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
-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.PatternFilter;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.MapLoader;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.map.Procedure;
-import org.apache.cayenne.project.Project;
-import org.apache.cayenne.project.ProjectSaver;
-import org.apache.cayenne.resource.URLResource;
-import org.apache.cayenne.validation.SimpleValidationFailure;
-import org.apache.cayenne.validation.ValidationFailure;
-import org.apache.cayenne.validation.ValidationResult;
-import org.apache.commons.logging.Log;
-import org.xml.sax.InputSource;
-
-import javax.sql.DataSource;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.sql.Connection;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * A default implementation of {@link DbImportAction} that can load DB schema and merge it to a new or an existing
- * DataMap.
- *
- * @since 4.0
- */
-public class DefaultDbImportAction implements DbImportAction {
-
-    private final ProjectSaver projectSaver;
-    private final Log logger;
-    private final DataSourceFactory dataSourceFactory;
-    private final DbAdapterFactory adapterFactory;
-    private final MapLoader mapLoader;
-    private final MergerTokenFactoryProvider mergerTokenFactoryProvider;
-
-    public DefaultDbImportAction(@Inject Log logger,
-                                 @Inject ProjectSaver projectSaver,
-                                 @Inject DataSourceFactory dataSourceFactory,
-                                 @Inject DbAdapterFactory adapterFactory,
-                                 @Inject MapLoader mapLoader,
-                                 @Inject MergerTokenFactoryProvider mergerTokenFactoryProvider) {
-        this.logger = logger;
-        this.projectSaver = projectSaver;
-        this.dataSourceFactory = dataSourceFactory;
-        this.adapterFactory = adapterFactory;
-        this.mapLoader = mapLoader;
-        this.mergerTokenFactoryProvider = mergerTokenFactoryProvider;
-    }
-
-    protected static List<MergerToken> sort(List<MergerToken> reverse) {
-        Collections.sort(reverse);
-        return reverse;
-    }
-
-    /**
-     * Flattens many-to-many relationships in the generated model.
-     */
-    public static void flattenManyToManyRelationships(DataMap map, Collection<ObjEntity> loadedObjEntities,
-                                                         ObjectNameGenerator objectNameGenerator) {
-        if (loadedObjEntities.isEmpty()) {
-            return;
-        }
-        Collection<ObjEntity> entitiesForDelete = new LinkedList<>();
-
-        for (ObjEntity curEntity : loadedObjEntities) {
-            ManyToManyCandidateEntity entity = ManyToManyCandidateEntity.build(curEntity);
-
-            if (entity != null) {
-                entity.optimizeRelationships(objectNameGenerator);
-                entitiesForDelete.add(curEntity);
-            }
-        }
-
-        // remove needed entities
-        for (ObjEntity curDeleteEntity : entitiesForDelete) {
-            map.removeObjEntity(curDeleteEntity.getName(), true);
-        }
-        loadedObjEntities.removeAll(entitiesForDelete);
-    }
-
-    @Override
-    public void execute(DbImportConfiguration config) throws Exception {
-
-        if (logger.isDebugEnabled()) {
-            logger.debug("DB connection: " + config.getDataSourceInfo());
-            logger.debug(config);
-        }
-
-        boolean hasChanges = false;
-        DataNodeDescriptor dataNodeDescriptor = config.createDataNodeDescriptor();
-        DataSource dataSource = dataSourceFactory.getDataSource(dataNodeDescriptor);
-        DbAdapter adapter = adapterFactory.createAdapter(dataNodeDescriptor, dataSource);
-        ObjectNameGenerator objectNameGenerator = config.createNameGenerator();
-
-        DataMap sourceDataMap;
-        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() + "'";
-
-            logger.info("");
-            logger.info("Map file does not exist. Loaded db model will be saved into '" + path);
-
-            hasChanges = true;
-            targetDataMap = newTargetDataMap(config);
-        }
-
-        // transform source DataMap before merging
-        transformSourceBeforeMerge(sourceDataMap, targetDataMap, config);
-
-        MergerTokenFactory mergerTokenFactory = mergerTokenFactoryProvider.get(adapter);
-
-        DbLoaderConfiguration loaderConfig = config.getDbLoaderConfig();
-        List<MergerToken> tokens = DataMapMerger.builder(mergerTokenFactory)
-                .filters(loaderConfig.getFiltersConfig())
-                .skipPKTokens(loaderConfig.isSkipPrimaryKeyLoading())
-                .skipRelationshipsTokens(loaderConfig.isSkipRelationshipsLoading())
-                .build()
-                .createMergeTokens(targetDataMap, sourceDataMap);
-
-        hasChanges |= syncDataMapProperties(targetDataMap, config);
-        hasChanges |= applyTokens(config.createMergeDelegate(),
-                targetDataMap,
-                log(sort(reverse(mergerTokenFactory, tokens))),
-                objectNameGenerator,
-                config.createMeaningfulPKFilter(),
-                config.isUsePrimitives());
-        hasChanges |= syncProcedures(targetDataMap, sourceDataMap, loaderConfig.getFiltersConfig());
-
-        if (hasChanges) {
-            saveLoaded(targetDataMap);
-        }
-    }
-
-
-    protected void transformSourceBeforeMerge(DataMap sourceDataMap,
-                                              DataMap targetDataMap,
-                                              DbImportConfiguration configuration) {
-
-        if (configuration.isForceDataMapCatalog()) {
-            String catalog = targetDataMap.getDefaultCatalog();
-            for (DbEntity e : sourceDataMap.getDbEntities()) {
-                e.setCatalog(catalog);
-            }
-        }
-
-        if (configuration.isForceDataMapSchema()) {
-            String schema = targetDataMap.getDefaultSchema();
-            for (DbEntity e : sourceDataMap.getDbEntities()) {
-                e.setSchema(schema);
-            }
-        }
-
-    }
-
-    private boolean syncDataMapProperties(DataMap targetDataMap, DbImportConfiguration config) {
-
-        String defaultPackage = config.getDefaultPackage();
-        if (defaultPackage == null || defaultPackage.trim().length() == 0) {
-            return false;
-        }
-
-        if (defaultPackage.equals(targetDataMap.getDefaultPackage())) {
-            return false;
-        }
-
-        targetDataMap.setDefaultPackage(defaultPackage);
-        return true;
-    }
-
-    private void relationshipsSanity(DataMap executed) {
-        for (ObjEntity objEntity : executed.getObjEntities()) {
-            List<ObjRelationship> rels = new LinkedList<>(objEntity.getRelationships());
-            for (ObjRelationship rel : rels) {
-                if (rel.getSourceEntity() == null || rel.getTargetEntity() == null) {
-                    logger.error("Incorrect obj relationship source or target entity is null: " + rel);
-
-                    objEntity.removeRelationship(rel.getName());
-                }
-            }
-        }
-    }
-
-    private Collection<MergerToken> log(List<MergerToken> tokens) {
-        logger.info("");
-        if (tokens.isEmpty()) {
-            logger.info("Detected changes: No changes to import.");
-            return tokens;
-        }
-
-        logger.info("Detected changes: ");
-        for (MergerToken token : tokens) {
-            logger.info(String.format("    %-20s %s", token.getTokenName(), token.getTokenValue()));
-        }
-        logger.info("");
-
-        return tokens;
-    }
-
-    protected DataMap existingTargetMap(DbImportConfiguration configuration) throws IOException {
-
-        File file = configuration.getTargetDataMap();
-        if (file != null && file.exists() && file.canRead()) {
-            DataMap dataMap = mapLoader.loadDataMap(new InputSource(file.getCanonicalPath()));
-            dataMap.setNamespace(new EntityResolver(Collections.singleton(dataMap)));
-            dataMap.setConfigurationSource(new URLResource(file.toURI().toURL()));
-
-            return dataMap;
-        }
-
-        return null;
-    }
-
-    protected DataMap newTargetDataMap(DbImportConfiguration config) throws IOException {
-
-        DataMap dataMap = new DataMap();
-
-        dataMap.setName(config.getDataMapName());
-        dataMap.setConfigurationSource(new URLResource(config.getTargetDataMap().toURI().toURL()));
-        dataMap.setNamespace(new EntityResolver(Collections.singleton(dataMap)));
-
-        // update map defaults
-
-        // do not override default package of existing DataMap unless it is
-        // explicitly requested by the plugin caller
-        String defaultPackage = config.getDefaultPackage();
-        if (defaultPackage != null && defaultPackage.length() > 0) {
-            dataMap.setDefaultPackage(defaultPackage);
-        }
-
-        CatalogFilter[] catalogs = config.getDbLoaderConfig().getFiltersConfig().getCatalogs();
-        if (catalogs.length > 0) {
-            // do not override default catalog of existing DataMap unless it is
-            // explicitly requested by the plugin caller, and the provided catalog is
-            // not a pattern
-            String catalog = catalogs[0].name;
-            if (catalog != null && catalog.length() > 0 && catalog.indexOf('%') < 0) {
-                dataMap.setDefaultCatalog(catalog);
-            }
-
-            // do not override default schema of existing DataMap unless it is
-            // explicitly requested by the plugin caller, and the provided schema is
-            // not a pattern
-            String schema = catalogs[0].schemas[0].name;
-            if (schema != null && schema.length() > 0 && schema.indexOf('%') < 0) {
-                dataMap.setDefaultSchema(schema);
-            }
-        }
-
-        return dataMap;
-    }
-
-    private List<MergerToken> reverse(MergerTokenFactory mergerTokenFactory, Iterable<MergerToken> mergeTokens)
-            throws IOException {
-
-        List<MergerToken> tokens = new LinkedList<>();
-        for (MergerToken token : mergeTokens) {
-            if (token instanceof AbstractToModelToken) {
-                continue;
-            }
-            tokens.add(token.createReverse(mergerTokenFactory));
-        }
-        return tokens;
-    }
-
-    private boolean applyTokens(ModelMergeDelegate mergeDelegate,
-                                DataMap targetDataMap,
-                                Collection<MergerToken> tokens,
-                                ObjectNameGenerator nameGenerator,
-                                NameFilter meaningfulPKFilter,
-                                boolean usingPrimitives) {
-
-        if (tokens.isEmpty()) {
-            logger.info("");
-            logger.info("Detected changes: No changes to import.");
-            return false;
-        }
-
-        final Collection<ObjEntity> loadedObjEntities = new LinkedList<>();
-
-        mergeDelegate = new ProxyModelMergeDelegate(mergeDelegate) {
-            @Override
-            public void objEntityAdded(ObjEntity ent) {
-                loadedObjEntities.add(ent);
-                super.objEntityAdded(ent);
-            }
-        };
-
-        MergerContext mergerContext = MergerContext.builder(targetDataMap)
-                .delegate(mergeDelegate)
-                .nameGenerator(nameGenerator)
-                .usingPrimitives(usingPrimitives)
-                .meaningfulPKFilter(meaningfulPKFilter)
-                .build();
-
-        for (MergerToken token : tokens) {
-            try {
-                token.execute(mergerContext);
-            } catch (Throwable th) {
-                String message = "Migration Error. Can't apply changes from token: " + token.getTokenName()
-                        + " (" + token.getTokenValue() + ")";
-
-                logger.error(message, th);
-                mergerContext.getValidationResult().addFailure(new SimpleValidationFailure(th, message));
-            }
-        }
-
-        ValidationResult failures = mergerContext.getValidationResult();
-        if (failures.hasFailures()) {
-            logger.info("Migration Complete.");
-            logger.warn("Migration finished. The following problem(s) were encountered and ignored.");
-            for (ValidationFailure failure : failures.getFailures()) {
-                logger.warn(failure.toString());
-            }
-        } else {
-            logger.info("Migration Complete Successfully.");
-        }
-
-        flattenManyToManyRelationships(targetDataMap, loadedObjEntities, nameGenerator);
-        relationshipsSanity(targetDataMap);
-        return true;
-    }
-
-    private boolean syncProcedures(DataMap targetDataMap, DataMap loadedDataMap, FiltersConfig filters) {
-        Collection<Procedure> procedures = loadedDataMap.getProcedures();
-        if (procedures.isEmpty()) {
-            return false;
-        }
-
-        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());
-                logger.info("Replace procedure " + procedure.getName());
-            } else {
-                logger.info("Add new procedure " + procedure.getName());
-            }
-            targetDataMap.addProcedure(procedure);
-            hasChanges = true;
-        }
-        return hasChanges;
-    }
-
-    protected void saveLoaded(DataMap dataMap) throws FileNotFoundException {
-        ConfigurationTree<DataMap> projectRoot = new ConfigurationTree<>(dataMap);
-        Project project = new Project(projectRoot);
-        projectSaver.save(project);
-    }
-
-    protected DataMap load(DbImportConfiguration config,
-                           DbAdapter adapter,
-                           Connection connection) throws Exception {
-        return createDbLoader(adapter, connection, config).load();
-    }
-
-    protected DbLoader createDbLoader(DbAdapter adapter,
-                                       Connection connection,
-                                       DbImportConfiguration config) {
-        return new DbLoader(adapter, connection,
-                config.getDbLoaderConfig(),
-                config.createLoaderDelegate(),
-                config.createNameGenerator());
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntity.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntity.java
deleted file mode 100644
index 7f183cf..0000000
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/ManyToManyCandidateEntity.java
+++ /dev/null
@@ -1,133 +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.tools.dbimport;
-
-import org.apache.cayenne.dbsync.naming.NameBuilder;
-import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * An ObjEntity that may be removed as a result of flattenning relationships.
- */
-class ManyToManyCandidateEntity {
-
-    private static final Log LOG = LogFactory.getLog(ManyToManyCandidateEntity.class);
-
-    private final ObjEntity joinEntity;
-
-    private final DbRelationship dbRel1;
-    private final DbRelationship dbRel2;
-
-    private final ObjEntity entity1;
-    private final ObjEntity entity2;
-
-    private final DbRelationship reverseRelationship1;
-    private final DbRelationship reverseRelationship2;
-
-    private ManyToManyCandidateEntity(ObjEntity entityValue, List<ObjRelationship> relationships) {
-        joinEntity = entityValue;
-
-        ObjRelationship rel1 = relationships.get(0);
-        ObjRelationship rel2 = relationships.get(1);
-
-        dbRel1 = rel1.getDbRelationships().get(0);
-        dbRel2 = rel2.getDbRelationships().get(0);
-
-        reverseRelationship1 = dbRel1.getReverseRelationship();
-        reverseRelationship2 = dbRel2.getReverseRelationship();
-
-        entity1 = rel1.getTargetEntity();
-        entity2 = rel2.getTargetEntity();
-    }
-
-    /**
-     * Method check - if current entity represent many to many temporary table
-     *
-     * @return true if current entity is represent many to many table; otherwise returns false
-     */
-    public static ManyToManyCandidateEntity build(ObjEntity joinEntity) {
-        ArrayList<ObjRelationship> relationships = new ArrayList<>(joinEntity.getRelationships());
-        if (relationships.size() != 2 || (relationships.get(0).getDbRelationships().isEmpty() || relationships.get(1).getDbRelationships().isEmpty())) {
-            return null;
-        }
-
-        ManyToManyCandidateEntity candidateEntity = new ManyToManyCandidateEntity(joinEntity, relationships);
-        if (candidateEntity.isManyToMany()) {
-            return candidateEntity;
-        }
-
-        return null;
-    }
-
-    private boolean isManyToMany() {
-        boolean isNotHaveAttributes = joinEntity.getAttributes().size() == 0;
-
-        return isNotHaveAttributes
-                && reverseRelationship1 != null && reverseRelationship1.isToDependentPK()
-                && reverseRelationship2 != null && reverseRelationship2.isToDependentPK()
-                && entity1 != null && entity2 != null;
-    }
-
-    private void addFlattenedRelationship(ObjectNameGenerator nameGenerator, ObjEntity srcEntity, ObjEntity dstEntity,
-                                          DbRelationship rel1, DbRelationship rel2) {
-
-        if (rel1.getSourceAttributes().isEmpty() && rel2.getTargetAttributes().isEmpty()) {
-            LOG.warn("Wrong call ManyToManyCandidateEntity.addFlattenedRelationship(... , " + srcEntity.getName()
-                    + ", " + dstEntity.getName() + ", ...)");
-
-            return;
-        }
-
-        ObjRelationship newRelationship = new ObjRelationship();
-        newRelationship.setName(NameBuilder
-                .builder(newRelationship, srcEntity)
-                .baseName(nameGenerator.relationshipName(rel1, rel2))
-                .name());
-
-        newRelationship.setSourceEntity(srcEntity);
-        newRelationship.setTargetEntityName(dstEntity);
-
-        newRelationship.addDbRelationship(rel1);
-        newRelationship.addDbRelationship(rel2);
-
-        srcEntity.addRelationship(newRelationship);
-    }
-
-    /**
-     * Method make direct relationships between 2 entities and remove relationships to
-     * many to many entity
-     *
-     * @param nameGenerator
-     */
-    public void optimizeRelationships(ObjectNameGenerator nameGenerator) {
-        entity1.removeRelationship(reverseRelationship1.getName());
-        entity2.removeRelationship(reverseRelationship2.getName());
-
-        addFlattenedRelationship(nameGenerator, entity1, entity2, reverseRelationship1, dbRel2);
-        addFlattenedRelationship(nameGenerator, entity2, entity1, reverseRelationship2, dbRel1);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbGeneratorTaskTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbGeneratorTaskTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbGeneratorTaskTest.java
index 12af0fd..bd02e12 100644
--- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbGeneratorTaskTest.java
+++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbGeneratorTaskTest.java
@@ -22,9 +22,9 @@ package org.apache.cayenne.tools;
 import org.apache.cayenne.dba.AutoAdapter;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.sqlserver.SQLServerAdapter;
+import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
 import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.tools.configuration.ToolsModule;
 import org.apache.commons.logging.Log;
 import org.junit.Test;
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
index 3d898fc..df746c2 100644
--- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
+++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
@@ -18,10 +18,10 @@
  ****************************************************************/
 package org.apache.cayenne.tools;
 
+import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfiguration;
 import org.apache.cayenne.test.file.FileUtil;
 import org.apache.cayenne.test.jdbc.SQLReader;
 import org.apache.cayenne.test.resource.ResourceUtil;
-import org.apache.cayenne.tools.dbimport.DbImportConfiguration;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.ProjectHelper;
 import org.apache.tools.ant.UnknownElement;
@@ -44,7 +44,7 @@ import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.List;
 
-import static org.apache.cayenne.dbimport.ReverseEngineeringUtils.*;
+import static org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineeringUtils.*;
 import static org.apache.commons.lang.StringUtils.isBlank;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/test/java/org/apache/cayenne/tools/configuration/ToolsModuleTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/configuration/ToolsModuleTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/configuration/ToolsModuleTest.java
deleted file mode 100644
index ae22f25..0000000
--- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/configuration/ToolsModuleTest.java
+++ /dev/null
@@ -1,65 +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.tools.configuration;
-
-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.server.DefaultDbAdapterFactory;
-import org.apache.cayenne.dba.AutoAdapter;
-import org.apache.cayenne.di.AdhocObjectFactory;
-import org.apache.cayenne.di.DIBootstrap;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
-import org.apache.commons.logging.Log;
-import org.junit.Test;
-
-import javax.sql.DataSource;
-
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-
-public class ToolsModuleTest {
-
-    @Test
-    public void testModuleContents() {
-
-        Log log = mock(Log.class);
-        Injector i = DIBootstrap.createInjector(new ToolsModule(log));
-
-        assertSame(log, i.getInstance(Log.class));
-        assertTrue(i.getInstance(DataSourceFactory.class) instanceof DriverDataSourceFactory);
-        assertTrue(i.getInstance(AdhocObjectFactory.class) instanceof DefaultAdhocObjectFactory);
-        assertTrue(i.getInstance(DbAdapterFactory.class) instanceof DefaultDbAdapterFactory);
-    }
-
-    @Test
-    public void testDbApdater() throws Exception {
-        Log log = mock(Log.class);
-        Injector i = DIBootstrap.createInjector(new ToolsModule(log));
-
-        DbAdapterFactory factory = i.getInstance(DbAdapterFactory.class);
-
-        DataNodeDescriptor nodeDescriptor = mock(DataNodeDescriptor.class);
-        DataSource dataSource = mock(DataSource.class);
-
-        assertTrue(factory.createAdapter(nodeDescriptor, dataSource) instanceof AutoAdapter);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportModuleTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportModuleTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportModuleTest.java
deleted file mode 100644
index 5e3e36a..0000000
--- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportModuleTest.java
+++ /dev/null
@@ -1,40 +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.tools.dbimport;
-
-import org.apache.cayenne.dbsync.DbSyncModule;
-import org.apache.cayenne.di.DIBootstrap;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.tools.configuration.ToolsModule;
-import org.apache.commons.logging.Log;
-import org.junit.Test;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-
-public class DbImportModuleTest {
-
-    @Test
-    public void testModuleContents() {
-
-        Log log = mock(Log.class);
-        Injector i = DIBootstrap.createInjector(new DbSyncModule(), new ToolsModule(log), new DbImportModule());
-        assertTrue(i.getInstance(DbImportAction.class) instanceof DbImportAction);
-    }
-}


[4/4] cayenne git commit: CAY-2215 move all DbImport code from cayenne-tools and cayenne-server modules to cayenne-dbsync module

Posted by nt...@apache.org.
CAY-2215 move all DbImport code from cayenne-tools and cayenne-server modules to cayenne-dbsync module


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

Branch: refs/heads/master
Commit: 660dd4b28635edea0f52a279c51f1da34d198ecc
Parents: 67bf710
Author: Nikita Timofeev <st...@gmail.com>
Authored: Wed Feb 1 12:26:29 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Wed Feb 1 12:26:29 2017 +0300

----------------------------------------------------------------------
 cayenne-dbsync/pom.xml                          |   8 +-
 .../configuration/DriverDataSourceFactory.java  |  54 +++
 .../reverse/configuration/ToolsModule.java      | 107 +++++
 .../reverse/dbimport/AntNestedElement.java      |  43 ++
 .../dbsync/reverse/dbimport/Catalog.java        |  39 ++
 .../dbsync/reverse/dbimport/DbImportAction.java |  30 ++
 .../reverse/dbimport/DbImportConfiguration.java | 302 +++++++++++++
 .../DbImportConfigurationValidator.java         |  78 ++++
 .../dbsync/reverse/dbimport/DbImportModule.java |  46 ++
 .../reverse/dbimport/DefaultDbImportAction.java | 422 +++++++++++++++++++
 .../dbsync/reverse/dbimport/ExcludeColumn.java  |  32 ++
 .../reverse/dbimport/ExcludeProcedure.java      |  32 ++
 .../dbsync/reverse/dbimport/ExcludeTable.java   |  32 ++
 .../reverse/dbimport/FilterContainer.java       | 172 ++++++++
 .../dbsync/reverse/dbimport/IncludeColumn.java  |  32 ++
 .../reverse/dbimport/IncludeProcedure.java      |  32 ++
 .../dbsync/reverse/dbimport/IncludeTable.java   |  84 ++++
 .../dbimport/ManyToManyCandidateEntity.java     | 134 ++++++
 .../dbsync/reverse/dbimport/PatternParam.java   |  83 ++++
 .../reverse/dbimport/ReverseEngineering.java    | 210 +++++++++
 .../cayenne/dbsync/reverse/dbimport/Schema.java |  39 ++
 .../reverse/dbimport/SchemaContainer.java       |  67 +++
 .../dbsync/reverse/dbimport/package-info.java   |  24 ++
 .../reverse/filters/FiltersConfigBuilder.java   |  20 +-
 .../reverse/configuration/ToolsModuleTest.java  |  66 +++
 .../reverse/dbimport/DbImportModuleTest.java    |  41 ++
 .../dbimport/DefaultDbImportActionTest.java     | 356 ++++++++++++++++
 .../dbimport/ManyToManyCandidateEntityTest.java | 116 +++++
 .../dbimport/ReverseEngineeringUtils.java       | 174 ++++++++
 .../filters/FiltersConfigBuilderTest.java       |  19 +-
 .../dbsync/reverse/filters/TableFilterTest.java |   1 -
 .../cayenne-relationship-optimisation.xml       |   4 +
 .../dbimport/relationship-optimisation.map.xml  |  43 ++
 .../cayenne/dbimport/AntNestedElement.java      |  42 --
 .../org/apache/cayenne/dbimport/Catalog.java    |  38 --
 .../apache/cayenne/dbimport/ExcludeColumn.java  |  31 --
 .../cayenne/dbimport/ExcludeProcedure.java      |  31 --
 .../apache/cayenne/dbimport/ExcludeTable.java   |  31 --
 .../cayenne/dbimport/FilterContainer.java       | 171 --------
 .../apache/cayenne/dbimport/IncludeColumn.java  |  31 --
 .../cayenne/dbimport/IncludeProcedure.java      |  31 --
 .../apache/cayenne/dbimport/IncludeTable.java   |  83 ----
 .../apache/cayenne/dbimport/PatternParam.java   |  82 ----
 .../cayenne/dbimport/ReverseEngineering.java    | 210 ---------
 .../org/apache/cayenne/dbimport/Schema.java     |  38 --
 .../cayenne/dbimport/SchemaContainer.java       |  67 ---
 .../apache/cayenne/dbimport/package-info.java   |  24 --
 .../dbimport/ReverseEngineeringUtils.java       | 173 --------
 .../apache/cayenne/tools/DbGeneratorTask.java   |   2 +-
 .../tools/DbImportConfigurationValidator.java   |  77 ----
 .../apache/cayenne/tools/DbImporterTask.java    |  34 +-
 .../configuration/DriverDataSourceFactory.java  |  53 ---
 .../tools/configuration/ToolsModule.java        | 106 -----
 .../cayenne/tools/dbimport/DbImportAction.java  |  30 --
 .../tools/dbimport/DbImportConfiguration.java   | 302 -------------
 .../cayenne/tools/dbimport/DbImportModule.java  |  47 ---
 .../tools/dbimport/DefaultDbImportAction.java   | 422 -------------------
 .../dbimport/ManyToManyCandidateEntity.java     | 133 ------
 .../cayenne/tools/DbGeneratorTaskTest.java      |   2 +-
 .../cayenne/tools/DbImporterTaskTest.java       |   4 +-
 .../tools/configuration/ToolsModuleTest.java    |  65 ---
 .../tools/dbimport/DbImportModuleTest.java      |  40 --
 .../dbimport/DefaultDbImportActionTest.java     | 356 ----------------
 .../dbimport/ManyToManyCandidateEntityTest.java | 115 -----
 .../cayenne-relationship-optimisation.xml       |   4 -
 .../dbimport/relationship-optimisation.map.xml  |  43 --
 .../modeler/dialog/db/load/DbLoaderContext.java |  14 +-
 .../modeler/dialog/db/load/LoadDataMapTask.java |   6 +-
 .../dialog/db/load/ModelerDbImportAction.java   |   4 +-
 .../dialog/db/load/ModelerSyncModule.java       |   2 +-
 .../modeler/dialog/db/merge/MergerOptions.java  |  12 +-
 plugins/cayenne-maven-plugin/pom.xml            |   2 +-
 .../apache/cayenne/tools/DbGeneratorMojo.java   |   2 +-
 .../apache/cayenne/tools/DbImporterMojo.java    |  11 +-
 .../tools/DbImporterMojoConfigurationTest.java  |   8 +-
 .../cayenne/tools/DbImporterMojoTest.java       |   8 +-
 plugins/maven-cayenne-plugin/pom.xml            |   2 +-
 .../DbImporterOldMojoConfigurationTest.java     |   8 +-
 78 files changed, 2980 insertions(+), 2959 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/pom.xml b/cayenne-dbsync/pom.xml
index 951babf..d94de3f 100644
--- a/cayenne-dbsync/pom.xml
+++ b/cayenne-dbsync/pom.xml
@@ -36,12 +36,18 @@
 			<artifactId>cayenne-server</artifactId>
 			<version>${project.version}</version>
 		</dependency>
+		<dependency>
+			<groupId>org.apache.cayenne</groupId>
+			<artifactId>cayenne-project</artifactId>
+			<version>${project.version}</version>
+			<scope>compile</scope>
+		</dependency>
         <dependency>
             <groupId>net.java.dev.inflector</groupId>
             <artifactId>inflector</artifactId>
             <scope>compile</scope>
         </dependency>
-
+		<!-- Test dependencies -->
 		<dependency>
 			<groupId>junit</groupId>
 			<artifactId>junit</artifactId>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/DriverDataSourceFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/DriverDataSourceFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/DriverDataSourceFactory.java
new file mode 100644
index 0000000..d24f367
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/DriverDataSourceFactory.java
@@ -0,0 +1,54 @@
+/*****************************************************************
+ *   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.reverse.configuration;
+
+import java.sql.Driver;
+
+import javax.sql.DataSource;
+
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.configuration.server.DataSourceFactory;
+import org.apache.cayenne.conn.DataSourceInfo;
+import org.apache.cayenne.datasource.DriverDataSource;
+import org.apache.cayenne.di.AdhocObjectFactory;
+import org.apache.cayenne.di.Inject;
+
+/**
+ * @since 4.0
+ */
+public class DriverDataSourceFactory implements DataSourceFactory {
+
+	private AdhocObjectFactory objectFactory;
+
+	public DriverDataSourceFactory(@Inject AdhocObjectFactory objectFactory) {
+		this.objectFactory = objectFactory;
+	}
+
+	public DataSource getDataSource(DataNodeDescriptor nodeDescriptor) throws Exception {
+		DataSourceInfo properties = nodeDescriptor.getDataSourceDescriptor();
+		if (properties == null) {
+			throw new IllegalArgumentException("'nodeDescriptor' contains no datasource descriptor");
+		}
+
+		Driver driver = objectFactory.newInstance(Driver.class, properties.getJdbcDriver());
+		return new DriverDataSource(driver, properties.getDataSourceUrl(), properties.getUserName(),
+				properties.getPassword());
+	}
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..bc5762e
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -0,0 +1,107 @@
+/*****************************************************************
+ *   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.reverse.configuration;
+
+import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
+import org.apache.cayenne.access.translator.batch.DefaultBatchTranslatorFactory;
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.configuration.DefaultRuntimeProperties;
+import org.apache.cayenne.configuration.RuntimeProperties;
+import org.apache.cayenne.configuration.server.DataSourceFactory;
+import org.apache.cayenne.configuration.server.DbAdapterFactory;
+import org.apache.cayenne.configuration.server.DefaultDbAdapterFactory;
+import org.apache.cayenne.configuration.server.ServerModule;
+import org.apache.cayenne.dba.db2.DB2Sniffer;
+import org.apache.cayenne.dba.derby.DerbySniffer;
+import org.apache.cayenne.dba.firebird.FirebirdSniffer;
+import org.apache.cayenne.dba.frontbase.FrontBaseSniffer;
+import org.apache.cayenne.dba.h2.H2Sniffer;
+import org.apache.cayenne.dba.hsqldb.HSQLDBSniffer;
+import org.apache.cayenne.dba.ingres.IngresSniffer;
+import org.apache.cayenne.dba.mysql.MySQLSniffer;
+import org.apache.cayenne.dba.openbase.OpenBaseSniffer;
+import org.apache.cayenne.dba.oracle.OracleSniffer;
+import org.apache.cayenne.dba.postgres.PostgresSniffer;
+import org.apache.cayenne.dba.sqlite.SQLiteSniffer;
+import org.apache.cayenne.dba.sqlserver.SQLServerSniffer;
+import org.apache.cayenne.dba.sybase.SybaseSniffer;
+import org.apache.cayenne.di.AdhocObjectFactory;
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.ClassLoaderManager;
+import org.apache.cayenne.di.Key;
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
+import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
+import org.apache.cayenne.log.CommonsJdbcEventLogger;
+import org.apache.cayenne.log.JdbcEventLogger;
+import org.apache.cayenne.resource.ClassLoaderResourceLocator;
+import org.apache.cayenne.resource.ResourceLocator;
+import org.apache.commons.logging.Log;
+
+/**
+ * A DI module to bootstrap DI container for Cayenne Ant tasks and Maven
+ * plugins.
+ * 
+ * @since 4.0
+ */
+public class ToolsModule implements Module {
+
+    private Log logger;
+
+    public ToolsModule(Log logger) {
+
+        if (logger == null) {
+            throw new NullPointerException("Null logger");
+        }
+
+        this.logger = logger;
+    }
+
+    public void configure(Binder binder) {
+
+        binder.bind(Log.class).toInstance(logger);
+
+        // configure empty global stack properties
+        ServerModule.contributeProperties(binder);
+
+        ServerModule.contributeDefaultTypes(binder);
+        ServerModule.contributeUserTypes(binder);
+        ServerModule.contributeTypeFactories(binder);
+
+        binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
+        binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
+        binder.bind(ResourceLocator.class).to(ClassLoaderResourceLocator.class);
+        binder.bind(Key.get(ResourceLocator.class, Constants.SERVER_RESOURCE_LOCATOR)).to(ClassLoaderResourceLocator.class);
+
+        binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
+        binder.bind(BatchTranslatorFactory.class).to(DefaultBatchTranslatorFactory.class);
+        binder.bind(JdbcEventLogger.class).to(CommonsJdbcEventLogger.class);
+
+        ServerModule.contributeAdapterDetectors(binder).add(FirebirdSniffer.class).add(OpenBaseSniffer.class)
+                .add(FrontBaseSniffer.class).add(IngresSniffer.class).add(SQLiteSniffer.class).add(DB2Sniffer.class)
+                .add(H2Sniffer.class).add(HSQLDBSniffer.class).add(SybaseSniffer.class).add(DerbySniffer.class)
+                .add(SQLServerSniffer.class).add(OracleSniffer.class).add(PostgresSniffer.class)
+                .add(MySQLSniffer.class);
+
+        binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
+        binder.bind(DataSourceFactory.class).to(DriverDataSourceFactory.class);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/AntNestedElement.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/AntNestedElement.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/AntNestedElement.java
new file mode 100644
index 0000000..3964e07
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/AntNestedElement.java
@@ -0,0 +1,43 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+/**
+ * Additional class to handle <name> element under <catalog> and <schema>
+ *      required for ant configuration
+ *
+ * @since 4.0.
+ */
+public class AntNestedElement {
+
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void addText(String str) {
+        name = str;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..3ed8755
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/Catalog.java
@@ -0,0 +1,39 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+/**
+ * @since 4.0.
+ */
+public class Catalog extends SchemaContainer {
+
+    public Catalog() {
+    }
+
+    public Catalog(String name) {
+        setName(name);
+    }
+
+    @Override
+    public StringBuilder toString(StringBuilder res, String prefix) {
+        res.append(prefix).append("Catalog: ").append(getName()).append("\n");
+        return super.toString(res, prefix + "  ");
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportAction.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportAction.java
new file mode 100644
index 0000000..88f92c6
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportAction.java
@@ -0,0 +1,30 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+/**
+ * An API of a strategy that can load DB schema and merge it to a new or an existing DataMap.
+ *
+ * @since 4.0
+ */
+public interface DbImportAction {
+	
+    void execute(DbImportConfiguration config) throws Exception;
+	
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..2e568cb
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java
@@ -0,0 +1,302 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.conn.DataSourceInfo;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.filter.NameFilter;
+import org.apache.cayenne.dbsync.filter.NamePatternMatcher;
+import org.apache.cayenne.dbsync.reverse.dbload.DefaultModelMergeDelegate;
+import org.apache.cayenne.dbsync.reverse.dbload.ModelMergeDelegate;
+import org.apache.cayenne.dbsync.naming.DbEntityNameStemmer;
+import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
+import org.apache.cayenne.dbsync.naming.NoStemStemmer;
+import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
+import org.apache.cayenne.dbsync.naming.PatternStemmer;
+import org.apache.cayenne.dbsync.reverse.dbload.DbLoaderConfiguration;
+import org.apache.cayenne.dbsync.reverse.dbload.DbLoaderDelegate;
+import org.apache.cayenne.dbsync.reverse.dbload.DefaultDbLoaderDelegate;
+import org.apache.cayenne.dbsync.reverse.dbload.LoggingDbLoaderDelegate;
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
+import org.apache.commons.logging.Log;
+
+import java.io.File;
+import java.util.regex.Pattern;
+
+/**
+ * @since 4.0
+ */
+public class DbImportConfiguration {
+
+    private static final String DATA_MAP_LOCATION_SUFFIX = ".map.xml";
+
+    private final DataSourceInfo dataSourceInfo;
+    private final DbLoaderConfiguration dbLoaderConfiguration;
+    private File targetDataMap;
+    private String defaultPackage;
+    private String meaningfulPkTables;
+    private String adapter;
+    private boolean usePrimitives;
+    private Log logger;
+    private String namingStrategy;
+    private String stripFromTableNames;
+    private boolean forceDataMapCatalog;
+    private boolean forceDataMapSchema;
+
+    public DbImportConfiguration() {
+        this.dataSourceInfo = new DataSourceInfo();
+        this.dbLoaderConfiguration = new DbLoaderConfiguration();
+    }
+
+    public String getStripFromTableNames() {
+        return stripFromTableNames;
+    }
+
+    public void setStripFromTableNames(String stripFromTableNames) {
+        this.stripFromTableNames = stripFromTableNames;
+    }
+
+    public Log getLogger() {
+        return logger;
+    }
+
+    public void setLogger(Log logger) {
+        this.logger = logger;
+    }
+
+    /**
+     * Returns DataMap XML file representing the target of the DB import operation.
+     */
+    public File getTargetDataMap() {
+        return targetDataMap;
+    }
+
+    public void setTargetDataMap(File map) {
+        this.targetDataMap = map;
+    }
+
+    /**
+     * Returns a default package for ObjEntity Java classes.
+     */
+    public String getDefaultPackage() {
+        return defaultPackage;
+    }
+
+    public void setDefaultPackage(String defaultPackage) {
+        this.defaultPackage = defaultPackage;
+    }
+
+    public String getNamingStrategy() {
+        return namingStrategy;
+    }
+
+    public void setNamingStrategy(String namingStrategy) {
+        this.namingStrategy = namingStrategy;
+    }
+
+    /**
+     * Returns the name of a Java class implementing {@link DbAdapter}. This attribute is optional, the default is
+     * {@link org.apache.cayenne.dba.AutoAdapter}, i.e. Cayenne will try to guess the DB type.
+     */
+    public String getAdapter() {
+        return adapter;
+    }
+
+    public void setAdapter(String adapter) {
+        this.adapter = adapter;
+    }
+
+    /**
+     * Returns a comma-separated list of Perl5 regular expressions that match
+     * table names for which {@link DbImportAction} should include ObjAttribute
+     * for PK.
+     */
+    public String getMeaningfulPkTables() {
+        return meaningfulPkTables;
+    }
+
+    public void setMeaningfulPkTables(String meaningfulPkTables) {
+        this.meaningfulPkTables = meaningfulPkTables;
+    }
+
+    public boolean isUsePrimitives() {
+        return usePrimitives;
+    }
+
+    public void setUsePrimitives(boolean usePrimitives) {
+        this.usePrimitives = usePrimitives;
+    }
+
+    public NameFilter createMeaningfulPKFilter() {
+
+        if (meaningfulPkTables == null) {
+            return NamePatternMatcher.EXCLUDE_ALL;
+        }
+
+        // TODO: this filter can't handle table names with comma in them
+        String[] patternStrings = meaningfulPkTables.split(",");
+        Pattern[] patterns = new Pattern[patternStrings.length];
+        for (int i = 0; i < patterns.length; i++) {
+            patterns[i] = Pattern.compile(patternStrings[i]);
+        }
+
+        return new NamePatternMatcher(patterns, new Pattern[0]);
+    }
+
+    public ObjectNameGenerator createNameGenerator() {
+
+        // TODO: not a singleton; called from different places...
+
+        // custom name generator
+        // TODO: support stemmer in non-standard generators...
+        // TODO: load via DI AdhocObjectFactory
+        String namingStrategy = getNamingStrategy();
+        if (namingStrategy != null && !namingStrategy.equals(DefaultObjectNameGenerator.class.getName())) {
+            try {
+                return (ObjectNameGenerator) Class.forName(namingStrategy).newInstance();
+            } catch (Exception e) {
+                throw new CayenneRuntimeException("Error creating name generator: " + namingStrategy, e);
+            }
+        }
+
+        return new DefaultObjectNameGenerator(createStemmer());
+    }
+
+    protected DbEntityNameStemmer createStemmer() {
+        return (stripFromTableNames == null || stripFromTableNames.length() == 0)
+                ? NoStemStemmer.getInstance()
+                : new PatternStemmer(stripFromTableNames, false);
+    }
+
+    public String getDriver() {
+        return dataSourceInfo.getJdbcDriver();
+    }
+
+    public void setDriver(String jdbcDriver) {
+        dataSourceInfo.setJdbcDriver(jdbcDriver);
+    }
+
+    public String getPassword() {
+        return dataSourceInfo.getPassword();
+    }
+
+    public void setPassword(String password) {
+        dataSourceInfo.setPassword(password);
+    }
+
+    public String getUsername() {
+        return dataSourceInfo.getUserName();
+    }
+
+    public void setUsername(String userName) {
+        dataSourceInfo.setUserName(userName);
+    }
+
+    public String getUrl() {
+        return dataSourceInfo.getDataSourceUrl();
+    }
+
+    public void setUrl(String dataSourceUrl) {
+        dataSourceInfo.setDataSourceUrl(dataSourceUrl);
+    }
+
+    public DataNodeDescriptor createDataNodeDescriptor() {
+        DataNodeDescriptor nodeDescriptor = new DataNodeDescriptor();
+        nodeDescriptor.setAdapterType(getAdapter());
+        nodeDescriptor.setDataSourceDescriptor(dataSourceInfo);
+
+        return nodeDescriptor;
+    }
+
+    public String getDataMapName() {
+        String name = targetDataMap.getName();
+        if (!name.endsWith(DATA_MAP_LOCATION_SUFFIX)) {
+            throw new CayenneRuntimeException("DataMap file name must end with '%s': '%s'", DATA_MAP_LOCATION_SUFFIX,
+                    name);
+        }
+        return name.substring(0, name.length() - DATA_MAP_LOCATION_SUFFIX.length());
+    }
+
+    public ModelMergeDelegate createMergeDelegate() {
+        return new DefaultModelMergeDelegate();
+    }
+
+    public DbLoaderDelegate createLoaderDelegate() {
+        if (getLogger() != null) {
+            return new LoggingDbLoaderDelegate(getLogger());
+        } else {
+            return new DefaultDbLoaderDelegate();
+        }
+    }
+
+    /**
+     * Returns configuration that should be used for DB import stage when the schema is loaded from the database.
+     */
+    public DbLoaderConfiguration getDbLoaderConfig() {
+        return dbLoaderConfiguration;
+    }
+
+    public void setFiltersConfig(FiltersConfig filtersConfig) {
+        dbLoaderConfiguration.setFiltersConfig(filtersConfig);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder res = new StringBuilder("Importer options:");
+        for (String line : dbLoaderConfiguration.toString().split("\n")) {
+            res.append("    ").append(line).append("\n");
+        }
+
+        return res.toString();
+    }
+
+    public DataSourceInfo getDataSourceInfo() {
+        return dataSourceInfo;
+    }
+
+    public void setSkipRelationshipsLoading(Boolean skipRelationshipsLoading) {
+        this.dbLoaderConfiguration.setSkipRelationshipsLoading(skipRelationshipsLoading);
+    }
+
+    public void setSkipPrimaryKeyLoading(Boolean skipPrimaryKeyLoading) {
+        this.dbLoaderConfiguration.setSkipPrimaryKeyLoading(skipPrimaryKeyLoading);
+    }
+
+    public void setTableTypes(String[] tableTypes) {
+        dbLoaderConfiguration.setTableTypes(tableTypes);
+    }
+
+    public void setForceDataMapCatalog(boolean forceDataMapCatalog) {
+        this.forceDataMapCatalog = forceDataMapCatalog;
+    }
+
+    public boolean isForceDataMapCatalog() {
+        return forceDataMapCatalog;
+    }
+
+    public void setForceDataMapSchema(boolean forceDataMapSchema) {
+        this.forceDataMapSchema = forceDataMapSchema;
+    }
+
+    public boolean isForceDataMapSchema() {
+        return forceDataMapSchema;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfigurationValidator.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfigurationValidator.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfigurationValidator.java
new file mode 100644
index 0000000..c301290
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfigurationValidator.java
@@ -0,0 +1,78 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.configuration.server.DataSourceFactory;
+import org.apache.cayenne.configuration.server.DbAdapterFactory;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.di.Injector;
+
+import java.util.Collection;
+import javax.sql.DataSource;
+
+/**
+ * @since 4.0
+ */
+public class DbImportConfigurationValidator implements Cloneable {
+    private final ReverseEngineering reverseEngineering;
+    private final DbImportConfiguration config;
+    private final Injector injector;
+
+    public DbImportConfigurationValidator(ReverseEngineering reverseEngineering, DbImportConfiguration config, Injector injector) {
+        this.reverseEngineering = reverseEngineering;
+        this.config = config;
+        this.injector = injector;
+    }
+
+    public void validate() throws Exception {
+        DataNodeDescriptor dataNodeDescriptor = config.createDataNodeDescriptor();
+        DbAdapter adapter;
+
+        try {
+            DataSource dataSource = injector.getInstance(DataSourceFactory.class).getDataSource(dataNodeDescriptor);
+            adapter = injector.getInstance(DbAdapterFactory.class).createAdapter(dataNodeDescriptor, dataSource);
+        } catch (Exception ex) {
+            throw new Exception("Error creating DataSource or DbAdapter for DataNodeDescriptor (" + dataNodeDescriptor + ")", ex);
+        }
+
+        if (adapter != null && !adapter.supportsCatalogsOnReverseEngineering() && !isReverseEngineeringCatalogsEmpty()) {
+            String message = "Your database does not support catalogs on reverse engineering. " +
+                    "It allows to connect to only one at the moment. " +
+                    "Please don't note catalogs in <dbimport> configuration.";
+            throw new Exception(message);
+        }
+    }
+
+    private boolean isReverseEngineeringCatalogsEmpty() {
+        Collection<Catalog> catalogs = reverseEngineering.getCatalogs();
+        if (catalogs == null || catalogs.isEmpty()) {
+            return true;
+        }
+
+        for (Catalog catalog : catalogs) {
+            if (catalog.getName() != null) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..f709886
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.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.reverse.dbimport;
+
+import org.apache.cayenne.configuration.ConfigurationNameMapper;
+import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.map.MapLoader;
+import org.apache.cayenne.project.FileProjectSaver;
+import org.apache.cayenne.project.ProjectSaver;
+
+/**
+ * A DI module that bootstraps {@link DbImportAction}.
+ * Should be used in conjunction with {@link org.apache.cayenne.dbsync.reverse.configuration.ToolsModule}
+ * and {@link org.apache.cayenne.dbsync.DbSyncModule}.
+ *
+ * @since 4.0
+ */
+public class DbImportModule implements Module {
+
+    public void configure(Binder binder) {
+        binder.bind(DbImportAction.class).to(DefaultDbImportAction.class);
+        binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
+        binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
+        binder.bind(MapLoader.class).to(MapLoader.class);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..3278dc4
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
@@ -0,0 +1,422 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+import org.apache.cayenne.configuration.ConfigurationTree;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.configuration.server.DataSourceFactory;
+import org.apache.cayenne.configuration.server.DbAdapterFactory;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.filter.NameFilter;
+import org.apache.cayenne.dbsync.merge.token.model.AbstractToModelToken;
+import org.apache.cayenne.dbsync.merge.DataMapMerger;
+import org.apache.cayenne.dbsync.merge.context.MergerContext;
+import org.apache.cayenne.dbsync.merge.token.MergerToken;
+import org.apache.cayenne.dbsync.reverse.dbload.ModelMergeDelegate;
+import org.apache.cayenne.dbsync.reverse.dbload.ProxyModelMergeDelegate;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
+import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
+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.PatternFilter;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.MapLoader;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.project.Project;
+import org.apache.cayenne.project.ProjectSaver;
+import org.apache.cayenne.resource.URLResource;
+import org.apache.cayenne.validation.SimpleValidationFailure;
+import org.apache.cayenne.validation.ValidationFailure;
+import org.apache.cayenne.validation.ValidationResult;
+import org.apache.commons.logging.Log;
+import org.xml.sax.InputSource;
+
+import javax.sql.DataSource;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.sql.Connection;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A default implementation of {@link DbImportAction} that can load DB schema and merge it to a new or an existing
+ * DataMap.
+ *
+ * @since 4.0
+ */
+public class DefaultDbImportAction implements DbImportAction {
+
+    private final ProjectSaver projectSaver;
+    private final Log logger;
+    private final DataSourceFactory dataSourceFactory;
+    private final DbAdapterFactory adapterFactory;
+    private final MapLoader mapLoader;
+    private final MergerTokenFactoryProvider mergerTokenFactoryProvider;
+
+    public DefaultDbImportAction(@Inject Log logger,
+                                 @Inject ProjectSaver projectSaver,
+                                 @Inject DataSourceFactory dataSourceFactory,
+                                 @Inject DbAdapterFactory adapterFactory,
+                                 @Inject MapLoader mapLoader,
+                                 @Inject MergerTokenFactoryProvider mergerTokenFactoryProvider) {
+        this.logger = logger;
+        this.projectSaver = projectSaver;
+        this.dataSourceFactory = dataSourceFactory;
+        this.adapterFactory = adapterFactory;
+        this.mapLoader = mapLoader;
+        this.mergerTokenFactoryProvider = mergerTokenFactoryProvider;
+    }
+
+    protected static List<MergerToken> sort(List<MergerToken> reverse) {
+        Collections.sort(reverse);
+        return reverse;
+    }
+
+    /**
+     * Flattens many-to-many relationships in the generated model.
+     */
+    public static void flattenManyToManyRelationships(DataMap map, Collection<ObjEntity> loadedObjEntities,
+                                                         ObjectNameGenerator objectNameGenerator) {
+        if (loadedObjEntities.isEmpty()) {
+            return;
+        }
+        Collection<ObjEntity> entitiesForDelete = new LinkedList<>();
+
+        for (ObjEntity curEntity : loadedObjEntities) {
+            ManyToManyCandidateEntity entity = ManyToManyCandidateEntity.build(curEntity);
+
+            if (entity != null) {
+                entity.optimizeRelationships(objectNameGenerator);
+                entitiesForDelete.add(curEntity);
+            }
+        }
+
+        // remove needed entities
+        for (ObjEntity curDeleteEntity : entitiesForDelete) {
+            map.removeObjEntity(curDeleteEntity.getName(), true);
+        }
+        loadedObjEntities.removeAll(entitiesForDelete);
+    }
+
+    @Override
+    public void execute(DbImportConfiguration config) throws Exception {
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("DB connection: " + config.getDataSourceInfo());
+            logger.debug(config);
+        }
+
+        boolean hasChanges = false;
+        DataNodeDescriptor dataNodeDescriptor = config.createDataNodeDescriptor();
+        DataSource dataSource = dataSourceFactory.getDataSource(dataNodeDescriptor);
+        DbAdapter adapter = adapterFactory.createAdapter(dataNodeDescriptor, dataSource);
+        ObjectNameGenerator objectNameGenerator = config.createNameGenerator();
+
+        DataMap sourceDataMap;
+        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() + "'";
+
+            logger.info("");
+            logger.info("Map file does not exist. Loaded db model will be saved into '" + path);
+
+            hasChanges = true;
+            targetDataMap = newTargetDataMap(config);
+        }
+
+        // transform source DataMap before merging
+        transformSourceBeforeMerge(sourceDataMap, targetDataMap, config);
+
+        MergerTokenFactory mergerTokenFactory = mergerTokenFactoryProvider.get(adapter);
+
+        DbLoaderConfiguration loaderConfig = config.getDbLoaderConfig();
+        List<MergerToken> tokens = DataMapMerger.builder(mergerTokenFactory)
+                .filters(loaderConfig.getFiltersConfig())
+                .skipPKTokens(loaderConfig.isSkipPrimaryKeyLoading())
+                .skipRelationshipsTokens(loaderConfig.isSkipRelationshipsLoading())
+                .build()
+                .createMergeTokens(targetDataMap, sourceDataMap);
+
+        hasChanges |= syncDataMapProperties(targetDataMap, config);
+        hasChanges |= applyTokens(config.createMergeDelegate(),
+                targetDataMap,
+                log(sort(reverse(mergerTokenFactory, tokens))),
+                objectNameGenerator,
+                config.createMeaningfulPKFilter(),
+                config.isUsePrimitives());
+        hasChanges |= syncProcedures(targetDataMap, sourceDataMap, loaderConfig.getFiltersConfig());
+
+        if (hasChanges) {
+            saveLoaded(targetDataMap);
+        }
+    }
+
+
+    protected void transformSourceBeforeMerge(DataMap sourceDataMap,
+                                              DataMap targetDataMap,
+                                              DbImportConfiguration configuration) {
+
+        if (configuration.isForceDataMapCatalog()) {
+            String catalog = targetDataMap.getDefaultCatalog();
+            for (DbEntity e : sourceDataMap.getDbEntities()) {
+                e.setCatalog(catalog);
+            }
+        }
+
+        if (configuration.isForceDataMapSchema()) {
+            String schema = targetDataMap.getDefaultSchema();
+            for (DbEntity e : sourceDataMap.getDbEntities()) {
+                e.setSchema(schema);
+            }
+        }
+
+    }
+
+    private boolean syncDataMapProperties(DataMap targetDataMap, DbImportConfiguration config) {
+
+        String defaultPackage = config.getDefaultPackage();
+        if (defaultPackage == null || defaultPackage.trim().length() == 0) {
+            return false;
+        }
+
+        if (defaultPackage.equals(targetDataMap.getDefaultPackage())) {
+            return false;
+        }
+
+        targetDataMap.setDefaultPackage(defaultPackage);
+        return true;
+    }
+
+    private void relationshipsSanity(DataMap executed) {
+        for (ObjEntity objEntity : executed.getObjEntities()) {
+            List<ObjRelationship> rels = new LinkedList<>(objEntity.getRelationships());
+            for (ObjRelationship rel : rels) {
+                if (rel.getSourceEntity() == null || rel.getTargetEntity() == null) {
+                    logger.error("Incorrect obj relationship source or target entity is null: " + rel);
+
+                    objEntity.removeRelationship(rel.getName());
+                }
+            }
+        }
+    }
+
+    private Collection<MergerToken> log(List<MergerToken> tokens) {
+        logger.info("");
+        if (tokens.isEmpty()) {
+            logger.info("Detected changes: No changes to import.");
+            return tokens;
+        }
+
+        logger.info("Detected changes: ");
+        for (MergerToken token : tokens) {
+            logger.info(String.format("    %-20s %s", token.getTokenName(), token.getTokenValue()));
+        }
+        logger.info("");
+
+        return tokens;
+    }
+
+    protected DataMap existingTargetMap(DbImportConfiguration configuration) throws IOException {
+
+        File file = configuration.getTargetDataMap();
+        if (file != null && file.exists() && file.canRead()) {
+            DataMap dataMap = mapLoader.loadDataMap(new InputSource(file.getCanonicalPath()));
+            dataMap.setNamespace(new EntityResolver(Collections.singleton(dataMap)));
+            dataMap.setConfigurationSource(new URLResource(file.toURI().toURL()));
+
+            return dataMap;
+        }
+
+        return null;
+    }
+
+    protected DataMap newTargetDataMap(DbImportConfiguration config) throws IOException {
+
+        DataMap dataMap = new DataMap();
+
+        dataMap.setName(config.getDataMapName());
+        dataMap.setConfigurationSource(new URLResource(config.getTargetDataMap().toURI().toURL()));
+        dataMap.setNamespace(new EntityResolver(Collections.singleton(dataMap)));
+
+        // update map defaults
+
+        // do not override default package of existing DataMap unless it is
+        // explicitly requested by the plugin caller
+        String defaultPackage = config.getDefaultPackage();
+        if (defaultPackage != null && defaultPackage.length() > 0) {
+            dataMap.setDefaultPackage(defaultPackage);
+        }
+
+        CatalogFilter[] catalogs = config.getDbLoaderConfig().getFiltersConfig().getCatalogs();
+        if (catalogs.length > 0) {
+            // do not override default catalog of existing DataMap unless it is
+            // explicitly requested by the plugin caller, and the provided catalog is
+            // not a pattern
+            String catalog = catalogs[0].name;
+            if (catalog != null && catalog.length() > 0 && catalog.indexOf('%') < 0) {
+                dataMap.setDefaultCatalog(catalog);
+            }
+
+            // do not override default schema of existing DataMap unless it is
+            // explicitly requested by the plugin caller, and the provided schema is
+            // not a pattern
+            String schema = catalogs[0].schemas[0].name;
+            if (schema != null && schema.length() > 0 && schema.indexOf('%') < 0) {
+                dataMap.setDefaultSchema(schema);
+            }
+        }
+
+        return dataMap;
+    }
+
+    private List<MergerToken> reverse(MergerTokenFactory mergerTokenFactory, Iterable<MergerToken> mergeTokens)
+            throws IOException {
+
+        List<MergerToken> tokens = new LinkedList<>();
+        for (MergerToken token : mergeTokens) {
+            if (token instanceof AbstractToModelToken) {
+                continue;
+            }
+            tokens.add(token.createReverse(mergerTokenFactory));
+        }
+        return tokens;
+    }
+
+    private boolean applyTokens(ModelMergeDelegate mergeDelegate,
+                                DataMap targetDataMap,
+                                Collection<MergerToken> tokens,
+                                ObjectNameGenerator nameGenerator,
+                                NameFilter meaningfulPKFilter,
+                                boolean usingPrimitives) {
+
+        if (tokens.isEmpty()) {
+            logger.info("");
+            logger.info("Detected changes: No changes to import.");
+            return false;
+        }
+
+        final Collection<ObjEntity> loadedObjEntities = new LinkedList<>();
+
+        mergeDelegate = new ProxyModelMergeDelegate(mergeDelegate) {
+            @Override
+            public void objEntityAdded(ObjEntity ent) {
+                loadedObjEntities.add(ent);
+                super.objEntityAdded(ent);
+            }
+        };
+
+        MergerContext mergerContext = MergerContext.builder(targetDataMap)
+                .delegate(mergeDelegate)
+                .nameGenerator(nameGenerator)
+                .usingPrimitives(usingPrimitives)
+                .meaningfulPKFilter(meaningfulPKFilter)
+                .build();
+
+        for (MergerToken token : tokens) {
+            try {
+                token.execute(mergerContext);
+            } catch (Throwable th) {
+                String message = "Migration Error. Can't apply changes from token: " + token.getTokenName()
+                        + " (" + token.getTokenValue() + ")";
+
+                logger.error(message, th);
+                mergerContext.getValidationResult().addFailure(new SimpleValidationFailure(th, message));
+            }
+        }
+
+        ValidationResult failures = mergerContext.getValidationResult();
+        if (failures.hasFailures()) {
+            logger.info("Migration Complete.");
+            logger.warn("Migration finished. The following problem(s) were encountered and ignored.");
+            for (ValidationFailure failure : failures.getFailures()) {
+                logger.warn(failure.toString());
+            }
+        } else {
+            logger.info("Migration Complete Successfully.");
+        }
+
+        flattenManyToManyRelationships(targetDataMap, loadedObjEntities, nameGenerator);
+        relationshipsSanity(targetDataMap);
+        return true;
+    }
+
+    private boolean syncProcedures(DataMap targetDataMap, DataMap loadedDataMap, FiltersConfig filters) {
+        Collection<Procedure> procedures = loadedDataMap.getProcedures();
+        if (procedures.isEmpty()) {
+            return false;
+        }
+
+        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());
+                logger.info("Replace procedure " + procedure.getName());
+            } else {
+                logger.info("Add new procedure " + procedure.getName());
+            }
+            targetDataMap.addProcedure(procedure);
+            hasChanges = true;
+        }
+        return hasChanges;
+    }
+
+    protected void saveLoaded(DataMap dataMap) throws FileNotFoundException {
+        ConfigurationTree<DataMap> projectRoot = new ConfigurationTree<>(dataMap);
+        Project project = new Project(projectRoot);
+        projectSaver.save(project);
+    }
+
+    protected DataMap load(DbImportConfiguration config,
+                           DbAdapter adapter,
+                           Connection connection) throws Exception {
+        return createDbLoader(adapter, connection, config).load();
+    }
+
+    protected DbLoader createDbLoader(DbAdapter adapter,
+                                       Connection connection,
+                                       DbImportConfiguration config) {
+        return new DbLoader(adapter, connection,
+                config.getDbLoaderConfig(),
+                config.createLoaderDelegate(),
+                config.createNameGenerator());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..a57400a
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeColumn.java
@@ -0,0 +1,32 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+/**
+ * @since 4.0.
+ */
+public class ExcludeColumn extends PatternParam {
+    public ExcludeColumn() {
+    }
+
+    public ExcludeColumn(String pattern) {
+        super(pattern);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..a42aa23
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeProcedure.java
@@ -0,0 +1,32 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+/**
+ * @since 4.0.
+ */
+public class ExcludeProcedure extends PatternParam {
+    public ExcludeProcedure() {
+    }
+
+    public ExcludeProcedure(String pattern) {
+        super(pattern);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..c55a5c4
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ExcludeTable.java
@@ -0,0 +1,32 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+/**
+ * @since 4.0.
+ */
+public class ExcludeTable extends PatternParam {
+    public ExcludeTable() {
+    }
+
+    public ExcludeTable(String pattern) {
+        super(pattern);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..197c287
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/FilterContainer.java
@@ -0,0 +1,172 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * @since 4.0.
+ */
+abstract class FilterContainer {
+
+    private String name;
+
+    private final Collection<IncludeTable> includeTableCollection = new LinkedList<>();
+
+    private final Collection<ExcludeTable> excludeTableCollection = new LinkedList<>();
+
+    private final Collection<IncludeColumn> includeColumnCollection = new LinkedList<>();
+
+    private final Collection<ExcludeColumn> excludeColumnCollection = new LinkedList<>();
+
+    private final Collection<IncludeProcedure> includeProcedureCollection = new LinkedList<>();
+
+    private final Collection<ExcludeProcedure> excludeProcedureCollection = new LinkedList<>();
+
+    public Collection<IncludeTable> getIncludeTables() {
+        return includeTableCollection;
+    }
+
+    public Collection<ExcludeTable> getExcludeTables() {
+        return excludeTableCollection;
+    }
+
+    public Collection<IncludeColumn> getIncludeColumns() {
+        return includeColumnCollection;
+    }
+
+    public Collection<ExcludeColumn> getExcludeColumns() {
+        return excludeColumnCollection;
+    }
+
+    public Collection<IncludeProcedure> getIncludeProcedures() {
+        return includeProcedureCollection;
+    }
+
+    public Collection<ExcludeProcedure> getExcludeProcedures() {
+        return excludeProcedureCollection;
+    }
+
+    public void addIncludeColumn(IncludeColumn includeColumn) {
+        this.includeColumnCollection.add(includeColumn);
+    }
+
+    public void addExcludeColumn(ExcludeColumn excludeColumn) {
+        this.excludeColumnCollection.add(excludeColumn);
+    }
+
+    public void addIncludeTable(IncludeTable includeTable) {
+        this.includeTableCollection.add(includeTable);
+    }
+
+    public void addExcludeTable(ExcludeTable excludeTable) {
+        this.excludeTableCollection.add(excludeTable);
+    }
+
+    public void addIncludeProcedure(IncludeProcedure includeProcedure) {
+        this.includeProcedureCollection.add(includeProcedure);
+    }
+
+    public void addExcludeProcedure(ExcludeProcedure excludeProcedure) {
+        this.excludeProcedureCollection.add(excludeProcedure);
+    }
+
+    public void clearIncludeTables() {
+        includeTableCollection.clear();
+    }
+
+    public void clearExcludeTables() {
+        excludeTableCollection.clear();
+    }
+
+    public void clearIncludeProcedures() {
+        includeProcedureCollection.clear();
+    }
+
+    public void clearExcludeProcedures() {
+        excludeProcedureCollection.clear();
+    }
+
+    public void clearIncludeColumns() {
+        includeColumnCollection.clear();
+    }
+
+    public void clearExcludeColumns() {
+        excludeColumnCollection.clear();
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void set(String name) {
+        setName(name);
+    }
+
+    public void addConfiguredName(AntNestedElement name) {
+        setName(name.getName());
+    }
+
+    public void addText(String name) {
+        if (name.trim().isEmpty()) {
+            return;
+        }
+        setName(name);
+    }
+
+    public boolean isEmptyContainer() {
+        return includeColumnCollection.isEmpty()    && excludeColumnCollection.isEmpty()
+            && includeTableCollection.isEmpty()     && excludeTableCollection.isEmpty()
+            && includeProcedureCollection.isEmpty() && excludeProcedureCollection.isEmpty();
+    }
+
+    static boolean isBlank(Collection<?> collection) {
+        return collection == null || collection.isEmpty();
+    }
+
+    @Override
+    public String toString() {
+        return toString(new StringBuilder(), "").toString();
+    }
+
+    public StringBuilder toString(StringBuilder res, String prefix) {
+        appendCollection(res, prefix, includeTableCollection);
+        appendCollection(res, prefix, excludeTableCollection);
+        appendCollection(res, prefix, includeColumnCollection);
+        appendCollection(res, prefix, excludeColumnCollection);
+        appendCollection(res, prefix, includeProcedureCollection);
+        appendCollection(res, prefix, excludeProcedureCollection);
+
+        return res;
+    }
+
+    protected void appendCollection(StringBuilder res, String prefix, Collection<? extends PatternParam> collection) {
+        if (!isBlank(collection)) {
+            for (PatternParam item : collection) {
+                item.toString(res, prefix);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..780eb86
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeColumn.java
@@ -0,0 +1,32 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+/**
+ * @since 4.0.
+ */
+public class IncludeColumn extends PatternParam {
+    public IncludeColumn() {
+    }
+
+    public IncludeColumn(String pattern) {
+        super(pattern);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..f3b9040
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeProcedure.java
@@ -0,0 +1,32 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+/**
+ * @since 4.0.
+ */
+public class IncludeProcedure extends PatternParam {
+    public IncludeProcedure() {
+    }
+
+    public IncludeProcedure(String pattern) {
+        super(pattern);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..b57e782
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/IncludeTable.java
@@ -0,0 +1,84 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * @since 4.0.
+ */
+public class IncludeTable extends PatternParam {
+
+    private final Collection<IncludeColumn> includeColumns = new LinkedList<>();
+
+    private final Collection<ExcludeColumn> excludeColumns = new LinkedList<>();
+
+    public IncludeTable() {
+    }
+
+    public IncludeTable(String pattern) {
+        super(pattern);
+    }
+
+    public Collection<IncludeColumn> getIncludeColumns() {
+        return includeColumns;
+    }
+
+    public void setIncludeColumns(Collection<IncludeColumn> includeColumns) {
+        this.includeColumns.addAll(includeColumns);
+    }
+
+    public Collection<ExcludeColumn> getExcludeColumns() {
+        return excludeColumns;
+    }
+
+    public void setExcludeColumns(Collection<ExcludeColumn> excludeColumns) {
+        this.excludeColumns.addAll(excludeColumns);
+    }
+
+    public void addIncludeColumn(IncludeColumn includeColumn) {
+        this.includeColumns.add(includeColumn);
+    }
+
+    public void addExcludeColumn(ExcludeColumn excludeColumn) {
+        this.excludeColumns.add(excludeColumn);
+    }
+
+    @Override
+    public StringBuilder toString(StringBuilder res, String s) {
+        super.toString(res, s);
+
+        String prefix = s + "  ";
+        if (includeColumns != null && !includeColumns.isEmpty()) {
+            for (IncludeColumn includeColumn : includeColumns) {
+                includeColumn.toString(res, prefix);
+            }
+        }
+
+        if (excludeColumns != null && !excludeColumns.isEmpty()) {
+            for (ExcludeColumn excludeColumn : excludeColumns) {
+                excludeColumn.toString(res, prefix);
+            }
+        }
+
+        return res;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntity.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntity.java
new file mode 100644
index 0000000..3c3cbf3
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntity.java
@@ -0,0 +1,134 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+import org.apache.cayenne.dbsync.naming.NameBuilder;
+import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An ObjEntity that may be removed as a result of flattenning relationships.
+ */
+class ManyToManyCandidateEntity {
+
+    private static final Log LOG = LogFactory.getLog(ManyToManyCandidateEntity.class);
+
+    private final ObjEntity joinEntity;
+
+    private final DbRelationship dbRel1;
+    private final DbRelationship dbRel2;
+
+    private final ObjEntity entity1;
+    private final ObjEntity entity2;
+
+    private final DbRelationship reverseRelationship1;
+    private final DbRelationship reverseRelationship2;
+
+    private ManyToManyCandidateEntity(ObjEntity entityValue, List<ObjRelationship> relationships) {
+        joinEntity = entityValue;
+
+        ObjRelationship rel1 = relationships.get(0);
+        ObjRelationship rel2 = relationships.get(1);
+
+        dbRel1 = rel1.getDbRelationships().get(0);
+        dbRel2 = rel2.getDbRelationships().get(0);
+
+        reverseRelationship1 = dbRel1.getReverseRelationship();
+        reverseRelationship2 = dbRel2.getReverseRelationship();
+
+        entity1 = rel1.getTargetEntity();
+        entity2 = rel2.getTargetEntity();
+    }
+
+    /**
+     * Method check - if current entity represent many to many temporary table
+     *
+     * @return true if current entity is represent many to many table; otherwise returns false
+     */
+    public static ManyToManyCandidateEntity build(ObjEntity joinEntity) {
+        ArrayList<ObjRelationship> relationships = new ArrayList<>(joinEntity.getRelationships());
+        if (relationships.size() != 2 || (relationships.get(0).getDbRelationships().isEmpty() || relationships.get(1).getDbRelationships().isEmpty())) {
+            return null;
+        }
+
+        ManyToManyCandidateEntity candidateEntity = new ManyToManyCandidateEntity(joinEntity, relationships);
+        if (candidateEntity.isManyToMany()) {
+            return candidateEntity;
+        }
+
+        return null;
+    }
+
+    private boolean isManyToMany() {
+        boolean isNotHaveAttributes = joinEntity.getAttributes().size() == 0;
+
+        return isNotHaveAttributes
+                && reverseRelationship1 != null && reverseRelationship1.isToDependentPK()
+                && reverseRelationship2 != null && reverseRelationship2.isToDependentPK()
+                && entity1 != null && entity2 != null;
+    }
+
+    private void addFlattenedRelationship(ObjectNameGenerator nameGenerator, ObjEntity srcEntity, ObjEntity dstEntity,
+                                          DbRelationship rel1, DbRelationship rel2) {
+
+        if (rel1.getSourceAttributes().isEmpty() && rel2.getTargetAttributes().isEmpty()) {
+            LOG.warn("Wrong call ManyToManyCandidateEntity.addFlattenedRelationship(... , " + srcEntity.getName()
+                    + ", " + dstEntity.getName() + ", ...)");
+
+            return;
+        }
+
+        ObjRelationship newRelationship = new ObjRelationship();
+        newRelationship.setName(NameBuilder
+                .builder(newRelationship, srcEntity)
+                .baseName(nameGenerator.relationshipName(rel1, rel2))
+                .name());
+
+        newRelationship.setSourceEntity(srcEntity);
+        newRelationship.setTargetEntityName(dstEntity);
+
+        newRelationship.addDbRelationship(rel1);
+        newRelationship.addDbRelationship(rel2);
+
+        srcEntity.addRelationship(newRelationship);
+    }
+
+    /**
+     * Method make direct relationships between 2 entities and remove relationships to
+     * many to many entity
+     *
+     * @param nameGenerator
+     */
+    public void optimizeRelationships(ObjectNameGenerator nameGenerator) {
+        entity1.removeRelationship(reverseRelationship1.getName());
+        entity2.removeRelationship(reverseRelationship2.getName());
+
+        addFlattenedRelationship(nameGenerator, entity1, entity2, reverseRelationship1, dbRel2);
+        addFlattenedRelationship(nameGenerator, entity2, entity1, reverseRelationship2, dbRel1);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/660dd4b2/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
new file mode 100644
index 0000000..4208e64
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/PatternParam.java
@@ -0,0 +1,83 @@
+/*****************************************************************
+ *   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.reverse.dbimport;
+
+/**
+ * @since 4.0.
+ */
+public class PatternParam {
+
+    private String pattern;
+
+    public PatternParam() {
+    }
+
+    public PatternParam(String pattern) {
+        this.pattern = pattern;
+    }
+
+    public String getPattern() {
+        return pattern;
+    }
+
+    public void setPattern(String pattern) {
+        this.pattern = pattern;
+    }
+
+    public void setName(String name) {
+        setPattern(name);
+    }
+
+    /**
+     * Used by Maven plugin
+     */
+    public void set(String pattern) {
+        setPattern(pattern);
+    }
+
+
+    /**
+     * Used by Ant task
+     */
+    public void addText(String pattern) {
+        if (pattern.trim().isEmpty()) {
+            return;
+        }
+
+        setPattern(pattern);
+    }
+
+    /**
+     * used by Ant?
+     */
+    public void addConfiguredPattern(AntNestedElement pattern) {
+        set(pattern.getName());
+    }
+
+    @Override
+    public String toString() {
+        return toString(new StringBuilder(), "").toString();
+    }
+
+    public StringBuilder toString(StringBuilder res, String s) {
+        res.append(s).append(getClass().getSimpleName()).append(": ").append(pattern).append("\n");
+        return res;
+    }
+}