cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dkazimirc...@apache.org
Subject [7/8] cayenne git commit: CAY-2051 | Applying new Reverse Engineering to the Modeler
Date Fri, 26 Feb 2016 08:40:56 GMT
CAY-2051 | Applying new Reverse Engineering to the Modeler


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

Branch: refs/heads/master
Commit: fe82b47e79f281dffec189039ce2e1e734c7c10f
Parents: 2f10481
Author: olga <ollybondareva@gmail.com>
Authored: Thu Jan 21 12:27:17 2016 +0300
Committer: Dzmitry Kazimirchyk <dkazimirchyk@gmail.com>
Committed: Fri Feb 26 11:38:57 2016 +0300

----------------------------------------------------------------------
 .../cayenne/project/ConfigurationSaver.java     |   8 +
 .../project/ConfigurationSourceGetter.java      |   6 +
 .../project/ConfigurationSourceSetter.java      |   7 +
 .../DefaultConfigurationNodeParentGetter.java   |   6 +
 .../cayenne/project/SaveableNodesGetter.java    |   9 +
 .../validation/DefaultProjectValidator.java     |  25 +-
 .../validation/ReverseEngineeringValidator.java |  42 ++
 .../project/ReverseEngineeringSaverTest.java    |  62 +++
 cayenne-server/pom.xml                          |   8 +-
 .../org/apache/cayenne/access/DbLoader.java     |   2 +-
 .../loader/DbAttributesPerSchemaLoader.java     |   5 +-
 .../access/loader/filters/PatternFilter.java    |  24 +-
 .../access/loader/filters/SchemaFilter.java     |   5 -
 .../access/loader/filters/TableFilter.java      |  11 +-
 .../BaseConfigurationNodeVisitor.java           |   4 +
 .../configuration/ConfigurationNodeVisitor.java |   3 +
 .../DefaultConfigurationNameMapper.java         |  18 +
 .../XMLDataChannelDescriptorLoader.java         |  31 +-
 .../cayenne/dbimport/AntNestedElement.java      |  42 ++
 .../org/apache/cayenne/dbimport/Catalog.java    | 114 ++++++
 .../DefaultReverseEngineeringLoader.java        | 222 +++++++++++
 .../DefaultReverseEngineeringWriter.java        |  58 +++
 .../apache/cayenne/dbimport/ExcludeColumn.java  |  31 ++
 .../cayenne/dbimport/ExcludeProcedure.java      |  31 ++
 .../apache/cayenne/dbimport/ExcludeTable.java   |  31 ++
 .../cayenne/dbimport/FilterContainer.java       | 159 ++++++++
 .../cayenne/dbimport/FiltersConfigBuilder.java  | 383 +++++++++++++++++++
 .../apache/cayenne/dbimport/IncludeColumn.java  |  31 ++
 .../cayenne/dbimport/IncludeProcedure.java      |  31 ++
 .../apache/cayenne/dbimport/IncludeTable.java   |  91 +++++
 .../apache/cayenne/dbimport/PatternParam.java   |  85 ++++
 .../cayenne/dbimport/ReverseEngineering.java    | 196 ++++++++++
 .../dbimport/ReverseEngineeringLoader.java      |  36 ++
 .../ReverseEngineeringLoaderException.java      |  37 ++
 .../dbimport/ReverseEngineeringWriter.java      |  33 ++
 .../org/apache/cayenne/dbimport/Schema.java     |  71 ++++
 .../java/org/apache/cayenne/map/DataMap.java    |  16 +
 .../java/org/apache/cayenne/map/DbEntity.java   |   8 +-
 .../java/org/apache/cayenne/map/MapLoader.java  |  24 ++
 .../apache/cayenne/map/naming/NameCheckers.java |  26 +-
 .../DefaultReverseEngineeringLoaderTest.java    | 240 ++++++++++++
 .../DefaultReverseEngineeringWriterTest.java    | 104 +++++
 .../dbimport/FiltersConfigBuilderTest.java      | 382 ++++++++++++++++++
 .../dbimport/reverseEngineering-ant-mapping.xml |  31 ++
 .../reverseEngineering-catalog-and-schema.xml   |  65 ++++
 .../dbimport/reverseEngineering-catalog.xml     |  68 ++++
 .../dbimport/reverseEngineering-expected.xml    |  22 ++
 .../dbimport/reverseEngineering-flat.xml        |  61 +++
 .../reverseEngineering-maven-mapping.xml        |  55 +++
 .../reverseEngineering-mixed-mapping.xml        |  43 +++
 .../dbimport/reverseEngineering-schema.xml      |  69 ++++
 ...reverseEngineering-skipPrimaryKeyLoading.xml |  23 ++
 ...erseEngineering-skipRelationshipsLoading.xml |  23 ++
 .../dbimport/reverseEngineering-tableTypes.xml  |  29 ++
 .../cayenne/dbimport/reverseEngineering.xml     |   3 +
 .../apache/cayenne/tools/DbImporterTask.java    |  21 +-
 .../org/apache/cayenne/tools/ExcludeTable.java  |  33 --
 .../cayenne/tools/dbimport/DbImportAction.java  | 254 +-----------
 .../tools/dbimport/DbImportActionDefault.java   | 281 ++++++++++++++
 .../cayenne/tools/dbimport/DbImportModule.java  |   4 +-
 .../tools/dbimport/config/AntNestedElement.java |  42 --
 .../cayenne/tools/dbimport/config/Catalog.java  | 110 ------
 .../config/DefaultReverseEngineeringLoader.java | 230 -----------
 .../tools/dbimport/config/ExcludeColumn.java    |  31 --
 .../tools/dbimport/config/ExcludeProcedure.java |  31 --
 .../tools/dbimport/config/FilterContainer.java  | 144 -------
 .../dbimport/config/FiltersConfigBuilder.java   | 367 ------------------
 .../tools/dbimport/config/IncludeColumn.java    |  31 --
 .../tools/dbimport/config/IncludeProcedure.java |  31 --
 .../tools/dbimport/config/IncludeTable.java     |  85 ----
 .../tools/dbimport/config/PatternParam.java     |  79 ----
 .../dbimport/config/ReverseEngineering.java     | 135 -------
 .../config/ReverseEngineeringLoader.java        |  31 --
 .../cayenne/tools/dbimport/config/Schema.java   |  65 ----
 .../cayenne/tools/dbimport/config/Type.java     |  15 +
 .../tools/dbimport/config/TypeMapper.java       |   6 +
 .../cayenne/tools/DbImporterTaskTest.java       |   7 +-
 .../tools/dbimport/DbImportActionTest.java      | 220 +++++------
 .../DefaultReverseEngineeringLoaderTest.java    | 241 ------------
 .../config/FiltersConfigBuilderTest.java        | 383 -------------------
 .../config/reverseEngineering-ant-mapping.xml   |  31 --
 .../reverseEngineering-catalog-and-schema.xml   |  65 ----
 .../config/reverseEngineering-catalog.xml       |  68 ----
 .../dbimport/config/reverseEngineering-flat.xml |  61 ---
 .../config/reverseEngineering-maven-mapping.xml |  55 ---
 .../config/reverseEngineering-mixed-mapping.xml |  43 ---
 .../config/reverseEngineering-schema.xml        |  69 ----
 ...reverseEngineering-skipPrimaryKeyLoading.xml |  23 --
 ...erseEngineering-skipRelationshipsLoading.xml |  23 --
 .../config/reverseEngineering-tableTypes.xml    |  29 --
 .../cayenne/modeler/CayenneModelerFrame.java    |   4 +-
 .../modeler/action/DefaultActionManager.java    |   4 +-
 .../cayenne/modeler/action/ImportDBAction.java  |  96 -----
 .../cayenne/modeler/action/MigrateAction.java   |  12 +-
 .../cayenne/modeler/action/RemoveAction.java    |   8 +-
 .../action/ReverseEngineeringAction.java        |  77 ++++
 .../modeler/dialog/db/ConnectionWizard.java     |  89 -----
 .../modeler/dialog/db/DBGeneratorOptions.java   |   2 +-
 .../modeler/dialog/db/DataMapViewModel.java     |  51 +++
 .../modeler/dialog/db/DataSourceController.java | 219 +++++++++++
 .../modeler/dialog/db/DataSourceView.java       | 100 +++++
 .../modeler/dialog/db/DataSourceWizard.java     | 224 -----------
 .../modeler/dialog/db/DataSourceWizardView.java | 100 -----
 .../dialog/db/DbImportActionModeler.java        | 120 ++++++
 .../modeler/dialog/db/DbLoaderHelper.java       | 179 ++++-----
 .../dialog/db/DbLoaderOptionsDialog.java        | 308 ---------------
 .../modeler/dialog/db/MergerOptions.java        |   4 -
 .../dialog/db/ReverseEngineeringController.java | 362 ++++++++++++++++++
 .../dialog/db/ReverseEngineeringScrollPane.java |  34 ++
 .../dialog/db/ReverseEngineeringView.java       | 274 +++++++++++++
 .../modeler/dialog/db/model/DBCatalog.java      |  37 ++
 .../modeler/dialog/db/model/DBColumn.java       |  39 ++
 .../modeler/dialog/db/model/DBElement.java      |  50 +++
 .../modeler/dialog/db/model/DBEntity.java       |  37 ++
 .../modeler/dialog/db/model/DBModel.java        |  38 ++
 .../modeler/dialog/db/model/DBProcedure.java    |  38 ++
 .../modeler/dialog/db/model/DBSchema.java       |  48 +++
 .../dialog/pref/FilteredTreeCellRenderer.java   |  85 ++++
 .../cayenne/modeler/dialog/pref/TreeEditor.java | 101 +++++
 .../cayenne/modeler/dialog/pref/TreeView.java   |  56 +++
 .../modeler/dialog/pref/XMLFileEditor.java      |  82 ++++
 .../cayenne/modeler/dialog/pref/XMLView.java    |  72 ++++
 .../modeler/editor/DataMapTabbedView.java       |  23 +-
 .../cayenne/modeler/util/CellRenderers.java     |  18 +-
 .../cayenne/modeler/dialog/db/templateXML.xml   |  16 +
 .../apache/cayenne/tools/DbImporterMojo.java    |   9 +-
 .../tools/DbImporterMojoConfigurationTest.java  |   5 +-
 .../cayenne/tools/DbImporterMojoTest.java       |   6 +-
 128 files changed, 5710 insertions(+), 3911 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java
index 9ed8a88..d6b9c97 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java
@@ -22,6 +22,7 @@ import java.io.PrintWriter;
 
 import org.apache.cayenne.configuration.BaseConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.dbimport.ReverseEngineering;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.util.XMLEncoder;
 
@@ -54,6 +55,13 @@ class ConfigurationSaver extends BaseConfigurationNodeVisitor<Void> {
         return null;
     }
 
+    @Override
+    public Void visitReverseEngineering(ReverseEngineering node) {
+        XMLEncoder encoder = new XMLEncoder(printWriter);
+        node.encodeAsXML(encoder);
+        return null;
+    }
+
     private void printXMLHeader(XMLEncoder encoder) {
         encoder.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceGetter.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceGetter.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceGetter.java
index db9c3c3..be68dad 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceGetter.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceGetter.java
@@ -20,6 +20,7 @@ package org.apache.cayenne.project;
 
 import org.apache.cayenne.configuration.BaseConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.dbimport.ReverseEngineering;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.resource.Resource;
 
@@ -39,4 +40,9 @@ class ConfigurationSourceGetter extends BaseConfigurationNodeVisitor<Resource> {
     public Resource visitDataMap(DataMap dataMap) {
         return dataMap.getConfigurationSource();
     }
+
+    @Override
+    public Resource visitReverseEngineering(ReverseEngineering reverseEngineering) {
+        return reverseEngineering.getConfigurationSource();
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceSetter.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceSetter.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceSetter.java
index 2854df1..7a3f5d3 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceSetter.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceSetter.java
@@ -21,6 +21,7 @@ package org.apache.cayenne.project;
 import org.apache.cayenne.configuration.BaseConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.dbimport.ReverseEngineering;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.resource.Resource;
 
@@ -54,4 +55,10 @@ class ConfigurationSourceSetter extends BaseConfigurationNodeVisitor<Void> {
         node.setConfigurationSource(configurationSource);
         return null;
     }
+
+    @Override
+    public Void visitReverseEngineering(ReverseEngineering node) {
+        node.setConfigurationSource(configurationSource);
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-project/src/main/java/org/apache/cayenne/project/DefaultConfigurationNodeParentGetter.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/DefaultConfigurationNodeParentGetter.java b/cayenne-project/src/main/java/org/apache/cayenne/project/DefaultConfigurationNodeParentGetter.java
index 3458c73..dc3c839 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/DefaultConfigurationNodeParentGetter.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/DefaultConfigurationNodeParentGetter.java
@@ -22,6 +22,7 @@ import org.apache.cayenne.configuration.BaseConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.dbimport.ReverseEngineering;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
@@ -113,5 +114,10 @@ public class DefaultConfigurationNodeParentGetter implements ConfigurationNodePa
         public ConfigurationNode visitQuery(QueryDescriptor query) {
             return query.getDataMap();
         }
+
+        @Override
+        public ConfigurationNode visitReverseEngineering(ReverseEngineering reverseEngineering) {
+            return reverseEngineering;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java b/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java
index ee20da3..61c9468 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java
@@ -25,6 +25,7 @@ import java.util.Collections;
 import org.apache.cayenne.configuration.BaseConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.dbimport.ReverseEngineering;
 import org.apache.cayenne.map.DataMap;
 
 /**
@@ -42,6 +43,9 @@ class SaveableNodesGetter extends
 
         for (DataMap map : descriptor.getDataMaps()) {
             nodes.add(map);
+            if (map.getReverseEngineering() != null) {
+                nodes.add(map.getReverseEngineering());
+            }
         }
 
         return nodes;
@@ -51,4 +55,9 @@ class SaveableNodesGetter extends
     public Collection<ConfigurationNode> visitDataMap(DataMap dataMap) {
         return Collections.<ConfigurationNode> singletonList(dataMap);
     }
+
+    @Override
+    public Collection<ConfigurationNode> visitReverseEngineering(ReverseEngineering reverseEngineering) {
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DefaultProjectValidator.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DefaultProjectValidator.java b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DefaultProjectValidator.java
index f50ecc5..f240fc8 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DefaultProjectValidator.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DefaultProjectValidator.java
@@ -24,7 +24,23 @@ import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.map.*;
+import org.apache.cayenne.dbimport.ReverseEngineering;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.EJBQLQueryDescriptor;
+import org.apache.cayenne.map.Embeddable;
+import org.apache.cayenne.map.EmbeddableAttribute;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.ProcedureParameter;
+import org.apache.cayenne.map.ProcedureQueryDescriptor;
+import org.apache.cayenne.map.QueryDescriptor;
+import org.apache.cayenne.map.SQLTemplateDescriptor;
+import org.apache.cayenne.map.SelectQueryDescriptor;
 import org.apache.cayenne.validation.ValidationResult;
 
 /**
@@ -49,6 +65,7 @@ public class DefaultProjectValidator implements ProjectValidator {
     private ProcedureQueryValidator procedureQueryValidator;
     private EJBQLQueryValidator ejbqlQueryValidator;
     private SQLTemplateValidator sqlTemplateValidator;
+    private ReverseEngineeringValidator reverseEngineeringValidator;
 
     DefaultProjectValidator() {
         dataChannelValidator = new DataChannelValidator();
@@ -68,6 +85,7 @@ public class DefaultProjectValidator implements ProjectValidator {
         procedureQueryValidator = new ProcedureQueryValidator();
         ejbqlQueryValidator = new EJBQLQueryValidator();
         sqlTemplateValidator = new SQLTemplateValidator();
+        reverseEngineeringValidator = new ReverseEngineeringValidator();
     }
 
     public ValidationResult validate(ConfigurationNode node) {
@@ -255,5 +273,10 @@ public class DefaultProjectValidator implements ProjectValidator {
 
             return validationResult;
         }
+
+        public ValidationResult visitReverseEngineering(ReverseEngineering reverseEngineering) {
+            reverseEngineeringValidator.validate(reverseEngineering, validationResult);
+            return validationResult;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ReverseEngineeringValidator.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ReverseEngineeringValidator.java b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ReverseEngineeringValidator.java
new file mode 100644
index 0000000..99b92ba
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ReverseEngineeringValidator.java
@@ -0,0 +1,42 @@
+/*****************************************************************
+ *   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.project.validation;
+
+import org.apache.cayenne.dbimport.ReverseEngineering;
+import org.apache.cayenne.util.Util;
+import org.apache.cayenne.validation.ValidationResult;
+
+/**
+ * @since 4.0
+ */
+public class ReverseEngineeringValidator extends ConfigurationNodeValidator{
+    void validate(ReverseEngineering reverseEngineering, ValidationResult validationResult) {
+        validateName(reverseEngineering, validationResult);
+    }
+
+    void validateName(ReverseEngineering reverseEngineering, ValidationResult validationResult) {
+        String name = reverseEngineering.getName();
+
+        // Must have name
+        if (Util.isEmptyString(name)) {
+            addFailure(validationResult, reverseEngineering, "Unnamed ReverseEngineering");
+            return;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-project/src/test/java/org/apache/cayenne/project/ReverseEngineeringSaverTest.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/ReverseEngineeringSaverTest.java b/cayenne-project/src/test/java/org/apache/cayenne/project/ReverseEngineeringSaverTest.java
new file mode 100644
index 0000000..38fe391
--- /dev/null
+++ b/cayenne-project/src/test/java/org/apache/cayenne/project/ReverseEngineeringSaverTest.java
@@ -0,0 +1,62 @@
+package org.apache.cayenne.project;
+
+import org.apache.cayenne.configuration.*;
+import org.apache.cayenne.dbimport.ReverseEngineering;
+import org.apache.cayenne.di.*;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.project.unit.Project2Case;
+import org.apache.cayenne.resource.URLResource;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.net.MalformedURLException;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @since 4.0
+ */
+public class ReverseEngineeringSaverTest extends Project2Case {
+    private FileProjectSaver saver;
+
+    @Before
+    public void setUp() throws Exception {
+        Module testModule = new Module() {
+
+            public void configure(Binder binder) {
+                binder.bind(ConfigurationNameMapper.class).to(
+                        DefaultConfigurationNameMapper.class);
+            }
+        };
+
+        saver = new FileProjectSaver();
+        Injector injector = DIBootstrap.createInjector(testModule);
+        injector.injectMembers(saver);
+    }
+
+    @Test
+    public void testSaveReversEngineering() throws MalformedURLException {
+        File testFolder = setupTestDirectory("testSaverRE");
+
+        DataChannelDescriptor rootNode = new DataChannelDescriptor();
+        rootNode.setName("test");
+
+        DataMap dataMap = new DataMap("datamap1");
+        dataMap.setReverseEngineering(new ReverseEngineering("reverseEngineering1"));
+        rootNode.getDataMaps().add(dataMap);
+
+        Project project = new Project(new ConfigurationTree<>(rootNode));
+        saver.saveAs(project, new URLResource(testFolder.toURL()));
+
+        DataMapLoader dataMapLoader = new XMLDataMapLoader();
+        DataMap dataMap1 = dataMapLoader.load(dataMap.getConfigurationSource());
+        String reverseEngineeringName = dataMap1.getReverseEngineering().getName();
+
+        File reFile = new File(testFolder, reverseEngineeringName + ".reverseEngineering.xml");
+        assertTrue(reFile.exists());
+        assertTrue(reFile.length() > 0);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-server/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/pom.xml b/cayenne-server/pom.xml
index 19b9063..dd93b45 100644
--- a/cayenne-server/pom.xml
+++ b/cayenne-server/pom.xml
@@ -151,7 +151,13 @@
     		<artifactId>slf4j-simple</artifactId>
     		<scope>test</scope>
 		</dependency>
-    </dependencies>
+		<dependency>
+			<groupId>xmlunit</groupId>
+			<artifactId>xmlunit</artifactId>
+			<version>1.5</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
 	<build>
 		<resources>
 			<resource>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
index 26cf333..af4358b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
@@ -766,7 +766,7 @@ public class DbLoader {
 				procedure.setCatalog(rs.getString("PROCEDURE_CAT"));
 				procedure.setSchema(rs.getString("PROCEDURE_SCHEM"));
 
-				if (filters.proceduresFilter(procedure.getCatalog(), procedure.getSchema()).isInclude(
+				if (!filters.proceduresFilter(procedure.getCatalog(), procedure.getSchema()).isInclude(
 						procedure.getName())) {
 					LOGGER.info("skipping Cayenne PK procedure: " + name);
 					continue;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesPerSchemaLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesPerSchemaLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesPerSchemaLoader.java
index 058494e..a7871ad 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesPerSchemaLoader.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesPerSchemaLoader.java
@@ -107,7 +107,10 @@ public class DbAttributesPerSchemaLoader extends DbAttributesBaseLoader {
 	protected List<DbAttribute> loadDbAttributes(String tableName) {
 		Map<String, List<DbAttribute>> attributes = getAttributes();
 		if (attributes != null) {
-			return attributes.get(tableName);
+			List<DbAttribute> dbAttributes = attributes.get(tableName);
+			if (dbAttributes != null) {
+				return dbAttributes;
+			}
 		}
 
 		return new LinkedList<DbAttribute>();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/PatternFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/PatternFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/PatternFilter.java
index 83789ba..82c45cc 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/PatternFilter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/PatternFilter.java
@@ -58,7 +58,12 @@ public class PatternFilter {
     public static final Comparator<Pattern> PATTERN_COMPARATOR = new Comparator<Pattern>() {
         @Override
         public int compare(Pattern o1, Pattern o2) {
-            return o1.pattern().compareTo(o2.pattern());
+            if (o1 != null && o2 != null) {
+                return o1.pattern().compareTo(o2.pattern());
+            }
+            else {
+                return -1;
+            }
         }
     };
 
@@ -66,8 +71,8 @@ public class PatternFilter {
     private final SortedSet<Pattern> excludes;
 
     public PatternFilter() {
-        this.includes = new TreeSet<Pattern>(PATTERN_COMPARATOR);
-        this.excludes = new TreeSet<Pattern>(PATTERN_COMPARATOR);
+        this.includes = new TreeSet<>(PATTERN_COMPARATOR);
+        this.excludes = new TreeSet<>(PATTERN_COMPARATOR);
     }
 
     public PatternFilter include(Pattern p) {
@@ -100,9 +105,11 @@ public class PatternFilter {
     public boolean isInclude(String obj) {
         boolean include = includes.isEmpty();
         for (Pattern p : includes) {
-            if (p.matcher(obj).matches()) {
-                include = true;
-                break;
+            if (p != null) {
+                if (p.matcher(obj).matches()) {
+                    include = true;
+                    break;
+                }
             }
         }
 
@@ -140,11 +147,6 @@ public class PatternFilter {
         return includes.hashCode();
     }
 
-    @Override
-    public String toString() {
-        return toString(new StringBuilder()).toString();
-    }
-
     public StringBuilder toString(StringBuilder res) {
         if (includes.isEmpty()) {
             // Do nothing.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/SchemaFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/SchemaFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/SchemaFilter.java
index 2331938..c294bc4 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/SchemaFilter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/SchemaFilter.java
@@ -32,11 +32,6 @@ public class SchemaFilter {
         this.procedures = procedures;
     }
 
-    @Override
-    public String toString() {
-        return toString(new StringBuilder(), "").toString();
-    }
-
     protected StringBuilder toString(StringBuilder res, String prefix) {
         res.append(prefix).append("Schema: ").append(name).append("\n");
         tables.toString(res, prefix + "  ");

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/TableFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/TableFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/TableFilter.java
index 640c0a8..7d3c8f6 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/TableFilter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/TableFilter.java
@@ -69,8 +69,10 @@ public class TableFilter {
         }
 
         for (Pattern p : excludes) {
-            if (p.matcher(tableName).matches()) {
-                return null;
+            if (p != null) {
+                if (p.matcher(tableName).matches()) {
+                    return null;
+                }
             }
         }
 
@@ -91,11 +93,6 @@ public class TableFilter {
         return new TableFilter(includes, new TreeSet<Pattern>());
     }
 
-    @Override
-    public String toString() {
-        return toString(new StringBuilder(), "").toString();
-    }
-
     protected StringBuilder toString(StringBuilder res, String prefix) {
         res.append(prefix).append("Tables: ").append("\n");
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-server/src/main/java/org/apache/cayenne/configuration/BaseConfigurationNodeVisitor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/BaseConfigurationNodeVisitor.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/BaseConfigurationNodeVisitor.java
index 65365b2..f34c813 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/BaseConfigurationNodeVisitor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/BaseConfigurationNodeVisitor.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.configuration;
 
+import org.apache.cayenne.dbimport.ReverseEngineering;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
@@ -98,4 +99,7 @@ public abstract class BaseConfigurationNodeVisitor<T> implements
         throw new UnsupportedOperationException("Not implemented for Query");
     }
 
+    public T visitReverseEngineering(ReverseEngineering reverseEngineering) {
+        throw new UnsupportedOperationException("Not implemented for ReverseEngineering");
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-server/src/main/java/org/apache/cayenne/configuration/ConfigurationNodeVisitor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/ConfigurationNodeVisitor.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/ConfigurationNodeVisitor.java
index 60d2900..508a5f8 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/ConfigurationNodeVisitor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/ConfigurationNodeVisitor.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.configuration;
 
+import org.apache.cayenne.dbimport.ReverseEngineering;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
@@ -66,4 +67,6 @@ public interface ConfigurationNodeVisitor<T> {
     T visitProcedureParameter(ProcedureParameter parameter);
 
     T visitQuery(QueryDescriptor query);
+
+    T visitReverseEngineering(ReverseEngineering reverseEngineering);
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java
index ffe2868..24cea5d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.configuration;
 
+import org.apache.cayenne.dbimport.ReverseEngineering;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.resource.Resource;
 
@@ -31,6 +32,8 @@ public class DefaultConfigurationNameMapper implements ConfigurationNameMapper {
 
 	private static final String DATA_MAP_SUFFIX = ".map.xml";
 
+	private static final String REVERSE_ENGINEERING_SUFFIX = ".reverseEngineering.xml";
+
 	protected ConfigurationNodeVisitor<String> nameMapper;
 
 	public DefaultConfigurationNameMapper() {
@@ -48,6 +51,8 @@ public class DefaultConfigurationNameMapper implements ConfigurationNameMapper {
 			return getDataChannelName(name);
 		} else if (DataMap.class.isAssignableFrom(type)) {
 			return getDataMapName(name);
+		} else if (ReverseEngineering.class.isAssignableFrom(type)) {
+			return getReverseEngineeringName(name);
 		}
 
 		throw new IllegalArgumentException("Unrecognized configuration type: " + type.getName());
@@ -104,6 +109,14 @@ public class DefaultConfigurationNameMapper implements ConfigurationNameMapper {
 		return name + DATA_MAP_SUFFIX;
 	}
 
+	private String getReverseEngineeringName(String name) {
+		if (name == null) {
+			throw new NullPointerException("Null Reverse Engineering name");
+		}
+
+		return name + REVERSE_ENGINEERING_SUFFIX;
+	}
+
 	final class NameMapper extends BaseConfigurationNodeVisitor<String> {
 
 		@Override
@@ -115,5 +128,10 @@ public class DefaultConfigurationNameMapper implements ConfigurationNameMapper {
 		public String visitDataMap(DataMap dataMap) {
 			return getDataMapName(dataMap.getName());
 		}
+
+		@Override
+		public String visitReverseEngineering(ReverseEngineering reverseEngineering) {
+			return getReverseEngineeringName(reverseEngineering.getName());
+		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java
index e763b5b..6e71e6a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java
@@ -27,6 +27,9 @@ import java.net.URL;
 
 import org.apache.cayenne.ConfigurationException;
 import org.apache.cayenne.conn.DataSourceInfo;
+import org.apache.cayenne.dbimport.DefaultReverseEngineeringLoader;
+import org.apache.cayenne.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbimport.ReverseEngineeringLoaderException;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.DataMap;
@@ -34,10 +37,9 @@ import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.util.Util;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.XMLReader;
+import org.xml.sax.*;
+
+import javax.xml.parsers.ParserConfigurationException;
 
 /**
  * @since 3.1
@@ -211,8 +213,25 @@ public class XMLDataChannelDescriptorLoader implements DataChannelDescriptorLoad
 				dataMap.setConfigurationSource(dataMapResource);
 				dataMap.setDataChannelDescriptor(descriptor);
 
-				descriptor.getDataMaps().add(dataMap);
-			} else if (localName.equals(NODE_TAG)) {
+                try {
+                    if (dataMap.getReverseEngineering() != null) {
+                        String reverseEngineeringName = dataMap.getReverseEngineering().getName();
+                        String reverseEngineeringLocation = nameMapper.configurationLocation(ReverseEngineering.class, reverseEngineeringName);
+                        Resource reverseEngineeringResource = baseResource.getRelativeResource(reverseEngineeringLocation);
+                        DefaultReverseEngineeringLoader reverseEngineeringLoader = new DefaultReverseEngineeringLoader();
+                        ReverseEngineering reverseEngineering = reverseEngineeringLoader.load(reverseEngineeringResource.getURL().openStream());
+                        reverseEngineering.setName(reverseEngineeringName);
+                        reverseEngineering.setConfigurationSource(reverseEngineeringResource);
+                        dataMap.setReverseEngineering(reverseEngineering);
+                    }
+                } catch (ReverseEngineeringLoaderException e) {
+                    logger.info(e.getMessage(), e);
+                } catch (IOException e) {
+                    logger.info(e.getMessage(), e);
+                }
+
+                descriptor.getDataMaps().add(dataMap);
+            } else if (localName.equals(NODE_TAG)) {
 
 				String nodeName = attributes.getValue("", "name");
 				if (nodeName == null) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/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
new file mode 100644
index 0000000..f300c02
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/AntNestedElement.java
@@ -0,0 +1,42 @@
+/*****************************************************************
+ *   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/fe82b47e/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
new file mode 100644
index 0000000..99cf4cc
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Catalog.java
@@ -0,0 +1,114 @@
+/*****************************************************************
+ *   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 javax.xml.bind.annotation.*;
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * @since 4.0.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Catalog extends FilterContainer {
+
+    @XmlAttribute(name = "name")
+    private String name;
+
+    @XmlElement(name = "schema")
+    private Collection<Schema> schemas = new LinkedList<Schema>();
+
+    public Catalog() {
+    }
+
+    public Catalog(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Collection<Schema> getSchemas() {
+        return schemas;
+    }
+
+    public void setSchemas(Collection<Schema> schemas) {
+        this.schemas = schemas;
+    }
+
+    public void addSchema(Schema schema) {
+        this.schemas.add(schema);
+    }
+
+    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 Catalog schema(Schema name) {
+        addSchema(name);
+        return this;
+    }
+
+    @Override
+    public boolean isEmptyContainer() {
+        if (!super.isEmptyContainer()) {
+            return false;
+        }
+
+        if (schemas.isEmpty()) {
+            return true;
+        }
+
+        for (Schema schema : schemas) {
+            if (!schema.isEmptyContainer()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public StringBuilder toString(StringBuilder res, String prefix) {
+        res.append(prefix).append("Catalog: ").append(name).append("\n");
+
+        if (!isBlank(schemas)) {
+            for (Schema schema : schemas) {
+                schema.toString(res, prefix + "  ");
+            }
+        }
+
+        return super.toString(res, prefix + "  ");
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringLoader.java
new file mode 100644
index 0000000..cb63ff9
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringLoader.java
@@ -0,0 +1,222 @@
+/*****************************************************************
+ *   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 org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @since 4.0.
+ */
+public class DefaultReverseEngineeringLoader implements ReverseEngineeringLoader {
+
+    private static final Log LOG = LogFactory.getLog(ReverseEngineeringLoader.class);
+
+    @Override
+    public ReverseEngineering load(InputStream inputStream) throws IOException, ReverseEngineeringLoaderException {
+        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+
+        DocumentBuilder dBuilder = null;
+        try {
+            dBuilder = dbFactory.newDocumentBuilder();
+            Document doc = dBuilder.parse(inputStream);
+
+            ReverseEngineering engineering = new ReverseEngineering();
+
+            Element root = doc.getDocumentElement();
+            engineering.setSkipRelationshipsLoading(loadBoolean(root, "skipRelationshipsLoading"));
+            engineering.setSkipPrimaryKeyLoading(loadBoolean(root, "skipPrimaryKeyLoading"));
+            engineering.setTableTypes(loadTableTypes(root));
+
+            engineering.setCatalogs(loadCatalogs(root));
+            engineering.setSchemas(loadSchemas(root));
+            engineering.setIncludeTables(loadIncludeTables(root));
+            engineering.setExcludeTables(loadExcludeTables(root));
+            engineering.setIncludeColumns(loadIncludeColumns(root));
+            engineering.setExcludeColumns(loadExcludeColumns(root));
+            engineering.setIncludeProcedures(loadIncludeProcedures(root));
+            engineering.setExcludeProcedures(loadExcludeProcedures(root));
+
+            return engineering;
+        } catch (ParserConfigurationException e) {
+            throw new ReverseEngineeringLoaderException(e.getMessage(), e);
+        } catch (SAXException e) {
+            throw new ReverseEngineeringLoaderException(e.getMessage(), e);
+        }
+    }
+
+    private Boolean loadBoolean(Element root, String name) {
+        return Boolean.valueOf(loadByName(root, name));
+    }
+
+    private Collection<ExcludeProcedure> loadExcludeProcedures(Node parent) {
+        return loadPatternParams(ExcludeProcedure.class, getElementsByTagName(parent, "excludeProcedure"));
+    }
+
+    private Collection<IncludeProcedure> loadIncludeProcedures(Node parent) {
+        return loadPatternParams(IncludeProcedure.class, getElementsByTagName(parent, "includeProcedure"));
+    }
+
+    private Collection<ExcludeColumn> loadExcludeColumns(Node parent) {
+        return loadPatternParams(ExcludeColumn.class, getElementsByTagName(parent, "excludeColumn"));
+    }
+
+    private Collection<IncludeColumn> loadIncludeColumns(Node parent) {
+        return loadPatternParams(IncludeColumn.class, getElementsByTagName(parent, "includeColumn"));
+    }
+
+    private Collection<ExcludeTable> loadExcludeTables(Node parent) {
+        return loadPatternParams(ExcludeTable.class, getElementsByTagName(parent, "excludeTable"));
+    }
+
+    private Collection<IncludeTable> loadIncludeTables(Node parent) {
+        List<Node> includeTables = getElementsByTagName(parent, "includeTable");
+        Collection<IncludeTable> res = new LinkedList<IncludeTable>();
+        for (Node node : includeTables) {
+            IncludeTable includeTable = new IncludeTable();
+
+            includeTable.setPattern(loadPattern(node));
+            includeTable.setIncludeColumns(loadIncludeColumns(node));
+            includeTable.setExcludeColumns(loadExcludeColumns(node));
+            res.add(includeTable);
+        }
+        return res;
+    }
+
+    private Collection<Schema> loadSchemas(Node parent) {
+        List<Node> schemas = getElementsByTagName(parent, "schema");
+        Collection<Schema> res = new LinkedList<Schema>();
+        for (Node schemaNode : schemas) {
+            Schema schema = new Schema();
+
+            schema.setName(loadName(schemaNode));
+            schema.setIncludeTables(loadIncludeTables(schemaNode));
+            schema.setExcludeTables(loadExcludeTables(schemaNode));
+            schema.setIncludeColumns(loadIncludeColumns(schemaNode));
+            schema.setExcludeColumns(loadExcludeColumns(schemaNode));
+            schema.setIncludeProcedures(loadIncludeProcedures(schemaNode));
+            schema.setExcludeProcedures(loadExcludeProcedures(schemaNode));
+            res.add(schema);
+        }
+
+        return res;
+    }
+
+    private Collection<Catalog> loadCatalogs(Node parent) {
+        List<Node> catalogs = getElementsByTagName(parent, "catalog");
+        Collection<Catalog> res = new LinkedList<Catalog>();
+        for (Node catalogNode : catalogs) {
+            Catalog catalog = new Catalog();
+
+            catalog.setName(loadName(catalogNode));
+            catalog.setSchemas(loadSchemas(catalogNode));
+            catalog.setIncludeTables(loadIncludeTables(catalogNode));
+            catalog.setExcludeTables(loadExcludeTables(catalogNode));
+            catalog.setIncludeColumns(loadIncludeColumns(catalogNode));
+            catalog.setExcludeColumns(loadExcludeColumns(catalogNode));
+            catalog.setIncludeProcedures(loadIncludeProcedures(catalogNode));
+            catalog.setExcludeProcedures(loadExcludeProcedures(catalogNode));
+
+            res.add(catalog);
+        }
+
+        return res;
+    }
+
+    private Collection<String> loadTableTypes(Node parent) {
+        List<Node> types = getElementsByTagName(parent, "tableType");
+        Collection<String> res = new LinkedList<String>();
+        for (Node typeNode : types) {
+            res.add(loadName(typeNode));
+        }
+
+        return res;
+    }
+
+    private String loadName(Node catalogNode) {
+        return loadByName(catalogNode, "name");
+    }
+
+    private String loadPattern(Node catalogNode) {
+        return loadByName(catalogNode, "pattern");
+    }
+
+    private String loadByName(Node node, String attrName) {
+        Node name = node.getAttributes().getNamedItem(attrName);
+        if (name != null) {
+            return name.getTextContent();
+        }
+
+        String content = node.getTextContent().trim();
+        if (!content.isEmpty()) {
+            return content;
+        }
+
+        List<Node> names = getElementsByTagName(node, attrName);
+        if (names.isEmpty()) {
+            return null;
+        }
+
+        return names.get(0).getTextContent();
+    }
+
+    private <T extends PatternParam> Collection<T> loadPatternParams(Class<T> clazz, List<Node> nodes) {
+        Collection<T> res = new LinkedList<T>();
+        for (Node node : nodes) {
+            try {
+                T obj = clazz.newInstance();
+                obj.setPattern(loadPattern(node));
+
+                res.add(obj);
+            } catch (InstantiationException e) {
+                LOG.info(e.getMessage(), e);
+            } catch (IllegalAccessException e) {
+                LOG.info(e.getMessage(), e);
+            }
+        }
+        return res;
+    }
+
+    private List<Node> getElementsByTagName(Node catalogNode, String name) {
+        List<Node> nodes = new LinkedList<Node>();
+        NodeList childNodes = catalogNode.getChildNodes();
+        for (int i = 0; i < childNodes.getLength(); i++) {
+            Node item = childNodes.item(i);
+            if (name.equals(item.getNodeName())) {
+                nodes.add(item);
+            }
+        }
+
+        return nodes;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriter.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriter.java
new file mode 100644
index 0000000..be9c7d5
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriter.java
@@ -0,0 +1,58 @@
+/*****************************************************************
+ *   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 org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.resource.Resource;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * @since 4.0
+ */
+public class DefaultReverseEngineeringWriter implements ReverseEngineeringWriter {
+    private final static Log LOGGER = LogFactory.getLog(DefaultReverseEngineeringWriter.class);
+
+    @Override
+    public Resource write(ReverseEngineering reverseEngineering, Writer writer) throws CayenneRuntimeException {
+
+        try {
+            JAXBContext context = JAXBContext.newInstance(reverseEngineering.getClass());
+            Marshaller marshaller = context.createMarshaller();
+            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+
+            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
+            marshaller.marshal(reverseEngineering, writer);
+            writer.close();
+            return reverseEngineering.getConfigurationSource();
+        } catch (JAXBException e) {
+            LOGGER.error(e.getMessage(), e);
+            throw new CayenneRuntimeException(e);
+        } catch (IOException e) {
+            LOGGER.error(e.getMessage(), e);
+            throw new CayenneRuntimeException(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/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
new file mode 100644
index 0000000..ff1e0e3
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeColumn.java
@@ -0,0 +1,31 @@
+/*****************************************************************
+ *   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/fe82b47e/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
new file mode 100644
index 0000000..e5d7b2d
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeProcedure.java
@@ -0,0 +1,31 @@
+/*****************************************************************
+ *   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/fe82b47e/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
new file mode 100644
index 0000000..3cbd8d4
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeTable.java
@@ -0,0 +1,31 @@
+/*****************************************************************
+ *   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/fe82b47e/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
new file mode 100644
index 0000000..5a42d3b
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FilterContainer.java
@@ -0,0 +1,159 @@
+/*****************************************************************
+ *   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 javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * @since 4.0.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+public abstract class FilterContainer {
+
+    @XmlElement(name = "includeTable")
+    private Collection<IncludeTable> includeTables = new LinkedList<IncludeTable>();
+
+    @XmlElement(name = "excludeTable")
+    private Collection<ExcludeTable> excludeTables = new LinkedList<ExcludeTable>();
+
+    @XmlElement(name = "includeColumn")
+    private Collection<IncludeColumn> includeColumns = new LinkedList<IncludeColumn>();
+
+    @XmlElement(name = "excludeColumn")
+    private Collection<ExcludeColumn> excludeColumns = new LinkedList<ExcludeColumn>();
+
+    @XmlElement(name = "includeProcedure")
+    private Collection<IncludeProcedure> includeProcedures = new LinkedList<IncludeProcedure>();
+
+    @XmlElement(name = "excludeProcedure")
+    private Collection<ExcludeProcedure> excludeProcedures = new LinkedList<ExcludeProcedure>();
+
+    public Collection<IncludeTable> getIncludeTables() {
+        return includeTables;
+    }
+
+    public void setIncludeTables(Collection<IncludeTable> includeTables) {
+        this.includeTables = includeTables;
+    }
+
+    public Collection<ExcludeTable> getExcludeTables() {
+        return excludeTables;
+    }
+
+    public void setExcludeTables(Collection<ExcludeTable> excludeTables) {
+        this.excludeTables = excludeTables;
+    }
+
+    public Collection<IncludeColumn> getIncludeColumns() {
+        return includeColumns;
+    }
+
+    public void setIncludeColumns(Collection<IncludeColumn> includeColumns) {
+        this.includeColumns = includeColumns;
+    }
+
+    public Collection<ExcludeColumn> getExcludeColumns() {
+        return excludeColumns;
+    }
+
+    public void setExcludeColumns(Collection<ExcludeColumn> excludeColumns) {
+        this.excludeColumns = excludeColumns;
+    }
+
+    public Collection<IncludeProcedure> getIncludeProcedures() {
+        return includeProcedures;
+    }
+
+    public void setIncludeProcedures(Collection<IncludeProcedure> includeProcedures) {
+        this.includeProcedures = includeProcedures;
+    }
+
+    public Collection<ExcludeProcedure> getExcludeProcedures() {
+        return excludeProcedures;
+    }
+
+    public void setExcludeProcedures(Collection<ExcludeProcedure> excludeProcedures) {
+        this.excludeProcedures = excludeProcedures;
+    }
+
+
+    public void addIncludeColumn(IncludeColumn includeColumn) {
+        this.includeColumns.add(includeColumn);
+    }
+
+    public void addExcludeColumn(ExcludeColumn excludeColumn) {
+        this.excludeColumns.add(excludeColumn);
+    }
+
+    public void addIncludeTable(IncludeTable includeTable) {
+        this.includeTables.add(includeTable);
+    }
+
+    public void addExcludeTable(ExcludeTable excludeTable) {
+        this.excludeTables.add(excludeTable);
+    }
+
+    public void addIncludeProcedure(IncludeProcedure includeProcedure) {
+        this.includeProcedures.add(includeProcedure);
+    }
+
+    public void addExcludeProcedure(ExcludeProcedure excludeProcedure) {
+        this.excludeProcedures.add(excludeProcedure);
+    }
+
+    public boolean isEmptyContainer() {
+        return includeColumns.isEmpty()    && excludeColumns.isEmpty()
+            && includeTables.isEmpty()     && excludeTables.isEmpty()
+            && includeProcedures.isEmpty() && excludeProcedures.isEmpty();
+    }
+
+    public 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, includeTables);
+        appendCollection(res, prefix, excludeTables);
+        appendCollection(res, prefix, includeColumns);
+        appendCollection(res, prefix, excludeColumns);
+        appendCollection(res, prefix, includeProcedures);
+        appendCollection(res, prefix, excludeProcedures);
+
+        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/fe82b47e/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FiltersConfigBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FiltersConfigBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FiltersConfigBuilder.java
new file mode 100644
index 0000000..2991bd1
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FiltersConfigBuilder.java
@@ -0,0 +1,383 @@
+/*****************************************************************
+ * 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 org.apache.cayenne.access.loader.filters.OldFilterConfigBridge;
+import org.apache.cayenne.access.loader.filters.CatalogFilter;
+import org.apache.cayenne.access.loader.filters.IncludeTableFilter;
+import org.apache.cayenne.access.loader.filters.SchemaFilter;
+import org.apache.cayenne.access.loader.filters.TableFilter;
+import org.apache.cayenne.access.loader.filters.FiltersConfig;
+import org.apache.cayenne.access.loader.filters.PatternFilter;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+import static org.apache.commons.lang.StringUtils.isBlank;
+
+/**
+ * @since 4.0.
+ */
+public final class FiltersConfigBuilder {
+
+    private final ReverseEngineering engineering;
+
+    public FiltersConfigBuilder(ReverseEngineering engineering) {
+        this.engineering = engineering;
+    }
+
+    public FiltersConfig filtersConfig() {
+        compact();
+
+        return new FiltersConfig(transformCatalogs(engineering.getCatalogs()));
+    }
+
+    private CatalogFilter[] transformCatalogs(Collection<Catalog> catalogs) {
+        CatalogFilter[] catalogFilters = new CatalogFilter[catalogs.size()];
+        int i = 0;
+        for (Catalog catalog : catalogs) {
+            catalogFilters[i] = new CatalogFilter(catalog.getName(), transformSchemas(catalog.getSchemas()));
+            i++;
+        }
+
+        return catalogFilters;
+    }
+
+    private SchemaFilter[] transformSchemas(Collection<Schema> schemas) {
+        SchemaFilter[] schemaFilters = new SchemaFilter[schemas.size()];
+        int i = 0;
+        for (Schema schema : schemas) {
+            schemaFilters[i] = new SchemaFilter(schema.getName(),
+                    new TableFilter(transformIncludeTable(schema.getIncludeTables()),
+                            transformExcludeTable(schema.getExcludeTables())),
+                    transform(schema.getIncludeProcedures(), schema.getExcludeProcedures()));
+            i++;
+        }
+
+        return schemaFilters;
+    }
+
+    private SortedSet<Pattern> transformExcludeTable(Collection<ExcludeTable> excludeTables) {
+        SortedSet<Pattern> res = new TreeSet<Pattern>(PatternFilter.PATTERN_COMPARATOR);
+        for (ExcludeTable exclude : excludeTables) {
+            res.add(PatternFilter.pattern(exclude.getPattern()));
+        }
+        return res;
+    }
+
+    private SortedSet<IncludeTableFilter> transformIncludeTable(Collection<IncludeTable> includeTables) {
+        SortedSet<IncludeTableFilter> includeTableFilters = new TreeSet<IncludeTableFilter>();
+        for (IncludeTable includeTable : includeTables) {
+            includeTableFilters.add(new IncludeTableFilter(includeTable.getPattern(),
+                    transform(includeTable.getIncludeColumns(), includeTable.getExcludeColumns())));
+        }
+
+        return includeTableFilters;
+    }
+
+    private PatternFilter transform(Collection<? extends PatternParam> include,
+                                    Collection<? extends PatternParam> exclude) {
+        PatternFilter filter = new PatternFilter();
+
+        for (PatternParam patternParam : include) {
+            filter.include(patternParam.getPattern());
+        }
+
+        for (PatternParam patternParam : exclude) {
+            filter.exclude(patternParam.getPattern());
+        }
+
+        return filter;
+
+    }
+
+    /**
+     * Goal of this method transform ReverseEngineering config into more regular form
+     * From
+     *      ReverseEngineering
+     *          Catalog
+     *              Schema
+     *                  IncludeTable
+     *                      IncludeColumn
+     *                      ExcludeColumn
+     *                  ExcludeTable
+     *                  IncludeProcedures
+     *                  ExcludeProcedures
+     *                  IncludeColumn
+     *                  ExcludeColumn
+     *              IncludeTable
+     *                  IncludeColumn
+     *                  ExcludeColumn
+     *              ExcludeTable
+     *              IncludeProcedures
+     *              ExcludeProcedures
+     *              IncludeColumn
+     *              ExcludeColumn
+     *          Schema
+     *              IncludeTable
+     *                  IncludeColumn
+     *                  ExcludeColumn
+     *              ExcludeTable
+     *              IncludeProcedures
+     *              ExcludeProcedures
+     *              IncludeColumn
+     *              ExcludeColumn
+     *          IncludeTable
+     *              IncludeColumn
+     *              ExcludeColumn
+     *          ExcludeTable
+     *          IncludeProcedures
+     *          ExcludeProcedures
+     *          IncludeColumn
+     *          ExcludeColumn
+     *
+     * Into
+     *      ReverseEngineering
+     *          Catalog
+     *              Schema
+     *                  IncludeTable
+     *                      IncludeColumn
+     *                      ExcludeColumn
+     *                  ExcludeTable
+     *                  IncludeProcedures
+     *                  ExcludeProcedures
+     *
+     *
+     * */
+    public void compact() {
+        addEmptyElements();
+
+        compactColumnFilters();
+        compactTableFilter();
+        compactProcedureFilter();
+        compactSchemas();
+    }
+
+    private void compactSchemas() {
+        for (Catalog catalog : engineering.getCatalogs()) {
+            catalog.getSchemas().addAll(engineering.getSchemas());
+        }
+        engineering.setSchemas(null);
+    }
+
+    private void compactProcedureFilter() {
+        Collection<IncludeProcedure> engIncludeProcedures = engineering.getIncludeProcedures();
+        Collection<ExcludeProcedure> engExcludeProcedures = engineering.getExcludeProcedures();
+
+        engineering.setIncludeProcedures(null);
+        engineering.setExcludeProcedures(null);
+
+        for (Catalog catalog : engineering.getCatalogs()) {
+            Collection<IncludeProcedure> catalogIncludeProcedures = catalog.getIncludeProcedures();
+            Collection<ExcludeProcedure> catalogExcludeProcedures = catalog.getExcludeProcedures();
+
+            catalog.setIncludeProcedures(null);
+            catalog.setExcludeProcedures(null);
+
+            for (Schema schema : catalog.getSchemas()) {
+                if (engIncludeProcedures != null) {
+                    schema.getIncludeProcedures().addAll(engIncludeProcedures);
+                    schema.getIncludeProcedures().addAll(catalogIncludeProcedures);
+                }
+                if (engExcludeProcedures != null) {
+                    schema.getExcludeProcedures().addAll(engExcludeProcedures);
+                    schema.getExcludeProcedures().addAll(catalogExcludeProcedures);
+                }
+            }
+        }
+
+        for (Schema schema : engineering.getSchemas()) {
+            schema.getIncludeProcedures().addAll(engIncludeProcedures);
+            schema.getExcludeProcedures().addAll(engExcludeProcedures);
+        }
+    }
+
+    private void compactTableFilter() {
+        Collection<IncludeTable> engIncludeTables = engineering.getIncludeTables();
+        Collection<ExcludeTable> engExcludeTables = engineering.getExcludeTables();
+
+        engineering.setIncludeTables(null);
+        engineering.setExcludeTables(null);
+
+        for (Catalog catalog : engineering.getCatalogs()) {
+            Collection<IncludeTable> catalogIncludeTables = catalog.getIncludeTables();
+            Collection<ExcludeTable> catalogExcludeTables = catalog.getExcludeTables();
+
+            catalog.setIncludeTables(null);
+            catalog.setExcludeTables(null);
+
+            for (Schema schema : catalog.getSchemas()) {
+                if (engIncludeTables != null) {
+                    schema.getIncludeTables().addAll(engIncludeTables);
+                    schema.getIncludeTables().addAll(catalogIncludeTables);
+                }
+                if (engExcludeTables != null) {
+                    schema.getExcludeTables().addAll(engExcludeTables);
+                    schema.getExcludeTables().addAll(catalogExcludeTables);
+                }
+            }
+        }
+
+        for (Schema schema : engineering.getSchemas()) {
+            schema.getIncludeTables().addAll(engIncludeTables);
+            schema.getExcludeTables().addAll(engExcludeTables);
+        }
+    }
+
+    private void compactColumnFilters() {
+        Collection<IncludeColumn> engIncludeColumns = engineering.getIncludeColumns();
+        Collection<ExcludeColumn> engExcludeColumns = engineering.getExcludeColumns();
+
+        engineering.setIncludeColumns(null);
+        engineering.setExcludeColumns(null);
+
+        for (Catalog catalog : engineering.getCatalogs()) {
+            Collection<IncludeColumn> catalogIncludeColumns = catalog.getIncludeColumns();
+            Collection<ExcludeColumn> catalogExcludeColumns = catalog.getExcludeColumns();
+
+            catalog.setIncludeColumns(null);
+            catalog.setExcludeColumns(null);
+
+            for (Schema schema : catalog.getSchemas()) {
+                Collection<IncludeColumn> schemaIncludeColumns = schema.getIncludeColumns();
+                Collection<ExcludeColumn> schemaExcludeColumns = schema.getExcludeColumns();
+
+                schema.setIncludeColumns(null);
+                schema.setExcludeColumns(null);
+
+                if (schema != null) {
+                    for (IncludeTable includeTable : schema.getIncludeTables()) {
+                        if (engIncludeColumns != null) {
+                            includeTable.getIncludeColumns().addAll(engIncludeColumns);
+                            includeTable.getIncludeColumns().addAll(catalogIncludeColumns);
+                            includeTable.getIncludeColumns().addAll(schemaIncludeColumns);
+                        }
+                        if (engExcludeColumns != null) {
+                            includeTable.getExcludeColumns().addAll(engExcludeColumns);
+                            includeTable.getExcludeColumns().addAll(catalogExcludeColumns);
+                            includeTable.getExcludeColumns().addAll(schemaExcludeColumns);
+                        }
+                    }
+                }
+            }
+
+            if (catalog.getIncludeTables() != null) {
+                for (IncludeTable includeTable : catalog.getIncludeTables()) {
+                    includeTable.getIncludeColumns().addAll(engIncludeColumns);
+                    includeTable.getIncludeColumns().addAll(catalogIncludeColumns);
+
+                    includeTable.getExcludeColumns().addAll(engExcludeColumns);
+                    includeTable.getExcludeColumns().addAll(catalogExcludeColumns);
+                }
+            }
+        }
+
+        for (Schema schema : engineering.getSchemas()) {
+            Collection<IncludeColumn> schemaIncludeColumns = schema.getIncludeColumns();
+            Collection<ExcludeColumn> schemaExcludeColumns = schema.getExcludeColumns();
+
+            schema.setIncludeColumns(null);
+            schema.setExcludeColumns(null);
+
+            for (IncludeTable includeTable : schema.getIncludeTables()) {
+                includeTable.getIncludeColumns().addAll(engIncludeColumns);
+                includeTable.getIncludeColumns().addAll(schemaIncludeColumns);
+
+                includeTable.getExcludeColumns().addAll(engExcludeColumns);
+                includeTable.getExcludeColumns().addAll(schemaExcludeColumns);
+            }
+        }
+
+        if (engineering.getIncludeTables() != null) {
+            for (IncludeTable includeTable : engineering.getIncludeTables()) {
+                includeTable.getIncludeColumns().addAll(engIncludeColumns);
+                includeTable.getExcludeColumns().addAll(engExcludeColumns);
+            }
+        }
+    }
+
+    private void addEmptyElements() {
+        if (engineering.getCatalogs().isEmpty()) {
+            engineering.addCatalog(new Catalog());
+        }
+
+        for (Catalog catalog : engineering.getCatalogs()) {
+            if (catalog.getSchemas().isEmpty()
+                    && engineering.getSchemas().isEmpty()) {
+                catalog.addSchema(new Schema());
+            }
+
+            for (Schema schema : catalog.getSchemas()) {
+                if (schema.getIncludeTables().isEmpty()
+                        && catalog.getIncludeTables().isEmpty()
+                        && engineering.getIncludeTables().isEmpty()) {
+
+                    schema.addIncludeTable(new IncludeTable());
+                }
+            }
+        }
+
+        if (engineering.getSchemas() == null) {
+            engineering.setSchemas(new LinkedList<Schema>());
+        }
+
+        for (Schema schema : engineering.getSchemas()) {
+            if (schema.getIncludeTables().isEmpty()
+                    && engineering.getIncludeTables().isEmpty()) {
+
+                schema.addIncludeTable(new IncludeTable());
+            }
+        }
+    }
+
+    public FiltersConfigBuilder add(OldFilterConfigBridge build) {
+        if (!isBlank(build.catalog())) {
+            engineering.addCatalog(new Catalog(build.catalog()));
+        }
+
+        if (!isBlank(build.schema())) {
+            engineering.addSchema(new Schema(build.schema()));
+        }
+
+        if (!isBlank(build.getIncludeTableFilters())) {
+            engineering.addIncludeTable(new IncludeTable(build.getIncludeTableFilters()));
+        }
+        if (!isBlank(build.getExcludeTableFilters())) {
+            engineering.addExcludeTable(new ExcludeTable(build.getExcludeTableFilters()));
+        }
+
+        if (!isBlank(build.getIncludeColumnFilters())) {
+            engineering.addIncludeColumn(new IncludeColumn(build.getIncludeColumnFilters()));
+        }
+        if (!isBlank(build.getExcludeColumnFilters())) {
+            engineering.addExcludeColumn(new ExcludeColumn(build.getExcludeColumnFilters()));
+        }
+
+        if (build.isLoadProcedures()) {
+            if (!isBlank(build.getIncludeProceduresFilters())) {
+                engineering.addIncludeProcedure(new IncludeProcedure(build.getIncludeProceduresFilters()));
+            }
+            if (!isBlank(build.getExcludeProceduresFilters())) {
+                engineering.addExcludeProcedure(new ExcludeProcedure(build.getExcludeProceduresFilters()));
+            }
+        }
+
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fe82b47e/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
new file mode 100644
index 0000000..899e987
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeColumn.java
@@ -0,0 +1,31 @@
+/*****************************************************************
+ *   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/fe82b47e/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
new file mode 100644
index 0000000..a249385
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeProcedure.java
@@ -0,0 +1,31 @@
+/*****************************************************************
+ *   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);
+    }
+}


Mime
View raw message