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

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

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;
-    }
-}