You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2014/10/29 19:40:36 UTC

[1/7] CAY-1946 CDbimport improvements

Repository: cayenne
Updated Branches:
  refs/heads/CAY-1946 [created] fde7761f8


http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-01.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-01.xml b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-01.xml
new file mode 100644
index 0000000..c3da6bb
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-01.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <name>DbImporterMojo Test1</name>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-cayenne-plugin</artifactId>
+                <configuration>
+                    <map>target/test/org/apache/cayenne/tools/dbimporter-map1.map.xml</map>
+                    <catalog>catalog-name-01</catalog>
+
+                    <catalog>
+                        <name>catalog-name-02</name>
+
+                        <schema>schema-name-01</schema>
+
+                        <schema>
+                            <name>schema-name-02</name>
+
+                            <includeTable>incTable-01</includeTable>
+                            <excludeTable>excTable-01</excludeTable>
+
+                            <includeTable>
+                                <pattern>incTable-02</pattern>
+
+                                <includeColumn>includeColumn-01</includeColumn>
+                                <excludeColumn>excludeColumn-01</excludeColumn>
+                            </includeTable>
+
+                            <includeColumn>includeColumn-02</includeColumn>
+                            <excludeColumn>excludeColumn-02</excludeColumn>
+                        </schema>
+
+                        <includeColumn>includeColumn-03</includeColumn>
+                        <excludeColumn>excludeColumn-03</excludeColumn>
+                    </catalog>
+
+                    <schema>schema-name-03</schema>
+
+                    <schema>
+                        <name>schema-name-04</name>
+
+                        <includeTable>incTable-04</includeTable>
+                        <excludeTable>excTable-04</excludeTable>
+
+                        <includeTable>
+                            <pattern>incTable-05</pattern>
+
+                            <includeColumn>includeColumn-04</includeColumn>
+                            <excludeColumn>excludeColumn-04</excludeColumn>
+                        </includeTable>
+
+                        <includeColumn>includeColumn-04</includeColumn>
+                        <excludeColumn>excludeColumn-04</excludeColumn>
+                    </schema>
+
+                    <includeTable>incTable-06</includeTable>
+                    <excludeTable>excTable-06</excludeTable>
+
+                    <includeTable>
+                        <pattern>incTable-07</pattern>
+
+                        <includeColumn>includeColumn-06</includeColumn>
+                        <excludeColumn>excludeColumn-06</excludeColumn>
+                    </includeTable>
+
+                    <includeColumn>includeColumn-05</includeColumn>
+                    <excludeColumn>excludeColumn-05</excludeColumn>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-catalog-and-schema.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-catalog-and-schema.xml b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-catalog-and-schema.xml
new file mode 100644
index 0000000..5b6932d
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-catalog-and-schema.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-cayenne-plugin</artifactId>
+                <configuration>
+                    <map>target/test/org/apache/cayenne/tools/dbimporter-map1.map.xml</map>
+
+                    <catalog>
+                        <name>catalog-name</name>
+                        <schema>
+                            <name>schema-name</name>
+                            <includeTable>includeTable-01</includeTable>
+
+                            <includeTable>
+                                <pattern>includeTable-02</pattern>
+                            </includeTable>
+
+                            <includeTable>
+                                <pattern>includeTable-03</pattern>
+
+                                <includeColumn>includeColumn-01</includeColumn>
+                                <excludeColumn>excludeColumn-01</excludeColumn>
+                            </includeTable>
+
+                            <excludeTable>excludeTable-01</excludeTable>
+                            <excludeTable>
+                                <pattern>excludeTable-02</pattern>
+                            </excludeTable>
+                            <excludeTable>excludeTable-03</excludeTable>
+
+                            <includeColumn>includeColumn-01</includeColumn>
+                            <includeColumn>
+                                <pattern>includeColumn-02</pattern>
+                            </includeColumn>
+                            <includeColumn>includeColumn-03</includeColumn>
+                            <excludeColumn>excludeColumn-01</excludeColumn>
+                            <excludeColumn>
+                                <pattern>excludeColumn-02</pattern>
+                            </excludeColumn>
+                            <excludeColumn>excludeColumn-03</excludeColumn>
+
+                            <includeProcedure>includeProcedure-01</includeProcedure>
+                            <includeProcedure>
+                                <pattern>includeProcedure-02</pattern>
+                            </includeProcedure>
+                            <includeProcedure>includeProcedure-03</includeProcedure>
+                            <excludeProcedure>excludeProcedure-01</excludeProcedure>
+                            <excludeProcedure>
+                                <pattern>excludeProcedure-02</pattern>
+                            </excludeProcedure>
+                            <excludeProcedure>excludeProcedure-03</excludeProcedure>
+                        </schema>
+                    </catalog>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-catalog.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-catalog.xml b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-catalog.xml
new file mode 100644
index 0000000..43bd650
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-catalog.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-cayenne-plugin</artifactId>
+                <configuration>
+                    <map>target/test/org/apache/cayenne/tools/dbimporter-map1.map.xml</map>
+
+                    <catalog>catalog-name-01</catalog>
+
+                    <catalog>
+                        <name>catalog-name-02</name>
+                    </catalog>
+
+                    <catalog>
+                        <name>catalog-name-03</name>
+                        <includeTable>includeTable-01</includeTable>
+
+                        <includeTable>
+                            <pattern>includeTable-02</pattern>
+                        </includeTable>
+
+                        <includeTable>
+                            <pattern>includeTable-03</pattern>
+
+                            <includeColumn>includeColumn-01</includeColumn>
+                            <excludeColumn>excludeColumn-01</excludeColumn>
+                        </includeTable>
+
+                        <excludeTable>excludeTable-01</excludeTable>
+                        <excludeTable>
+                            <pattern>excludeTable-02</pattern>
+                        </excludeTable>
+                        <excludeTable>excludeTable-03</excludeTable>
+
+                        <includeColumn>includeColumn-01</includeColumn>
+                        <includeColumn>
+                            <pattern>includeColumn-02</pattern>
+                        </includeColumn>
+                        <includeColumn>includeColumn-03</includeColumn>
+                        <excludeColumn>excludeColumn-01</excludeColumn>
+                        <excludeColumn>
+                            <pattern>excludeColumn-02</pattern>
+                        </excludeColumn>
+                        <excludeColumn>excludeColumn-03</excludeColumn>
+
+                        <includeProcedure>includeProcedure-01</includeProcedure>
+                        <includeProcedure>
+                            <pattern>includeProcedure-02</pattern>
+                        </includeProcedure>
+                        <includeProcedure>includeProcedure-03</includeProcedure>
+                        <excludeProcedure>excludeProcedure-01</excludeProcedure>
+                        <excludeProcedure>
+                            <pattern>excludeProcedure-02</pattern>
+                        </excludeProcedure>
+                        <excludeProcedure>excludeProcedure-03</excludeProcedure>
+                    </catalog>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-flat.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-flat.xml b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-flat.xml
new file mode 100644
index 0000000..0645fe3
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-flat.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-cayenne-plugin</artifactId>
+                <configuration>
+                    <map>target/test/org/apache/cayenne/tools/dbimporter-map1.map.xml</map>
+
+                    <includeTable>includeTable-01</includeTable>
+
+                    <includeTable>
+                        <pattern>includeTable-02</pattern>
+                    </includeTable>
+
+                    <includeTable>
+                        <pattern>includeTable-03</pattern>
+
+                        <includeColumn>includeColumn-01</includeColumn>
+                        <excludeColumn>excludeColumn-01</excludeColumn>
+                    </includeTable>
+
+                    <excludeTable>excludeTable-01</excludeTable>
+                    <excludeTable>
+                        <pattern>excludeTable-02</pattern>
+                    </excludeTable>
+                    <excludeTable>excludeTable-03</excludeTable>
+
+                    <includeColumn>includeColumn-01</includeColumn>
+                    <includeColumn>
+                        <pattern>includeColumn-02</pattern>
+                    </includeColumn>
+                    <includeColumn>includeColumn-03</includeColumn>
+                    <excludeColumn>excludeColumn-01</excludeColumn>
+                    <excludeColumn>
+                        <pattern>excludeColumn-02</pattern>
+                    </excludeColumn>
+                    <excludeColumn>excludeColumn-03</excludeColumn>
+
+                    <includeProcedure>includeProcedure-01</includeProcedure>
+                    <includeProcedure>
+                        <pattern>includeProcedure-02</pattern>
+                    </includeProcedure>
+                    <includeProcedure>includeProcedure-03</includeProcedure>
+                    <excludeProcedure>excludeProcedure-01</excludeProcedure>
+                    <excludeProcedure>
+                        <pattern>excludeProcedure-02</pattern>
+                    </excludeProcedure>
+                    <excludeProcedure>excludeProcedure-03</excludeProcedure>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-mapping.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-mapping.xml b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-mapping.xml
new file mode 100644
index 0000000..10c99da
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-mapping.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-cayenne-plugin</artifactId>
+                <configuration>
+                    <map>target/test/org/apache/cayenne/tools/dbimporter-map1.map.xml</map>
+
+                    <typeMapper >
+                        <mapperClassName>class</mapperClassName>
+                        <usePrimitives>false</usePrimitives>
+
+                        <type>
+                            <java>my.personal.type</java>
+                            <jdbc>varchar</jdbc>
+                        </type>
+                        <type>
+                            <java>java-01</java>
+                            <jdbc>jdbc-01</jdbc>
+                        </type>
+                        <type>
+                            <java>java-02</java>
+                            <jdbc>jdbc-02</jdbc>
+                            <length>21</length>
+                            <notNull>true</notNull>
+                        </type>
+                        <type>
+                            <java>java-03</java>
+                            <jdbc>jdbc-03</jdbc>
+                            <precision>5</precision>
+                            <scale>2</scale>
+                        </type>
+                        <type>
+                            <java>java-03</java>
+                            <jdbc>jdbc-03</jdbc>
+                            <precision>7</precision>
+                            <notNull>true</notNull>
+                        </type>
+                    </typeMapper>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-schema.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-schema.xml b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-schema.xml
new file mode 100644
index 0000000..62fc3f5
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/config/pom-schema.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-cayenne-plugin</artifactId>
+                <configuration>
+                    <map>target/test/org/apache/cayenne/tools/dbimporter-map1.map.xml</map>
+
+                    <schema>schema-name-01</schema>
+
+                    <schema>
+                        <name>schema-name-02</name>
+                    </schema>
+
+                    <schema>
+                        <name>schema-name-03</name>
+                        <includeTable>includeTable-01</includeTable>
+
+                        <includeTable>
+                            <pattern>includeTable-02</pattern>
+                        </includeTable>
+
+                        <includeTable>
+                            <pattern>includeTable-03</pattern>
+
+                            <includeColumn>includeColumn-01</includeColumn>
+                            <excludeColumn>excludeColumn-01</excludeColumn>
+                        </includeTable>
+
+                        <excludeTable>excludeTable-01</excludeTable>
+                        <excludeTable>
+                            <pattern>excludeTable-02</pattern>
+                        </excludeTable>
+                        <excludeTable>excludeTable-03</excludeTable>
+
+                        <includeColumn>includeColumn-01</includeColumn>
+                        <includeColumn>
+                            <pattern>includeColumn-02</pattern>
+                        </includeColumn>
+                        <includeColumn>includeColumn-03</includeColumn>
+                        <excludeColumn>excludeColumn-01</excludeColumn>
+                        <excludeColumn>
+                            <pattern>excludeColumn-02</pattern>
+                        </excludeColumn>
+                        <excludeColumn>excludeColumn-03</excludeColumn>
+
+                        <includeProcedure>includeProcedure-01</includeProcedure>
+                        <includeProcedure>
+                            <pattern>includeProcedure-02</pattern>
+                        </includeProcedure>
+                        <includeProcedure>includeProcedure-03</includeProcedure>
+                        <excludeProcedure>excludeProcedure-01</excludeProcedure>
+                        <excludeProcedure>
+                            <pattern>excludeProcedure-02</pattern>
+                        </excludeProcedure>
+                        <excludeProcedure>excludeProcedure-03</excludeProcedure>
+                    </schema>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema-pom.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema-pom.xml b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema-pom.xml
new file mode 100644
index 0000000..70806d7
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema-pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<name>DbImporterMojo Test1</name>	
+
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-cayenne-plugin</artifactId>
+				<configuration>
+					<map>target/test-classes/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.map.xml</map>
+                    <driver>org.apache.derby.jdbc.EmbeddedDriver</driver>
+                    <url>jdbc:derby:memory:DbImporterMojoTest;create=true</url>
+
+                    <schema>SCHEMA_01</schema>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.map.xml-result
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.map.xml-result b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.map.xml-result
new file mode 100644
index 0000000..093f6cc
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.map.xml-result
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+	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.
+-->
+<data-map xmlns="http://cayenne.apache.org/schema/7/modelMap"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://cayenne.apache.org/schema/7/modelMap http://cayenne.apache.org/schema/7/modelMap.xsd"
+          project-version="7">
+    <property name="defaultSchema" value="SCHEMA_01"/>
+    <db-entity name="CHILD" schema="SCHEMA_01">
+        <db-attribute name="COL3" type="DECIMAL" length="10" scale="2"/>
+        <db-attribute name="COL4" type="VARCHAR" length="25"/>
+        <db-attribute name="COL5" type="DATE" length="10"/>
+        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+        <db-attribute name="PARENT_ID" type="CHAR" length="25"/>
+    </db-entity>
+    <db-entity name="PARENT" schema="SCHEMA_01">
+        <db-attribute name="COL2" type="CHAR" length="25"/>
+        <db-attribute name="COL3" type="DECIMAL" length="10" scale="2"/>
+        <db-attribute name="COL4" type="VARCHAR" length="25"/>
+        <db-attribute name="COL5" type="DATE" length="10"/>
+        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+    </db-entity>
+    <obj-entity name="Child" className="Child" dbEntityName="CHILD">
+        <obj-attribute name="col3" type="java.math.BigDecimal" db-attribute-path="COL3"/>
+        <obj-attribute name="col4" type="java.lang.String" db-attribute-path="COL4"/>
+        <obj-attribute name="col5" type="java.util.Date" db-attribute-path="COL5"/>
+        <obj-attribute name="parentId" type="java.lang.String" db-attribute-path="PARENT_ID"/>
+    </obj-entity>
+    <obj-entity name="Parent" className="Parent" dbEntityName="PARENT">
+        <obj-attribute name="col2" type="java.lang.String" db-attribute-path="COL2"/>
+        <obj-attribute name="col3" type="java.math.BigDecimal" db-attribute-path="COL3"/>
+        <obj-attribute name="col4" type="java.lang.String" db-attribute-path="COL4"/>
+        <obj-attribute name="col5" type="java.util.Date" db-attribute-path="COL5"/>
+    </obj-entity>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.sql
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.sql b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.sql
new file mode 100644
index 0000000..7e172f5
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.sql
@@ -0,0 +1,48 @@
+
+CREATE SCHEMA schema_01;
+SET SCHEMA schema_01;
+
+CREATE TABLE schema_01.Parent (
+  id INTEGER NOT NULL,
+  COL2 CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id),
+  UNIQUE (COL3)
+);
+
+CREATE TABLE schema_01.Child (
+  id INTEGER NOT NULL,
+  Parent_id CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id)
+);
+
+CREATE SCHEMA schema_02;
+SET SCHEMA schema_02;
+
+CREATE TABLE schema_02.Parent (
+  id INTEGER NOT NULL,
+  COL2 CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id),
+  UNIQUE (COL3)
+);
+
+CREATE TABLE schema_02.Child (
+  id INTEGER NOT NULL,
+  Parent_id CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id)
+);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude-pom.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude-pom.xml b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude-pom.xml
new file mode 100644
index 0000000..8b1ba32
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude-pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<name>DbImporterMojo Test1</name>	
+
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-cayenne-plugin</artifactId>
+				<configuration>
+					<map>target/test-classes/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude.map.xml</map>
+                    <driver>org.apache.derby.jdbc.EmbeddedDriver</driver>
+                    <url>jdbc:derby:memory:DbImporterMojoTest;create=true</url>
+
+                    <schema>SCHEMA_01</schema>
+
+                    <tablePattern>Parent</tablePattern>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude.map.xml-result
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude.map.xml-result b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude.map.xml-result
new file mode 100644
index 0000000..5853842
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude.map.xml-result
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+	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.
+-->
+<data-map xmlns="http://cayenne.apache.org/schema/7/modelMap"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://cayenne.apache.org/schema/7/modelMap http://cayenne.apache.org/schema/7/modelMap.xsd"
+          project-version="7">
+    <db-entity name="PARENT" schema="SCHEMA_01">
+        <db-attribute name="COL2" type="CHAR" length="25"/>
+        <db-attribute name="COL3" type="DECIMAL" length="10" scale="2"/>
+        <db-attribute name="COL4" type="VARCHAR" length="25"/>
+        <db-attribute name="COL5" type="DATE" length="10"/>
+        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+    </db-entity>
+    <obj-entity name="Parent" className="Parent" dbEntityName="PARENT">
+        <obj-attribute name="col2" type="java.lang.String" db-attribute-path="COL2"/>
+        <obj-attribute name="col3" type="java.math.BigDecimal" db-attribute-path="COL3"/>
+        <obj-attribute name="col4" type="java.lang.String" db-attribute-path="COL4"/>
+        <obj-attribute name="col5" type="java.util.Date" db-attribute-path="COL5"/>
+    </obj-entity>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude.sql
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude.sql b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude.sql
new file mode 100644
index 0000000..7e172f5
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOldParamsSchemasAndTableExclude.sql
@@ -0,0 +1,48 @@
+
+CREATE SCHEMA schema_01;
+SET SCHEMA schema_01;
+
+CREATE TABLE schema_01.Parent (
+  id INTEGER NOT NULL,
+  COL2 CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id),
+  UNIQUE (COL3)
+);
+
+CREATE TABLE schema_01.Child (
+  id INTEGER NOT NULL,
+  Parent_id CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id)
+);
+
+CREATE SCHEMA schema_02;
+SET SCHEMA schema_02;
+
+CREATE TABLE schema_02.Parent (
+  id INTEGER NOT NULL,
+  COL2 CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id),
+  UNIQUE (COL3)
+);
+
+CREATE TABLE schema_02.Child (
+  id INTEGER NOT NULL,
+  Parent_id CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id)
+);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude-pom.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude-pom.xml b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude-pom.xml
new file mode 100644
index 0000000..f6665f8
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude-pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<name>DbImporterMojo Test1</name>	
+
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-cayenne-plugin</artifactId>
+				<configuration>
+					<map>target/test-classes/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.map.xml</map>
+                    <driver>org.apache.derby.jdbc.EmbeddedDriver</driver>
+                    <url>jdbc:derby:memory:DbImporterMojoTest;create=true</url>
+
+                    <schema>
+                        <name>SCHEMA_01</name>
+                    </schema>
+
+                    <excludeTable>Child</excludeTable>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.map.xml-result
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.map.xml-result b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.map.xml-result
new file mode 100644
index 0000000..5853842
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.map.xml-result
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+	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.
+-->
+<data-map xmlns="http://cayenne.apache.org/schema/7/modelMap"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://cayenne.apache.org/schema/7/modelMap http://cayenne.apache.org/schema/7/modelMap.xsd"
+          project-version="7">
+    <db-entity name="PARENT" schema="SCHEMA_01">
+        <db-attribute name="COL2" type="CHAR" length="25"/>
+        <db-attribute name="COL3" type="DECIMAL" length="10" scale="2"/>
+        <db-attribute name="COL4" type="VARCHAR" length="25"/>
+        <db-attribute name="COL5" type="DATE" length="10"/>
+        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+    </db-entity>
+    <obj-entity name="Parent" className="Parent" dbEntityName="PARENT">
+        <obj-attribute name="col2" type="java.lang.String" db-attribute-path="COL2"/>
+        <obj-attribute name="col3" type="java.math.BigDecimal" db-attribute-path="COL3"/>
+        <obj-attribute name="col4" type="java.lang.String" db-attribute-path="COL4"/>
+        <obj-attribute name="col5" type="java.util.Date" db-attribute-path="COL5"/>
+    </obj-entity>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.sql
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.sql b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.sql
new file mode 100644
index 0000000..7e172f5
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.sql
@@ -0,0 +1,48 @@
+
+CREATE SCHEMA schema_01;
+SET SCHEMA schema_01;
+
+CREATE TABLE schema_01.Parent (
+  id INTEGER NOT NULL,
+  COL2 CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id),
+  UNIQUE (COL3)
+);
+
+CREATE TABLE schema_01.Child (
+  id INTEGER NOT NULL,
+  Parent_id CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id)
+);
+
+CREATE SCHEMA schema_02;
+SET SCHEMA schema_02;
+
+CREATE TABLE schema_02.Parent (
+  id INTEGER NOT NULL,
+  COL2 CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id),
+  UNIQUE (COL3)
+);
+
+CREATE TABLE schema_02.Child (
+  id INTEGER NOT NULL,
+  Parent_id CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id)
+);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSimpleFiltering-pom.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSimpleFiltering-pom.xml b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSimpleFiltering-pom.xml
new file mode 100644
index 0000000..00f10ff
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSimpleFiltering-pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<name>DbImporterMojo Test1</name>	
+
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-cayenne-plugin</artifactId>
+				<configuration>
+					<map>target/test-classes/org/apache/cayenne/tools/dbimport/testSimpleFiltering.map.xml</map>
+                    <driver>org.apache.derby.jdbc.EmbeddedDriver</driver>
+                    <url>jdbc:derby:memory:DbImporterMojoTest;create=true</url>
+
+                    <includeTable>Parent</includeTable>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSimpleFiltering.map.xml-result
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSimpleFiltering.map.xml-result b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSimpleFiltering.map.xml-result
new file mode 100644
index 0000000..f8eb58e
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSimpleFiltering.map.xml-result
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+	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.
+-->
+<data-map xmlns="http://cayenne.apache.org/schema/7/modelMap"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://cayenne.apache.org/schema/7/modelMap http://cayenne.apache.org/schema/7/modelMap.xsd"
+          project-version="7">
+    <db-entity name="PARENT" schema="APP">
+        <db-attribute name="COL2" type="CHAR" length="25"/>
+        <db-attribute name="COL3" type="DECIMAL" length="10" scale="2"/>
+        <db-attribute name="COL4" type="VARCHAR" length="25"/>
+        <db-attribute name="COL5" type="DATE" length="10"/>
+        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+    </db-entity>
+    <obj-entity name="Parent" className="Parent" dbEntityName="PARENT">
+        <obj-attribute name="col2" type="java.lang.String" db-attribute-path="COL2"/>
+        <obj-attribute name="col3" type="java.math.BigDecimal" db-attribute-path="COL3"/>
+        <obj-attribute name="col4" type="java.lang.String" db-attribute-path="COL4"/>
+        <obj-attribute name="col5" type="java.util.Date" db-attribute-path="COL5"/>
+    </obj-entity>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSimpleFiltering.sql
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSimpleFiltering.sql b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSimpleFiltering.sql
new file mode 100644
index 0000000..fb820b7
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSimpleFiltering.sql
@@ -0,0 +1,20 @@
+CREATE TABLE Parent (
+  id INTEGER NOT NULL,
+  COL2 CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id),
+  UNIQUE (COL3)
+);
+
+CREATE TABLE Child (
+  id INTEGER NOT NULL,
+  Parent_id CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id)
+);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 042f904..5408e03 100644
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -96,6 +96,22 @@
 					</execution>
 				</executions>
 			</plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-plugin-plugin</artifactId>
+                <version>3.3</version>
+                <configuration>
+                    <goalPrefix>signature</goalPrefix>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>descriptor</goal>
+                        </goals>
+                        <phase>process-classes</phase>
+                    </execution>
+                </executions>
+            </plugin>
 		</plugins>
 	</build>
 </project>


[3/7] CAY-1946 CDbimport improvements

Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeColumn.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeColumn.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeColumn.java
new file mode 100644
index 0000000..46b5672
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/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.tools.dbimport.config;
+
+/**
+ * @since 3.2.
+ */
+public class IncludeColumn extends PatternParam {
+    public IncludeColumn() {
+    }
+
+    public IncludeColumn(String pattern) {
+        super(pattern);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeProcedure.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeProcedure.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeProcedure.java
new file mode 100644
index 0000000..a5c8ea2
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/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.tools.dbimport.config;
+
+/**
+ * @since 3.2.
+ */
+public class IncludeProcedure extends PatternParam {
+    public IncludeProcedure() {
+    }
+
+    public IncludeProcedure(String pattern) {
+        super(pattern);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeTable.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeTable.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeTable.java
new file mode 100644
index 0000000..e627eea
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeTable.java
@@ -0,0 +1,77 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.tools.dbimport.config;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+import static org.apache.commons.lang.StringUtils.join;
+
+/**
+ * @since 3.2.
+ */
+public class IncludeTable extends PatternParam {
+
+    private Collection<IncludeColumn> includeColumns = new LinkedList<IncludeColumn>();
+    private Collection<ExcludeColumn> excludeColumns = new LinkedList<ExcludeColumn>();
+
+    public IncludeTable() {
+    }
+
+    public IncludeTable(String pattern) {
+        super(pattern);
+    }
+
+    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 void addIncludeColumn(IncludeColumn includeColumn) {
+        this.includeColumns.add(includeColumn);
+    }
+
+    public void addExcludeColumn(ExcludeColumn excludeColumn) {
+        this.excludeColumns.add(excludeColumn);
+    }
+
+    @Override
+    public String toString() {
+        String str = "+(" + getPattern() + ") ";
+        if (includeColumns != null && !includeColumns.isEmpty()) {
+            str += "+Columns(" + join(includeColumns, ", ") + ") ";
+        }
+
+        if (excludeColumns != null && !excludeColumns.isEmpty()) {
+            str += "-Columns(" + join(excludeColumns, ", ") + ") ";
+        }
+        return str;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/PatternParam.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/PatternParam.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/PatternParam.java
new file mode 100644
index 0000000..3d8297c
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/PatternParam.java
@@ -0,0 +1,74 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.tools.dbimport.config;
+
+/**
+ * @since 3.2.
+ */
+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;
+    }
+
+    /**
+     * used my maven
+     *
+     * @param pattern
+     */
+    public void set(String pattern) {
+        setPattern(pattern);
+    }
+
+
+    /**
+     * used my ant
+     *
+     * @param pattern
+     */
+    public void addText(String pattern) {
+        if (pattern.trim().isEmpty()) {
+            return;
+        }
+
+        setPattern(pattern);
+    }
+
+    public void addConfiguredPattern(AntNestedElement pattern) {
+        set(pattern.getName());
+    }
+
+    @Override
+    public String toString() {
+        return "RegExp(" + pattern + ")";
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineering.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineering.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineering.java
new file mode 100644
index 0000000..8f4277b
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineering.java
@@ -0,0 +1,60 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.tools.dbimport.config;
+
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * @since 3.2.
+ */
+public class ReverseEngineering extends FilterContainer {
+
+    private Collection<Catalog> catalogs = new LinkedList<Catalog>();
+    private Collection<Schema> schemas = new LinkedList<Schema>();
+
+    public ReverseEngineering() {
+    }
+
+    public Collection<Catalog> getCatalogs() {
+        return catalogs;
+    }
+
+    public void setCatalogs(Collection<Catalog> catalogs) {
+        this.catalogs = catalogs;
+    }
+
+    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 addCatalog(Catalog catalog) {
+        this.catalogs.add(catalog);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineeringLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineeringLoader.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineeringLoader.java
new file mode 100644
index 0000000..8e663b6
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineeringLoader.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.tools.dbimport.config;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.resource.Resource;
+
+/**
+ * @since 3.2.
+ */
+public interface ReverseEngineeringLoader {
+
+    ReverseEngineering load(Resource configurationResource) throws CayenneRuntimeException;
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Schema.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Schema.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Schema.java
new file mode 100644
index 0000000..1a399f0
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Schema.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.tools.dbimport.config;
+
+/**
+ * @since 3.2.
+ */
+public class Schema extends FilterContainer {
+
+    private String name;
+
+    public Schema() {
+    }
+
+    public Schema(String name) {
+        this.name = name;
+    }
+
+    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);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Type.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Type.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Type.java
new file mode 100644
index 0000000..bbd1039
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Type.java
@@ -0,0 +1,136 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.tools.dbimport.config;
+
+import org.apache.cayenne.util.ToStringBuilder;
+
+/**
+ * @since 3.2.
+ */
+public class Type {
+
+    private String jdbc;
+    private String java;
+
+    private Integer length;
+    private Integer precision;
+    private Integer scale;
+    private Boolean notNull;
+
+    public String getJdbc() {
+        return jdbc;
+    }
+
+    public void setJdbc(String jdbc) {
+        this.jdbc = jdbc;
+    }
+
+    public String getJava() {
+        return java;
+    }
+
+    public void setJava(String java) {
+        this.java = java;
+    }
+
+    public Integer getLength() {
+        return length;
+    }
+
+    public void setLength(Integer length) {
+        this.length = length;
+    }
+
+    public Integer getPrecision() {
+        return precision;
+    }
+
+    public void setPrecision(Integer precision) {
+        this.precision = precision;
+    }
+
+    public Integer getScale() {
+        return scale;
+    }
+
+    public void setScale(Integer scale) {
+        this.scale = scale;
+    }
+
+    public Boolean getNotNull() {
+        return notNull;
+    }
+
+    public void setNotNull(Boolean notNull) {
+        this.notNull = notNull;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        Type type = (Type) o;
+
+        if (jdbc != null ? !jdbc.equals(type.jdbc) : type.jdbc != null) {
+            return false;
+        }
+        if (!length.equals(type.length)) {
+            return false;
+        }
+        if (!notNull.equals(type.notNull)) {
+            return false;
+        }
+        if (!precision.equals(type.precision)) {
+            return false;
+        }
+        if (!scale.equals(type.scale)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = jdbc != null ? jdbc.hashCode() : 0;
+        result = 31 * result + length.hashCode();
+        result = 31 * result + precision.hashCode();
+        result = 31 * result + scale.hashCode();
+        result = 31 * result + notNull.hashCode();
+        return result;
+    }
+
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this)
+                .append("jdbc", jdbc)
+                .append("java", java)
+                .append("length", length)
+                .append("precision", precision)
+                .append("scale", scale)
+                .append("notNull", notNull)
+                .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/TypeMapper.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/TypeMapper.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/TypeMapper.java
new file mode 100644
index 0000000..ed84fff
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/TypeMapper.java
@@ -0,0 +1,95 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.tools.dbimport.config;
+
+import org.apache.cayenne.util.EqualsBuilder;
+import org.apache.cayenne.util.HashCodeBuilder;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * @since 3.2.
+ */
+public class TypeMapper {
+
+    private String mapperClassName;
+
+    private Boolean usePrimitives;
+
+    private Collection<Type> types = new LinkedList<Type>();
+
+    public String getMapperClassName() {
+        return mapperClassName;
+    }
+
+    public void setMapperClassName(String mapperClassName) {
+        this.mapperClassName = mapperClassName;
+    }
+
+    public Boolean getUsePrimitives() {
+        return usePrimitives;
+    }
+
+    public void setUsePrimitives(Boolean usePrimitives) {
+        this.usePrimitives = usePrimitives;
+    }
+
+    public Collection<Type> getTypes() {
+        return types;
+    }
+
+    public void setTypes(Collection<Type> types) {
+        this.types = types;
+    }
+
+    public void addType(Type type) {
+        this.types.add(type);
+    }
+
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (obj == this) {
+            return true;
+        }
+        if (obj.getClass() != getClass()) {
+            return false;
+        }
+        TypeMapper rhs = (TypeMapper) obj;
+        return new EqualsBuilder()
+                .append(this.mapperClassName, rhs.mapperClassName)
+                .append(this.usePrimitives, rhs.usePrimitives)
+                .append(this.types, rhs.types)
+                .isEquals();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(mapperClassName).append(usePrimitives).append(types).toHashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "TypeMapper {mapperClassName=" + mapperClassName + ", usePrimitives=" + usePrimitives + ", types=" + types + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
new file mode 100644
index 0000000..647b66d
--- /dev/null
+++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ */
+
+package org.apache.cayenne.tools;
+
+import org.apache.cayenne.tools.dbimport.DbImportConfiguration;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.UnknownElement;
+import org.apache.tools.ant.util.FileUtils;
+import org.custommonkey.xmlunit.DetailedDiff;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import static org.apache.cayenne.tools.dbimport.config.DefaultReverseEngineeringLoaderTest.*;
+import static org.apache.commons.lang.StringUtils.isBlank;
+import static org.junit.Assert.fail;
+
+public class DbImporterTaskTest {
+
+    static {
+        XMLUnit.setIgnoreWhitespace(true);
+    }
+
+    @Test
+    public void testLoadCatalog() throws Exception {
+        assertCatalog(getCdbImport("build-catalog.xml").getReverseEngineering());
+    }
+
+    @Test
+    public void testLoadSchema() throws Exception {
+        assertSchema(getCdbImport("build-schema.xml").getReverseEngineering());
+    }
+
+    @Test
+    public void testLoadCatalogAndSchema() throws Exception {
+        assertCatalogAndSchema(getCdbImport("build-catalog-and-schema.xml").getReverseEngineering());
+    }
+
+    @Test
+    public void testLoadFlat() throws Exception {
+        assertFlat(getCdbImport("build-flat.xml").getReverseEngineering());
+    }
+
+    @Test
+    public void testIncludeTable() throws Exception {
+        test("build-include-table.xml");
+    }
+
+
+    private DbImporterTask getCdbImport(String buildFile) {
+        Project project = new Project();
+        ProjectHelper.configureProject(project, new File(getPackagePath() + "/" + buildFile));
+
+        UnknownElement task = (UnknownElement) project.getTargets().get("dist").getTasks()[0];
+        task.maybeConfigure();
+
+        return (DbImporterTask) task.getRealThing();
+    }
+
+    private String getPackagePath() {
+        return getClass().getClassLoader().getResource(getClass().getPackage().getName().replace('.', '/')).getPath();
+    }
+
+    private void test(String name) throws Exception {
+        DbImporterTask cdbImport = getCdbImport("dbimport/" + name);
+        File mapFile = cdbImport.getMap();
+        File mapFileCopy = new File(mapFile.getParentFile(), "copy-" + mapFile.getName());
+        if (mapFile.exists()) {
+            FileUtils.getFileUtils().copyFile(mapFile, mapFileCopy);
+            cdbImport.setMap(mapFileCopy);
+        } else {
+            mapFileCopy = mapFile;
+        }
+
+        prepareDatabase(name, cdbImport.toParameters());
+
+        try {
+            cdbImport.execute();
+            verifyResult(mapFile, mapFileCopy);
+        } finally {
+            cleanDb(cdbImport.toParameters());
+        }
+    }
+
+    private void cleanDb(DbImportConfiguration dbImportConfiguration) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
+        Class.forName(dbImportConfiguration.getDriver()).newInstance();
+        // Get a connection
+        Connection connection = DriverManager.getConnection(dbImportConfiguration.getUrl());
+        Statement stmt = connection.createStatement();
+
+        ResultSet tables = connection.getMetaData().getTables(null, null, null, new String[]{"TABLE"});
+        while (tables.next()) {
+            String schema = tables.getString("TABLE_SCHEM");
+            System.out.println("DROP TABLE " + (isBlank(schema) ? "" : schema + ".") + tables.getString("TABLE_NAME"));
+            stmt.execute("DROP TABLE " + (isBlank(schema) ? "" : schema + ".") + tables.getString("TABLE_NAME"));
+        }
+
+        ResultSet schemas = connection.getMetaData().getSchemas();
+        while (schemas.next()) {
+            String schem = schemas.getString("TABLE_SCHEM");
+            if (schem.startsWith("SCHEMA")) {
+                System.out.println("DROP SCHEMA " + schem);
+                stmt.execute("DROP SCHEMA " + schem + " RESTRICT");
+            }
+        }
+    }
+
+    private void verifyResult(File map, File mapFileCopy) {
+        try {
+            FileReader control = new FileReader(map.getAbsolutePath() + "-result");
+            FileReader test = new FileReader(mapFileCopy);
+
+            DetailedDiff diff = new DetailedDiff(new Diff(control, test));
+            if (!diff.similar()) {
+                System.out.println(" >>>> " + map.getAbsolutePath() + "-result");
+                System.out.println(" >>>> " + mapFileCopy);
+                fail(diff.toString());
+            }
+
+        } catch (SAXException e) {
+            e.printStackTrace();
+            fail();
+        } catch (IOException e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+    private void prepareDatabase(String sqlFile, DbImportConfiguration dbImportConfiguration) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException, IOException, URISyntaxException {
+        Class.forName(dbImportConfiguration.getDriver()).newInstance();
+        // Get a connection
+        Statement stmt = DriverManager.getConnection(dbImportConfiguration.getUrl()).createStatement();
+
+        for (String sql : FileUtils.readFully(new FileReader(getPackagePath() + "/dbimport/" + sqlFile + ".sql")).split(";")) {
+            stmt.execute(sql);
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java
index 143a473..a67e85b 100644
--- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java
+++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java
@@ -21,40 +21,25 @@ package org.apache.cayenne.tools;
 
 import junit.framework.TestCase;
 
+import org.apache.cayenne.access.loader.NamePatternMatcher;
 import org.apache.tools.ant.Task;
 
+import static org.apache.cayenne.access.loader.NamePatternMatcher.replaceWildcardInStringWithString;
+
 public class NamePatternMatcherTest extends TestCase {
 
     /**
      * Test pattern expansion.
      */
     public void testReplaceWildcardInStringWithString() throws Exception {
-        assertEquals(null, NamePatternMatcher.replaceWildcardInStringWithString(
-                "*",
-                null,
-                "Entity"));
-        assertEquals("*.java", NamePatternMatcher.replaceWildcardInStringWithString(
-                null,
-                "*.java",
-                "Entity"));
-        assertEquals("Entity.java", NamePatternMatcher.replaceWildcardInStringWithString(
-                "*",
-                "*.java",
-                "Entity"));
-        assertEquals("java.Entity", NamePatternMatcher.replaceWildcardInStringWithString(
-                "*",
-                "java.*",
-                "Entity"));
-        assertEquals("Entity.Entity", NamePatternMatcher
-                .replaceWildcardInStringWithString("*", "*.*", "Entity"));
-        assertEquals("EntityEntity", NamePatternMatcher
-                .replaceWildcardInStringWithString("*", "**", "Entity"));
-        assertEquals("EditEntityReport.vm", NamePatternMatcher
-                .replaceWildcardInStringWithString("*", "Edit*Report.vm", "Entity"));
-        assertEquals("Entity", NamePatternMatcher.replaceWildcardInStringWithString(
-                "*",
-                "*",
-                "Entity"));
+        assertEquals(null, replaceWildcardInStringWithString("*", null, "Entity"));
+        assertEquals("*.java", replaceWildcardInStringWithString(null, "*.java", "Entity"));
+        assertEquals("Entity.java", replaceWildcardInStringWithString("*", "*.java", "Entity"));
+        assertEquals("java.Entity", replaceWildcardInStringWithString("*", "java.*", "Entity"));
+        assertEquals("Entity.Entity", replaceWildcardInStringWithString("*", "*.*", "Entity"));
+        assertEquals("EntityEntity", replaceWildcardInStringWithString("*", "**", "Entity"));
+        assertEquals("EditEntityReport.vm", replaceWildcardInStringWithString("*", "Edit*Report.vm", "Entity"));
+        assertEquals("Entity", replaceWildcardInStringWithString("*", "*", "Entity"));
     }
 
     /**
@@ -71,10 +56,8 @@ public class NamePatternMatcherTest extends TestCase {
 
         String includePattern = "billing_*,user?";
         String excludePattern = null;
-        NamePatternMatcher namePatternMatcher = new NamePatternMatcher(
-                new AntLogger(parentTask),
-                includePattern,
-                excludePattern);
+        NamePatternMatcher namePatternMatcher = NamePatternMatcher.build(
+                new AntLogger(parentTask), includePattern, excludePattern);
 
         String[] nullFilters = namePatternMatcher.tokenizePattern(null);
         assertEquals(0, nullFilters.length);
@@ -99,10 +82,8 @@ public class NamePatternMatcherTest extends TestCase {
 
         String includePattern = "Organization,SecGroup,SecIndividual";
         String excludePattern = null;
-        NamePatternMatcher namePatternMatcher = new NamePatternMatcher(
-                new AntLogger(parentTask),
-                includePattern,
-                excludePattern);
+        NamePatternMatcher namePatternMatcher = NamePatternMatcher.build(
+                new AntLogger(parentTask), includePattern, excludePattern);
 
         String[] filters = namePatternMatcher.tokenizePattern(includePattern);
         assertEquals(3, filters.length);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java
index 2977576..72d1df4 100644
--- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java
+++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java
@@ -1,25 +1,26 @@
-/*****************************************************************
- *   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
+/*
+ * 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
+ *      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.
- ****************************************************************/
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ */
 package org.apache.cayenne.tools.dbimport;
 
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.access.DbLoader;
+import org.apache.cayenne.access.loader.DbLoaderConfiguration;
 import org.apache.cayenne.access.DbLoaderDelegate;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
@@ -69,16 +70,10 @@ public class DbImportActionTest {
     @Test
     public void testNewDataMapImport() throws Exception {
 
-        final boolean[] haveWeTriedToLoadProcedures = {false};
         DbLoader dbLoader = new DbLoader(null, null, null) {
             @Override
-            public void load(DataMap dataMap, String catalogPattern, String schemaPattern, String tablePattern, String... tableTypes) throws SQLException {
-                new DataMapBuilder(dataMap).withDbEntities(2);
-            }
-
-            @Override
-            public void loadProcedures(DataMap dataMap, String catalogPattern, String schemaPattern, String namePattern) throws SQLException {
-                haveWeTriedToLoadProcedures[0] = true;
+            public DataMap load(DbLoaderConfiguration config) throws SQLException {
+                return new DataMapBuilder(new DataMap()).withDbEntities(2).build();
             }
 
             @Override
@@ -93,7 +88,10 @@ public class DbImportActionTest {
 
         when(params.createDataMap()).thenReturn(new DataMap("testImport"));
         when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
-        when(params.isImportProcedures()).thenReturn(true);
+        when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
+
+        final DataMap DATA_MAP = new DataMap();
+        when(params.initializeDataMap(any(DataMap.class))).thenReturn(DATA_MAP);
 
         final boolean[] haveWeTriedToSave = {false};
         DbImportAction action = buildDbImportAction(new FileProjectSaver() {
@@ -102,14 +100,12 @@ public class DbImportActionTest {
                 haveWeTriedToSave[0] = true;
 
                 // Validation phase
-                DataMap rootNode = (DataMap) project.getRootNode();
-                assertEquals(2, rootNode.getDbEntityMap().size());
+                assertEquals(DATA_MAP, project.getRootNode());
             }
         }, null);
 
         action.execute(params);
 
-        assertTrue("We should try to load procedures.", haveWeTriedToLoadProcedures[0]);
         assertTrue("We should try to save.", haveWeTriedToSave[0]);
     }
 
@@ -117,7 +113,8 @@ public class DbImportActionTest {
     public void testImportWithFieldChanged() throws Exception {
         DbLoader dbLoader = new DbLoader(null, null, null) {
             @Override
-            public void load(DataMap dataMap, String catalogPattern, String schemaPattern, String tablePattern, String... tableTypes) throws SQLException {
+            public DataMap load(DbLoaderConfiguration config) throws SQLException {
+                DataMap dataMap = new DataMap("dataMap");
                 new DataMapBuilder(dataMap).with(
                         dbEntity("ARTGROUP").attributes(
                                 dbAttr("GROUP_ID").typeInt().primaryKey(),
@@ -128,6 +125,8 @@ public class DbImportActionTest {
                         objEntity("org.apache.cayenne.testdo.testmap", "ArtGroup", "ARTGROUP").attributes(
                                 objAttr("name").type(String.class).dbPath("NAME")
                 ));
+
+                return dataMap;
             }
 
             @Override
@@ -143,6 +142,7 @@ public class DbImportActionTest {
         when(params.createDataMap()).thenReturn(new DataMap("testImport"));
         when(params.getDataMapFile()).thenReturn(FILE_STUB);
         when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
+        when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
 
         final boolean[] haveWeTriedToSave = {false};
         DbImportAction action = buildDbImportAction(new FileProjectSaver() {
@@ -185,11 +185,13 @@ public class DbImportActionTest {
     public void testImportWithoutChanges() throws Exception {
         DbLoader dbLoader = new DbLoader(null, null, null) {
             @Override
-            public void load(DataMap dataMap, String catalogPattern, String schemaPattern, String tablePattern, String... tableTypes) throws SQLException {
+            public DataMap load(DbLoaderConfiguration config) throws SQLException {
+                DataMap dataMap = new DataMap("dataMap");
                 new DataMapBuilder(dataMap).with(
                         dbEntity("ARTGROUP").attributes(
                                 dbAttr("NAME").typeVarchar(100).mandatory()
                         ));
+                return dataMap;
             }
 
             @Override
@@ -205,6 +207,7 @@ public class DbImportActionTest {
         when(params.createDataMap()).thenReturn(new DataMap("testImport"));
         when(params.getDataMapFile()).thenReturn(FILE_STUB);
         when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
+        when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
 
         Log log = mock(Log.class);
         when(log.isDebugEnabled()).thenReturn(false);
@@ -231,7 +234,7 @@ public class DbImportActionTest {
     public void testImportWithDbError() throws Exception {
         DbLoader dbLoader = mock(DbLoader.class);
         when(dbLoader.getDefaultTableTypes()).thenReturn(null);
-        doThrow(new SQLException()).when(dbLoader).load(any(DataMap.class), anyString(), anyString(), anyString());
+        doThrow(new SQLException()).when(dbLoader).load(any(DataMap.class), any(DbLoaderConfiguration.class));
 
         DbImportConfiguration params = mock(DbImportConfiguration.class);
         when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class)))

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportConfigurationTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportConfigurationTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportConfigurationTest.java
index 18aeeb4..e8f03d0 100644
--- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportConfigurationTest.java
+++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportConfigurationTest.java
@@ -18,214 +18,21 @@
  ****************************************************************/
 package org.apache.cayenne.tools.dbimport;
 
-import org.apache.cayenne.access.DbLoader;
-import org.apache.cayenne.access.DbLoaderDelegate;
-import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.util.XMLEncoder;
 import org.junit.Test;
 
 import java.io.File;
 import java.io.PrintWriter;
-import java.lang.reflect.Field;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.sql.Connection;
-import java.sql.Types;
-import java.util.List;
 
 import static org.junit.Assert.*;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
 
 public class DbImportConfigurationTest {
 
     @Test
-    public void testCreateLoader() throws Exception {
-        DbImportConfiguration parameters = new DbImportConfiguration();
-
-        Connection connection = mock(Connection.class);
-
-        DbLoader loader = parameters.createLoader(mock(DbAdapter.class), connection,
-                mock(DbLoaderDelegate.class));
-        assertNotNull(loader);
-        assertSame(connection, loader.getConnection());
-        assertTrue(loader.includeTableName("dummy"));
-    }
-
-    @Test
-    public void testCreateLoader_IncludeExclude() throws Exception {
-        DbImportConfiguration parameters = new DbImportConfiguration();
-        parameters.setIncludeTables("a,b,c*");
-
-        DbLoader loader1 = parameters.createLoader(mock(DbAdapter.class), mock(Connection.class),
-                mock(DbLoaderDelegate.class));
-
-        assertFalse(loader1.includeTableName("dummy"));
-        assertFalse(loader1.includeTableName("ab"));
-        assertTrue(loader1.includeTableName("a"));
-        assertTrue(loader1.includeTableName("b"));
-        assertTrue(loader1.includeTableName("cd"));
-
-        parameters.setExcludeTables("cd");
-
-        DbLoader loader2 = parameters.createLoader(mock(DbAdapter.class), mock(Connection.class),
-                mock(DbLoaderDelegate.class));
-
-        assertFalse(loader2.includeTableName("dummy"));
-        assertFalse(loader2.includeTableName("ab"));
-        assertTrue(loader2.includeTableName("a"));
-        assertTrue(loader2.includeTableName("b"));
-        assertFalse(loader2.includeTableName("cd"));
-        assertTrue(loader2.includeTableName("cx"));
-    }
-
-
-    @Test
-    public void testCreateLoader_MeaningfulPk_Default() throws Exception {
-        DbImportConfiguration parameters = new DbImportConfiguration();
-        assertNull(parameters.getMeaningfulPkTables());
-
-        DbLoader loader1 = parameters.createLoader(mock(DbAdapter.class), mock(Connection.class),
-                mock(DbLoaderDelegate.class));
-
-        DataMap map = new DataMap();
-
-        DbEntity e1 = new DbEntity("e1");
-        DbAttribute pk = new DbAttribute("pk", Types.INTEGER, e1);
-        pk.setPrimaryKey(true);
-        e1.addAttribute(pk);
-        DbAttribute nonPk = new DbAttribute("nonPk", Types.INTEGER, e1);
-        e1.addAttribute(nonPk);
-
-        map.addDbEntity(e1);
-
-        // DbLoader is so ugly and hard to test..
-        Field dbEntityList = DbLoader.class.getDeclaredField("dbEntityList");
-        dbEntityList.setAccessible(true);
-        List<DbEntity> entities = (List<DbEntity>) dbEntityList.get(loader1);
-        entities.add(e1);
-
-        loader1.loadObjEntities(map);
-
-        ObjEntity oe1 = map.getObjEntity("E1");
-        assertEquals(1, oe1.getAttributes().size());
-        assertNotNull(oe1.getAttribute("nonPk"));
-    }
-
-    @Test
-    public void testCreateLoader_MeaningfulPk_Specified() throws Exception {
-        DbImportConfiguration parameters = new DbImportConfiguration();
-        parameters.setMeaningfulPkTables("a*");
-
-        DbLoader loader1 = parameters.createLoader(mock(DbAdapter.class), mock(Connection.class),
-                mock(DbLoaderDelegate.class));
-
-        // DbLoader is so ugly and hard to test..
-        Field dbEntityList = DbLoader.class.getDeclaredField("dbEntityList");
-        dbEntityList.setAccessible(true);
-        List<DbEntity> entities = (List<DbEntity>) dbEntityList.get(loader1);
-
-        DataMap map = new DataMap();
-
-        DbEntity e1 = new DbEntity("e1");
-        DbAttribute pk = new DbAttribute("pk", Types.INTEGER, e1);
-        pk.setPrimaryKey(true);
-        e1.addAttribute(pk);
-        DbAttribute nonPk = new DbAttribute("nonPk", Types.INTEGER, e1);
-        e1.addAttribute(nonPk);
-
-        map.addDbEntity(e1);
-        entities.add(e1);
-
-        DbEntity a1 = new DbEntity("a1");
-        DbAttribute apk = new DbAttribute("pk", Types.INTEGER, a1);
-        apk.setPrimaryKey(true);
-        a1.addAttribute(apk);
-        DbAttribute anonPk = new DbAttribute("nonPk", Types.INTEGER, a1);
-        a1.addAttribute(anonPk);
-
-        map.addDbEntity(a1);
-        entities.add(a1);
-
-        loader1.loadObjEntities(map);
-
-        ObjEntity oe1 = map.getObjEntity("E1");
-        assertEquals(1, oe1.getAttributes().size());
-        assertNotNull(oe1.getAttribute("nonPk"));
-
-        ObjEntity oe2 = map.getObjEntity("A1");
-        assertEquals(2, oe2.getAttributes().size());
-        assertNotNull(oe2.getAttribute("nonPk"));
-        assertNotNull(oe2.getAttribute("pk"));
-    }
-
-    @Test
-    public void testCreateLoader_UsePrimitives_False() throws Exception {
-        DbImportConfiguration parameters = new DbImportConfiguration();
-        parameters.setUsePrimitives(false);
-
-        DbLoader loader1 = parameters.createLoader(mock(DbAdapter.class), mock(Connection.class),
-                mock(DbLoaderDelegate.class));
-
-        DataMap map = new DataMap();
-
-        DbEntity e1 = new DbEntity("e1");
-        DbAttribute nonPk = new DbAttribute("nonPk", Types.INTEGER, e1);
-        e1.addAttribute(nonPk);
-
-        map.addDbEntity(e1);
-
-        // DbLoader is so ugly and hard to test..
-        Field dbEntityList = DbLoader.class.getDeclaredField("dbEntityList");
-        dbEntityList.setAccessible(true);
-        List<DbEntity> entities = (List<DbEntity>) dbEntityList.get(loader1);
-        entities.add(e1);
-
-        loader1.loadObjEntities(map);
-
-        ObjEntity oe1 = map.getObjEntity("E1");
-
-        ObjAttribute oa1 = oe1.getAttribute("nonPk");
-        assertEquals("java.lang.Integer", oa1.getType());
-    }
-
-    @Test
-    public void testCreateLoader_UsePrimitives_True() throws Exception {
-        DbImportConfiguration parameters = new DbImportConfiguration();
-        parameters.setUsePrimitives(true);
-
-        DbLoader loader1 = parameters.createLoader(mock(DbAdapter.class), mock(Connection.class),
-                mock(DbLoaderDelegate.class));
-
-        DataMap map = new DataMap();
-
-        DbEntity e1 = new DbEntity("e1");
-        DbAttribute nonPk = new DbAttribute("nonPk", Types.INTEGER, e1);
-        e1.addAttribute(nonPk);
-
-        map.addDbEntity(e1);
-
-        // DbLoader is so ugly and hard to test..
-        Field dbEntityList = DbLoader.class.getDeclaredField("dbEntityList");
-        dbEntityList.setAccessible(true);
-        List<DbEntity> entities = (List<DbEntity>) dbEntityList.get(loader1);
-        entities.add(e1);
-
-        loader1.loadObjEntities(map);
-
-        ObjEntity oe1 = map.getObjEntity("E1");
-
-        ObjAttribute oa1 = oe1.getAttribute("nonPk");
-        assertEquals("int", oa1.getType());
-    }
-
-
-    @Test
     public void testCreateDataMap_New() throws Exception {
         URL outUrl = dataMapUrl("testCreateDataMap1.map.xml");
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoaderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoaderTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoaderTest.java
new file mode 100644
index 0000000..16c9735
--- /dev/null
+++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoaderTest.java
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ */
+
+package org.apache.cayenne.tools.dbimport.config;
+
+import org.apache.cayenne.resource.URLResource;
+import org.junit.Test;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.util.Iterator;
+
+import static org.junit.Assert.assertEquals;
+
+public class DefaultReverseEngineeringLoaderTest {
+
+    @Test
+    public void testLoadCatalog() throws Exception {
+        ReverseEngineering engineering = new DefaultReverseEngineeringLoader()
+                .load(getResource("/reverseEngineering-catalog.xml"));
+
+        assertCatalog(engineering);
+    }
+
+    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());
+
+        Catalog catalog = catalogs.next();
+        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());
+    }
+
+    @Test
+    public void testLoadSchema() throws Exception {
+        ReverseEngineering engineering = new DefaultReverseEngineeringLoader()
+                .load(getResource("/reverseEngineering-schema.xml"));
+
+        assertSchema(engineering);
+    }
+
+    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());
+    }
+
+    @Test
+    public void testLoadCatalogAndSchema() throws Exception {
+        ReverseEngineering engineering = new DefaultReverseEngineeringLoader()
+                .load(getResource("/reverseEngineering-catalog-and-schema.xml"));
+
+        assertCatalogAndSchema(engineering);
+    }
+
+    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);
+    }
+
+    @Test
+    public void testLoadFlat() throws Exception {
+        ReverseEngineering engineering = new DefaultReverseEngineeringLoader()
+                .load(getResource("/reverseEngineering-flat.xml"));
+
+        assertFlat(engineering);
+    }
+
+    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());
+    }
+
+    protected URLResource getResource(String file) throws MalformedURLException {
+        return new URLResource(new File(getPackagePath() + file).toURI().toURL());
+    }
+
+    private String getPackagePath() {
+        return getClass().getClassLoader().getResource(getClass().getPackage().getName().replace('.', '/')).getPath();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/FiltersConfigBuilderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/FiltersConfigBuilderTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/FiltersConfigBuilderTest.java
new file mode 100644
index 0000000..54fb4c0
--- /dev/null
+++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/FiltersConfigBuilderTest.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ */
+
+package org.apache.cayenne.tools.dbimport.config;
+
+import org.apache.cayenne.access.loader.filters.DbPath;
+import org.apache.cayenne.access.loader.filters.EntityFilters;
+import org.apache.cayenne.access.loader.filters.FiltersConfig;
+import org.junit.Test;
+
+import static org.apache.cayenne.access.loader.filters.FilterFactory.*;
+import static org.apache.cayenne.access.loader.filters.FiltersFactory.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+public class FiltersConfigBuilderTest {
+
+    @Test
+    public void testEmptyDbEntitiesFilters() throws Exception {
+        ReverseEngineering engineering = new ReverseEngineering();
+        FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
+
+        assertEquals("If nothing was configured we have to import everything. Filter %/%/% true/true/true",
+                new FiltersConfig(eFilters(path(), TRUE, TRUE, NULL)),
+                executions);
+    }
+
+    @Test
+    public void testOnlyOneCatalogDbEntitiesFilters() throws Exception {
+        ReverseEngineering engineering = new ReverseEngineering();
+        engineering.addCatalog(new Catalog("catalog_01"));
+        FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
+
+
+        assertEquals(new FiltersConfig(eFilters(path("catalog_01", null), TRUE, TRUE, NULL)),
+                executions);
+    }
+
+    @Test
+    public void testCatalogDbEntitiesFilters() throws Exception {
+        ReverseEngineering engineering = new ReverseEngineering();
+        engineering.addCatalog(new Catalog("catalog_01"));
+        engineering.addCatalog(new Catalog("catalog_02").schema(new Schema("schema_01")));
+        engineering.addCatalog(new Catalog("catalog_02").schema(new Schema("schema_02")));
+        engineering.addCatalog(new Catalog("catalog_02").schema(new Schema("schema_03")));
+        engineering.addCatalog(new Catalog("catalog_03").schema(new Schema("schema_01")));
+        engineering.addCatalog(new Catalog("catalog_03").schema(new Schema("schema_01")));
+        engineering.addCatalog(new Catalog("catalog_03").schema(new Schema("schema_01")));
+        engineering.addCatalog(new Catalog("catalog_03").schema(new Schema("schema_01")));
+        FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
+
+
+        assertEquals(new FiltersConfig(
+                        eFilters(path("catalog_01", null), TRUE, TRUE, NULL),
+                        eFilters(path("catalog_02", "schema_01"), TRUE, TRUE, NULL),
+                        eFilters(path("catalog_02", "schema_02"), TRUE, TRUE, NULL),
+                        eFilters(path("catalog_02", "schema_03"), TRUE, TRUE, NULL),
+                        eFilters(path("catalog_03", "schema_01"), TRUE, TRUE, NULL)
+                ),
+                executions);
+    }
+
+    @Test
+    public void testSchemaDbEntitiesFilters() throws Exception {
+        ReverseEngineering engineering = new ReverseEngineering();
+        engineering.addSchema(new Schema("schema_01"));
+        engineering.addSchema(new Schema("schema_02"));
+        engineering.addSchema(new Schema("schema_03"));
+        FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
+
+
+        assertEquals(new FiltersConfig(
+                        eFilters(path(null, "schema_01"), TRUE, TRUE, NULL),
+                        eFilters(path(null, "schema_02"), TRUE, TRUE, NULL),
+                        eFilters(path(null, "schema_03"), TRUE, TRUE, NULL)
+                ),
+                executions);
+    }
+
+    @Test
+    public void testFiltersDbEntitiesFilters() throws Exception {
+        ReverseEngineering engineering = new ReverseEngineering();
+        engineering.addIncludeTable(new IncludeTable("IncludeTable"));
+        engineering.addIncludeColumn(new IncludeColumn("IncludeColumn"));
+        engineering.addIncludeProcedure(new IncludeProcedure("IncludeProcedure"));
+        engineering.addExcludeTable(new ExcludeTable("ExcludeTable"));
+        engineering.addExcludeColumn(new ExcludeColumn("ExcludeColumn"));
+        engineering.addExcludeProcedure(new ExcludeProcedure("ExcludeProcedure"));
+
+        FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
+
+        assertEquals(new FiltersConfig(
+                        eFilters(path(),
+                            list(include("IncludeTable"), exclude("ExcludeTable")),
+                            list(include("IncludeColumn"), exclude("ExcludeColumn")),
+                            list(include("IncludeProcedure"), exclude("ExcludeProcedure"))),
+                        eFilters(path(null, null, "IncludeTable"), NULL, TRUE, NULL)
+                ),
+                executions);
+    }
+
+    @Test
+    public void testComplexConfiguration() throws Exception {
+        IncludeTable table = new IncludeTable("table");
+        table.addIncludeColumn(new IncludeColumn("column"));
+
+        Schema schema = new Schema("schema");
+        schema.addIncludeTable(table);
+
+        Catalog catalog = new Catalog("catalog");
+        catalog.addSchema(schema);
+
+        ReverseEngineering engineering = new ReverseEngineering();
+        engineering.addCatalog(catalog);
+
+        FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
+
+        assertEquals(new FiltersConfig(
+                        eFilters(path("catalog", "schema"), include("table"), NULL, NULL),
+                        eFilters(path("catalog", "schema", "table"), NULL, include("column"), NULL)
+                        ),
+                executions);
+    }
+
+    @Test
+    public void testAddNull() throws Exception {
+        FiltersConfigBuilder builder = new FiltersConfigBuilder(new ReverseEngineering());
+        DbPath path = new DbPath();
+        builder.add(new EntityFilters(path, NULL, NULL, NULL));
+        builder.add(new EntityFilters(path, NULL, NULL, NULL));
+        builder.add(new EntityFilters(path, NULL, NULL, NULL));
+        builder.add(new EntityFilters(path, NULL, NULL, NULL));
+
+        EntityFilters filter = builder.filtersConfig().filter(path);
+        assertFalse(filter.isEmpty());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-catalog-and-schema.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-catalog-and-schema.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-catalog-and-schema.xml
new file mode 100644
index 0000000..64ee1bc
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-catalog-and-schema.xml
@@ -0,0 +1,78 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~    or more contributor license agreements.  See the NOTICE file
+  ~    distributed with this work for additional information
+  ~    regarding copyright ownership.  The ASF licenses this file
+  ~    to you under the Apache License, Version 2.0 (the
+  ~    "License"); you may not use this file except in compliance
+  ~    with the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~    Unless required by applicable law or agreed to in writing,
+  ~    software distributed under the License is distributed on an
+  ~    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~    KIND, either express or implied.  See the License for the
+  ~    specific language governing permissions and limitations
+  ~    under the License.
+  -->
+
+<project name="MyProject" default="dist" basedir=".">
+
+    <taskdef name="cdbimport" classname="org.apache.cayenne.tools.DbImporterTask" taskname="cdbimport"
+             classpath="${basedir}"  />
+
+    <target name="dist">
+        <cdbimport map="${context.dir}/WEB-INF/DefaultMap.map.xml"
+                   adapter="org.apache.cayenne.dba.hsqldb.HSQLDBAdapter"
+                   driver="org.hsqldb.jdbcDriver"
+                   url="jdbc:hsqldb:hsql://localhost/bookmarker"
+                   username="sa">
+
+            <catalog name="catalog-name">
+                <schema name="schema-name">
+                    <includeTable>includeTable-01</includeTable>
+
+                    <includeTable>
+                        <pattern>includeTable-02</pattern>
+                    </includeTable>
+
+                    <includeTable pattern="includeTable-03">
+                        <includeColumn pattern="includeColumn-01" />
+                        <excludeColumn pattern="excludeColumn-01" />
+                    </includeTable>
+
+                    <excludeTable>excludeTable-01</excludeTable>
+                    <excludeTable>
+                        <pattern>excludeTable-02</pattern>
+                    </excludeTable>
+                    <excludeTable pattern="excludeTable-03" />
+
+                    <includeColumn>includeColumn-01</includeColumn>
+                    <includeColumn>
+                        <pattern>includeColumn-02</pattern>
+                    </includeColumn>
+                    <includeColumn pattern="includeColumn-03" />
+                    <excludeColumn>excludeColumn-01</excludeColumn>
+                    <excludeColumn>
+                        <pattern>excludeColumn-02</pattern>
+                    </excludeColumn>
+                    <excludeColumn pattern="excludeColumn-03" />
+
+                    <includeProcedure>includeProcedure-01</includeProcedure>
+                    <includeProcedure>
+                        <pattern>includeProcedure-02</pattern>
+                    </includeProcedure>
+                    <includeProcedure pattern="includeProcedure-03" />
+                    <excludeProcedure>excludeProcedure-01</excludeProcedure>
+                    <excludeProcedure>
+                        <pattern>excludeProcedure-02</pattern>
+                    </excludeProcedure>
+                    <excludeProcedure pattern="excludeProcedure-03" />
+                </schema>
+            </catalog>
+        </cdbimport>
+    </target>
+
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-catalog.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-catalog.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-catalog.xml
new file mode 100644
index 0000000..32d7c7a
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-catalog.xml
@@ -0,0 +1,83 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~    or more contributor license agreements.  See the NOTICE file
+  ~    distributed with this work for additional information
+  ~    regarding copyright ownership.  The ASF licenses this file
+  ~    to you under the Apache License, Version 2.0 (the
+  ~    "License"); you may not use this file except in compliance
+  ~    with the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~    Unless required by applicable law or agreed to in writing,
+  ~    software distributed under the License is distributed on an
+  ~    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~    KIND, either express or implied.  See the License for the
+  ~    specific language governing permissions and limitations
+  ~    under the License.
+  -->
+
+<project name="MyProject" default="dist" basedir=".">
+
+    <taskdef name="cdbimport" classname="org.apache.cayenne.tools.DbImporterTask" taskname="cdbimport"
+             classpath="${basedir}"  />
+
+    <target name="dist">
+        <cdbimport map="${context.dir}/WEB-INF/DefaultMap.map.xml"
+                   adapter="org.apache.cayenne.dba.hsqldb.HSQLDBAdapter"
+                   driver="org.hsqldb.jdbcDriver"
+                   url="jdbc:hsqldb:hsql://localhost/bookmarker"
+                   username="sa">
+
+            <catalog>catalog-name-01</catalog>
+
+            <catalog>
+                <name>catalog-name-02</name>
+            </catalog>
+
+            <catalog name="catalog-name-03">
+                <includeTable>includeTable-01</includeTable>
+
+                <includeTable>
+                    <pattern>includeTable-02</pattern>
+                </includeTable>
+
+                <includeTable pattern="includeTable-03">
+                    <includeColumn pattern="includeColumn-01" />
+                    <excludeColumn pattern="excludeColumn-01" />
+                </includeTable>
+
+                <excludeTable>excludeTable-01</excludeTable>
+                <excludeTable>
+                    <pattern>excludeTable-02</pattern>
+                </excludeTable>
+                <excludeTable pattern="excludeTable-03" />
+
+                <includeColumn>includeColumn-01</includeColumn>
+                <includeColumn>
+                    <pattern>includeColumn-02</pattern>
+                </includeColumn>
+                <includeColumn pattern="includeColumn-03" />
+                <excludeColumn>excludeColumn-01</excludeColumn>
+                <excludeColumn>
+                    <pattern>excludeColumn-02</pattern>
+                </excludeColumn>
+                <excludeColumn pattern="excludeColumn-03" />
+
+                <includeProcedure>includeProcedure-01</includeProcedure>
+                <includeProcedure>
+                    <pattern>includeProcedure-02</pattern>
+                </includeProcedure>
+                <includeProcedure pattern="includeProcedure-03" />
+                <excludeProcedure>excludeProcedure-01</excludeProcedure>
+                <excludeProcedure>
+                    <pattern>excludeProcedure-02</pattern>
+                </excludeProcedure>
+                <excludeProcedure pattern="excludeProcedure-03" />
+            </catalog>
+
+        </cdbimport>
+    </target>
+
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-flat.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-flat.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-flat.xml
new file mode 100644
index 0000000..29f9e72
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-flat.xml
@@ -0,0 +1,75 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~    or more contributor license agreements.  See the NOTICE file
+  ~    distributed with this work for additional information
+  ~    regarding copyright ownership.  The ASF licenses this file
+  ~    to you under the Apache License, Version 2.0 (the
+  ~    "License"); you may not use this file except in compliance
+  ~    with the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~    Unless required by applicable law or agreed to in writing,
+  ~    software distributed under the License is distributed on an
+  ~    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~    KIND, either express or implied.  See the License for the
+  ~    specific language governing permissions and limitations
+  ~    under the License.
+  -->
+
+<project name="MyProject" default="dist" basedir=".">
+
+    <taskdef name="cdbimport" classname="org.apache.cayenne.tools.DbImporterTask" taskname="cdbimport"
+             classpath="${basedir}"  />
+
+    <target name="dist">
+        <cdbimport map="${context.dir}/WEB-INF/DefaultMap.map.xml"
+                   adapter="org.apache.cayenne.dba.hsqldb.HSQLDBAdapter"
+                   driver="org.hsqldb.jdbcDriver"
+                   url="jdbc:hsqldb:hsql://localhost/bookmarker"
+                   username="sa">
+
+            <includeTable>includeTable-01</includeTable>
+
+            <includeTable>
+                <pattern>includeTable-02</pattern>
+            </includeTable>
+
+            <includeTable pattern="includeTable-03">
+                <includeColumn pattern="includeColumn-01" />
+                <excludeColumn pattern="excludeColumn-01" />
+            </includeTable>
+
+            <excludeTable>excludeTable-01</excludeTable>
+            <excludeTable>
+                <pattern>excludeTable-02</pattern>
+            </excludeTable>
+            <excludeTable pattern="excludeTable-03" />
+
+            <includeColumn>includeColumn-01</includeColumn>
+            <includeColumn>
+                <pattern>includeColumn-02</pattern>
+            </includeColumn>
+            <includeColumn pattern="includeColumn-03" />
+            <excludeColumn>excludeColumn-01</excludeColumn>
+            <excludeColumn>
+                <pattern>excludeColumn-02</pattern>
+            </excludeColumn>
+            <excludeColumn pattern="excludeColumn-03" />
+
+            <includeProcedure>includeProcedure-01</includeProcedure>
+            <includeProcedure>
+                <pattern>includeProcedure-02</pattern>
+            </includeProcedure>
+            <includeProcedure pattern="includeProcedure-03" />
+            <excludeProcedure>excludeProcedure-01</excludeProcedure>
+            <excludeProcedure>
+                <pattern>excludeProcedure-02</pattern>
+            </excludeProcedure>
+            <excludeProcedure pattern="excludeProcedure-03" />
+
+        </cdbimport>
+    </target>
+
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-mapping.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-mapping.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-mapping.xml
new file mode 100644
index 0000000..90d6116
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-mapping.xml
@@ -0,0 +1,44 @@
+<!--
+  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.
+  -->
+
+<project name="MyProject" default="dist" basedir=".">
+
+    <taskdef name="cdbimport" classname="org.apache.cayenne.tools.DbImporterTask" taskname="cdbimport"
+             classpath="${basedir}"  />
+
+    <target name="dist">
+        <cdbimport map="${context.dir}/WEB-INF/DefaultMap.map.xml"
+                   adapter="org.apache.cayenne.dba.hsqldb.HSQLDBAdapter"
+                   driver="org.hsqldb.jdbcDriver"
+                   url="jdbc:hsqldb:hsql://localhost/bookmarker"
+                   username="sa">
+
+            <typeMapper mapperClassName="class" usePrimitives="false">
+                <type java="my.personal.type" jdbc="varchar" />
+                <type java="java-01" jdbc="jdbc-01" />
+                <type java="java-02" jdbc="jdbc-02" length="21" notNull="true" />
+                <type java="java-03" jdbc="jdbc-03" precision="5" scale="2" />
+                <type java="java-03" jdbc="jdbc-03" precision="7" notNull="true" />
+            </typeMapper>
+
+        </cdbimport>
+    </target>
+
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-reverse-engineering-in-external-file.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-reverse-engineering-in-external-file.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-reverse-engineering-in-external-file.xml
new file mode 100644
index 0000000..8cd89e8
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-reverse-engineering-in-external-file.xml
@@ -0,0 +1,33 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+
+<project name="MyProject" default="dist" basedir=".">
+
+    <taskdef name="cdbimport" classname="org.apache.cayenne.tools.DbImporterTask" taskname="cdbimport"
+             classpath="${basedir}"  />
+
+    <target name="dist">
+        <cdbimport map="dbimport/build-include-table.map.xml"
+                   driver="org.apache.derby.jdbc.EmbeddedDriver"
+                   url="jdbc:derby:memory:DbImporterMojoTest;create=true"
+                   reverseEngineeringFile="dbimport/config/reverseEngineering-catalog-and-schema.xml" />
+    </target>
+
+
+</project>
\ No newline at end of file


[2/7] CAY-1946 CDbimport improvements

Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-schema.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-schema.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-schema.xml
new file mode 100644
index 0000000..2d7bb6b
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/build-schema.xml
@@ -0,0 +1,83 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~    or more contributor license agreements.  See the NOTICE file
+  ~    distributed with this work for additional information
+  ~    regarding copyright ownership.  The ASF licenses this file
+  ~    to you under the Apache License, Version 2.0 (the
+  ~    "License"); you may not use this file except in compliance
+  ~    with the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~    Unless required by applicable law or agreed to in writing,
+  ~    software distributed under the License is distributed on an
+  ~    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~    KIND, either express or implied.  See the License for the
+  ~    specific language governing permissions and limitations
+  ~    under the License.
+  -->
+
+<project name="MyProject" default="dist" basedir=".">
+
+    <taskdef name="cdbimport" classname="org.apache.cayenne.tools.DbImporterTask" taskname="cdbimport"
+             classpath="${basedir}"  />
+
+    <target name="dist">
+        <cdbimport map="${context.dir}/WEB-INF/DefaultMap.map.xml"
+                   adapter="org.apache.cayenne.dba.hsqldb.HSQLDBAdapter"
+                   driver="org.hsqldb.jdbcDriver"
+                   url="jdbc:hsqldb:hsql://localhost/bookmarker"
+                   username="sa">
+
+            <schema>schema-name-01</schema>
+
+            <schema>
+                <name>schema-name-02</name>
+            </schema>
+
+            <schema name="schema-name-03">
+                <includeTable>includeTable-01</includeTable>
+
+                <includeTable>
+                    <pattern>includeTable-02</pattern>
+                </includeTable>
+
+                <includeTable pattern="includeTable-03">
+                    <includeColumn pattern="includeColumn-01" />
+                    <excludeColumn pattern="excludeColumn-01" />
+                </includeTable>
+
+                <excludeTable>excludeTable-01</excludeTable>
+                <excludeTable>
+                    <pattern>excludeTable-02</pattern>
+                </excludeTable>
+                <excludeTable pattern="excludeTable-03" />
+
+                <includeColumn>includeColumn-01</includeColumn>
+                <includeColumn>
+                    <pattern>includeColumn-02</pattern>
+                </includeColumn>
+                <includeColumn pattern="includeColumn-03" />
+                <excludeColumn>excludeColumn-01</excludeColumn>
+                <excludeColumn>
+                    <pattern>excludeColumn-02</pattern>
+                </excludeColumn>
+                <excludeColumn pattern="excludeColumn-03" />
+
+                <includeProcedure>includeProcedure-01</includeProcedure>
+                <includeProcedure>
+                    <pattern>includeProcedure-02</pattern>
+                </includeProcedure>
+                <includeProcedure pattern="includeProcedure-03" />
+                <excludeProcedure>excludeProcedure-01</excludeProcedure>
+                <excludeProcedure>
+                    <pattern>excludeProcedure-02</pattern>
+                </excludeProcedure>
+                <excludeProcedure pattern="excludeProcedure-03" />
+            </schema>
+
+        </cdbimport>
+    </target>
+
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/build-include-table.map.xml-result
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/build-include-table.map.xml-result b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/build-include-table.map.xml-result
new file mode 100644
index 0000000..8854a8b
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/build-include-table.map.xml-result
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+	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.
+-->
+<data-map xmlns="http://cayenne.apache.org/schema/7/modelMap"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://cayenne.apache.org/schema/7/modelMap http://cayenne.apache.org/schema/7/modelMap.xsd"
+          project-version="7">
+    <db-entity name="PARENT" schema="APP">
+        <db-attribute name="COL2" type="CHAR" length="25"/>
+        <db-attribute name="COL3" type="DECIMAL" length="10" scale="2"/>
+        <db-attribute name="COL4" type="VARCHAR" length="25"/>
+        <db-attribute name="COL5" type="DATE" length="10"/>
+        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+    </db-entity>
+    <obj-entity name="Parent" className="Parent" dbEntityName="PARENT">
+        <obj-attribute name="col2" type="java.lang.String" db-attribute-path="COL2"/>
+        <obj-attribute name="col3" type="java.math.BigDecimal" db-attribute-path="COL3"/>
+        <obj-attribute name="col4" type="java.lang.String" db-attribute-path="COL4"/>
+        <obj-attribute name="col5" type="java.util.Date" db-attribute-path="COL5"/>
+    </obj-entity>
+</data-map>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/build-include-table.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/build-include-table.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/build-include-table.xml
new file mode 100644
index 0000000..897869d
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/build-include-table.xml
@@ -0,0 +1,35 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~    or more contributor license agreements.  See the NOTICE file
+  ~    distributed with this work for additional information
+  ~    regarding copyright ownership.  The ASF licenses this file
+  ~    to you under the Apache License, Version 2.0 (the
+  ~    "License"); you may not use this file except in compliance
+  ~    with the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~    Unless required by applicable law or agreed to in writing,
+  ~    software distributed under the License is distributed on an
+  ~    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~    KIND, either express or implied.  See the License for the
+  ~    specific language governing permissions and limitations
+  ~    under the License.
+  -->
+
+<project name="MyProject" default="dist" basedir="../">
+
+    <taskdef name="cdbimport" classname="org.apache.cayenne.tools.DbImporterTask" taskname="cdbimport"
+             classpath="${basedir}"  />
+
+    <target name="dist">
+        <cdbimport map="dbimport/build-include-table.map.xml"
+                   driver="org.apache.derby.jdbc.EmbeddedDriver"
+                   url="jdbc:derby:memory:DbImporterMojoTest;create=true">
+
+            <includeTable>Parent</includeTable>
+        </cdbimport>
+    </target>
+
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/build-include-table.xml.sql
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/build-include-table.xml.sql b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/build-include-table.xml.sql
new file mode 100644
index 0000000..fb820b7
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/build-include-table.xml.sql
@@ -0,0 +1,20 @@
+CREATE TABLE Parent (
+  id INTEGER NOT NULL,
+  COL2 CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id),
+  UNIQUE (COL3)
+);
+
+CREATE TABLE Child (
+  id INTEGER NOT NULL,
+  Parent_id CHAR(25),
+  COL3 DECIMAL(10,2),
+  COL4 VARCHAR(25),
+  COL5 DATE,
+
+  PRIMARY KEY (id)
+);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-ant-mapping.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-ant-mapping.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-ant-mapping.xml
new file mode 100644
index 0000000..4bdd44a
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-ant-mapping.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+
+<reverseEngineering>
+
+    <typeMapper mapperClassName="class" usePrimitives="false">
+        <type java="my.personal.type" jdbc="varchar" />
+        <type java="java-01" jdbc="jdbc-01" />
+        <type java="java-02" jdbc="jdbc-02" length="21" notNull="true" />
+        <type java="java-03" jdbc="jdbc-03" precision="5" scale="2" />
+        <type java="java-03" jdbc="jdbc-03" precision="7" notNull="true" />
+    </typeMapper>
+
+</reverseEngineering>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-catalog-and-schema.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-catalog-and-schema.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-catalog-and-schema.xml
new file mode 100644
index 0000000..46c26d0
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-catalog-and-schema.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<reverseEngineering>
+    <catalog name="catalog-name">
+        <schema name="schema-name">
+            <includeTable>includeTable-01</includeTable>
+
+            <includeTable>
+                <pattern>includeTable-02</pattern>
+            </includeTable>
+
+            <includeTable pattern="includeTable-03">
+                <includeColumn pattern="includeColumn-01" />
+                <excludeColumn pattern="excludeColumn-01" />
+            </includeTable>
+
+            <excludeTable>excludeTable-01</excludeTable>
+            <excludeTable>
+                <pattern>excludeTable-02</pattern>
+            </excludeTable>
+            <excludeTable pattern="excludeTable-03" />
+
+            <includeColumn>includeColumn-01</includeColumn>
+            <includeColumn>
+                <pattern>includeColumn-02</pattern>
+            </includeColumn>
+            <includeColumn pattern="includeColumn-03" />
+            <excludeColumn>excludeColumn-01</excludeColumn>
+            <excludeColumn>
+                <pattern>excludeColumn-02</pattern>
+            </excludeColumn>
+            <excludeColumn pattern="excludeColumn-03" />
+
+            <includeProcedure>includeProcedure-01</includeProcedure>
+            <includeProcedure>
+                <pattern>includeProcedure-02</pattern>
+            </includeProcedure>
+            <includeProcedure pattern="includeProcedure-03" />
+            <excludeProcedure>excludeProcedure-01</excludeProcedure>
+            <excludeProcedure>
+                <pattern>excludeProcedure-02</pattern>
+            </excludeProcedure>
+            <excludeProcedure pattern="excludeProcedure-03" />
+        </schema>
+    </catalog>
+
+</reverseEngineering>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-catalog.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-catalog.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-catalog.xml
new file mode 100644
index 0000000..d820aa4
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-catalog.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<reverseEngineering>
+    <catalog>catalog-name-01</catalog>
+
+    <catalog>
+        <name>catalog-name-02</name>
+    </catalog>
+
+    <catalog name="catalog-name-03">
+        <includeTable>includeTable-01</includeTable>
+
+        <includeTable>
+            <pattern>includeTable-02</pattern>
+        </includeTable>
+
+        <includeTable pattern="includeTable-03">
+            <includeColumn pattern="includeColumn-01" />
+            <excludeColumn pattern="excludeColumn-01" />
+        </includeTable>
+
+        <excludeTable>excludeTable-01</excludeTable>
+        <excludeTable>
+            <pattern>excludeTable-02</pattern>
+        </excludeTable>
+        <excludeTable pattern="excludeTable-03" />
+
+        <includeColumn>includeColumn-01</includeColumn>
+        <includeColumn>
+            <pattern>includeColumn-02</pattern>
+        </includeColumn>
+        <includeColumn pattern="includeColumn-03" />
+        <excludeColumn>excludeColumn-01</excludeColumn>
+        <excludeColumn>
+            <pattern>excludeColumn-02</pattern>
+        </excludeColumn>
+        <excludeColumn pattern="excludeColumn-03" />
+
+        <includeProcedure>includeProcedure-01</includeProcedure>
+        <includeProcedure>
+            <pattern>includeProcedure-02</pattern>
+        </includeProcedure>
+        <includeProcedure pattern="includeProcedure-03" />
+        <excludeProcedure>excludeProcedure-01</excludeProcedure>
+        <excludeProcedure>
+            <pattern>excludeProcedure-02</pattern>
+        </excludeProcedure>
+        <excludeProcedure pattern="excludeProcedure-03" />
+    </catalog>
+</reverseEngineering>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-flat.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-flat.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-flat.xml
new file mode 100644
index 0000000..5b785af
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-flat.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<reverseEngineering>
+    <includeTable>includeTable-01</includeTable>
+
+    <includeTable>
+        <pattern>includeTable-02</pattern>
+    </includeTable>
+
+    <includeTable pattern="includeTable-03">
+        <includeColumn pattern="includeColumn-01" />
+        <excludeColumn pattern="excludeColumn-01" />
+    </includeTable>
+
+    <excludeTable>excludeTable-01</excludeTable>
+    <excludeTable>
+        <pattern>excludeTable-02</pattern>
+    </excludeTable>
+    <excludeTable pattern="excludeTable-03" />
+
+    <includeColumn>includeColumn-01</includeColumn>
+    <includeColumn>
+        <pattern>includeColumn-02</pattern>
+    </includeColumn>
+    <includeColumn pattern="includeColumn-03" />
+    <excludeColumn>excludeColumn-01</excludeColumn>
+    <excludeColumn>
+        <pattern>excludeColumn-02</pattern>
+    </excludeColumn>
+    <excludeColumn pattern="excludeColumn-03" />
+
+    <includeProcedure>includeProcedure-01</includeProcedure>
+    <includeProcedure>
+        <pattern>includeProcedure-02</pattern>
+    </includeProcedure>
+    <includeProcedure pattern="includeProcedure-03" />
+    <excludeProcedure>excludeProcedure-01</excludeProcedure>
+    <excludeProcedure>
+        <pattern>excludeProcedure-02</pattern>
+    </excludeProcedure>
+    <excludeProcedure pattern="excludeProcedure-03" />
+
+</reverseEngineering>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-maven-mapping.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-maven-mapping.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-maven-mapping.xml
new file mode 100644
index 0000000..c9d722e
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-maven-mapping.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+
+<reverseEngineering>
+
+    <typeMapper >
+        <mapperClassName>class</mapperClassName>
+        <usePrimitives>false</usePrimitives>
+
+        <type>
+            <java>my.personal.type</java>
+            <jdbc>varchar</jdbc>
+        </type>
+        <type>
+            <java>java-01</java>
+            <jdbc>jdbc-01</jdbc>
+        </type>
+        <type>
+            <java>java-02</java>
+            <jdbc>jdbc-02</jdbc>
+            <length>21</length>
+            <notNull>true</notNull>
+        </type>
+        <type>
+            <java>java-03</java>
+            <jdbc>jdbc-03</jdbc>
+            <precision>5</precision>
+            <scale>2</scale>
+        </type>
+        <type>
+            <java>java-03</java>
+            <jdbc>jdbc-03</jdbc>
+            <precision>7</precision>
+            <notNull>true</notNull>
+        </type>
+    </typeMapper>
+
+</reverseEngineering>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-mixed-mapping.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-mixed-mapping.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-mixed-mapping.xml
new file mode 100644
index 0000000..deb3dab
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-mixed-mapping.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+
+<reverseEngineering>
+
+    <typeMapper >
+        <mapperClassName>class</mapperClassName>
+        <usePrimitives>false</usePrimitives>
+
+        <type java="my.personal.type" jdbc="varchar" />
+        <type java="java-01" jdbc="jdbc-01" />
+        <type java="java-02" jdbc="jdbc-02">
+            <length>21</length>
+            <notNull>true</notNull>
+        </type>
+        <type java="java-03" jdbc="jdbc-03">
+            <precision>5</precision>
+            <scale>2</scale>
+        </type>
+        <type precision="7" notNull="true">
+            <java>java-03</java>
+            <jdbc>jdbc-03</jdbc>
+        </type>
+    </typeMapper>
+
+</reverseEngineering>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-schema.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-schema.xml b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-schema.xml
new file mode 100644
index 0000000..97c2c6f
--- /dev/null
+++ b/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-schema.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<reverseEngineering>
+    <schema>schema-name-01</schema>
+
+    <schema>
+        <name>schema-name-02</name>
+    </schema>
+
+    <schema name="schema-name-03">
+        <includeTable>includeTable-01</includeTable>
+
+        <includeTable>
+            <pattern>includeTable-02</pattern>
+        </includeTable>
+
+        <includeTable pattern="includeTable-03">
+            <includeColumn pattern="includeColumn-01" />
+            <excludeColumn pattern="excludeColumn-01" />
+        </includeTable>
+
+        <excludeTable>excludeTable-01</excludeTable>
+        <excludeTable>
+            <pattern>excludeTable-02</pattern>
+        </excludeTable>
+        <excludeTable pattern="excludeTable-03" />
+
+        <includeColumn>includeColumn-01</includeColumn>
+        <includeColumn>
+            <pattern>includeColumn-02</pattern>
+        </includeColumn>
+        <includeColumn pattern="includeColumn-03" />
+        <excludeColumn>excludeColumn-01</excludeColumn>
+        <excludeColumn>
+            <pattern>excludeColumn-02</pattern>
+        </excludeColumn>
+        <excludeColumn pattern="excludeColumn-03" />
+
+        <includeProcedure>includeProcedure-01</includeProcedure>
+        <includeProcedure>
+            <pattern>includeProcedure-02</pattern>
+        </includeProcedure>
+        <includeProcedure pattern="includeProcedure-03" />
+        <excludeProcedure>excludeProcedure-01</excludeProcedure>
+        <excludeProcedure>
+            <pattern>excludeProcedure-02</pattern>
+        </excludeProcedure>
+        <excludeProcedure pattern="excludeProcedure-03" />
+    </schema>
+
+</reverseEngineering>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java
index 9a0fd41..7381886 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java
@@ -41,111 +41,106 @@ import org.apache.cayenne.util.EntityMergeSupport;
 
 public class CreateObjEntityAction extends CayenneAction {
 
-	public static String getActionName() {
-		return "Create ObjEntity";
-	}
-
-	/**
-	 * Constructor for CreateObjEntityAction.
-	 */
-	public CreateObjEntityAction(Application application) {
-		super(getActionName(), application);
-	}
-
-	@Override
-	public String getIconName() {
-		return "icon-new_objentity.gif";
-	}
-
-	/**
-	 * @see org.apache.cayenne.modeler.util.CayenneAction#performAction(ActionEvent)
-	 */
-	@Override
-	public void performAction(ActionEvent e) {
-		createObjEntity();
-	}
-
-	protected void createObjEntity() {
-		ProjectController mediator = getProjectController();
-
-		DataMap dataMap = mediator.getCurrentDataMap();
-		ObjEntity entity = new ObjEntity(DefaultUniqueNameGenerator.generate(NameCheckers.objEntity, dataMap));
-
-		// init defaults
-		entity.setSuperClassName(dataMap.getDefaultSuperclass());
-		entity.setDeclaredLockType(dataMap.getDefaultLockType());
-
-		DbEntity dbEntity = mediator.getCurrentDbEntity();
-		if (dbEntity != null) {
-			entity.setDbEntity(dbEntity);
-			String baseName = NameConverter.underscoredToJava(dbEntity.getName(), true);
-			entity.setName(DefaultUniqueNameGenerator.generate(NameCheckers.objEntity, dbEntity.getDataMap(), baseName));
-		}
-
-		String pkg = dataMap.getDefaultPackage();
-		if (pkg != null) {
-			if (!pkg.endsWith(".")) {
-				pkg = pkg + ".";
-			}
-
-			entity.setClassName(pkg + entity.getName());
-		}
-
-		if (dataMap.isClientSupported()) {
-			String clientPkg = dataMap.getDefaultClientPackage();
-			if (clientPkg != null) {
-				if (!clientPkg.endsWith(".")) {
-					clientPkg = clientPkg + ".";
-				}
-
-				entity.setClientClassName(clientPkg + entity.getName());
-			}
-
-			entity.setClientSuperClassName(dataMap.getDefaultClientSuperclass());
-		}
-
-		dataMap.addObjEntity(entity);
-
-		// perform the merge
-		EntityMergeSupport merger = new EntityMergeSupport(dataMap);
-		merger.addEntityMergeListener(DeleteRuleUpdater.getEntityMergeListener());
-		merger.synchronizeWithDbEntity(entity);
-
-		fireObjEntityEvent(this, mediator, dataMap, entity);
-
-		application.getUndoManager().addEdit(new CreateObjEntityUndoableEdit(dataMap, entity));
-	}
-
-	public void createObjEntity(DataMap dataMap, ObjEntity entity) {
-		ProjectController mediator = getProjectController();
-		dataMap.addObjEntity(entity);
-		fireObjEntityEvent(this, mediator, dataMap, entity);
-	}
-
-	/**
-	 * Fires events when a obj entity was added
-	 */
-	static void fireObjEntityEvent(Object src, ProjectController mediator, DataMap dataMap, ObjEntity entity) {
-		mediator.fireObjEntityEvent(new EntityEvent(src, entity, MapEvent.ADD));
-		EntityDisplayEvent displayEvent = new EntityDisplayEvent(src, entity, dataMap, mediator.getCurrentDataNode(),
-				(DataChannelDescriptor) mediator.getProject().getRootNode());
-		displayEvent.setMainTabFocus(true);
-		mediator.fireObjEntityDisplayEvent(displayEvent);
-	}
-
-	/**
-	 * Returns <code>true</code> if path contains a DataMap object.
-	 */
-	@Override
-	public boolean enableForPath(ConfigurationNode object) {
-		if (object == null) {
-			return false;
-		}
-
-		if (object instanceof ObjEntity) {
-			return ((ObjEntity) object).getParent() != null && ((ObjEntity) object).getParent() instanceof DataMap;
-		}
-
-		return false;
-	}
+    public static String getActionName() {
+        return "Create ObjEntity";
+    }
+
+    /**
+     * Constructor for CreateObjEntityAction.
+     */
+    public CreateObjEntityAction(Application application) {
+        super(getActionName(), application);
+    }
+
+    @Override
+    public String getIconName() {
+        return "icon-new_objentity.gif";
+    }
+
+    /**
+     * @see org.apache.cayenne.modeler.util.CayenneAction#performAction(ActionEvent)
+     */
+    @Override
+    public void performAction(ActionEvent e) {
+        createObjEntity();
+    }
+
+    protected void createObjEntity() {
+        ProjectController mediator = getProjectController();
+
+        DataMap dataMap = mediator.getCurrentDataMap();
+        ObjEntity entity = new ObjEntity(DefaultUniqueNameGenerator.generate(NameCheckers.objEntity, dataMap));
+
+        // init defaults
+        entity.setSuperClassName(dataMap.getDefaultSuperclass());
+        entity.setDeclaredLockType(dataMap.getDefaultLockType());
+
+        DbEntity dbEntity = mediator.getCurrentDbEntity();
+        if (dbEntity != null) {
+            entity.setDbEntity(dbEntity);
+            String baseName = NameConverter.underscoredToJava(dbEntity.getName(), true);
+            entity.setName(DefaultUniqueNameGenerator.generate(NameCheckers.objEntity, dbEntity.getDataMap(), baseName));
+        }
+
+        entity.setClassName(dataMap.getNameWithDefaultPackage(entity.getName()));
+
+        if (dataMap.isClientSupported()) {
+            entity.setClientClassName(dataMap.getNameWithDefaultClientPackage(entity.getName()));
+            entity.setClientSuperClassName(dataMap.getDefaultClientSuperclass());
+        }
+
+        dataMap.addObjEntity(entity);
+
+        // perform the merge
+        EntityMergeSupport merger = new EntityMergeSupport(dataMap);
+        merger.addEntityMergeListener(DeleteRuleUpdater.getEntityMergeListener());
+        merger.synchronizeWithDbEntity(entity);
+
+        fireObjEntityEvent(this, mediator, dataMap, entity);
+
+        application.getUndoManager().addEdit(
+                new CreateObjEntityUndoableEdit(dataMap, entity));
+    }
+
+    public void createObjEntity(DataMap dataMap, ObjEntity entity) {
+        ProjectController mediator = getProjectController();
+        dataMap.addObjEntity(entity);
+        fireObjEntityEvent(this, mediator, dataMap, entity);
+    }
+
+    /**
+     * Fires events when a obj entity was added
+     */
+    static void fireObjEntityEvent(
+            Object src,
+            ProjectController mediator,
+            DataMap dataMap,
+            ObjEntity entity) {
+        mediator.fireObjEntityEvent(new EntityEvent(src, entity, MapEvent.ADD));
+        EntityDisplayEvent displayEvent = new EntityDisplayEvent(
+                src,
+                entity,
+                dataMap,
+                mediator.getCurrentDataNode(),
+                (DataChannelDescriptor) mediator.getProject().getRootNode());
+        displayEvent.setMainTabFocus(true);
+        mediator.fireObjEntityDisplayEvent(displayEvent);
+    }
+
+    /**
+     * Returns <code>true</code> if path contains a DataMap object.
+     */
+    @Override
+    public boolean enableForPath(ConfigurationNode object) {
+        if (object == null) {
+            return false;
+        }
+
+        if (object instanceof ObjEntity) {
+            return ((ObjEntity) object).getParent() != null
+                    && ((ObjEntity) object).getParent() instanceof DataMap;
+        }
+
+        return false;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java
index ddc7509..c5f3314 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java
@@ -20,8 +20,6 @@
 package org.apache.cayenne.modeler.action;
 
 import java.awt.event.ActionEvent;
-import java.sql.SQLException;
-import java.util.ArrayList;
 import java.util.List;
 
 import javax.sql.DataSource;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/datamap/PackageUpdateController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/datamap/PackageUpdateController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/datamap/PackageUpdateController.java
index 1681b25..f1d6a8b 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/datamap/PackageUpdateController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/datamap/PackageUpdateController.java
@@ -94,13 +94,6 @@ public class PackageUpdateController extends DefaultsPreferencesController {
 
     protected void updatePackage() {
         boolean doAll = isAllEntities();
-        String defaultPackage = getDefaultPackage();
-        if (Util.isEmptyString(defaultPackage)) {
-            defaultPackage = "";
-        }
-        else if (!defaultPackage.endsWith(".")) {
-            defaultPackage = defaultPackage + '.';
-        }
 
         Map<String, String> oldNameEmbeddableToNewName = new HashMap<String,String>();
         
@@ -114,7 +107,7 @@ public class PackageUpdateController extends DefaultsPreferencesController {
             
             if (doAll || Util.isEmptyString(oldName) || oldName.indexOf('.') < 0) {
                 EmbeddableEvent e = new EmbeddableEvent(this, embeddable, embeddable.getClassName());
-                String newClassName = defaultPackage + className;
+                String newClassName = getNameWithDefaultPackage(className);
                 oldNameEmbeddableToNewName.put(oldName, newClassName);
                 embeddable.setClassName(newClassName);
                 mediator.fireEmbeddableEvent(e, mediator.getCurrentDataMap());
@@ -127,7 +120,7 @@ public class PackageUpdateController extends DefaultsPreferencesController {
             if (doAll || Util.isEmptyString(oldName) || oldName.indexOf('.') < 0) {
                 String className = extractClassName(Util.isEmptyString(oldName) ? entity
                         .getName() : oldName);
-                setClassName(entity, defaultPackage + className);
+                setClassName(entity, getNameWithDefaultPackage(className));
             }
             
             for(ObjAttribute attribute: entity.getAttributes()){
@@ -155,9 +148,12 @@ public class PackageUpdateController extends DefaultsPreferencesController {
                 : "";
     }
 
-    protected String getDefaultPackage() {
-        return clientUpdate ? dataMap.getDefaultClientPackage() : dataMap
-                .getDefaultPackage();
+    protected String getNameWithDefaultPackage(String name) {
+        if (clientUpdate) {
+            return dataMap.getNameWithDefaultClientPackage(name);
+        } else {
+            return dataMap.getNameWithDefaultPackage(name);
+        }
     }
 
     protected String getClassName(ObjEntity entity) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java
index 9b604e1..c48c2b2 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java
@@ -1,21 +1,21 @@
-/*****************************************************************
- *   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
+/*
+ * 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
+ *      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.
- ****************************************************************/
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ */
 
 package org.apache.cayenne.modeler.dialog.db;
 
@@ -34,6 +34,10 @@ import org.apache.cayenne.CayenneException;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.access.DbLoader;
 import org.apache.cayenne.access.DbLoaderDelegate;
+import org.apache.cayenne.access.loader.DbLoaderConfiguration;
+import org.apache.cayenne.access.loader.filters.EntityFilters;
+import org.apache.cayenne.access.loader.filters.FilterFactory;
+import org.apache.cayenne.access.loader.filters.FiltersConfig;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.event.DataMapEvent;
 import org.apache.cayenne.dba.DbAdapter;
@@ -54,6 +58,8 @@ import org.apache.cayenne.util.Util;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import static org.apache.cayenne.access.loader.filters.FilterFactory.NULL;
+
 /**
  * Stateful helper class that encapsulates access to DbLoader.
  * 
@@ -78,13 +84,11 @@ public class DbLoaderHelper {
     protected String dbUserName;
     protected DbLoader loader;
     protected DataMap dataMap;
-    protected String schemaName;
-    protected String tableNamePattern;
-    protected boolean loadProcedures;
     protected boolean meaningfulPk;
-    protected String procedureNamePattern;
     protected List<String> schemas;
 
+    private final EntityFilters.Builder filterBuilder = new EntityFilters.Builder();
+
     protected String loadStatusNote;
 
     /**
@@ -168,11 +172,12 @@ public class DbLoaderHelper {
             return;
         }
 
-        this.schemaName = dialog.getSelectedSchema();
-        this.tableNamePattern = dialog.getTableNamePattern();
-        this.loadProcedures = dialog.isLoadingProcedures();
+        this.filterBuilder.schema(dialog.getSelectedSchema());
+        this.filterBuilder.includeTables(dialog.getTableNamePattern());
+        this.filterBuilder.setProceduresFilters(dialog.isLoadingProcedures() ? FilterFactory.TRUE : FilterFactory.NULL);
+        this.filterBuilder.includeProcedures(dialog.getProcedureNamePattern());
+
         this.meaningfulPk = dialog.isMeaningfulPk();
-        this.procedureNamePattern = dialog.getProcedureNamePattern();
         this.addedObjEntities = new ArrayList<ObjEntity>();
 
         this.loader.setNameGenerator(dialog.getNamingStrategy());
@@ -347,41 +352,15 @@ public class DbLoaderHelper {
             if (!existingMap) {
                 dataMap = new DataMap(DefaultUniqueNameGenerator.generate(NameCheckers.dataMap));
                 dataMap.setName(DefaultUniqueNameGenerator.generate(NameCheckers.dataMap, mediator.getProject().getRootNode()));
-                dataMap.setDefaultSchema(schemaName);
+                dataMap.setDefaultSchema(filterBuilder.schema());
             }
 
             if (isCanceled()) {
                 return;
             }
 
-            loadStatusNote = "Importing tables...";
-
-            try {
-                loader.setCreatingMeaningfulPK(meaningfulPk);
-                loader.loadDataMapFromDB(schemaName, tableNamePattern, dataMap);
-
-                /**
-                 * Update default rules for relationships
-                 */
-                for (ObjEntity addedObjEntity : addedObjEntities) {
-                    DeleteRuleUpdater.updateObjEntity(addedObjEntity);
-                }
-            } catch (Throwable th) {
-                if (!isCanceled()) {
-                    processException(th, "Error Reengineering Database");
-                }
-            }
-
-            if (loadProcedures) {
-                loadStatusNote = "Importing procedures...";
-                try {
-                    loader.loadProceduresFromDB(schemaName, procedureNamePattern, dataMap);
-                } catch (Throwable th) {
-                    if (!isCanceled()) {
-                        processException(th, "Error Reengineering Database");
-                    }
-                }
-            }
+            importingTables();
+            importingProcedures();
 
             cleanup();
 
@@ -404,5 +383,49 @@ public class DbLoaderHelper {
                 mediator.addDataMap(Application.getFrame(), dataMap);
             }
         }
+
+        private void importingProcedures() {
+            if (!filterBuilder.proceduresFilters().equals(NULL)) {
+                return;
+            }
+
+            loadStatusNote = "Importing procedures...";
+            try {
+                DbLoaderConfiguration configuration = new DbLoaderConfiguration();
+                configuration.setFiltersConfig(new FiltersConfig(filterBuilder.build()));
+
+                loader.loadProcedures(dataMap, new DbLoaderConfiguration());
+            } catch (Throwable th) {
+                if (!isCanceled()) {
+                    processException(th, "Error Reengineering Database");
+                }
+            }
+        }
+
+        private void importingTables() {
+            loadStatusNote = "Importing tables...";
+            try {
+                loader.setCreatingMeaningfulPK(meaningfulPk);
+                String[] types = loader.getDefaultTableTypes();
+                if (types.length == 0) {
+                    throw new SQLException("No supported table types found.");
+                }
+
+                DbLoaderConfiguration configuration = new DbLoaderConfiguration();
+                configuration.setFiltersConfig(new FiltersConfig(filterBuilder.build()));
+                loader.load(dataMap, configuration, types);
+
+                /**
+                 * Update default rules for relationships
+                 */
+                for (ObjEntity addedObjEntity : addedObjEntities) {
+                    DeleteRuleUpdater.updateObjEntity(addedObjEntity);
+                }
+            } catch (Throwable th) {
+                if (!isCanceled()) {
+                    processException(th, "Error Reengineering Database");
+                }
+            }
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
index 125a4fd..dc05932 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
@@ -1,21 +1,21 @@
-/*****************************************************************
- *   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
+/*
+ * 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
+ *      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.
- ****************************************************************/
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ */
 
 package org.apache.cayenne.modeler.dialog.db;
 
@@ -34,6 +34,10 @@ import javax.swing.WindowConstants;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
 
+import org.apache.cayenne.access.loader.DbLoaderConfiguration;
+import org.apache.cayenne.access.loader.filters.DbPath;
+import org.apache.cayenne.access.loader.filters.EntityFilters;
+import org.apache.cayenne.access.loader.filters.FiltersConfig;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.dba.JdbcAdapter;
@@ -161,14 +165,18 @@ public class MergerOptions extends CayenneController {
      */
     protected void prepareMigrator() {
         try {
-            adapter = (JdbcAdapter) connectionInfo.makeAdapter(getApplication()
-                    .getClassLoadingService());
+            adapter = (JdbcAdapter) connectionInfo.makeAdapter(getApplication().getClassLoadingService());
             tokens.setMergerFactory(adapter.mergerFactory());
-            merger = new DbMerger(adapter.mergerFactory(), defaultSchema);
+            merger = new DbMerger(adapter.mergerFactory());
+
+            DbLoaderConfiguration config = new DbLoaderConfiguration();
+            config.setFiltersConfig(new FiltersConfig(new EntityFilters(new DbPath(null, defaultSchema))));
+
             List<MergerToken> mergerTokens = merger.createMergeTokens(
-                    connectionInfo.makeDataSource(getApplication()
-                            .getClassLoadingService()), adapter,
-                    dataMap);
+                    connectionInfo.makeDataSource(getApplication().getClassLoadingService()),
+                    adapter,
+                    dataMap,
+                    config);
             tokens.setTokens(mergerTokens);
         }
         catch (Exception ex) {
@@ -181,15 +189,12 @@ public class MergerOptions extends CayenneController {
      */
     protected void createSQL() {
         // convert them to string representation for display
-        final StringBuilder buf = new StringBuilder();
+        StringBuilder buf = new StringBuilder();
 
         Iterator<MergerToken> it = tokens.getSelectedTokens().iterator();
         String batchTerminator = adapter.getBatchTerminator();
 
-        final String lineEnd = (batchTerminator != null) ? "\n"
-                + batchTerminator
-                + "\n\n" : "\n\n";
-
+        String lineEnd = batchTerminator != null ? "\n" + batchTerminator + "\n\n" : "\n\n";
         while (it.hasNext()) {
             MergerToken token = it.next();
 
@@ -267,7 +272,7 @@ public class MergerOptions extends CayenneController {
                 .getRootNode();
         final DataNodeDescriptor node = getProjectController().getCurrentDataNode();
 
-        final ModelMergeDelegate delegate = new ModelMergeDelegate() {
+        ModelMergeDelegate delegate = new ModelMergeDelegate() {
 
             public void dbAttributeAdded(DbAttribute att) {
                 if (c.getCurrentDbEntity() == att.getEntity()) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ClassNameUpdater.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ClassNameUpdater.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ClassNameUpdater.java
index a9fc623..449d10a 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ClassNameUpdater.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ClassNameUpdater.java
@@ -24,6 +24,7 @@ import java.awt.Component;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 
+import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.modeler.util.CayenneController;
 
@@ -120,9 +121,7 @@ public class ClassNameUpdater extends CayenneController {
     }
 
     private String suggestedServerClassName() {
-        String pkg = entity.getDataMap() != null ? entity
-                .getDataMap()
-                .getDefaultPackage() : null;
+        String pkg = entity.getDataMap() == null ? null : entity.getDataMap().getDefaultPackage();
         return suggestedClassName(entity.getName(), pkg, entity.getClassName());
     }
 
@@ -132,21 +131,16 @@ public class ClassNameUpdater extends CayenneController {
             return null;
         }
 
-        String pkg = entity.getDataMap() != null ? entity
-                .getDataMap()
-                .getDefaultClientPackage() : null;
+        String pkg = entity.getDataMap() == null ? null : entity.getDataMap().getDefaultClientPackage();
         return suggestedClassName(entity.getName(), pkg, entity.getClientClassName());
     }
 
     /**
      * Suggests a new class name based on new entity name and current selections.
      */
-    private String suggestedClassName(
-            String entityName,
-            String suggestedPackage,
-            String oldClassName) {
+    private static String suggestedClassName(String entityName, String suggestedPackage, String oldClassName) {
 
-        if (entityName == null || entityName.trim().length() == 0) {
+        if (entityName == null || entityName.trim().isEmpty()) {
             return null;
         }
 
@@ -156,20 +150,13 @@ public class ClassNameUpdater extends CayenneController {
             pkg = oldClassName.substring(0, oldClassName.lastIndexOf('.'));
         }
 
-        if (pkg == null) {
-            pkg = "";
-        }
-        else {
-            pkg = pkg + '.';
-        }
-
         // build suggested class name
-        int dot = entityName.lastIndexOf('.');
-        if (dot >= 0 && dot < entityName.length() - 1) {
-            entityName = entityName.substring(dot + 1);
+        int lastDotIndex = entityName.lastIndexOf('.');
+        if (lastDotIndex >= 0 && lastDotIndex < entityName.length() - 1) {
+            entityName = entityName.substring(lastDotIndex + 1);
         }
 
-        return pkg + entityName;
+        return DataMap.getNameWithPackage(pkg, entityName);
     }
 
     protected void initBindings(

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/EntitySyncController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/EntitySyncController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/EntitySyncController.java
index cce0262..6e07559 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/EntitySyncController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/EntitySyncController.java
@@ -27,14 +27,17 @@ import java.util.Collections;
 
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.naming.DefaultNameGenerator;
+import org.apache.cayenne.map.naming.ObjectNameGenerator;
 import org.apache.cayenne.modeler.util.CayenneController;
+import org.apache.cayenne.modeler.util.NameGeneratorPreferences;
 import org.apache.cayenne.util.EntityMergeSupport;
 
 public class EntitySyncController extends CayenneController {
 
-    protected DbEntity dbEntity;
-    protected ObjEntity objEntity;
-    protected EntitySyncDialog view;
+    private final DbEntity dbEntity;
+    private ObjEntity objEntity;
+    private EntitySyncDialog view;
 
     /**
      * Creates a controller for synchronizing all ObjEntities mapped to a given DbEntity.
@@ -58,18 +61,26 @@ public class EntitySyncController extends CayenneController {
             return null;
         }
 
-        final EntityMergeSupport merger = new EntityMergeSupport(dbEntity.getDataMap());
+
+        ObjectNameGenerator namingStrategy;
+        try {
+            namingStrategy = NameGeneratorPreferences.getInstance().createNamingStrategy(application);
+        } catch (Throwable e) {
+            namingStrategy = NameGeneratorPreferences.defaultNameGenerator();
+
+            // TODO log exception
+        }
+
+        EntityMergeSupport merger = new EntityMergeSupport(dbEntity.getDataMap(), namingStrategy, true);
 
         // see if we need to remove meaningful attributes...
-        boolean showDialog = false;
         for (ObjEntity entity : entities) {
             if (!merger.getMeaningfulFKs(entity).isEmpty()) {
-                showDialog = true;
-                break;
+                return configureMerger(merger);
             }
         }
 
-        return (showDialog) ? configureMerger(merger) : merger;
+        return merger;
     }
 
     /**
@@ -113,9 +124,8 @@ public class EntitySyncController extends CayenneController {
     }
 
     protected Collection<ObjEntity> getObjEntities() {
-        return (objEntity != null) ? Collections.singleton(objEntity) : dbEntity
-                .getDataMap()
-                .getMappedEntities(dbEntity);
+        return objEntity == null ? dbEntity.getDataMap().getMappedEntities(dbEntity)
+                    : Collections.singleton(objEntity);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/NameGeneratorPreferences.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/NameGeneratorPreferences.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/NameGeneratorPreferences.java
index eef86f2..fa15083 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/NameGeneratorPreferences.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/NameGeneratorPreferences.java
@@ -24,6 +24,7 @@ import java.util.prefs.Preferences;
 
 import org.apache.cayenne.map.naming.LegacyNameGenerator;
 import org.apache.cayenne.map.naming.DefaultNameGenerator;
+import org.apache.cayenne.map.naming.ObjectNameGenerator;
 import org.apache.cayenne.modeler.Application;
 
 /**
@@ -84,10 +85,21 @@ public class NameGeneratorPreferences {
         for (String str : strategies) {
             res.append(str).append(",");
         }
-        if (strategies.size() > 0) {
+        if (!strategies.isEmpty()) {
             res.deleteCharAt(res.length() - 1);
         }
 
         getPreference().put(STRATEGIES_PREFERENCE, res.toString());
     }
+
+    public ObjectNameGenerator createNamingStrategy(Application application)
+            throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+
+        return application.getClassLoadingService()
+                .loadClass(ObjectNameGenerator.class, getLastUsedStrategies().get(0)).newInstance();
+    }
+
+    public static ObjectNameGenerator defaultNameGenerator() {
+        return new DefaultNameGenerator();
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/pom.xml b/plugins/maven-cayenne-plugin/pom.xml
index 5401797..1458865 100644
--- a/plugins/maven-cayenne-plugin/pom.xml
+++ b/plugins/maven-cayenne-plugin/pom.xml
@@ -128,15 +128,37 @@
 			<scope>test</scope>
 		</dependency>
 
+       <dependency>
+            <groupId>org.apache.cayenne</groupId>
+            <artifactId>cayenne-server</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.cayenne</groupId>
+            <artifactId>cayenne-tools</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
     </dependencies>
 
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-plugin-plugin</artifactId>
+                <version>2.5.1</version>
+            </plugin>
+        </plugins>
+    </reporting>
+
     <build>
         <plugins>
             <plugin>
                 <artifactId>maven-checkstyle-plugin</artifactId>
-                <!--<configuration>
-                    <suppressionsLocation>${project.basedir}/cayenne-checkstyle-suppression.xml</suppressionsLocation>
-                </configuration>-->
             </plugin>
             <plugin>
                 <artifactId>maven-pmd-plugin</artifactId>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
index 12b4468..3c9d548 100644
--- a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
+++ b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
@@ -21,6 +21,7 @@ package org.apache.cayenne.tools;
 
 import java.io.File;
 
+import org.apache.cayenne.access.loader.NamePatternMatcher;
 import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.gen.ClientClassGenerationAction;
 import org.apache.cayenne.map.DataMap;
@@ -202,8 +203,7 @@ public class CayenneGeneratorMojo extends AbstractMojo {
 
 		CayenneGeneratorEntityFilterAction filterAction = new CayenneGeneratorEntityFilterAction();
 		filterAction.setClient(client);
-		filterAction.setNameFilter(new NamePatternMatcher(logger,
-				includeEntities, excludeEntities));
+		filterAction.setNameFilter(NamePatternMatcher.build(logger, includeEntities, excludeEntities));
 
 		try {
 			loaderAction.setAdditionalDataMapFiles(convertAdditionalDataMaps());

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
index d8ea086..1918106 100644
--- a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
+++ b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
@@ -16,11 +16,22 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
-
 package org.apache.cayenne.tools;
 
 import java.io.File;
 
+import org.apache.cayenne.access.loader.filters.EntityFilters;
+import org.apache.cayenne.access.loader.filters.FilterFactory;
+import org.apache.cayenne.tools.dbimport.config.Catalog;
+import org.apache.cayenne.tools.dbimport.config.ExcludeColumn;
+import org.apache.cayenne.tools.dbimport.config.ExcludeProcedure;
+import org.apache.cayenne.tools.dbimport.config.ExcludeTable;
+import org.apache.cayenne.tools.dbimport.config.FiltersConfigBuilder;
+import org.apache.cayenne.tools.dbimport.config.IncludeColumn;
+import org.apache.cayenne.tools.dbimport.config.IncludeProcedure;
+import org.apache.cayenne.tools.dbimport.config.IncludeTable;
+import org.apache.cayenne.tools.dbimport.config.ReverseEngineering;
+import org.apache.cayenne.tools.dbimport.config.Schema;
 import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.tools.configuration.ToolsModule;
@@ -71,86 +82,6 @@ public class DbImporterMojo extends AbstractMojo {
     private boolean overwrite;
 
     /**
-     * DB schema to use for DB importing.
-     * 
-     * @parameter expression="${cdbimport.schemaName}"
-     * @deprecated since 3.2 renamed to "schema"
-     */
-    private String schemaName;
-
-    /**
-     * DB schema to use for DB importing.
-     * 
-     * @parameter expression="${cdbimport.catalog}"
-     * @since 3.2
-     */
-    private String catalog;
-
-    /**
-     * DB schema to use for DB importing.
-     * 
-     * @parameter expression="${cdbimport.schema}"
-     * @since 3.2
-     */
-    private String schema;
-
-    /**
-     * Pattern for tables to import from DB.
-     * 
-     * The default is to match against all tables.
-     * 
-     * @parameter expression="${cdbimport.tablePattern}"
-     */
-    private String tablePattern;
-
-    /**
-     * A comma-separated list of Perl5 regex that defines tables that should be
-     * included in import.
-     * 
-     * @parameter expression="${cdbimport.includeTables}"
-     */
-    private String includeTables;
-
-    /**
-     * A comma-separated list of Perl5 regex that defines tables that should be
-     * skipped from import.
-     * 
-     * @parameter expression="${cdbimport.excludeTables}"
-     */
-    private String excludeTables;
-
-    /**
-     * Indicates whether stored procedures should be imported.
-     * 
-     * Default is <code>false</code>.
-     * 
-     * @parameter expression="${cdbimport.importProcedures}"
-     *            default-value="false"
-     */
-    private boolean importProcedures;
-
-    /**
-     * Pattern for stored procedures to import from DB. This is only meaningful
-     * if <code>importProcedures</code> is set to <code>true</code>.
-     * 
-     * The default is to match against all stored procedures.
-     * 
-     * @parameter expression="${cdbimport.procedurePattern}"
-     */
-    private String procedurePattern;
-
-    /**
-     * Indicates whether primary keys should be mapped as meaningful attributes
-     * in the object entities.
-     * 
-     * Default is <code>false</code>.
-     * 
-     * @parameter expression="${cdbimport.meaningfulPk}" default-value="false"
-     * @deprecated since 3.2 use meaningfulPkTables
-     */
-    private boolean meaningfulPk;
-
-    /**
      * @parameter expression="${cdbimport.meaningfulPkTables}"
      * @since 3.2
      */
@@ -215,15 +146,101 @@ public class DbImporterMojo extends AbstractMojo {
      */
     private boolean usePrimitives;
 
+    private final ReverseEngineering reverseEngineering = new ReverseEngineering();
+
+    private final EntityFilters.Builder filterBuilder = new EntityFilters.Builder();
+
+    /**
+     * DB schema to use for DB importing.
+     *
+     * @parameter expression="${cdbimport.schemaName}"
+     * @deprecated since 3.2 renamed to "schema"
+     */
+    private void setSchemaName(String schemaName) {
+        getLog().warn("'schemaName' property is deprecated. Use 'schema' instead");
+
+        filterBuilder.schema(schemaName);
+    }
+
+    /**
+     * DB schema to use for DB importing.
+     *
+     * @parameter expression="${cdbimport.catalog}"
+     * @since 3.2
+     */
+    private void setCatalog(String catalog) {
+        filterBuilder.catalog(catalog);
+    }
+
+    /**
+     * DB schema to use for DB importing.
+     *
+     * @parameter expression="${cdbimport.schema}"
+     * @since 3.2
+     */
+    private void setSchema(String schema) {
+        filterBuilder.schema(schema);
+    }
+
+    /**
+     * Pattern for tables to import from DB.
+     *
+     * The default is to match against all tables.
+     *
+     * @parameter expression="${cdbimport.tablePattern}"
+     */
+    private void setTablePattern(String tablePattern) {
+        filterBuilder.includeTables(tablePattern);
+    }
+
+    /**
+     * Indicates whether stored procedures should be imported.
+     *
+     * Default is <code>false</code>.
+     *
+     * @parameter expression="${cdbimport.importProcedures}"
+     *            default-value="false"
+     */
+    private void setImportProcedures(boolean importProcedures) {
+        filterBuilder.setProceduresFilters(importProcedures ? FilterFactory.TRUE : FilterFactory.NULL);
+    }
+
+    /**
+     * Pattern for stored procedures to import from DB. This is only meaningful
+     * if <code>importProcedures</code> is set to <code>true</code>.
+     *
+     * The default is to match against all stored procedures.
+     *
+     * @parameter expression="${cdbimport.procedurePattern}"
+     */
+    private void setProcedurePattern(String procedurePattern) {
+        filterBuilder.includeProcedures(procedurePattern);
+    }
+
+    /**
+     * Indicates whether primary keys should be mapped as meaningful attributes
+     * in the object entities.
+     *
+     * Default is <code>false</code>.
+     *
+     * @parameter expression="${cdbimport.meaningfulPk}" default-value="false"
+     * @deprecated since 3.2 use meaningfulPkTables
+     */
+    public void setMeaningfulPk(boolean meaningfulPk) {
+        getLog().warn("'meaningfulPk' property is deprecated. Use 'meaningfulPkTables' pattern instead");
+
+        this.meaningfulPkTables = meaningfulPk ? "*" : null;
+    }
+
     public void execute() throws MojoExecutionException, MojoFailureException {
 
         Log logger = new MavenLogger(this);
 
-        DbImportConfiguration parameters = toParameters();
+        DbImportConfiguration config = toParameters();
         Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule());
 
         try {
-            injector.getInstance(DbImportAction.class).execute(parameters);
+            injector.getInstance(DbImportAction.class).execute(config);
         } catch (Exception ex) {
             Throwable th = Util.unwindException(ex);
 
@@ -239,46 +256,25 @@ public class DbImporterMojo extends AbstractMojo {
     }
 
     DbImportConfiguration toParameters() {
-        DbImportConfiguration parameters = new DbImportConfiguration();
-        parameters.setAdapter(adapter);
-        parameters.setCatalog(catalog);
-        parameters.setDefaultPackage(defaultPackage);
-        parameters.setDriver(driver);
-        parameters.setImportProcedures(importProcedures);
-        parameters.setDataMapFile(map);
-        parameters.setMeaningfulPkTables(getMeaningfulPkTables());
-        parameters.setNamingStrategy(namingStrategy);
-        parameters.setOverwrite(overwrite);
-        parameters.setPassword(password);
-        parameters.setProcedurePattern(procedurePattern);
-        parameters.setSchema(getSchema());
-        parameters.setTablePattern(tablePattern);
-        parameters.setUrl(url);
-        parameters.setUsername(username);
-        parameters.setIncludeTables(includeTables);
-        parameters.setExcludeTables(excludeTables);
-        parameters.setUsePrimitives(usePrimitives);
-        return parameters;
+        DbImportConfiguration config = new DbImportConfiguration();
+        config.setAdapter(adapter);
+        config.setDefaultPackage(defaultPackage);
+        config.setDriver(driver);
+        config.setDataMapFile(map);
+        config.setMeaningfulPkTables(meaningfulPkTables);
+        config.setNamingStrategy(namingStrategy);
+        config.setOverwrite(overwrite);
+        config.setPassword(password);
+        config.setUrl(url);
+        config.setUsername(username);
+        config.setUsePrimitives(usePrimitives);
+        config.setFiltersConfig(new FiltersConfigBuilder(reverseEngineering)
+                .add(filterBuilder.build()).filtersConfig());
+        return config;
     }
 
     private String getSchema() {
-        if (schemaName != null) {
-            getLog().warn("'schemaName' property is deprecated. Use 'schema' instead");
-        }
-
-        return schema != null ? schema : schemaName;
-    }
-
-    private String getMeaningfulPkTables() {
-        if (meaningfulPk) {
-            getLog().warn("'meaningfulPk' property is deprecated. Use 'meaningfulPkTables' pattern instead");
-        }
-
-        if (meaningfulPkTables != null) {
-            return meaningfulPkTables;
-        }
-
-        return meaningfulPk ? "*" : null;
+        return filterBuilder.schema();
     }
 
     public File getMap() {
@@ -304,4 +300,40 @@ public class DbImporterMojo extends AbstractMojo {
     public void setUrl(String url) {
         this.url = url;
     }
+
+    public void addIncludeColumn(IncludeColumn includeColumn) {
+        reverseEngineering.addIncludeColumn(includeColumn);
+    }
+
+    public void addExcludeColumn(ExcludeColumn excludeColumn) {
+        reverseEngineering.addExcludeColumn(excludeColumn);
+    }
+
+    public void addIncludeTable(IncludeTable includeTable) {
+        reverseEngineering.addIncludeTable(includeTable);
+    }
+
+    public void addExcludeTable(ExcludeTable excludeTable) {
+        reverseEngineering.addExcludeTable(excludeTable);
+    }
+
+    public void addIncludeProcedure(IncludeProcedure includeProcedure) {
+        reverseEngineering.addIncludeProcedure(includeProcedure);
+    }
+
+    public void addExcludeProcedure(ExcludeProcedure excludeProcedure) {
+        reverseEngineering.addExcludeProcedure(excludeProcedure);
+    }
+
+    public void addSchema(Schema schema) {
+        reverseEngineering.addSchema(schema);
+    }
+
+    public void addCatalog(Catalog catalog) {
+        reverseEngineering.addCatalog(catalog);
+    }
+
+    public ReverseEngineering getReverseEngineering() {
+        return reverseEngineering;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java
new file mode 100644
index 0000000..e5a3a49
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java
@@ -0,0 +1,56 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.tools;
+
+import static org.apache.cayenne.tools.dbimport.config.DefaultReverseEngineeringLoaderTest.*;
+import org.apache.maven.plugin.testing.AbstractMojoTestCase;
+import org.junit.Test;
+
+/**
+ * @since 3.2.
+ */
+public class DbImporterMojoConfigurationTest extends AbstractMojoTestCase {
+
+    @Test
+    public void testLoadCatalog() throws Exception {
+        assertCatalog(getCdbImport("pom-catalog.xml").getReverseEngineering());
+    }
+
+    @Test
+    public void testLoadSchema() throws Exception {
+        assertSchema(getCdbImport("pom-schema.xml").getReverseEngineering());
+    }
+
+    @Test
+    public void testLoadCatalogAndSchema() throws Exception {
+        assertCatalogAndSchema(getCdbImport("pom-catalog-and-schema.xml").getReverseEngineering());
+    }
+
+    @Test
+    public void testLoadFlat() throws Exception {
+        assertFlat(getCdbImport("pom-flat.xml").getReverseEngineering());
+
+    }
+
+    private DbImporterMojo getCdbImport(String pomFileName) throws Exception {
+        return (DbImporterMojo) lookupMojo("cdbimport",
+                getTestFile("src/test/resources/org/apache/cayenne/tools/config/" + pomFileName));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
index a255a9c..682f180 100644
--- a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
+++ b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
@@ -27,15 +27,20 @@ import java.sql.DriverManager;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.Iterator;
 
+import org.apache.cayenne.tools.dbimport.config.Catalog;
+import org.apache.cayenne.tools.dbimport.config.IncludeTable;
+import org.apache.cayenne.tools.dbimport.config.Schema;
 import org.apache.cayenne.tools.dbimport.DbImportConfiguration;
 import org.apache.maven.plugin.testing.AbstractMojoTestCase;
 import org.codehaus.plexus.util.FileUtils;
+import org.custommonkey.xmlunit.DetailedDiff;
+import org.custommonkey.xmlunit.Diff;
 import org.custommonkey.xmlunit.XMLUnit;
 import org.xml.sax.SAXException;
 
-import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
-import static org.junit.Assert.assertNotNull;
+import static org.apache.commons.lang.StringUtils.isBlank;
 
 public class DbImporterMojoTest extends AbstractMojoTestCase {
 
@@ -85,6 +90,18 @@ public class DbImporterMojoTest extends AbstractMojoTestCase {
         test("testImportAddTableAndColumn");
     }
 
+    public void testSimpleFiltering() throws Exception {
+        test("testSimpleFiltering");
+    }
+
+    public void testFilteringWithSchema() throws Exception {
+        test("testFilteringWithSchema");
+    }
+
+    public void testSchemasAndTableExclude() throws Exception {
+        test("testSchemasAndTableExclude");
+    }
+
     private void test(String name) throws Exception {
         DbImporterMojo cdbImport = getCdbImport("dbimport/" + name + "-pom.xml");
         File mapFile = cdbImport.getMap();
@@ -114,14 +131,33 @@ public class DbImporterMojoTest extends AbstractMojoTestCase {
 
         ResultSet tables = connection.getMetaData().getTables(null, null, null, new String[]{"TABLE"});
         while (tables.next()) {
-            System.out.println("DROP TABLE " + tables.getString("TABLE_NAME"));
-            stmt.execute("DROP TABLE " + tables.getString("TABLE_NAME"));
+            String schema = tables.getString("TABLE_SCHEM");
+            System.out.println("DROP TABLE " + (isBlank(schema) ? "" : schema + ".") + tables.getString("TABLE_NAME"));
+            stmt.execute("DROP TABLE " + (isBlank(schema) ? "" : schema + ".") + tables.getString("TABLE_NAME"));
+        }
+
+        ResultSet schemas = connection.getMetaData().getSchemas();
+        while (schemas.next()) {
+            String schem = schemas.getString("TABLE_SCHEM");
+            if (schem.startsWith("SCHEMA")) {
+                System.out.println("DROP SCHEMA " + schem);
+                stmt.execute("DROP SCHEMA " + schem + " RESTRICT");
+            }
         }
     }
 
     private void verifyResult(File map, File mapFileCopy) {
         try {
-            assertXMLEqual(new FileReader(map.getAbsolutePath() + "-result"), new FileReader(mapFileCopy));
+            FileReader control = new FileReader(map.getAbsolutePath() + "-result");
+            FileReader test = new FileReader(mapFileCopy);
+
+            DetailedDiff diff = new DetailedDiff(new Diff(control, test));
+            if (!diff.similar()) {
+                System.out.println(" >>>> " + map.getAbsolutePath() + "-result");
+                System.out.println(" >>>> " + mapFileCopy);
+                fail(diff.toString());
+            }
+
         } catch (SAXException e) {
             e.printStackTrace();
             fail();
@@ -131,6 +167,59 @@ public class DbImporterMojoTest extends AbstractMojoTestCase {
         }
     }
 
+    public void testFilteringConfig() throws Exception {
+        DbImporterMojo cdbImport = getCdbImport("config/pom-01.xml");
+
+        assertEquals(2, cdbImport.getReverseEngineering().getCatalogs().size());
+        Iterator<Catalog> iterator = cdbImport.getReverseEngineering().getCatalogs().iterator();
+        assertEquals("catalog-name-01", iterator.next().getName());
+
+        Catalog catalog = iterator.next();
+        assertEquals("catalog-name-02", catalog.getName());
+        Iterator<Schema> schemaIterator = catalog.getSchemas().iterator();
+
+        assertEquals("schema-name-01", schemaIterator.next().getName());
+
+        Schema schema = schemaIterator.next();
+        assertEquals("schema-name-02", schema.getName());
+
+        Iterator<IncludeTable> includeTableIterator = schema.getIncludeTables().iterator();
+        assertEquals("incTable-01", includeTableIterator.next().getPattern());
+
+        IncludeTable includeTable = includeTableIterator.next();
+        assertEquals("incTable-02", includeTable.getPattern());
+        assertEquals("includeColumn-01", includeTable.getIncludeColumns().iterator().next().getPattern());
+        assertEquals("excludeColumn-01", includeTable.getExcludeColumns().iterator().next().getPattern());
+
+        assertEquals("includeColumn-02", schema.getIncludeColumns().iterator().next().getPattern());
+        assertEquals("excludeColumn-02", schema.getExcludeColumns().iterator().next().getPattern());
+
+        assertEquals("includeColumn-03", catalog.getIncludeColumns().iterator().next().getPattern());
+        assertEquals("excludeColumn-03", catalog.getExcludeColumns().iterator().next().getPattern());
+
+        schemaIterator = cdbImport.getReverseEngineering().getSchemas().iterator();
+        schema = schemaIterator.next();
+        assertEquals("schema-name-03", schema.getName());
+
+        schema = schemaIterator.next();
+        assertEquals("schema-name-04", schema.getName());
+
+        includeTableIterator = schema.getIncludeTables().iterator();
+        assertEquals("incTable-04", includeTableIterator.next().getPattern());
+        assertEquals("excTable-04", schema.getExcludeTables().iterator().next().getPattern());
+
+        includeTable = includeTableIterator.next();
+        assertEquals("incTable-05", includeTable.getPattern());
+        assertEquals("includeColumn-04", includeTable.getIncludeColumns().iterator().next().getPattern());
+        assertEquals("excludeColumn-04", includeTable.getExcludeColumns().iterator().next().getPattern());
+
+        assertEquals("includeColumn-04", schema.getIncludeColumns().iterator().next().getPattern());
+        assertEquals("excludeColumn-04", schema.getExcludeColumns().iterator().next().getPattern());
+
+        assertEquals("includeColumn-03", catalog.getIncludeColumns().iterator().next().getPattern());
+        assertEquals("excludeColumn-03", catalog.getExcludeColumns().iterator().next().getPattern());
+    }
+
     private void prepareDatabase(String sqlFile, DbImportConfiguration dbImportConfiguration) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException, IOException, URISyntaxException {
         Class.forName(dbImportConfiguration.getDriver()).newInstance();
         // Get a connection


[7/7] git commit: CAY-1946 CDbimport improvements

Posted by aa...@apache.org.
CAY-1946 CDbimport improvements

    * pull request #15 by AlexKolonitsky
    * andrus: merging against extracted POM changes on master
    * andrus: standardizing/adding missing license headers
    * andrus: squashing a few random changes


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

Branch: refs/heads/CAY-1946
Commit: fde7761f80ed8db65df3e157ab4acd5f47d75004
Parents: 5be9a2e
Author: aadamchik <aa...@apache.org>
Authored: Wed Oct 29 20:56:05 2014 +0300
Committer: aadamchik <aa...@apache.org>
Committed: Wed Oct 29 21:23:41 2014 +0300

----------------------------------------------------------------------
 .../org/apache/cayenne/access/DbLoader.java     | 785 +++++++++----------
 .../cayenne/access/DbLoaderConfiguration.java   |  48 --
 .../cayenne/access/DefaultDbLoaderDelegate.java |  54 --
 .../access/ManyToManyCandidateEntity.java       | 126 ---
 .../access/loader/BooleanNameFilter.java        |  35 +
 .../access/loader/DbLoaderConfiguration.java    | 115 +++
 .../access/loader/DefaultDbLoaderDelegate.java  |  55 ++
 .../loader/ManyToManyCandidateEntity.java       | 126 +++
 .../cayenne/access/loader/NameFilter.java       |  27 +
 .../access/loader/NamePatternMatcher.java       | 225 ++++++
 .../cayenne/access/loader/filters/DbPath.java   | 154 ++++
 .../access/loader/filters/EntityFilters.java    | 399 ++++++++++
 .../access/loader/filters/ExcludeFilter.java    |  42 +
 .../cayenne/access/loader/filters/Filter.java   |  31 +
 .../access/loader/filters/FilterFactory.java    |  94 +++
 .../access/loader/filters/FiltersConfig.java    | 180 +++++
 .../access/loader/filters/IncludeFilter.java    |  76 ++
 .../access/loader/filters/ListFilter.java       | 123 +++
 .../cayenne/access/loader/mapper/DbType.java    | 195 +++++
 .../mapper/DefaultJdbc2JavaTypeMapper.java      | 282 +++++++
 .../loader/mapper/Jdbc2JavaTypeMapper.java      |  33 +
 .../DefaultConfigurationNameMapper.java         |  66 +-
 .../org/apache/cayenne/dba/JdbcAdapter.java     |  93 ++-
 .../java/org/apache/cayenne/map/DataMap.java    |  35 +
 .../org/apache/cayenne/map/DbRelationship.java  |  21 +-
 .../java/org/apache/cayenne/map/ObjEntity.java  |  13 +-
 .../map/naming/DefaultUniqueNameGenerator.java  |   7 +-
 .../apache/cayenne/map/naming/NameCheckers.java |   6 +-
 .../org/apache/cayenne/merge/AddColumnToDb.java |  72 +-
 .../cayenne/merge/CreateTableToModel.java       |  20 +-
 .../java/org/apache/cayenne/merge/DbMerger.java |  91 +--
 .../apache/cayenne/merge/SetColumnTypeToDb.java |  68 +-
 .../apache/cayenne/util/EntityMergeSupport.java | 170 ++--
 .../cayenne/access/DbLoaderPartialTest.java     |   2 +-
 .../org/apache/cayenne/access/DbLoaderTest.java | 220 +++++-
 .../access/ManyToManyCandidateEntityTest.java   | 106 ---
 .../loader/ManyToManyCandidateEntityTest.java   | 106 +++
 .../access/loader/filters/DbPathTest.java       |  75 ++
 .../loader/filters/EntityFiltersTest.java       |  62 ++
 .../loader/filters/FiltersConfigTest.java       | 198 +++++
 .../access/loader/filters/FiltersFactory.java   |  44 ++
 .../access/loader/mapper/DbTypeTest.java        |  87 ++
 .../org/apache/cayenne/merge/MergeCase.java     |   5 +-
 .../cayenne-relationship-optimisation.xml       |   4 -
 .../cayenne-relationship-optimisation.xml       |   4 +
 .../loader/relationship-optimisation.map.xml    |  43 +
 .../access/relationship-optimisation.map.xml    |  43 -
 cayenne-tools/pom.xml                           |  26 +
 .../cayenne/gen/ClassGenerationAction.java      |   2 +-
 .../cayenne/gen/ClientDataMapArtifact.java      |  17 +-
 .../org/apache/cayenne/gen/DataMapArtifact.java |  13 +-
 .../cayenne/tools/AntDataPortDelegate.java      |   7 +-
 .../CayenneGeneratorEntityFilterAction.java     |  20 +-
 .../cayenne/tools/CayenneGeneratorTask.java     |   6 +-
 .../apache/cayenne/tools/DbImporterTask.java    | 182 +++--
 .../cayenne/tools/NamePatternMatcher.java       | 294 -------
 .../cayenne/tools/dbimport/DbImportAction.java  |  65 +-
 .../tools/dbimport/DbImportConfiguration.java   | 322 +++-----
 .../tools/dbimport/config/AntNestedElement.java |  38 +
 .../cayenne/tools/dbimport/config/Catalog.java  |  82 ++
 .../config/DefaultReverseEngineeringLoader.java | 211 +++++
 .../config/DefaultTypeMapperBuilder.java        |  82 ++
 .../tools/dbimport/config/ExcludeColumn.java    |  31 +
 .../tools/dbimport/config/ExcludeProcedure.java |  31 +
 .../tools/dbimport/config/ExcludeTable.java     |  31 +
 .../tools/dbimport/config/FilterContainer.java  | 109 +++
 .../dbimport/config/FiltersConfigBuilder.java   | 169 ++++
 .../tools/dbimport/config/IncludeColumn.java    |  31 +
 .../tools/dbimport/config/IncludeProcedure.java |  31 +
 .../tools/dbimport/config/IncludeTable.java     |  77 ++
 .../tools/dbimport/config/PatternParam.java     |  74 ++
 .../dbimport/config/ReverseEngineering.java     |  60 ++
 .../config/ReverseEngineeringLoader.java        |  31 +
 .../cayenne/tools/dbimport/config/Schema.java   |  58 ++
 .../cayenne/tools/dbimport/config/Type.java     | 136 ++++
 .../tools/dbimport/config/TypeMapper.java       |  95 +++
 .../cayenne/tools/DbImporterTaskTest.java       | 168 ++++
 .../cayenne/tools/NamePatternMatcherTest.java   |  49 +-
 .../tools/dbimport/DbImportActionTest.java      |  65 +-
 .../dbimport/DbImportConfigurationTest.java     | 193 -----
 .../DefaultReverseEngineeringLoaderTest.java    | 203 +++++
 .../config/FiltersConfigBuilderTest.java        | 153 ++++
 .../cayenne/tools/build-catalog-and-schema.xml  |  78 ++
 .../org/apache/cayenne/tools/build-catalog.xml  |  83 ++
 .../org/apache/cayenne/tools/build-flat.xml     |  75 ++
 .../org/apache/cayenne/tools/build-mapping.xml  |  44 ++
 ...ild-reverse-engineering-in-external-file.xml |  33 +
 .../org/apache/cayenne/tools/build-schema.xml   |  83 ++
 .../dbimport/build-include-table.map.xml-result |  37 +
 .../tools/dbimport/build-include-table.xml      |  35 +
 .../tools/dbimport/build-include-table.xml.sql  |  20 +
 .../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 ++
 .../modeler/action/CreateObjEntityAction.java   | 209 +++--
 .../cayenne/modeler/action/MigrateAction.java   |   2 -
 .../dialog/datamap/PackageUpdateController.java |  20 +-
 .../modeler/dialog/db/DbLoaderHelper.java       | 129 +--
 .../modeler/dialog/db/MergerOptions.java        |  61 +-
 .../dialog/objentity/ClassNameUpdater.java      |  31 +-
 .../dialog/objentity/EntitySyncController.java  |  32 +-
 .../modeler/util/NameGeneratorPreferences.java  |  14 +-
 plugins/maven-cayenne-plugin/pom.xml            |  28 +-
 .../cayenne/tools/CayenneGeneratorMojo.java     |   4 +-
 .../apache/cayenne/tools/DbImporterMojo.java    | 272 ++++---
 .../tools/DbImporterMojoConfigurationTest.java  |  56 ++
 .../cayenne/tools/DbImporterMojoTest.java       |  99 ++-
 .../org/apache/cayenne/tools/config/pom-01.xml  |  96 +++
 .../tools/config/pom-catalog-and-schema.xml     |  82 ++
 .../apache/cayenne/tools/config/pom-catalog.xml |  85 ++
 .../apache/cayenne/tools/config/pom-flat.xml    |  76 ++
 .../apache/cayenne/tools/config/pom-mapping.xml |  67 ++
 .../apache/cayenne/tools/config/pom-schema.xml  |  85 ++
 .../dbimport/testFilteringWithSchema-pom.xml    |  41 +
 .../testFilteringWithSchema.map.xml-result      |  51 ++
 .../tools/dbimport/testFilteringWithSchema.sql  |  48 ++
 .../testOldParamsSchemasAndTableExclude-pom.xml |  43 +
 ...dParamsSchemasAndTableExclude.map.xml-result |  37 +
 .../testOldParamsSchemasAndTableExclude.sql     |  48 ++
 .../dbimport/testSchemasAndTableExclude-pom.xml |  45 ++
 .../testSchemasAndTableExclude.map.xml-result   |  37 +
 .../dbimport/testSchemasAndTableExclude.sql     |  48 ++
 .../tools/dbimport/testSimpleFiltering-pom.xml  |  41 +
 .../dbimport/testSimpleFiltering.map.xml-result |  37 +
 .../tools/dbimport/testSimpleFiltering.sql      |  20 +
 plugins/pom.xml                                 |  16 +
 130 files changed, 8404 insertions(+), 2464 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/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 4f8fdee..a994ce2 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
@@ -16,7 +16,6 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
-
 package org.apache.cayenne.access;
 
 import java.sql.Connection;
@@ -28,12 +27,18 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.access.loader.DbLoaderConfiguration;
+import org.apache.cayenne.access.loader.ManyToManyCandidateEntity;
+import org.apache.cayenne.access.loader.filters.EntityFilters;
+import org.apache.cayenne.access.loader.filters.Filter;
+import org.apache.cayenne.access.loader.filters.FiltersConfig;
+import org.apache.cayenne.access.loader.filters.DbPath;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.map.DataMap;
@@ -47,66 +52,46 @@ import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.Procedure;
 import org.apache.cayenne.map.ProcedureParameter;
-import org.apache.cayenne.map.naming.LegacyNameGenerator;
+import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator;
 import org.apache.cayenne.map.naming.ExportedKey;
+import org.apache.cayenne.map.naming.LegacyNameGenerator;
+import org.apache.cayenne.map.naming.NameCheckers;
 import org.apache.cayenne.map.naming.ObjectNameGenerator;
 import org.apache.cayenne.util.EntityMergeSupport;
-import org.apache.cayenne.util.Util;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import static org.apache.cayenne.access.loader.filters.FilterFactory.*;
+
 /**
  * Utility class that does reverse engineering of the database. It can create
  * DataMaps using database meta data obtained via JDBC driver.
  */
 public class DbLoader {
 
-    private static final Log logger = LogFactory.getLog(DbLoader.class);
-
-    // TODO: remove this hardcoded stuff once delegate starts to support
-    // procedure
-    // loading...
-    private static final Collection<String> EXCLUDED_PROCEDURES = Arrays.asList("auto_pk_for_table",
-            "auto_pk_for_table;1" /*
-                                   * the last name is some Mac OS X Sybase
-                                   * artifact
-                                   */
-    );
+    private static final Log LOGGER = LogFactory.getLog(DbLoader.class);
 
     public static final String WILDCARD = "%";
 
-    /** List of db entities to process. */
-    private List<DbEntity> dbEntityList = new ArrayList<DbEntity>();
-
     /**
-     * CAY-479 - need to track which entities are skipped in the loader so that
-     * relationships to non-skipped entities can be loaded
+     * CAY-479 - need to track which entities which are skipped during loading from db since it it already present in
+     * dataMap and haven't marked for overriding so that relationships to non-skipped entities can be loaded
      */
     private Set<DbEntity> skippedEntities = new HashSet<DbEntity>();
 
-    /** Creates a unique name for loaded relationship on the given entity. */
-    private static String uniqueRelName(Entity entity, String preferredName) {
-        int currentSuffix = 1;
-        String relName = preferredName;
+    private final Connection connection;
+    private final DbAdapter adapter;
+    private final DbLoaderDelegate delegate;
 
-        while (entity.getRelationship(relName) != null || entity.getAttribute(relName) != null) {
-            relName = preferredName + currentSuffix;
-            currentSuffix++;
-        }
-        return relName;
-    }
+    private boolean creatingMeaningfulPK;
+
+    private DatabaseMetaData metaData;
 
-    protected Connection connection;
-    protected DbAdapter adapter;
-    protected DatabaseMetaData metaData;
-    protected DbLoaderDelegate delegate;
-    protected String genericClassName;
-    protected boolean creatingMeaningfulPK;
 
     /**
      * Strategy for choosing names for entities, attributes and relationships
      */
-    protected ObjectNameGenerator nameGenerator;
+    private ObjectNameGenerator nameGenerator;
 
     /**
      * Creates new DbLoader.
@@ -131,7 +116,7 @@ public class DbLoader {
     /**
      * Returns DatabaseMetaData object associated with this DbLoader.
      */
-    public DatabaseMetaData getMetaData() throws SQLException {
+    private DatabaseMetaData getMetaData() throws SQLException {
         if (metaData == null) {
             metaData = connection.getMetaData();
         }
@@ -148,7 +133,7 @@ public class DbLoader {
     /**
      * Returns true if the generator should map all primary key columns as
      * ObjAttributes.
-     * 
+     *
      * @since 3.0
      */
     public boolean isCreatingMeaningfulPK() {
@@ -165,32 +150,6 @@ public class DbLoader {
     }
 
     /**
-     * Returns a name of a generic class that should be used for all
-     * ObjEntities. The most common generic class is
-     * {@link org.apache.cayenne.CayenneDataObject}. If generic class name is
-     * null (which is the default), DbLoader will assign each entity a unique
-     * class name derived from the table name.
-     * 
-     * @since 1.2
-     */
-    public String getGenericClassName() {
-        return genericClassName;
-    }
-
-    /**
-     * Sets a name of a generic class that should be used for all ObjEntities.
-     * The most common generic class is
-     * {@link org.apache.cayenne.CayenneDataObject}. If generic class name is
-     * set to null (which is the default), DbLoader will assign each entity a
-     * unique class name derived from the table name.
-     * 
-     * @since 1.2
-     */
-    public void setGenericClassName(String genericClassName) {
-        this.genericClassName = genericClassName;
-    }
-
-    /**
      * Returns DbAdapter associated with this DbLoader.
      * 
      * @since 1.1
@@ -200,31 +159,12 @@ public class DbLoader {
     }
 
     /**
-     * A method that return true if the given table name should be included. The
-     * default implementation include all tables.
-     */
-    public boolean includeTableName(String tableName) {
-        return true;
-    }
-
-    /**
      * Retrieves catalogs for the database associated with this DbLoader.
      * 
      * @return List with the catalog names, empty Array if none found.
      */
     public List<String> getCatalogs() throws SQLException {
-        List<String> catalogs = new ArrayList<String>();
-        ResultSet rs = getMetaData().getCatalogs();
-
-        try {
-            while (rs.next()) {
-                String catalog_name = rs.getString(1);
-                catalogs.add(catalog_name);
-            }
-        } finally {
-            rs.close();
-        }
-        return catalogs;
+        return getStrings(getMetaData().getCatalogs());
     }
 
     /**
@@ -233,23 +173,26 @@ public class DbLoader {
      * @return List with the schema names, empty Array if none found.
      */
     public List<String> getSchemas() throws SQLException {
-        List<String> schemas = new ArrayList<String>();
-        ResultSet rs = getMetaData().getSchemas();
+        return getStrings(getMetaData().getSchemas());
+    }
 
+    private static List<String> getStrings(ResultSet rs) throws SQLException {
+        List<String> strings = new ArrayList<String>();
         try {
             while (rs.next()) {
-                String schema_name = rs.getString(1);
-                schemas.add(schema_name);
+                strings.add(rs.getString(1));
             }
         } finally {
             rs.close();
         }
-        return schemas;
+        return strings;
     }
 
     /**
      * Returns all the table types for the given database. Types may be such as
-     * "TABLE", "VIEW", "SYSTEM TABLE", etc.
+     * Typical types are "TABLE",
+     *                  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
+     *                  "LOCAL TEMPORARY", "ALIAS", "SYNONYM"., etc.
      * 
      * @return List of Strings, empty array if nothing found.
      */
@@ -271,32 +214,33 @@ public class DbLoader {
      * Returns all tables for given combination of the criteria. Tables returned
      * as DbEntities without any attributes or relationships.
      * 
-     * @param catalogPattern
-     *            The name of the catalog, may be null.
-     * @param schemaPattern
-     *            The pattern for schema name, use "%" for wildcard.
-     * @param tableNamePattern
-     *            The pattern for table names, % for wildcard, if null or ""
-     *            defaults to "%".
+     *
+     * @param config
+     *
      * @param types
      *            The types of table names to retrieve, null returns all types.
-     * @return List of TableInfo objects, empty array if nothing found.
+     * @return
+     * @since 3.2
      */
-    public List<DbEntity> getTables(String catalogPattern, String schemaPattern, String tableNamePattern, String[] types)
+    public List<DbEntity> getTables(DbLoaderConfiguration config, String[] types)
             throws SQLException {
 
-        if (logger.isDebugEnabled()) {
-            logger.debug("Read tables: catalog=" + catalogPattern + ", schema=" + schemaPattern + ", tableNames="
-                    + tableNamePattern);
+        List<DbEntity> tables = new LinkedList<DbEntity>();
+        FiltersConfig filters = config.getFiltersConfig();
+        for (DbPath path : filters.pathsForQueries()) {
+            tables.addAll(getDbEntities(filters, path, types));
+        }
 
-            if (types != null && types.length > 0) {
-                for (String type : types) {
-                    logger.debug("Read tables: table type=" + type);
-                }
-            }
+        return tables;
+    }
+
+    private List<DbEntity> getDbEntities(FiltersConfig filters, DbPath dbPath, String[] types) throws SQLException {
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Read tables: catalog=" + dbPath.catalog + ", schema=" + dbPath.schema + ", types="
+                    + Arrays.toString(types));
         }
 
-        ResultSet rs = getMetaData().getTables(catalogPattern, schemaPattern, tableNamePattern, types);
+        ResultSet rs = getMetaData().getTables(dbPath.catalog, dbPath.schema, WILDCARD, types);
 
         List<DbEntity> tables = new ArrayList<DbEntity>();
         try {
@@ -306,16 +250,22 @@ public class DbLoader {
                 // in errors on reverse engineering as their names have special chars like
                 // "/", etc. So skip them all together
 
-                // TODO: Andrus, 10/29/2005 - this type of filtering should be delegated to adapter
                 String name = rs.getString("TABLE_NAME");
-                if (name == null || name.startsWith("BIN$") || !includeTableName(name)) {
+                if (name == null) {
                     continue;
                 }
 
                 DbEntity table = new DetectedDbEntity(name);
-                table.setCatalog(rs.getString("TABLE_CAT"));
-                table.setSchema(rs.getString("TABLE_SCHEM"));
-                tables.add(table);
+
+                String catalog = rs.getString("TABLE_CAT");
+                table.setCatalog(catalog);
+
+                String schema = rs.getString("TABLE_SCHEM");
+                table.setSchema(schema);
+
+                if (filters.filter(new DbPath(catalog, schema)).tableFilter().isInclude(table)) {
+                    tables.add(table);
+                }
             }
         } finally {
             rs.close();
@@ -328,104 +278,46 @@ public class DbLoader {
      * 
      * @param map
      *            DataMap to be populated with DbEntities.
+     * @param config
      * @param tables
      *            The list of org.apache.cayenne.ashwood.dbutil.Table objects
-     *            for which DbEntities must be created.
-     * @return false if loading must be immediately aborted.
+     *            for which DbEntities must be created.  @return false if loading must be immediately aborted.
      */
-    public boolean loadDbEntities(DataMap map, List<? extends DbEntity> tables) throws SQLException {
-        this.dbEntityList = new ArrayList<DbEntity>();
+    public List<DbEntity> loadDbEntities(DataMap map, DbLoaderConfiguration config, Collection<? extends DbEntity> tables) throws SQLException {
+        /** List of db entities to process. */
+        List<DbEntity> dbEntityList = new ArrayList<DbEntity>();
         for (DbEntity dbEntity : tables) {
+
             // Check if there already is a DbEntity under such name
             // if so, consult the delegate what to do
             DbEntity oldEnt = map.getDbEntity(dbEntity.getName());
             if (oldEnt != null) {
                 if (delegate == null) {
-                    // no delegate, don't know what to do, cancel import
-                    break;
+                    break; // no delegate, don't know what to do, cancel import
+                    // TODO continue?
                 }
 
                 try {
                     if (delegate.overwriteDbEntity(oldEnt)) {
-                        logger.debug("Overwrite: " + oldEnt.getName());
+                        LOGGER.debug("Overwrite: " + oldEnt.getName());
                         map.removeDbEntity(oldEnt.getName(), true);
                         delegate.dbEntityRemoved(oldEnt);
                     } else {
-                        logger.debug("Keep old: " + oldEnt.getName());
+                        LOGGER.debug("Keep old: " + oldEnt.getName());
 
-                        // cay-479 - need to track entities that were not loaded
-                        // for
+                        // cay-479 - need to track entities that were not loaded for
                         // relationships exported to entities that were
                         skippedEntities.add(oldEnt);
                         continue;
                     }
                 } catch (CayenneException ex) {
-                    logger.debug("Load canceled.");
+                    LOGGER.debug("Load canceled.");
 
-                    // cancel immediately
-                    return false;
+                    return null; // cancel immediately
                 }
             }
 
-            // Create DbAttributes from column information --
-            ResultSet rs = getMetaData().getColumns(dbEntity.getCatalog(), dbEntity.getSchema(), dbEntity.getName(),
-                    "%");
-
-            try {
-                while (rs.next()) {
-                    // for a reason not quiet apparent to me, Oracle sometimes
-                    // returns duplicate record sets for the same table, messing
-                    // up table
-                    // names. E.g. for the system table "WK$_ATTR_MAPPING"
-                    // columns are
-                    // returned twice - as "WK$_ATTR_MAPPING" and
-                    // "WK$$_ATTR_MAPPING"...
-                    // Go figure
-
-                    String tableName = rs.getString("TABLE_NAME");
-                    if (!dbEntity.getName().equals(tableName)) {
-                        logger.info("Incorrectly returned columns for '" + tableName + ", skipping.");
-                        continue;
-                    }
-
-                    // gets attribute's (column's) information
-                    String columnName = rs.getString("COLUMN_NAME");
-
-                    boolean allowNulls = rs.getBoolean("NULLABLE");
-                    int columnType = rs.getInt("DATA_TYPE");
-                    int columnSize = rs.getInt("COLUMN_SIZE");
-                    String typeName = rs.getString("TYPE_NAME");
-
-                    // ignore precision of non-decimal columns
-                    int decimalDigits = -1;
-                    if (TypesMapping.isDecimal(columnType)) {
-                        decimalDigits = rs.getInt("DECIMAL_DIGITS");
-                        if (rs.wasNull()) {
-                            decimalDigits = -1;
-                        }
-                    }
-
-                    // create attribute delegating this task to adapter
-                    DbAttribute attr = adapter.buildAttribute(columnName, typeName, columnType, columnSize,
-                            decimalDigits, allowNulls);
-
-                    if (adapter.supportsGeneratedKeys()) {
-
-                        // TODO: this actually throws on some drivers... need to
-                        // ensure that 'supportsGeneratedKeys' check is enough
-                        // to prevent an exception here.
-                        String autoIncrement = rs.getString("IS_AUTOINCREMENT");
-                        if ("YES".equals(autoIncrement)) {
-                            attr.setGenerated(true);
-                        }
-                    }
 
-                    attr.setEntity(dbEntity);
-                    dbEntity.addAttribute(attr);
-                }
-            } finally {
-                rs.close();
-            }
 
             map.addDbEntity(dbEntity);
 
@@ -433,108 +325,163 @@ public class DbLoader {
             if (delegate != null) {
                 delegate.dbEntityAdded(dbEntity);
             }
+            loadDbAttributes(config.getFiltersConfig(), dbEntity);
 
-            // delegate might have thrown this entity out... so check if it is
-            // still
+            // delegate might have thrown this entity out... so check if it is still
             // around before continuing processing
             if (map.getDbEntity(dbEntity.getName()) == dbEntity) {
-                this.dbEntityList.add(dbEntity);
+                dbEntityList.add(dbEntity);
             }
         }
 
         // get primary keys for each table and store it in dbEntity
+        getPrimaryKeysForEachTableAndStoreItInDbEntity(map, tables);
+
+        // cay-479 - iterate skipped DbEntities to populate exported keys
+        for (DbEntity skippedEntity : skippedEntities) {
+            loadDbRelationships(map, skippedEntity, config);
+        }
+
+        return dbEntityList;
+
+    }
+
+    private void getPrimaryKeysForEachTableAndStoreItInDbEntity(DataMap map, Collection<? extends DbEntity> tables)
+            throws SQLException {
+
         for (DbEntity dbEntity : map.getDbEntities()) {
-            if (tables.contains(dbEntity)) {
-                String tableName = dbEntity.getName();
-                ResultSet rs = metaData.getPrimaryKeys(dbEntity.getCatalog(), dbEntity.getSchema(), tableName);
-                try {
-                    while (rs.next()) {
-                        String columnName = rs.getString(4);
-                        DbAttribute attribute = dbEntity.getAttribute(columnName);
-
-                        if (attribute != null) {
-                            attribute.setPrimaryKey(true);
-                        } else {
-                            // why an attribute might be null is not quiet clear
-                            // but there is a bug report 731406 indicating that
-                            // it is
-                            // possible
-                            // so just print the warning, and ignore
-                            logger.warn("Can't locate attribute for primary key: " + columnName);
-                        }
-
-                        String pkName = rs.getString(6);
-                        if ((pkName != null) && (dbEntity instanceof DetectedDbEntity)) {
-                            ((DetectedDbEntity) dbEntity).setPrimaryKeyName(pkName);
-                        }
+            if (!tables.contains(dbEntity)) { // TODO is it ok? equals is not overridden
+                continue;
+            }
+
+            ResultSet rs = getMetaData().getPrimaryKeys(dbEntity.getCatalog(), dbEntity.getSchema(), dbEntity.getName());
+            try {
+                while (rs.next()) {
+                    String columnName = rs.getString(4); // COLUMN_NAME
+                    DbAttribute attribute = dbEntity.getAttribute(columnName);
+
+                    if (attribute != null) {
+                        attribute.setPrimaryKey(true);
+                    } else {
+                        // why an attribute might be null is not quiet clear
+                        // but there is a bug report 731406 indicating that it is possible
+                        // so just print the warning, and ignore
+                        LOGGER.warn("Can't locate attribute for primary key: " + columnName);
+                    }
+
+                    String pkName = rs.getString(6); // PK_NAME
+                    if (pkName != null && dbEntity instanceof DetectedDbEntity) {
+                        ((DetectedDbEntity) dbEntity).setPrimaryKeyName(pkName);
                     }
-                } finally {
-                    rs.close();
                 }
+            } finally {
+                rs.close();
             }
         }
+    }
 
-        // cay-479 - iterate skipped DbEntities to populate exported keys
-        for (DbEntity skippedEntity : skippedEntities) {
-            loadDbRelationships(skippedEntity, map);
+    private void loadDbAttributes(FiltersConfig filters, DbEntity dbEntity) throws SQLException {
+        ResultSet rs = getMetaData().getColumns(dbEntity.getCatalog(), dbEntity.getSchema(), dbEntity.getName(), "%");
+
+        try {
+            while (rs.next()) {
+                // for a reason not quiet apparent to me, Oracle sometimes
+                // returns duplicate record sets for the same table, messing up table
+                // names. E.g. for the system table "WK$_ATTR_MAPPING" columns are
+                // returned twice - as "WK$_ATTR_MAPPING" and "WK$$_ATTR_MAPPING"... Go figure
+
+                String tableName = rs.getString("TABLE_NAME");
+                if (!dbEntity.getName().equals(tableName)) {
+                    LOGGER.info("Incorrectly returned columns for '" + tableName + ", skipping.");
+                    continue;
+                }
+
+                DbAttribute attr = loadDbAttribute(rs);
+                attr.setEntity(dbEntity);
+                if (!filters.filter(new DbPath(dbEntity.getCatalog(), dbEntity.getSchema(), tableName))
+                        .columnFilter().isInclude(attr)) {
+
+                    continue;
+                }
+
+
+                dbEntity.addAttribute(attr);
+            }
+        } finally {
+            rs.close();
         }
+    }
+
+    private DbAttribute loadDbAttribute(ResultSet rs) throws SQLException {
+        // gets attribute's (column's) information
+        int columnType = rs.getInt("DATA_TYPE");
+
+        // ignore precision of non-decimal columns
+        int decimalDigits = -1;
+        if (TypesMapping.isDecimal(columnType)) {
+            decimalDigits = rs.getInt("DECIMAL_DIGITS");
+            if (rs.wasNull()) {
+                decimalDigits = -1;
+            }
+        }
+
+        // create attribute delegating this task to adapter
+        DbAttribute attr = adapter.buildAttribute(
+                rs.getString("COLUMN_NAME"),
+                rs.getString("TYPE_NAME"),
+                columnType,
+                rs.getInt("COLUMN_SIZE"),
+                decimalDigits,
+                rs.getBoolean("NULLABLE"));
 
-        return true;
+        if (adapter.supportsGeneratedKeys()) {
 
+            // TODO: this actually throws on some drivers... need to
+            // ensure that 'supportsGeneratedKeys' check is enough
+            // to prevent an exception here.
+            String autoIncrement = rs.getString("IS_AUTOINCREMENT");
+            if ("YES".equals(autoIncrement)) {
+                attr.setGenerated(true);
+            }
+        }
+        return attr;
     }
 
     /**
      * Creates an ObjEntity for each DbEntity in the map. ObjEntities are
      * created empty without
      */
-    public void loadObjEntities(DataMap map) {
-
-        Iterator<DbEntity> dbEntities = dbEntityList.iterator();
-        if (!dbEntities.hasNext()) {
+    protected void loadObjEntities(DataMap map, DbLoaderConfiguration config, Collection<DbEntity> entities) {
+        if (entities.isEmpty()) {
             return;
         }
 
-        List<ObjEntity> loadedEntities = new ArrayList<ObjEntity>(dbEntityList.size());
+        Collection<ObjEntity> loadedEntities = new ArrayList<ObjEntity>(entities.size());
 
-        String packageName = map.getDefaultPackage();
-        if (Util.isEmptyString(packageName)) {
-            packageName = "";
-        } else if (!packageName.endsWith(".")) {
-            packageName = packageName + ".";
-        }
-
-        // load empty ObjEntities for all the tables
-        while (dbEntities.hasNext()) {
-            DbEntity dbEntity = dbEntities.next();
+        // doLoad empty ObjEntities for all the tables
+        for (DbEntity dbEntity : entities) {
 
             // check if there are existing entities
             Collection<ObjEntity> existing = map.getMappedEntities(dbEntity);
-            if (existing.size() > 0) {
+            if (!existing.isEmpty()) {
                 loadedEntities.addAll(existing);
                 continue;
             }
 
-            String objEntityName = nameGenerator.createObjEntityName(dbEntity);
-            // this loop will terminate even if no valid name is found
-            // to prevent loader from looping forever (though such case is very
-            // unlikely)
-            String baseName = objEntityName;
-            for (int i = 1; i < 1000 && map.getObjEntity(objEntityName) != null; i++) {
-                objEntityName = baseName + i;
-            }
+            String objEntityName = DefaultUniqueNameGenerator.generate(NameCheckers.objEntity, map,
+                    nameGenerator.createObjEntityName(dbEntity));
 
             ObjEntity objEntity = new ObjEntity(objEntityName);
             objEntity.setDbEntity(dbEntity);
+            objEntity.setClassName(config.getGenericClassName() != null ? config.getGenericClassName()
+                    : map.getNameWithDefaultPackage(objEntity.getName()));
 
-            objEntity.setClassName(getGenericClassName() != null ? getGenericClassName() : packageName
-                    + objEntity.getName());
             map.addObjEntity(objEntity);
             loadedEntities.add(objEntity);
         }
 
         // update ObjEntity attributes and relationships
-        EntityMergeSupport objEntityMerger = createEntityMerger(map);
-        objEntityMerger.synchronizeWithDbEntities(loadedEntities);
+        createEntityMerger(map).synchronizeWithDbEntities(loadedEntities);
     }
 
     /**
@@ -545,24 +492,23 @@ public class DbLoader {
     }
 
     /** Loads database relationships into a DataMap. */
-    public void loadDbRelationships(DataMap map) throws SQLException {
-        for (DbEntity pkEntity : dbEntityList) {
-            loadDbRelationships(pkEntity, map);
+    protected void loadDbRelationships(DataMap map, DbLoaderConfiguration config, Iterable<DbEntity> entities) throws SQLException {
+        for (DbEntity pkEntity : entities) {
+            loadDbRelationships(map, pkEntity, config);
         }
     }
 
-    private void loadDbRelationships(DbEntity pkEntity, DataMap map) throws SQLException {
-        DatabaseMetaData md = getMetaData();
-        String pkEntName = pkEntity.getName();
+    protected void loadDbRelationships(DataMap map, DbEntity entity, DbLoaderConfiguration config) throws SQLException {
+        String pkEntName = entity.getName();
 
         // Get all the foreign keys referencing this table
-        ResultSet rs = null;
+        ResultSet rs;
 
         try {
-            rs = md.getExportedKeys(pkEntity.getCatalog(), pkEntity.getSchema(), pkEntity.getName());
+            rs = getMetaData().getExportedKeys(entity.getCatalog(), entity.getSchema(), entity.getName());
         } catch (SQLException cay182Ex) {
             // Sybase-specific - the line above blows on VIEWS, see CAY-182.
-            logger.info("Error getting relationships for '" + pkEntName + "', ignoring.");
+            LOGGER.info("Error getting relationships for '" + pkEntName + "', ignoring.");
             return;
         }
 
@@ -571,24 +517,21 @@ public class DbLoader {
                 return;
             }
 
-            // these will be initailzed every time a new target entity
-            // is found in the result set (which should be ordered by table name
-            // among
-            // other things)
+            // these will be initialized every time a new target entity is found
+            // in the result set (which should be ordered by table name among other things)
             DbRelationship forwardRelationship = null;
             DbRelationshipDetected reverseRelationship = null;
             DbEntity fkEntity = null;
-            ExportedKey key = null;
+            ExportedKey key;
 
             do {
-                // extract data from resultset
                 key = ExportedKey.extractData(rs);
 
                 short keySeq = rs.getShort("KEY_SEQ");
                 if (keySeq == 1) {
 
                     if (forwardRelationship != null) {
-                        postprocessMasterDbRelationship(forwardRelationship, key);
+                        postProcessMasterDbRelationship(forwardRelationship, key);
                         forwardRelationship = null;
                     }
 
@@ -596,33 +539,35 @@ public class DbLoader {
                     String fkEntityName = key.getFKTableName();
                     String fkName = key.getFKName();
 
-                    if (!includeTableName(fkEntityName)) {
+                    fkEntity = map.getDbEntity(fkEntityName);
+                    DbPath path = new DbPath(entity.getCatalog(), entity.getSchema(), entity.getName());
+                    if (!config.getFiltersConfig().filter(path).tableFilter().isInclude(fkEntity)) {
                         continue;
                     }
 
-                    fkEntity = map.getDbEntity(fkEntityName);
-
                     if (fkEntity == null) {
-                        logger.info("FK warning: no entity found for name '" + fkEntityName + "'");
-                    } else if (skippedEntities.contains(pkEntity) && skippedEntities.contains(fkEntity)) {
-                        // cay-479 - don't load relationships between two
-                        // skipped entities.
+                        LOGGER.info("FK warning: no entity found for name '" + fkEntityName + "'");
+                    } else if (skippedEntities.contains(entity) && skippedEntities.contains(fkEntity)) {
+                        // cay-479 - don't doLoad relationships between two skipped entities.
                         continue;
                     } else {
                         // init relationship
                         String forwardPreferredName = nameGenerator.createDbRelationshipName(key, true);
-                        forwardRelationship = new DbRelationship(uniqueRelName(pkEntity, forwardPreferredName));
+                        forwardRelationship = new DbRelationship(DefaultUniqueNameGenerator
+                                .generate(NameCheckers.dbRelationship, entity, forwardPreferredName));
 
-                        forwardRelationship.setSourceEntity(pkEntity);
+                        forwardRelationship.setSourceEntity(entity);
                         forwardRelationship.setTargetEntity(fkEntity);
-                        pkEntity.addRelationship(forwardRelationship);
+                        entity.addRelationship(forwardRelationship);
 
                         String reversePreferredName = nameGenerator.createDbRelationshipName(key, false);
-                        reverseRelationship = new DbRelationshipDetected(uniqueRelName(fkEntity, reversePreferredName));
+                        reverseRelationship = new DbRelationshipDetected(DefaultUniqueNameGenerator
+                                .generate(NameCheckers.dbRelationship, fkEntity, reversePreferredName));
+
                         reverseRelationship.setFkName(fkName);
                         reverseRelationship.setToMany(false);
                         reverseRelationship.setSourceEntity(fkEntity);
-                        reverseRelationship.setTargetEntity(pkEntity);
+                        reverseRelationship.setTargetEntity(entity);
                         fkEntity.addRelationship(reverseRelationship);
                     }
                 }
@@ -633,15 +578,15 @@ public class DbLoader {
                     String fkName = key.getFKColumnName();
 
                     // skip invalid joins...
-                    DbAttribute pkAtt = pkEntity.getAttribute(pkName);
+                    DbAttribute pkAtt = entity.getAttribute(pkName);
                     if (pkAtt == null) {
-                        logger.info("no attribute for declared primary key: " + pkName);
+                        LOGGER.info("no attribute for declared primary key: " + pkName);
                         continue;
                     }
 
                     DbAttribute fkAtt = fkEntity.getAttribute(fkName);
                     if (fkAtt == null) {
-                        logger.info("no attribute for declared foreign key: " + fkName);
+                        LOGGER.info("no attribute for declared foreign key: " + fkName);
                         continue;
                     }
 
@@ -656,7 +601,7 @@ public class DbLoader {
             } while (rs.next());
 
             if (forwardRelationship != null) {
-                postprocessMasterDbRelationship(forwardRelationship, key);
+                postProcessMasterDbRelationship(forwardRelationship, key);
                 forwardRelationship = null;
             }
 
@@ -669,7 +614,7 @@ public class DbLoader {
      * Detects correct relationship multiplicity and "to dep pk" flag. Only
      * called on relationships from PK to FK, not the reverse ones.
      */
-    protected void postprocessMasterDbRelationship(DbRelationship relationship, ExportedKey key) {
+    protected void postProcessMasterDbRelationship(DbRelationship relationship, ExportedKey key) {
         boolean toPK = true;
         List<DbJoin> joins = relationship.getJoins();
 
@@ -681,33 +626,25 @@ public class DbLoader {
 
         }
 
-        boolean toDependentPK = false;
-        boolean toMany = true;
-
-        if (toPK) {
-            toDependentPK = true;
-            if (relationship.getTargetEntity().getPrimaryKeys().size() == joins.size()) {
-                toMany = false;
-            }
-        }
+        relationship.setToDependentPK(toPK);
+        relationship.setToMany(!(toPK && relationship.getTargetEntity().getPrimaryKeys().size() == joins.size()));
 
         // if this is really to-one we need to rename the relationship
-        if (!toMany) {
+        if (!relationship.isToMany()) {
             Entity source = relationship.getSourceEntity();
             source.removeRelationship(relationship.getName());
-            relationship.setName(DbLoader.uniqueRelName(source, nameGenerator.createDbRelationshipName(key, false)));
+            relationship.setName(DefaultUniqueNameGenerator.generate(NameCheckers.dbRelationship, source,
+                    nameGenerator.createDbRelationshipName(key, false)));
+
             source.addRelationship(relationship);
         }
-
-        relationship.setToDependentPK(toDependentPK);
-        relationship.setToMany(toMany);
     }
 
     /**
      * Flattens many-to-many relationships in the generated model.
      */
     private void flattenManyToManyRelationships(DataMap map) {
-        List<ObjEntity> entitiesForDelete = new ArrayList<ObjEntity>();
+        Collection<ObjEntity> entitiesForDelete = new LinkedList<ObjEntity>();
 
         for (ObjEntity curEntity : map.getObjEntities()) {
             ManyToManyCandidateEntity entity = ManyToManyCandidateEntity.build(curEntity);
@@ -734,24 +671,26 @@ public class DbLoader {
     }
 
     /**
+     * By default we want to load Tables and Views for mo types
+     *
+     * @see DbLoader#getTableTypes()
+     *
      * @since 3.2
      */
     public String[] getDefaultTableTypes() {
-        String viewType = adapter.tableTypeForView();
-        String tableType = adapter.tableTypeForTable();
-
-        // use types that are not null
         List<String> list = new ArrayList<String>(2);
+
+        String viewType = adapter.tableTypeForView();
         if (viewType != null) {
             list.add(viewType);
         }
+
+        String tableType = adapter.tableTypeForTable();
         if (tableType != null) {
             list.add(tableType);
         }
 
-        String[] types = new String[list.size()];
-        list.toArray(types);
-        return types;
+        return list.toArray(new String[list.size()]);
     }
 
     /**
@@ -761,7 +700,7 @@ public class DbLoader {
      * 
      * @since 1.0.7
      * @deprecated since 3.2 use
-     *             {@link #load(DataMap, String, String, String, String...)}
+     *             {@link #load(org.apache.cayenne.map.DataMap, DbLoaderConfiguration, String...)}
      *             method that supports catalogs.
      */
     @Deprecated
@@ -772,7 +711,10 @@ public class DbLoader {
             throw new SQLException("No supported table types found.");
         }
 
-        load(dataMap, null, schemaPattern, tablePattern, types);
+        DbLoaderConfiguration configuration = new DbLoaderConfiguration();
+        configuration.setFiltersConfig(new FiltersConfig(new EntityFilters(
+                new DbPath(null, schemaPattern), include(tablePattern), TRUE, NULL)));
+        load(dataMap, configuration, types);
         return dataMap;
     }
 
@@ -782,7 +724,7 @@ public class DbLoader {
      * of tables to read.
      * 
      * @deprecated since 3.2 use
-     *             {@link #load(DataMap, String, String, String, String...)}
+     *             {@link #load(org.apache.cayenne.map.DataMap, DbLoaderConfiguration, String...)}
      *             method that supports catalogs.
      */
     @Deprecated
@@ -790,10 +732,24 @@ public class DbLoader {
             throws SQLException {
         dataMap.clear();
 
-        load(dataMap, null, schemaPattern, tablePattern, tableTypes);
+        DbLoaderConfiguration config = new DbLoaderConfiguration();
+        config.setFiltersConfig(new FiltersConfig(new EntityFilters(
+                new DbPath(null, schemaPattern), transformPatternToFilter(tablePattern), TRUE, NULL)));
+
+        load(dataMap, config, tableTypes);
         return dataMap;
     }
 
+    private Filter<String> transformPatternToFilter(String tablePattern) {
+        Filter<String> table;
+        if (tablePattern == null) {
+            table = NULL;
+        } else {
+            table = include(tablePattern.replaceAll("%", ".*"));
+        }
+        return table;
+    }
+
     /**
      * Performs database reverse engineering to match the specified catalog,
      * schema, table name and table type patterns and fills the specified
@@ -801,25 +757,38 @@ public class DbLoader {
      * 
      * @since 3.2
      */
-    public void load(DataMap dataMap, String catalogPattern, String schemaPattern, String tablePattern,
-            String... tableTypes) throws SQLException {
-
-        if (tablePattern == null) {
-            tablePattern = WILDCARD;
-        }
+    public void load(DataMap dataMap, DbLoaderConfiguration config, String... tableTypes) throws SQLException {
 
-        List<DbEntity> tables = getTables(catalogPattern, schemaPattern, tablePattern, tableTypes);
+        List<DbEntity> entities = loadDbEntities(dataMap, config, getTables(config, tableTypes));
 
-        if (loadDbEntities(dataMap, tables)) {
-            loadDbRelationships(dataMap);
+        if (entities != null) {
+            loadDbRelationships(dataMap, config, entities);
+            loadObjEntities(dataMap, config, entities);
 
-            loadObjEntities(dataMap);
             flattenManyToManyRelationships(dataMap);
             fireObjEntitiesAddedEvents(dataMap);
         }
     }
 
     /**
+     * Performs database reverse engineering to match the specified catalog,
+     * schema, table name and table type patterns and fills the specified
+     * DataMap object with DB and object mapping info.
+     *
+     * @since 3.2
+     */
+    public DataMap load(DbLoaderConfiguration config) throws SQLException {
+
+        DataMap dataMap = new DataMap();
+        String[] tableTypes = config.getTableTypes() == null ? this.getDefaultTableTypes() : config.getTableTypes();
+
+        load(dataMap, config, tableTypes);
+        loadProcedures(dataMap, config);
+
+        return dataMap;
+    }
+
+    /**
      * Loads database stored procedures into the DataMap.
      * <p>
      * <i>As of 1.1 there is no boolean property or delegate method to make
@@ -830,11 +799,16 @@ public class DbLoader {
      * 
      * @since 1.1
      * @deprecated since 3.2 use
-     *             {@link #loadProcedures(DataMap, String, String, String)} that
+     *             {@link #loadProcedures(org.apache.cayenne.map.DataMap, org.apache.cayenne.access.loader.DbLoaderConfiguration)} that
      *             supports "catalog" pattern.
      */
+    @Deprecated
     public void loadProceduresFromDB(String schemaPattern, String namePattern, DataMap dataMap) throws SQLException {
-        loadProcedures(dataMap, null, schemaPattern, namePattern);
+        DbLoaderConfiguration configuration = new DbLoaderConfiguration();
+        configuration.setFiltersConfig(new FiltersConfig(new EntityFilters(
+                new DbPath(null, schemaPattern), NULL, NULL, include(namePattern))));
+
+        loadProcedures(dataMap, configuration);
     }
 
     /**
@@ -848,103 +822,56 @@ public class DbLoader {
      * 
      * @since 3.2
      */
-    public void loadProcedures(DataMap dataMap, String catalogPattern, String schemaPattern, String namePattern)
+    public Map<String, Procedure> loadProcedures(DataMap dataMap, DbLoaderConfiguration config)
             throws SQLException {
 
-        Map<String, Procedure> procedures = null;
-
-        // get procedures
-        ResultSet rs = getMetaData().getProcedures(catalogPattern, schemaPattern, namePattern);
-        try {
-            while (rs.next()) {
-                String name = rs.getString("PROCEDURE_NAME");
-
-                // TODO: this will be moved to Delegate...
-                if (EXCLUDED_PROCEDURES.contains(name)) {
-                    logger.info("skipping Cayenne PK procedure: " + name);
-                    continue;
-                }
-
-                String catalog = rs.getString("PROCEDURE_CAT");
-                String schema = rs.getString("PROCEDURE_SCHEM");
-
-                short type = rs.getShort("PROCEDURE_TYPE");
-
-                Procedure procedure = new Procedure(name);
-                procedure.setCatalog(catalog);
-                procedure.setSchema(schema);
-
-                switch (type) {
-                case DatabaseMetaData.procedureNoResult:
-                case DatabaseMetaData.procedureResultUnknown:
-                    procedure.setReturningValue(false);
-                    break;
-                case DatabaseMetaData.procedureReturnsResult:
-                    procedure.setReturningValue(true);
-                    break;
-                }
+        Map<String, Procedure> procedures = loadProcedures(config);
+        if (procedures.isEmpty()) {
+            return procedures;
+        }
 
-                if (procedures == null) {
-                    procedures = new HashMap<String, Procedure>();
-                }
+        loadProceduresColumns(procedures);
 
-                procedures.put(procedure.getFullyQualifiedName(), procedure);
-            }
-        } finally {
-            rs.close();
+        for (Procedure procedure : procedures.values()) {
+            dataMap.addProcedure(procedure);
         }
 
-        // if nothing found, return
-        if (procedures == null) {
-            return;
-        }
+        return procedures;
+    }
 
-        // get columns
-        ResultSet columnsRS = getMetaData().getProcedureColumns(null, schemaPattern, namePattern, null);
+    private void loadProceduresColumns(Map<String, Procedure> procedures) throws SQLException {
+        ResultSet columnsRS = getMetaData().getProcedureColumns(null, null, null, null); // TODO catalog, schema
         try {
             while (columnsRS.next()) {
 
                 String schema = columnsRS.getString("PROCEDURE_SCHEM");
                 String name = columnsRS.getString("PROCEDURE_NAME");
-
-                // TODO: this will be moved to Delegate...
-                if (EXCLUDED_PROCEDURES.contains(name)) {
+                String key = (schema == null ? "" : schema + '.') + name ;
+                Procedure procedure = procedures.get(key);
+                if (procedure == null) {
                     continue;
                 }
 
                 String columnName = columnsRS.getString("COLUMN_NAME");
-                short type = columnsRS.getShort("COLUMN_TYPE");
 
-                String key = (schema != null) ? schema + '.' + name : name;
-
-                // skip ResultSet columns, as they are not described in Cayenne
-                // procedures
-                // yet...
+                // skip ResultSet columns, as they are not described in Cayenne procedures yet...
+                short type = columnsRS.getShort("COLUMN_TYPE");
                 if (type == DatabaseMetaData.procedureColumnResult) {
-                    logger.debug("skipping ResultSet column: " + key + "." + columnName);
+                    LOGGER.debug("skipping ResultSet column: " + key + "." + columnName);
                 }
 
-                Procedure procedure = procedures.get(key);
-
-                if (procedure == null) {
-                    logger.info("invalid procedure column, no procedure found: " + key + "." + columnName);
-                    continue;
-                }
-
-                ProcedureParameter column = new ProcedureParameter(columnName);
-
                 if (columnName == null) {
                     if (type == DatabaseMetaData.procedureColumnReturn) {
-                        logger.debug("null column name, assuming result column: " + key);
-                        column.setName("_return_value");
+                        LOGGER.debug("null column name, assuming result column: " + key);
+                        columnName = "_return_value";
+                        procedure.setReturningValue(true);
                     } else {
-                        logger.info("invalid null column name, skipping column : " + key);
+                        LOGGER.info("invalid null column name, skipping column : " + key);
                         continue;
                     }
                 }
 
                 int columnType = columnsRS.getInt("DATA_TYPE");
-                int columnSize = columnsRS.getInt("LENGTH");
 
                 // ignore precision of non-decimal columns
                 int decimalDigits = -1;
@@ -955,35 +882,86 @@ public class DbLoader {
                     }
                 }
 
-                switch (type) {
-                case DatabaseMetaData.procedureColumnIn:
-                    column.setDirection(ProcedureParameter.IN_PARAMETER);
-                    break;
-                case DatabaseMetaData.procedureColumnInOut:
-                    column.setDirection(ProcedureParameter.IN_OUT_PARAMETER);
-                    break;
-                case DatabaseMetaData.procedureColumnOut:
-                    column.setDirection(ProcedureParameter.OUT_PARAMETER);
-                    break;
-                case DatabaseMetaData.procedureColumnReturn:
-                    procedure.setReturningValue(true);
-                    break;
+                ProcedureParameter column = new ProcedureParameter(columnName);
+                int direction = getDirection(type);
+                if (direction != -1) {
+                    column.setDirection(direction);
                 }
 
-                column.setMaxLength(columnSize);
+                column.setType(columnType);
+                column.setMaxLength(columnsRS.getInt("LENGTH"));
                 column.setPrecision(decimalDigits);
+
                 column.setProcedure(procedure);
-                column.setType(columnType);
                 procedure.addCallParameter(column);
             }
         } finally {
             columnsRS.close();
         }
+    }
 
-        for (final Procedure procedure : procedures.values()) {
-            // overwrite existing procedures...
-            dataMap.addProcedure(procedure);
+    private static int getDirection(short type) {
+        switch (type) {
+            case DatabaseMetaData.procedureColumnIn:
+                return ProcedureParameter.IN_PARAMETER;
+            case DatabaseMetaData.procedureColumnInOut:
+                return ProcedureParameter.IN_OUT_PARAMETER;
+            case DatabaseMetaData.procedureColumnOut:
+                return ProcedureParameter.OUT_PARAMETER;
+            default:
+                return -1;
+        }
+    }
+
+    private Map<String, Procedure> loadProcedures(DbLoaderConfiguration config) throws SQLException {
+        Map<String, Procedure> procedures = new HashMap<String, Procedure>();
+
+        FiltersConfig filters = config.getFiltersConfig();
+        for (DbPath dbPath : filters.pathsForQueries()) {
+            if (filters.filter(dbPath).procedureFilter().equals(NULL)) {
+                continue;
+            }
+
+            procedures.putAll(loadProcedures(filters, dbPath));
+        }
+
+        return procedures;
+    }
+
+    private Map<String, Procedure> loadProcedures(FiltersConfig filters, DbPath dbPath) throws SQLException {
+        Map<String, Procedure> procedures = new HashMap<String, Procedure>();
+        // get procedures
+        ResultSet rs = getMetaData().getProcedures(dbPath.catalog, dbPath.schema, WILDCARD);
+        try {
+            while (rs.next()) {
+
+                String name = rs.getString("PROCEDURE_NAME");
+                Procedure procedure = new Procedure(name);
+                procedure.setCatalog(rs.getString("PROCEDURE_CAT"));
+                procedure.setSchema(rs.getString("PROCEDURE_SCHEM"));
+
+                if (filters.filter(new DbPath(procedure.getCatalog(), procedure.getSchema()))
+                                .procedureFilter().isInclude(procedure)) {
+                    LOGGER.info("skipping Cayenne PK procedure: " + name);
+                    continue;
+                }
+
+                switch (rs.getShort("PROCEDURE_TYPE")) {
+                    case DatabaseMetaData.procedureNoResult:
+                    case DatabaseMetaData.procedureResultUnknown:
+                        procedure.setReturningValue(false);
+                        break;
+                    case DatabaseMetaData.procedureReturnsResult:
+                        procedure.setReturningValue(true);
+                        break;
+                }
+
+                procedures.put(procedure.getFullyQualifiedName(), procedure);
+            }
+        } finally {
+            rs.close();
         }
+        return procedures;
     }
 
     /**
@@ -992,7 +970,6 @@ public class DbLoader {
      * @since 3.0
      */
     public void setNameGenerator(ObjectNameGenerator strategy) {
-        // null values are not allowed
         if (strategy == null) {
             throw new NullPointerException("Null strategy not allowed");
         }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoaderConfiguration.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoaderConfiguration.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoaderConfiguration.java
deleted file mode 100644
index 9d56964..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoaderConfiguration.java
+++ /dev/null
@@ -1,48 +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.access;
-
-/**
- * @since 3.2.
- */
-public class DbLoaderConfiguration {
-
-    private String catalog;
-
-    private String schema;
-
-
-    public String getCatalog() {
-        return catalog;
-    }
-
-    public void setCatalog(String catalog) {
-        this.catalog = catalog;
-    }
-
-    public String getSchema() {
-        return schema;
-    }
-
-    public void setSchema(String schema) {
-        this.schema = schema;
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/DefaultDbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DefaultDbLoaderDelegate.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DefaultDbLoaderDelegate.java
deleted file mode 100644
index 08e229e..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DefaultDbLoaderDelegate.java
+++ /dev/null
@@ -1,54 +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.access;
-
-import org.apache.cayenne.CayenneException;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.ObjEntity;
-
-/**
- * @since 3.2.
- */
-public class DefaultDbLoaderDelegate implements DbLoaderDelegate {
-
-    @Override
-    public boolean overwriteDbEntity(DbEntity entity) throws CayenneException {
-        return false;
-    }
-
-    @Override
-    public void dbEntityAdded(DbEntity entity) {
-
-    }
-
-    @Override
-    public void dbEntityRemoved(DbEntity entity) {
-
-    }
-
-    @Override
-    public void objEntityAdded(ObjEntity entity) {
-
-    }
-
-    @Override
-    public void objEntityRemoved(ObjEntity entity) {
-
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/ManyToManyCandidateEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/ManyToManyCandidateEntity.java b/cayenne-server/src/main/java/org/apache/cayenne/access/ManyToManyCandidateEntity.java
deleted file mode 100644
index 4f68344..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/ManyToManyCandidateEntity.java
+++ /dev/null
@@ -1,126 +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.access;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator;
-import org.apache.cayenne.map.naming.ExportedKey;
-import org.apache.cayenne.map.naming.NameCheckers;
-import org.apache.cayenne.map.naming.ObjectNameGenerator;
-
-/**
- * Class represent ObjEntity that may be optimized using flattened relationships
- * as many to many table
- */
-class ManyToManyCandidateEntity {
-    private final ObjEntity joinEntity;
-
-    private final DbRelationship dbRel1;
-    private final DbRelationship dbRel2;
-
-    private final ObjEntity entity1;
-    private final ObjEntity entity2;
-
-    private final DbRelationship reverseRelationship1;
-    private final DbRelationship reverseRelationship2;
-
-    private ManyToManyCandidateEntity(ObjEntity entityValue, List<ObjRelationship> relationships) {
-        joinEntity = entityValue;
-
-        ObjRelationship rel1 = relationships.get(0);
-        ObjRelationship rel2 = relationships.get(1);
-
-        dbRel1 = rel1.getDbRelationships().get(0);
-        dbRel2 = rel2.getDbRelationships().get(0);
-
-        reverseRelationship1 = dbRel1.getReverseRelationship();
-        reverseRelationship2 = dbRel2.getReverseRelationship();
-
-        entity1 = rel1.getTargetEntity();
-        entity2 = rel2.getTargetEntity();
-    }
-
-    /**
-     * Method check - if current entity represent many to many temporary table
-     * @return true if current entity is represent many to many table; otherwise returns false
-     */
-    public static ManyToManyCandidateEntity build(ObjEntity joinEntity) {
-        ArrayList<ObjRelationship> relationships = new ArrayList<ObjRelationship>(joinEntity.getRelationships());
-        if (relationships.size() != 2) {
-            return null;
-        }
-
-        ManyToManyCandidateEntity candidateEntity = new ManyToManyCandidateEntity(joinEntity, relationships);
-        if (candidateEntity.isManyToMany()) {
-            return candidateEntity;
-        }
-
-        return null;
-    }
-
-    private boolean isManyToMany() {
-        boolean isNotHaveAttributes = joinEntity.getAttributes().size() == 0;
-
-        return isNotHaveAttributes && reverseRelationship1.isToDependentPK() && reverseRelationship2.isToDependentPK()
-                && !entity1.equals(entity2);
-    }
-
-    private void addFlattenedRelationship(ObjectNameGenerator nameGenerator, ObjEntity srcEntity, ObjEntity dstEntity,
-                                          DbRelationship rel1, DbRelationship rel2) {
-
-        ExportedKey key = new ExportedKey(rel1.getSourceEntity().getName(),
-                rel1.getSourceAttributes().iterator().next().getName(),
-                null,
-                rel2.getTargetEntity().getName(),
-                rel2.getTargetAttributes().iterator().next().getName(),
-                null);
-
-        ObjRelationship newRelationship = new ObjRelationship();
-        newRelationship.setName(DefaultUniqueNameGenerator.generate(NameCheckers.objRelationship, srcEntity,
-                nameGenerator.createDbRelationshipName(key, true)));
-
-        newRelationship.setSourceEntity(srcEntity);
-        newRelationship.setTargetEntity(dstEntity);
-
-        newRelationship.addDbRelationship(rel1);
-        newRelationship.addDbRelationship(rel2);
-
-        srcEntity.addRelationship(newRelationship);
-    }
-
-    /**
-     * Method make direct relationships between 2 entities and remove relationships to
-     * many to many entity
-     *
-     * @param nameGenerator
-     */
-    public void optimizeRelationships(ObjectNameGenerator nameGenerator) {
-        entity1.removeRelationship(reverseRelationship1.getName());
-        entity2.removeRelationship(reverseRelationship2.getName());
-
-        addFlattenedRelationship(nameGenerator, entity1, entity2, reverseRelationship1, dbRel2);
-        addFlattenedRelationship(nameGenerator, entity2, entity1, reverseRelationship2, dbRel1);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/BooleanNameFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/BooleanNameFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/BooleanNameFilter.java
new file mode 100644
index 0000000..c816af8
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/BooleanNameFilter.java
@@ -0,0 +1,35 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.access.loader;
+
+/**
+ * @since 3.2.
+ */
+public class BooleanNameFilter implements NameFilter {
+    private final boolean isInclude;
+
+    public BooleanNameFilter(boolean isInclude) {
+        this.isInclude = isInclude;
+    }
+
+    @Override
+    public boolean isIncluded(String string) {
+        return this.isInclude;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbLoaderConfiguration.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbLoaderConfiguration.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbLoaderConfiguration.java
new file mode 100644
index 0000000..461c687
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbLoaderConfiguration.java
@@ -0,0 +1,115 @@
+/*****************************************************************
+ *   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.access.loader;
+
+import org.apache.cayenne.access.loader.filters.DbPath;
+import org.apache.cayenne.access.loader.filters.EntityFilters;
+import org.apache.cayenne.access.loader.filters.FilterFactory;
+import org.apache.cayenne.access.loader.filters.FiltersConfig;
+
+/**
+ * @since 3.2.
+ */
+public class DbLoaderConfiguration {
+
+    /**
+     * Returns a name of a generic class that should be used for all
+     * ObjEntities. The most common generic class is
+     * {@link org.apache.cayenne.CayenneDataObject}. If generic class name is
+     * null (which is the default), DbLoader will assign each entity a unique
+     * class name derived from the table name.
+     *
+     */
+    private String genericClassName;
+
+/*
+    // TODO: Andrus, 10/29/2005 - this type of filtering should be delegated to adapter
+    */
+/* TODO by default should skip name.startsWith("BIN$") *//*
+
+    private NameFilter tableFilter = NamePatternMatcher.build(null, null, "BIN$");
+
+    private NameFilter columnFilter;
+
+    private NameFilter proceduresFilter = new NameFilter() {
+        private final Collection<String> excludedProcedures = Arrays.asList(
+                "auto_pk_for_table",
+                "auto_pk_for_table;1" // the last name is some Mac OS X Sybase artifact
+        );
+
+        @Override
+        public boolean isIncluded(String string) {
+            return !excludedProcedures.contains(string);
+        }
+    };
+*/
+
+
+    /**
+     * Java class implementing org.apache.cayenne.map.naming.NamingStrategy.
+     * This is used to specify how ObjEntities will be mapped from the imported
+     * DB schema.
+     */
+    private String namingStrategy;
+
+    private String[] tableTypes;
+
+    private FiltersConfig filtersConfig;
+
+    public String getGenericClassName() {
+        return genericClassName;
+    }
+
+    public void setGenericClassName(String genericClassName) {
+        this.genericClassName = genericClassName;
+    }
+
+    public String[] getTableTypes() {
+        return tableTypes;
+    }
+
+    public void setTableTypes(String[] tableTypes) {
+        this.tableTypes = tableTypes;
+    }
+
+    public String getNamingStrategy() {
+        return namingStrategy;
+    }
+
+    public void setNamingStrategy(String namingStrategy) {
+        this.namingStrategy = namingStrategy;
+    }
+
+    public FiltersConfig getFiltersConfig() {
+        if (filtersConfig == null) {
+            // this case is used often in tests where config not initialized properly
+            return new FiltersConfig(new EntityFilters(new DbPath(), FilterFactory.TRUE, FilterFactory.TRUE, FilterFactory.TRUE));
+        }
+        return filtersConfig;
+    }
+
+    public void setFiltersConfig(FiltersConfig filtersConfig) {
+        this.filtersConfig = filtersConfig;
+    }
+
+    @Override
+    public String toString() {
+        return "EntitiesFilters: " + getFiltersConfig();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DefaultDbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DefaultDbLoaderDelegate.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DefaultDbLoaderDelegate.java
new file mode 100644
index 0000000..2ca2d97
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DefaultDbLoaderDelegate.java
@@ -0,0 +1,55 @@
+/*****************************************************************
+ *   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.access.loader;
+
+import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.access.DbLoaderDelegate;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjEntity;
+
+/**
+ * @since 3.2.
+ */
+public class DefaultDbLoaderDelegate implements DbLoaderDelegate {
+
+    @Override
+    public boolean overwriteDbEntity(DbEntity entity) throws CayenneException {
+        return false;
+    }
+
+    @Override
+    public void dbEntityAdded(DbEntity entity) {
+
+    }
+
+    @Override
+    public void dbEntityRemoved(DbEntity entity) {
+
+    }
+
+    @Override
+    public void objEntityAdded(ObjEntity entity) {
+
+    }
+
+    @Override
+    public void objEntityRemoved(ObjEntity entity) {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java
new file mode 100644
index 0000000..8cf4ae1
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java
@@ -0,0 +1,126 @@
+/*****************************************************************
+ *   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.access.loader;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator;
+import org.apache.cayenne.map.naming.ExportedKey;
+import org.apache.cayenne.map.naming.NameCheckers;
+import org.apache.cayenne.map.naming.ObjectNameGenerator;
+
+/**
+ * Class represent ObjEntity that may be optimized using flattened relationships
+ * as many to many table
+ */
+public class ManyToManyCandidateEntity {
+    private final ObjEntity joinEntity;
+
+    private final DbRelationship dbRel1;
+    private final DbRelationship dbRel2;
+
+    private final ObjEntity entity1;
+    private final ObjEntity entity2;
+
+    private final DbRelationship reverseRelationship1;
+    private final DbRelationship reverseRelationship2;
+
+    private ManyToManyCandidateEntity(ObjEntity entityValue, List<ObjRelationship> relationships) {
+        joinEntity = entityValue;
+
+        ObjRelationship rel1 = relationships.get(0);
+        ObjRelationship rel2 = relationships.get(1);
+
+        dbRel1 = rel1.getDbRelationships().get(0);
+        dbRel2 = rel2.getDbRelationships().get(0);
+
+        reverseRelationship1 = dbRel1.getReverseRelationship();
+        reverseRelationship2 = dbRel2.getReverseRelationship();
+
+        entity1 = rel1.getTargetEntity();
+        entity2 = rel2.getTargetEntity();
+    }
+
+    /**
+     * Method check - if current entity represent many to many temporary table
+     * @return true if current entity is represent many to many table; otherwise returns false
+     */
+    public static ManyToManyCandidateEntity build(ObjEntity joinEntity) {
+        ArrayList<ObjRelationship> relationships = new ArrayList<ObjRelationship>(joinEntity.getRelationships());
+        if (relationships.size() != 2) {
+            return null;
+        }
+
+        ManyToManyCandidateEntity candidateEntity = new ManyToManyCandidateEntity(joinEntity, relationships);
+        if (candidateEntity.isManyToMany()) {
+            return candidateEntity;
+        }
+
+        return null;
+    }
+
+    private boolean isManyToMany() {
+        boolean isNotHaveAttributes = joinEntity.getAttributes().size() == 0;
+
+        return isNotHaveAttributes && reverseRelationship1.isToDependentPK() && reverseRelationship2.isToDependentPK()
+                && !entity1.equals(entity2);
+    }
+
+    private void addFlattenedRelationship(ObjectNameGenerator nameGenerator, ObjEntity srcEntity, ObjEntity dstEntity,
+                                          DbRelationship rel1, DbRelationship rel2) {
+
+        ExportedKey key = new ExportedKey(rel1.getSourceEntity().getName(),
+                rel1.getSourceAttributes().iterator().next().getName(),
+                null,
+                rel2.getTargetEntity().getName(),
+                rel2.getTargetAttributes().iterator().next().getName(),
+                null);
+
+        ObjRelationship newRelationship = new ObjRelationship();
+        newRelationship.setName(DefaultUniqueNameGenerator.generate(NameCheckers.objRelationship, srcEntity,
+                nameGenerator.createDbRelationshipName(key, true)));
+
+        newRelationship.setSourceEntity(srcEntity);
+        newRelationship.setTargetEntity(dstEntity);
+
+        newRelationship.addDbRelationship(rel1);
+        newRelationship.addDbRelationship(rel2);
+
+        srcEntity.addRelationship(newRelationship);
+    }
+
+    /**
+     * Method make direct relationships between 2 entities and remove relationships to
+     * many to many entity
+     *
+     * @param nameGenerator
+     */
+    public void optimizeRelationships(ObjectNameGenerator nameGenerator) {
+        entity1.removeRelationship(reverseRelationship1.getName());
+        entity2.removeRelationship(reverseRelationship2.getName());
+
+        addFlattenedRelationship(nameGenerator, entity1, entity2, reverseRelationship1, dbRel2);
+        addFlattenedRelationship(nameGenerator, entity2, entity1, reverseRelationship2, dbRel1);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NameFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NameFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NameFilter.java
new file mode 100644
index 0000000..6e28b33
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NameFilter.java
@@ -0,0 +1,27 @@
+/*****************************************************************
+ *   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.access.loader;
+
+/**
+ * @since 3.2.
+ */
+public interface NameFilter {
+
+    boolean isIncluded(String string);
+}


[5/7] CAY-1946 CDbimport improvements

Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToDb.java
index 2192203..77b7486 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToDb.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToDb.java
@@ -1,30 +1,29 @@
-/*****************************************************************
- *   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
+/*
+ * 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
+ *      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.
- ****************************************************************/
+ *    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.merge;
 
 import java.util.Collections;
 import java.util.List;
 
-import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
 import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
@@ -52,41 +51,8 @@ public class AddColumnToDb extends AbstractToDbToken.EntityAndColumn {
         QuotingStrategy context = adapter.getQuotingStrategy();
         appendPrefix(sqlBuffer, context);
 
-        // copied from JdbcAdapter.createTableAppendColumn
-        String[] types = adapter.externalTypesForJdbcType(getColumn().getType());
-        if (types == null || types.length == 0) {
-            String entityName = getColumn().getEntity() != null ? getColumn()
-                    .getEntity().getFullyQualifiedName() : "<null>";
-            throw new CayenneRuntimeException("Undefined type for attribute '"
-                    + entityName + "." + getColumn().getName() + "': " + getColumn().getType());
-        }
-
-        String type = types[0];
-        sqlBuffer.append(type);
-
-        // append size and precision (if applicable)
-        if (adapter.typeSupportsLength(getColumn().getType())) {
-            int len = getColumn().getMaxLength();
-            int scale = TypesMapping.isDecimal(getColumn().getType()) ? getColumn().getScale() : -1;
-
-            // sanity check
-            if (scale > len) {
-                scale = -1;
-            }
-
-            if (len > 0) {
-                sqlBuffer.append('(').append(len);
-
-                if (scale >= 0) {
-                    sqlBuffer.append(", ").append(scale);
-                }
-
-                sqlBuffer.append(')');
-            }
-        }
-
-        // use separate token to set value and not null if needed
-        // sqlBuffer.append(" NULL");
+        sqlBuffer.append(JdbcAdapter.getType(adapter, getColumn()));
+        sqlBuffer.append(JdbcAdapter.sizeAndPrecision(adapter, getColumn()));
 
         return Collections.singletonList(sqlBuffer.toString());
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
index d2f538f..61a266a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
@@ -72,30 +72,14 @@ public class CreateTableToModel extends AbstractToModelToken.Entity {
         String className = objEntityClassName;
         if (className == null) {
             // we should generate a className based on the objEntityName
-            String packageName = map.getDefaultPackage();
-            if (Util.isEmptyString(packageName)) {
-                packageName = "";
-            }
-            else if (!packageName.endsWith(".")) {
-                packageName = packageName + ".";
-            }
-            className = packageName + objEntityName;
+            className = map.getNameWithDefaultPackage(objEntityName);
         }
 
         objEntity.setClassName(className);
-        
         objEntity.setSuperClassName(map.getDefaultSuperclass());
         
         if (map.isClientSupported()) {
-            String clientPkg = map.getDefaultClientPackage();
-            if (clientPkg != null) {
-                if (!clientPkg.endsWith(".")) {
-                    clientPkg = clientPkg + ".";
-                }
-
-                objEntity.setClientClassName(clientPkg + objEntity.getName());
-            }
-
+            objEntity.setClientClassName(map.getNameWithDefaultClientPackage(objEntity.getName()));
             objEntity.setClientSuperClassName(map.getDefaultClientSuperclass());
         }
         

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java
index 55219f2..31cb65c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java
@@ -1,27 +1,29 @@
-/*****************************************************************
- *   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
+/*
+ * 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
+ *      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.
- ****************************************************************/
+ *    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.merge;
 
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.access.DataNode;
 import org.apache.cayenne.access.DbLoader;
-import org.apache.cayenne.access.DefaultDbLoaderDelegate;
+import org.apache.cayenne.access.loader.DbLoaderConfiguration;
+import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate;
+import org.apache.cayenne.access.loader.NameFilter;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.map.Attribute;
 import org.apache.cayenne.map.DataMap;
@@ -55,20 +57,13 @@ public class DbMerger {
     
     private final ValueForNullProvider valueForNull;
 
-    private final String schema;
-
     public DbMerger(MergerFactory factory) {
         this(factory, null);
     }
 
-    public DbMerger(MergerFactory factory, String schema) {
-        this(factory,  null, schema);
-    }
-
-    public DbMerger(MergerFactory factory, ValueForNullProvider valueForNull, String schema) {
+    public DbMerger(MergerFactory factory, ValueForNullProvider valueForNull) {
         this.factory = factory;
         this.valueForNull = valueForNull == null ? new EmptyValueForNullProvider() : valueForNull;
-        this.schema = schema;
     }
 
     /**
@@ -83,24 +78,24 @@ public class DbMerger {
      * Create and return a {@link List} of {@link MergerToken}s to alter the given
      * {@link DataNode} to match the given {@link DataMap}
      */
-    public List<MergerToken> createMergeTokens(DataNode dataNode, DataMap existing) {
-        return createMergeTokens(dataNode.getDataSource(), dataNode.getAdapter(), existing);
+    public List<MergerToken> createMergeTokens(DataNode dataNode, DataMap existing, DbLoaderConfiguration config) {
+        return createMergeTokens(dataNode.getDataSource(), dataNode.getAdapter(), existing, config);
     }
 
     /**
      * Create and return a {@link List} of {@link MergerToken}s to alter the given
      * {@link DataNode} to match the given {@link DataMap}
      */
-    public List<MergerToken> createMergeTokens(DbLoader dbLoader, DataMap existing) {
-        return createMergeTokens(existing, loadDataMapFromDb(dbLoader));
+    public List<MergerToken> createMergeTokens(DbLoader dbLoader, DataMap existing, DbLoaderConfiguration config) {
+        return createMergeTokens(existing, loadDataMapFromDb(dbLoader, config));
     }
 
     /**
      * Create and return a {@link List} of {@link MergerToken}s to alter the given
      * {@link DataNode} to match the given {@link DataMap}
      */
-    public List<MergerToken> createMergeTokens(DataSource dataSource, DbAdapter adapter, DataMap existingDataMap) {
-        return createMergeTokens(existingDataMap, loadDataMapFromDb(dataSource, adapter));
+    public List<MergerToken> createMergeTokens(DataSource dataSource, DbAdapter adapter, DataMap existingDataMap, DbLoaderConfiguration config) {
+        return createMergeTokens(existingDataMap, loadDataMapFromDb(dataSource, adapter, config));
     }
 
     /**
@@ -131,26 +126,17 @@ public class DbMerger {
         return tokens;
     }
 
-    private DataMap loadDataMapFromDb(DataSource dataSource, DbAdapter adapter) {
+    private DataMap loadDataMapFromDb(DataSource dataSource, DbAdapter adapter, DbLoaderConfiguration config) {
         Connection conn = null;
         try {
             conn = dataSource.getConnection();
 
-            final DbMerger merger = this;
-
             // TODO pass naming strategy
-            DbLoader dbLoader = new DbLoader(conn, adapter, new DefaultDbLoaderDelegate()) {
-
-                @Override
-                public boolean includeTableName(String tableName) {
-                    return merger.includeTableName(tableName);
-                }
-            };
-
-            return loadDataMapFromDb(dbLoader);
+            DbLoader dbLoader = new DbLoader(conn, adapter, new DefaultDbLoaderDelegate());
+            return loadDataMapFromDb(dbLoader, config);
         }
         catch (SQLException e) {
-            throw new CayenneRuntimeException("Can't load dataMap from db.", e);
+            throw new CayenneRuntimeException("Can't doLoad dataMap from db.", e);
         }
         finally {
             if (conn != null) {
@@ -164,10 +150,10 @@ public class DbMerger {
         }
     }
 
-    private DataMap loadDataMapFromDb(DbLoader dbLoader) {
+    private DataMap loadDataMapFromDb(DbLoader dbLoader, DbLoaderConfiguration config) {
         DataMap detectedDataMap = new DataMap();
         try {
-            dbLoader.load(detectedDataMap, null, schema, null, (String[]) null);
+            dbLoader.load(detectedDataMap, config, (String[]) null);
         } catch (SQLException e) {
             // TODO log
         }
@@ -190,6 +176,8 @@ public class DbMerger {
             String tableName = dbEntity.getName();
 
             if (!includeTableName(tableName)) {
+                // TODO we have to cut this entities in db loader
+                // TODO log
                 continue;
             }
 
@@ -359,20 +347,15 @@ public class DbMerger {
         Collection<DbAttribute> primaryKeyNew = dbEntity.getPrimaryKeys();
 
         String primaryKeyName = null;
-        if ((detectedEntity instanceof DetectedDbEntity)) {
+        if (detectedEntity instanceof DetectedDbEntity) {
             primaryKeyName = ((DetectedDbEntity) detectedEntity).getPrimaryKeyName();
         }
 
-        if (upperCaseEntityNames(primaryKeyOriginal).equals(
-                upperCaseEntityNames(primaryKeyNew))) {
+        if (upperCaseEntityNames(primaryKeyOriginal).equals(upperCaseEntityNames(primaryKeyNew))) {
             return null;
         }
 
-        return factory.createSetPrimaryKeyToDb(
-                dbEntity,
-                primaryKeyOriginal,
-                primaryKeyNew,
-                primaryKeyName);
+        return factory.createSetPrimaryKeyToDb(dbEntity, primaryKeyOriginal, primaryKeyNew, primaryKeyName);
     }
     
     private Set<String> upperCaseEntityNames(Collection<? extends Attribute> attrs) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToDb.java
index a074188..466a9d9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToDb.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToDb.java
@@ -1,21 +1,21 @@
-/*****************************************************************
- *   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
+/*
+ * 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
+ *      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.
- ****************************************************************/
+ *    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.merge;
 
 import java.util.Collections;
@@ -23,6 +23,7 @@ import java.util.List;
 
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
 import org.apache.cayenne.dba.QuotingStrategy;
 import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.map.DbAttribute;
@@ -57,41 +58,10 @@ public class SetColumnTypeToDb extends AbstractToDbToken.Entity {
     @Override
     public List<String> createSql(DbAdapter adapter) {
         StringBuffer sqlBuffer = new StringBuffer();
-       
         appendPrefix(sqlBuffer, adapter.getQuotingStrategy());
   
-        // copied from JdbcAdapter.createTableAppendColumn
-        String[] types = adapter.externalTypesForJdbcType(columnNew.getType());
-        if (types == null || types.length == 0) {
-            String entityName = columnNew.getEntity() != null ? columnNew
-                    .getEntity().getFullyQualifiedName() : "<null>";
-            throw new CayenneRuntimeException("Undefined type for attribute '"
-                    + entityName + "." + columnNew.getName() + "': " + columnNew.getType());
-        }
-
-        String type = types[0];
-        sqlBuffer.append(type);
-
-        // append size and precision (if applicable)
-        if (adapter.typeSupportsLength(columnNew.getType())) {
-            int len = columnNew.getMaxLength();
-            int scale = TypesMapping.isDecimal(columnNew.getType()) ? columnNew.getScale() : -1;
-
-            // sanity check
-            if (scale > len) {
-                scale = -1;
-            }
-
-            if (len > 0) {
-                sqlBuffer.append('(').append(len);
-
-                if (scale >= 0) {
-                    sqlBuffer.append(", ").append(scale);
-                }
-
-                sqlBuffer.append(')');
-            }
-        }
+        sqlBuffer.append(JdbcAdapter.getType(adapter, columnNew));
+        sqlBuffer.append(JdbcAdapter.sizeAndPrecision(adapter, columnNew));
 
         return Collections.singletonList(sqlBuffer.toString());
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java b/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
index 1b1fa90..e1555eb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
@@ -46,20 +46,21 @@ import org.apache.cayenne.map.naming.ObjectNameGenerator;
  */
 public class EntityMergeSupport {
 
-    private static final Map<String, String> CLASS_TO_PRIMITVE;
+    private static final Map<String, String> CLASS_TO_PRIMITIVE;
 
     static {
-        CLASS_TO_PRIMITVE = new HashMap<String, String>();
-        CLASS_TO_PRIMITVE.put(Byte.class.getName(), "byte");
-        CLASS_TO_PRIMITVE.put(Long.class.getName(), "long");
-        CLASS_TO_PRIMITVE.put(Double.class.getName(), "double");
-        CLASS_TO_PRIMITVE.put(Boolean.class.getName(), "boolean");
-        CLASS_TO_PRIMITVE.put(Float.class.getName(), "float");
-        CLASS_TO_PRIMITVE.put(Short.class.getName(), "short");
-        CLASS_TO_PRIMITVE.put(Integer.class.getName(), "int");
+        CLASS_TO_PRIMITIVE = new HashMap<String, String>();
+        CLASS_TO_PRIMITIVE.put(Byte.class.getName(), "byte");
+        CLASS_TO_PRIMITIVE.put(Long.class.getName(), "long");
+        CLASS_TO_PRIMITIVE.put(Double.class.getName(), "double");
+        CLASS_TO_PRIMITIVE.put(Boolean.class.getName(), "boolean");
+        CLASS_TO_PRIMITIVE.put(Float.class.getName(), "float");
+        CLASS_TO_PRIMITIVE.put(Short.class.getName(), "short");
+        CLASS_TO_PRIMITIVE.put(Integer.class.getName(), "int");
     }
 
-    protected DataMap map;
+    private final DataMap map;
+
     protected boolean removeMeaningfulFKs;
     protected boolean removeMeaningfulPKs;
     protected boolean usePrimitives;
@@ -67,12 +68,12 @@ public class EntityMergeSupport {
     /**
      * Strategy for choosing names for entities, attributes and relationships
      */
-    protected ObjectNameGenerator nameGenerator;
+    private final ObjectNameGenerator nameGenerator;
 
     /**
      * Listeners of merge process.
      */
-    protected List<EntityMergeListener> listeners;
+    private final List<EntityMergeListener> listeners = new ArrayList<EntityMergeListener>();
 
     public EntityMergeSupport(DataMap map) {
         this(map, new LegacyNameGenerator(), true);
@@ -83,10 +84,9 @@ public class EntityMergeSupport {
      */
     public EntityMergeSupport(DataMap map, ObjectNameGenerator nameGenerator, boolean removeMeaningfulPKs) {
         this.map = map;
+        this.nameGenerator = nameGenerator;
         this.removeMeaningfulFKs = true;
-        this.listeners = new ArrayList<EntityMergeListener>();
         this.removeMeaningfulPKs = removeMeaningfulPKs;
-        this.nameGenerator = nameGenerator;
 
         /**
          * Adding a listener, so that all created ObjRelationships would have
@@ -102,7 +102,7 @@ public class EntityMergeSupport {
      * @return true if any ObjEntity has changed as a result of synchronization.
      * @since 1.2 changed signature to use Collection instead of List.
      */
-    public boolean synchronizeWithDbEntities(Collection<ObjEntity> objEntities) {
+    public boolean synchronizeWithDbEntities(Iterable<ObjEntity> objEntities) {
         boolean changed = false;
         for (ObjEntity nextEntity : objEntities) {
             if (synchronizeWithDbEntity(nextEntity)) {
@@ -147,71 +147,79 @@ public class EntityMergeSupport {
         boolean changed = false;
 
         // synchronization on DataMap is some (weak) protection
-        // against simultaneous modification of the map (like double-clicking on
-        // sync
-        // button)
+        // against simultaneous modification of the map (like double-clicking on sync button)
         synchronized (map) {
 
             if (removeFK(dbEntity)) {
-
-                // get rid of attributes that are now src attributes for
-                // relationships
-                for (DbAttribute da : getMeaningfulFKs(entity)) {
-                    ObjAttribute oa = entity.getAttributeForDbAttribute(da);
-                    while (oa != null) {
-                        String attrName = oa.getName();
-                        entity.removeAttribute(attrName);
-                        changed = true;
-                        oa = entity.getAttributeForDbAttribute(da);
-                    }
-                }
+                changed = getRidOfAttributesThatAreNowSrcAttributesForRelationships(entity);
             }
 
-            // add missing attributes
-            for (DbAttribute da : getAttributesToAdd(entity)) {
+            changed |= addMissingAttributes(entity);
+            changed |= addMissingRelationships(entity);
+        }
 
-                String attrName = nameGenerator.createObjAttributeName(da);
-                // avoid duplicate names
-                attrName = DefaultUniqueNameGenerator.generate(NameCheckers.objAttribute, entity, attrName);
+        return changed;
+    }
 
-                String type = TypesMapping.getJavaBySqlType(da.getType());
+    private boolean addMissingRelationships(ObjEntity entity) {
+        boolean changed = false;
+        for (DbRelationship dr : getRelationshipsToAdd(entity)) {
+            DbEntity targetEntity = dr.getTargetEntity();
 
-                if (usePrimitives) {
-                    String primitive = CLASS_TO_PRIMITVE.get(type);
-                    if (primitive != null) {
-                        type = primitive;
-                    }
-                }
+            for (Entity mappedTarget : map.getMappedEntities(targetEntity)) {
 
-                ObjAttribute oa = new ObjAttribute(attrName, type, entity);
-                oa.setDbAttributePath(da.getName());
-                entity.addAttribute(oa);
-                fireAttributeAdded(oa);
-                changed = true;
-            }
+                // avoid duplicate names
+                String relationshipName = nameGenerator.createObjRelationshipName(dr);
+                relationshipName = DefaultUniqueNameGenerator.generate(NameCheckers.objRelationship, entity, relationshipName);
 
-            // add missing relationships
-            for (DbRelationship dr : getRelationshipsToAdd(entity)) {
-                DbEntity targetEntity = (DbEntity) dr.getTargetEntity();
+                ObjRelationship or = new ObjRelationship(relationshipName);
+                or.addDbRelationship(dr);
+                or.setSourceEntity(entity);
+                or.setTargetEntity(mappedTarget);
+                entity.addRelationship(or);
 
-                for (Entity mappedTarget : map.getMappedEntities(targetEntity)) {
+                fireRelationshipAdded(or);
+                changed = true;
+            }
+        }
+        return changed;
+    }
 
-                    // avoid duplicate names
-                    String relationshipName = nameGenerator.createObjRelationshipName(dr);
-                    relationshipName = DefaultUniqueNameGenerator.generate(NameCheckers.objRelationship, entity, relationshipName);
+    private boolean addMissingAttributes(ObjEntity entity) {
+        boolean changed = false;
+        for (DbAttribute da : getAttributesToAdd(entity)) {
 
-                    ObjRelationship or = new ObjRelationship(relationshipName);
-                    or.addDbRelationship(dr);
-                    or.setSourceEntity(entity);
-                    or.setTargetEntity(mappedTarget);
-                    entity.addRelationship(or);
+            String attrName = DefaultUniqueNameGenerator.generate(NameCheckers.objAttribute, entity,
+                    nameGenerator.createObjAttributeName(da));
 
-                    fireRelationshipAdded(or);
-                    changed = true;
+            String type = TypesMapping.getJavaBySqlType(da.getType());
+            if (usePrimitives) {
+                String primitive = CLASS_TO_PRIMITIVE.get(type);
+                if (primitive != null) {
+                    type = primitive;
                 }
             }
+
+            ObjAttribute oa = new ObjAttribute(attrName, type, entity);
+            oa.setDbAttributePath(da.getName());
+            entity.addAttribute(oa);
+            fireAttributeAdded(oa);
+            changed = true;
         }
+        return changed;
+    }
 
+    private boolean getRidOfAttributesThatAreNowSrcAttributesForRelationships(ObjEntity entity) {
+        boolean changed = false;
+        for (DbAttribute da : getMeaningfulFKs(entity)) {
+            ObjAttribute oa = entity.getAttributeForDbAttribute(da);
+            while (oa != null) {
+                String attrName = oa.getName();
+                entity.removeAttribute(attrName);
+                changed = true;
+                oa = entity.getAttributeForDbAttribute(da);
+            }
+        }
         return changed;
     }
 
@@ -249,16 +257,11 @@ public class EntityMergeSupport {
 
         for (DbAttribute dba : dbEntity.getAttributes()) {
 
-            if (dba.getName() == null) {
-                continue;
-            }
-
-            if (objEntity.getAttributeForDbAttribute(dba) != null) {
+            if (dba.getName() == null || objEntity.getAttributeForDbAttribute(dba) != null) {
                 continue;
             }
 
             boolean removeMeaningfulPKs = removePK(dbEntity);
-
             if (removeMeaningfulPKs && dba.isPrimaryKey()) {
                 continue;
             }
@@ -330,28 +333,20 @@ public class EntityMergeSupport {
 
     protected List<DbRelationship> getRelationshipsToAdd(ObjEntity objEntity) {
         List<DbRelationship> missing = new ArrayList<DbRelationship>();
-        for (DbRelationship dbrel : objEntity.getDbEntity().getRelationships()) {
+        for (DbRelationship dbRel : objEntity.getDbEntity().getRelationships()) {
             // check if adding it makes sense at all
-            if (dbrel.getName() == null) {
+            if (dbRel.getName() == null) {
                 continue;
             }
 
-            if (objEntity.getRelationshipForDbRelationship(dbrel) == null) {
-                missing.add(dbrel);
+            if (objEntity.getRelationshipForDbRelationship(dbRel) == null) {
+                missing.add(dbRel);
             }
         }
 
         return missing;
     }
 
-    public DataMap getMap() {
-        return map;
-    }
-
-    public void setMap(DataMap map) {
-        this.map = map;
-    }
-
     /**
      * @since 1.2
      */
@@ -391,8 +386,8 @@ public class EntityMergeSupport {
      * Notifies all listeners that an ObjAttribute was added
      */
     protected void fireAttributeAdded(ObjAttribute attr) {
-        for (int i = 0; i < listeners.size(); i++) {
-            listeners.get(i).objAttributeAdded(attr);
+        for (EntityMergeListener listener : listeners) {
+            listener.objAttributeAdded(attr);
         }
     }
 
@@ -400,19 +395,12 @@ public class EntityMergeSupport {
      * Notifies all listeners that an ObjRelationship was added
      */
     protected void fireRelationshipAdded(ObjRelationship rel) {
-        for (int i = 0; i < listeners.size(); i++) {
-            listeners.get(i).objRelationshipAdded(rel);
+        for (EntityMergeListener listener : listeners) {
+            listener.objRelationshipAdded(rel);
         }
     }
 
     /**
-     * Sets new naming strategy for reverse engineering
-     */
-    public void setNameGenerator(ObjectNameGenerator strategy) {
-        this.nameGenerator = strategy;
-    }
-
-    /**
      * @return naming strategy for reverse engineering
      */
     public ObjectNameGenerator getNameGenerator() {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderPartialTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderPartialTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderPartialTest.java
index 72d6fce..8b75c37 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderPartialTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderPartialTest.java
@@ -26,7 +26,7 @@ import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate;
 import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.ServerCaseDataSourceFactory;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderTest.java
index b8898c4..baf484e 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderTest.java
@@ -23,6 +23,7 @@ import java.sql.Types;
 import java.util.Collection;
 import java.util.List;
 
+import org.apache.cayenne.access.loader.DbLoaderConfiguration;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.TypesMapping;
@@ -41,6 +42,7 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 @UseServerRuntime(ServerCase.TESTMAP_PROJECT)
 public class DbLoaderTest extends ServerCase {
 
+    public static final DbLoaderConfiguration CONFIG = new DbLoaderConfiguration();
     @Inject
     private ServerRuntime runtime;
 
@@ -86,7 +88,7 @@ public class DbLoaderTest extends ServerCase {
 
         String tableLabel = adapter.tableTypeForTable();
 
-        List<DbEntity> tables = loader.getTables(null, null, "%", new String[] { tableLabel });
+        List<DbEntity> tables = loader.getTables(new DbLoaderConfiguration(), new String[] { tableLabel });
 
         assertNotNull(tables);
 
@@ -105,20 +107,21 @@ public class DbLoaderTest extends ServerCase {
     public void testLoadWithMeaningfulPK() throws Exception {
 
         DataMap map = new DataMap();
-        String tableLabel = adapter.tableTypeForTable();
+        String[] tableLabel = { adapter.tableTypeForTable() };
 
         loader.setCreatingMeaningfulPK(true);
 
-        List<DbEntity> testLoader = loader.getTables(null, null, "artist", new String[] { tableLabel });
-        if (testLoader.size() == 0) {
-            testLoader = loader.getTables(null, null, "ARTIST", new String[] { tableLabel });
+        List<DbEntity> testLoader = loader.getTables(CONFIG, tableLabel);
+        if (testLoader.isEmpty()) {
+            testLoader = loader.getTables(CONFIG, tableLabel);
         }
 
-        loader.loadDbEntities(map, testLoader);
+        List<DbEntity> entities = loader.loadDbEntities(map, CONFIG, testLoader);
+        loader.loadObjEntities(map, CONFIG, entities);
 
-        loader.loadObjEntities(map);
         ObjEntity artist = map.getObjEntity("Artist");
         assertNotNull(artist);
+
         ObjAttribute id = artist.getAttribute("artistId");
         assertNotNull(id);
     }
@@ -141,7 +144,7 @@ public class DbLoaderTest extends ServerCase {
         String tableLabel = adapter.tableTypeForTable();
 
         // *** TESTING THIS ***
-        loader.loadDbEntities(map, loader.getTables(null, null, "%", new String[] { tableLabel }));
+        List<DbEntity> entities = loader.loadDbEntities(map, CONFIG, loader.getTables(CONFIG, new String[]{tableLabel}));
 
         assertDbEntities(map);
 
@@ -150,12 +153,12 @@ public class DbLoaderTest extends ServerCase {
         }
 
         // *** TESTING THIS ***
-        loader.loadDbRelationships(map);
+        loader.loadDbRelationships(map, CONFIG, entities);
 
         if (supportsFK) {
             Collection<DbRelationship> rels = getDbEntity(map, "ARTIST").getRelationships();
             assertNotNull(rels);
-            assertTrue(rels.size() > 0);
+            assertTrue(!rels.isEmpty());
 
             // test one-to-one
             rels = getDbEntity(map, "PAINTING").getRelationships();
@@ -182,7 +185,7 @@ public class DbLoaderTest extends ServerCase {
 
         // *** TESTING THIS ***
         loader.setCreatingMeaningfulPK(false);
-        loader.loadObjEntities(map);
+        loader.loadObjEntities(map, CONFIG, entities);
 
         assertObjEntities(map);
 
@@ -277,7 +280,7 @@ public class DbLoaderTest extends ServerCase {
         assertNotNull(blobEnt);
         // BLOBs should be mapped as byte[]
         ObjAttribute blobAttr = blobEnt.getAttribute("blobCol");
-        assertNotNull("BlobTest.blobCol failed to load", blobAttr);
+        assertNotNull("BlobTest.blobCol failed to doLoad", blobAttr);
         assertEquals("byte[]", blobAttr.getType());
         ObjEntity clobEnt = map.getObjEntity("ClobTest");
         assertNotNull(clobEnt);
@@ -359,19 +362,200 @@ public class DbLoaderTest extends ServerCase {
         }
     }
 
-    private String msgForTypeMismatch(DbAttribute origAttr, DbAttribute newAttr) {
+    private static String msgForTypeMismatch(DbAttribute origAttr, DbAttribute newAttr) {
         return msgForTypeMismatch(origAttr.getType(), newAttr);
     }
 
-    private String msgForTypeMismatch(int origType, DbAttribute newAttr) {
+    private static String msgForTypeMismatch(int origType, DbAttribute newAttr) {
         String nt = TypesMapping.getSqlNameByType(newAttr.getType());
         String ot = TypesMapping.getSqlNameByType(origType);
         return attrMismatch(newAttr.getName(), "expected type: <" + ot + ">, but was <" + nt + ">");
     }
 
-    private String attrMismatch(String attrName, String msg) {
-        StringBuffer buf = new StringBuffer();
-        buf.append("[Error loading attribute '").append(attrName).append("': ").append(msg).append("]");
-        return buf.toString();
+    private static String attrMismatch(String attrName, String msg) {
+        return "[Error loading attribute '" + attrName + "': " + msg + "]";
+    }
+
+/*
+    TODO
+
+    @Test
+    public void testCreateLoader() throws Exception {
+
+        DbLoader loader = parameters.createLoader(mock(DbAdapter.class), connection,
+                mock(DbLoaderDelegate.class));
+        assertNotNull(loader);
+        assertSame(connection, loader.getConnection());
+
+        assertTrue(loader.includeTableName("dummy"));
+    }
+
+    @Test
+    public void testCreateLoader_IncludeExclude() throws Exception {
+        DbImportConfiguration parameters = new DbImportConfiguration();
+        parameters.setIncludeTables("a,b,c*");
+
+        DbLoader loader1 = parameters.createLoader(mock(DbAdapter.class), mock(Connection.class),
+                mock(DbLoaderDelegate.class));
+
+        assertFalse(loader1.includeTableName("dummy"));
+        assertFalse(loader1.includeTableName("ab"));
+        assertTrue(loader1.includeTableName("a"));
+        assertTrue(loader1.includeTableName("b"));
+        assertTrue(loader1.includeTableName("cd"));
+
+        parameters.setExcludeTables("cd");
+
+        DbLoader loader2 = parameters.createLoader(mock(DbAdapter.class), mock(Connection.class),
+                mock(DbLoaderDelegate.class));
+
+        assertFalse(loader2.includeTableName("dummy"));
+        assertFalse(loader2.includeTableName("ab"));
+        assertTrue(loader2.includeTableName("a"));
+        assertTrue(loader2.includeTableName("b"));
+        assertFalse(loader2.includeTableName("cd"));
+        assertTrue(loader2.includeTableName("cx"));
     }
+
+
+    @Test
+    public void testCreateLoader_MeaningfulPk_Default() throws Exception {
+        DbImportConfiguration parameters = new DbImportConfiguration();
+        assertNull(parameters.getMeaningfulPkTables());
+
+        DbLoader loader1 = parameters.createLoader(mock(DbAdapter.class), mock(Connection.class),
+                mock(DbLoaderDelegate.class));
+
+        DataMap map = new DataMap();
+
+        DbEntity e1 = new DbEntity("e1");
+        DbAttribute pk = new DbAttribute("pk", Types.INTEGER, e1);
+        pk.setPrimaryKey(true);
+        e1.addAttribute(pk);
+        DbAttribute nonPk = new DbAttribute("nonPk", Types.INTEGER, e1);
+        e1.addAttribute(nonPk);
+
+        map.addDbEntity(e1);
+
+        // DbLoader is so ugly and hard to test..
+        Field dbEntityList = DbLoader.class.getDeclaredField("dbEntityList");
+        dbEntityList.setAccessible(true);
+        List<DbEntity> entities = (List<DbEntity>) dbEntityList.get(loader1);
+        entities.add(e1);
+
+        loader1.loadObjEntities(map, entities);
+
+        ObjEntity oe1 = map.getObjEntity("E1");
+        assertEquals(1, oe1.getAttributes().size());
+        assertNotNull(oe1.getAttribute("nonPk"));
+    }
+
+    @Test
+    public void testCreateLoader_MeaningfulPk_Specified() throws Exception {
+        DbImportConfiguration parameters = new DbImportConfiguration();
+        parameters.setMeaningfulPkTables("a*");
+
+        DbLoader loader1 = parameters.createLoader(mock(DbAdapter.class), mock(Connection.class),
+                mock(DbLoaderDelegate.class));
+
+        // DbLoader is so ugly and hard to test..
+        Field dbEntityList = DbLoader.class.getDeclaredField("dbEntityList");
+        dbEntityList.setAccessible(true);
+        Collection<DbEntity> entities = (List<DbEntity>) dbEntityList.get(loader1);
+
+        DataMap map = new DataMap();
+
+        DbEntity e1 = new DbEntity("e1");
+        DbAttribute pk = new DbAttribute("pk", Types.INTEGER, e1);
+        pk.setPrimaryKey(true);
+        e1.addAttribute(pk);
+        DbAttribute nonPk = new DbAttribute("nonPk", Types.INTEGER, e1);
+        e1.addAttribute(nonPk);
+
+        map.addDbEntity(e1);
+        entities.add(e1);
+
+        DbEntity a1 = new DbEntity("a1");
+        DbAttribute apk = new DbAttribute("pk", Types.INTEGER, a1);
+        apk.setPrimaryKey(true);
+        a1.addAttribute(apk);
+        DbAttribute anonPk = new DbAttribute("nonPk", Types.INTEGER, a1);
+        a1.addAttribute(anonPk);
+
+        map.addDbEntity(a1);
+        entities.add(a1);
+
+        loader1.loadObjEntities(map, entities);
+
+        ObjEntity oe1 = map.getObjEntity("E1");
+        assertEquals(1, oe1.getAttributes().size());
+        assertNotNull(oe1.getAttribute("nonPk"));
+
+        ObjEntity oe2 = map.getObjEntity("A1");
+        assertEquals(2, oe2.getAttributes().size());
+        assertNotNull(oe2.getAttribute("nonPk"));
+        assertNotNull(oe2.getAttribute("pk"));
+    }
+
+    @Test
+    public void testCreateLoader_UsePrimitives_False() throws Exception {
+        DbImportConfiguration parameters = new DbImportConfiguration();
+        parameters.setUsePrimitives(false);
+
+        DbLoader loader1 = parameters.createLoader(mock(DbAdapter.class), mock(Connection.class),
+                mock(DbLoaderDelegate.class));
+
+        DataMap map = new DataMap();
+
+        DbEntity e1 = new DbEntity("e1");
+        DbAttribute nonPk = new DbAttribute("nonPk", Types.INTEGER, e1);
+        e1.addAttribute(nonPk);
+
+        map.addDbEntity(e1);
+
+        // DbLoader is so ugly and hard to test..
+        Field dbEntityList = DbLoader.class.getDeclaredField("dbEntityList");
+        dbEntityList.setAccessible(true);
+        List<DbEntity> entities = (List<DbEntity>) dbEntityList.get(loader1);
+        entities.add(e1);
+
+        loader1.loadObjEntities(map, entities);
+
+        ObjEntity oe1 = map.getObjEntity("E1");
+
+        ObjAttribute oa1 = oe1.getAttribute("nonPk");
+        assertEquals("java.lang.Integer", oa1.getType());
+    }
+
+    @Test
+    public void testCreateLoader_UsePrimitives_True() throws Exception {
+        DbImportConfiguration parameters = new DbImportConfiguration();
+        parameters.setUsePrimitives(true);
+
+        DbLoader loader1 = parameters.createLoader(mock(DbAdapter.class), mock(Connection.class),
+                mock(DbLoaderDelegate.class));
+
+        DataMap map = new DataMap();
+
+        DbEntity e1 = new DbEntity("e1");
+        DbAttribute nonPk = new DbAttribute("nonPk", Types.INTEGER, e1);
+        e1.addAttribute(nonPk);
+
+        map.addDbEntity(e1);
+
+        // DbLoader is so ugly and hard to test..
+        Field dbEntityList = DbLoader.class.getDeclaredField("dbEntityList");
+        dbEntityList.setAccessible(true);
+        List<DbEntity> entities = (List<DbEntity>) dbEntityList.get(loader1);
+        entities.add(e1);
+
+        loader1.loadObjEntities(map, entities);
+
+        ObjEntity oe1 = map.getObjEntity("E1");
+
+        ObjAttribute oa1 = oe1.getAttribute("nonPk");
+        assertEquals("int", oa1.getType());
+    }
+*/
+
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/test/java/org/apache/cayenne/access/ManyToManyCandidateEntityTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/ManyToManyCandidateEntityTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/ManyToManyCandidateEntityTest.java
deleted file mode 100644
index 7be3c3d..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/ManyToManyCandidateEntityTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.access;
-
-import junit.framework.TestCase;
-
-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.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.map.naming.LegacyNameGenerator;
-import org.apache.cayenne.resource.URLResource;
-
-import java.net.URL;
-import java.util.ArrayList;
-
-public class ManyToManyCandidateEntityTest extends TestCase {
-
-    private DataMap map;
-
-    @Override
-    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);
-    }
-
-    public void testMatchingForManyToManyEntity() throws Exception {
-        ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
-
-        assertNotNull(ManyToManyCandidateEntity.build(manyToManyEntity));
-    }
-
-    public void testMatchingForNotManyToManyEntity() throws Exception {
-        ObjEntity entity = map.getObjEntity("Table1");
-
-        assertNull(ManyToManyCandidateEntity.build(entity));
-    }
-
-    public void testOptimisationForManyToManyEntity() {
-        ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
-
-        ManyToManyCandidateEntity.build(manyToManyEntity).optimizeRelationships(new LegacyNameGenerator());
-
-        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/fde7761f/cayenne-server/src/test/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntityTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntityTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntityTest.java
new file mode 100644
index 0000000..4348edf
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntityTest.java
@@ -0,0 +1,106 @@
+/*****************************************************************
+ *   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.access.loader;
+
+import junit.framework.TestCase;
+
+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.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.map.naming.LegacyNameGenerator;
+import org.apache.cayenne.resource.URLResource;
+
+import java.net.URL;
+import java.util.ArrayList;
+
+public class ManyToManyCandidateEntityTest extends TestCase {
+
+    private DataMap map;
+
+    @Override
+    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);
+    }
+
+    public void testMatchingForManyToManyEntity() throws Exception {
+        ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
+
+        assertNotNull(ManyToManyCandidateEntity.build(manyToManyEntity));
+    }
+
+    public void testMatchingForNotManyToManyEntity() throws Exception {
+        ObjEntity entity = map.getObjEntity("Table1");
+
+        assertNull(ManyToManyCandidateEntity.build(entity));
+    }
+
+    public void testOptimisationForManyToManyEntity() {
+        ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
+
+        ManyToManyCandidateEntity.build(manyToManyEntity).optimizeRelationships(new LegacyNameGenerator());
+
+        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/fde7761f/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/DbPathTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/DbPathTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/DbPathTest.java
new file mode 100644
index 0000000..60d4933
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/DbPathTest.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ */
+
+package org.apache.cayenne.access.loader.filters;
+
+import org.junit.Test;
+
+import static org.apache.cayenne.access.loader.filters.FiltersFactory.path;
+import static org.junit.Assert.*;
+
+public class DbPathTest {
+
+    @Test
+    public void testIsCover() throws Exception {
+        assertTrue(path(null, null).isCover(path("Hello", "World")));
+        assertTrue(path(null, null).isCover(path("Hello", null)));
+        assertTrue(path(null, null).isCover(path(null, null)));
+        assertTrue(path(null, "Yo").isCover(path("Yo!", "Yo")));
+        assertTrue(path(null, "Yo").isCover(path(null, "Yo")));
+
+        assertFalse(path(null, "Yo!").isCover(path(null, "Yo!!")));
+        assertFalse(path("aa", "Yo!").isCover(path(null, "Yo!!")));
+        assertFalse(path("aaa", "Yo!").isCover(path("aa", "Yo!!")));
+
+        assertTrue(path("aa", null).isCover(path("aa", null)));
+        assertTrue(path("aa", null).isCover(path("aa", "bb")));
+        assertTrue(path("aa", "Yo!").isCover(path("aa", "Yo!")));
+        assertFalse(path("aa", "Yo!").isCover(path("aa", "Yo!!")));
+
+        assertFalse(path("", "APP").isCover(path(null, null)));
+
+        assertTrue(path(null, "schema_01").isCover(path("", "schema_01")));
+        assertTrue(path(null, "schema_01").isCover(path(null, "schema_01")));
+        assertFalse(path(null, "schema_01").isCover(path("", "schema_02")));
+        assertFalse(path(null, "schema_02").isCover(path("", "schema_01")));
+    }
+
+    @Test
+    public void testToString() throws Exception {
+        assertEquals("%", path(null, null).toString());
+        assertEquals("/schema", path("", "schema").toString());
+        assertEquals("%/schema", path(null, "schema").toString());
+        assertEquals("catalog/schema", path("catalog", "schema").toString());
+        assertEquals("catalog//table", path("catalog", "", "table").toString());
+        assertEquals("catalog/%/table", path("catalog", null, "table").toString());
+        assertEquals("//table", path("", "", "table").toString());
+        assertEquals("%/%/table", path(null, null, "table").toString());
+        assertEquals("%", path(null, null, null).toString());
+        assertEquals("c/%/", path("c", null, "").toString());
+    }
+
+    @Test
+    public void testMerge() throws Exception {
+        DbPath path1 = path(null, null);
+        DbPath path2 = path("", "APP");
+        assertEquals(path1, path1.merge(path2));
+        assertEquals(path1, path2.merge(path1));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/EntityFiltersTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/EntityFiltersTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/EntityFiltersTest.java
new file mode 100644
index 0000000..5b936ac
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/EntityFiltersTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.access.loader.filters;
+
+import org.junit.Test;
+
+import static org.apache.cayenne.access.loader.filters.FilterFactory.*;
+import static org.junit.Assert.*;
+
+public class EntityFiltersTest {
+
+    @Test
+    public void testJoinWithEmpty() throws Exception {
+        EntityFilters filter1 = new EntityFilters(null, null, null, null);
+        EntityFilters filter2 = new EntityFilters(null, include("table"), include("column"), include("procedure"));
+
+        assertEquals(filter2, filter1.join(filter2));
+        assertEquals(filter2, filter2.join(filter1));
+    }
+
+    @Test
+    public void testJoinExcludeInclude() throws Exception {
+        EntityFilters filter1 = new EntityFilters(null, exclude("table"), exclude("column"), exclude("procedure"));
+        EntityFilters filter2 = new EntityFilters(null, include("table"), include("column"), include("procedure"));
+
+        assertEquals(new EntityFilters(null,
+                        list(exclude("table"), include("table")),
+                        list(exclude("column"), include("column")),
+                        list(exclude("procedure"), include("procedure"))),
+                filter1.join(filter2));
+        assertEquals(new EntityFilters(null,
+                        list(include("table"), exclude("table")),
+                        list(include("column"), exclude("column")),
+                        list(include("procedure"), exclude("procedure"))),
+                filter2.join(filter1));
+    }
+
+    @Test
+    public void testEquals() throws Exception {
+        EntityFilters filters = new EntityFilters(new DbPath(), NULL, NULL, NULL);
+        assertTrue(filters.tableFilter().equals(NULL));
+        assertTrue(filters.columnFilter().equals(NULL));
+        assertTrue(filters.procedureFilter().equals(NULL));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/FiltersConfigTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/FiltersConfigTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/FiltersConfigTest.java
new file mode 100644
index 0000000..c6097ec
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/FiltersConfigTest.java
@@ -0,0 +1,198 @@
+/*
+ * 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.access.loader.filters;
+
+import org.junit.Test;
+
+import java.util.Iterator;
+import java.util.List;
+
+import static org.apache.cayenne.access.loader.filters.FilterFactory.*;
+import static org.apache.cayenne.access.loader.filters.FiltersFactory.path;
+import static org.apache.cayenne.access.loader.filters.FiltersFactory.eFilters;
+import static org.junit.Assert.*;
+
+public class FiltersConfigTest {
+
+    @Test
+    public void testSorting() throws Exception {
+        FiltersConfig filters = new FiltersConfig(
+                entityFilter("", ""),
+                entityFilter("aaa", ""),
+                entityFilter("aa", ""),
+                entityFilter("aa", "a"),
+                entityFilter("aa", "aa"),
+                entityFilter("aa", "aa"),
+                entityFilter("b", "b")
+        );
+
+        Iterator<DbPath> iterator = filters.getDbPaths().iterator();
+        assertEquals(path("", ""), iterator.next());
+        assertEquals(path("aa", ""), iterator.next());
+        assertEquals(path("aa", "a"), iterator.next());
+        assertEquals(path("aa", "aa"), iterator.next());
+        assertEquals(path("aaa", ""), iterator.next());
+        assertEquals(path("b", "b"), iterator.next());
+    }
+
+    private EntityFilters entityFilter(String s, String s1) {
+        return new EntityFilters(new DbPath(s, s1), include("IncludeTable"), TRUE, TRUE);
+    }
+
+    @Test
+    public void testActionsWithEmptyCatalog() throws Exception {
+        FiltersConfig filters = new FiltersConfig(
+                entityFilter(null, null),
+                entityFilter("aaa", null),
+                entityFilter("aa", null)
+        );
+
+        List<DbPath> actions = filters.pathsForQueries();
+        assertEquals(1L, actions.size());
+        assertEquals(path(), actions.get(0));
+    }
+
+    @Test
+    public void testActionsWithEmptySchemas() throws Exception {
+        FiltersConfig filters = new FiltersConfig(
+                entityFilter("aaa", null),
+                entityFilter("aaa", "11"),
+                entityFilter("aa", null),
+                entityFilter("aa", "a"),
+                entityFilter("aa", "aa"),
+                entityFilter("aa", "aa")
+        );
+
+
+        List<DbPath> actions = filters.pathsForQueries();
+        assertEquals(2L, actions.size());
+        assertEquals(path("aa", null), actions.get(0));
+        assertEquals(path("aaa", null), actions.get(1));
+    }
+
+    @Test
+    public void testActionsWithSchemas() throws Exception {
+        FiltersConfig filters = new FiltersConfig(
+                entityFilter("aaa", ""),
+                entityFilter("aa", "a"),
+                entityFilter("aa", "aa"),
+                entityFilter("aa", "aa"),
+                entityFilter("aa", "b"),
+                entityFilter("aa", "b"),
+                entityFilter("aa", "b")
+        );
+
+
+        List<DbPath> actions = filters.pathsForQueries();
+        assertEquals(4L, actions.size());
+        assertEquals(path("aa", "a"), actions.get(0));
+        assertEquals(path("aa", "aa"), actions.get(1));
+        assertEquals(path("aa", "b"), actions.get(2));
+        assertEquals(path("aaa", ""), actions.get(3));
+    }
+
+    @Test
+    public void testActionsWithSchemasAndEmptyCatalog() throws Exception {
+        FiltersConfig filters = new FiltersConfig(
+                entityFilter("", "a"),
+                entityFilter("", "aa"),
+                entityFilter("", "aa"),
+                entityFilter("", "b"),
+                entityFilter("", "b"),
+                entityFilter("", "b")
+        );
+
+
+        List<DbPath> actions = filters.pathsForQueries();
+        assertEquals(3L, actions.size());
+        assertEquals(path("", "b"), actions.get(2));
+        assertEquals(path("", "aa"), actions.get(1));
+        assertEquals(path("", "a"), actions.get(0));
+
+    }
+
+    @Test
+    public void testFiltersOneFilter() throws Exception {
+        FiltersConfig filters = new FiltersConfig(
+                eFilters(path("", "a"), include("table")),
+                entityFilter("", "aa"),
+                entityFilter("", "aa"),
+                entityFilter("", "b"),
+                entityFilter("", "b"),
+                entityFilter("", "b")
+        );
+
+        assertEquals(eFilters(path("", "a"), include("table")),
+                     filters.filter(path("", "a")));
+    }
+
+    @Test
+    public void testFiltersJoinFilters() throws Exception {
+        FiltersConfig filters = new FiltersConfig(
+                eFilters(path("", "a"), include("table")),
+                eFilters(path("", "a"), exclude("table")),
+                entityFilter("", "aa"),
+                entityFilter("", "aa")
+        );
+
+        assertEquals(eFilters(path("", "a"), list(include("table"), exclude("table"))),
+                filters.filter(path("", "a")));
+
+        assertEquals(entityFilter("", "aa"), filters.filter(path("", "aa")));
+    }
+
+    @Test
+    public void testFiltersJoinFiltersWithNull() throws Exception {
+        FiltersConfig filters = new FiltersConfig(
+                eFilters(path("", "a"), include("table")),
+                eFilters(path("", "a"), exclude("table")),
+                eFilters(path("", "a"), null)
+        );
+
+        assertEquals(eFilters(path("", "a"), list(include("table"), exclude("table"))),
+                     filters.filter(path("", "a")));
+    }
+
+    @Test
+    public void testFiltersTopLevelTables() throws Exception {
+        FiltersConfig filters = new FiltersConfig(
+            eFilters(path(null, null), include("TableName"))
+        );
+
+        assertEquals(eFilters(path(null, null), include("TableName")),
+                     filters.filter(path("", "APP")));
+    }
+
+    @Test
+    public void testFiltersFor2Schemas() throws Exception {
+        FiltersConfig filters = new FiltersConfig(
+                eFilters(path(null, "schema_01"), include("TableName_01")),
+                eFilters(path(null, "schema_02"), include("TableName_01"))
+        );
+
+        assertEquals(
+                eFilters(path(null, "schema_01"), include("TableName_01")),
+                filters.filter(path("", "schema_01")));
+
+        assertEquals("In case we don't have filter that cover path we should return null filter ",
+                eFilters(path("", "app"), null),
+                filters.filter(path("", "app")));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/FiltersFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/FiltersFactory.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/FiltersFactory.java
new file mode 100644
index 0000000..1ef7428
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/FiltersFactory.java
@@ -0,0 +1,44 @@
+/*
+ * 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.access.loader.filters;
+
+/**
+ * @since 3.2.
+ */
+public class FiltersFactory {
+
+    public static DbPath path(String catalog, String schema, String table) {
+        return new DbPath(catalog, schema, table);
+    }
+
+    public static DbPath path(String catalog, String schema) {
+        return new DbPath(catalog, schema);
+    }
+
+    public static DbPath path() {
+        return new DbPath();
+    }
+
+    public static EntityFilters eFilters(DbPath path, Filter<String> tableFilter) {
+        return new EntityFilters(path, tableFilter, null, null);
+    }
+    public static EntityFilters eFilters(DbPath path, Filter<String> table, Filter<String> column, Filter<String> proc) {
+        return new EntityFilters(path, table, column, proc);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/test/java/org/apache/cayenne/access/loader/mapper/DbTypeTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/mapper/DbTypeTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/mapper/DbTypeTest.java
new file mode 100644
index 0000000..8b2e8d4
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/mapper/DbTypeTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.access.loader.mapper;
+
+import org.junit.Test;
+
+import java.util.Iterator;
+import java.util.TreeSet;
+
+import static org.junit.Assert.*;
+
+public class DbTypeTest {
+
+    @Test
+    public void testCompareTo() throws Exception {
+        TreeSet<DbType> set = new TreeSet<DbType>();
+        set.add(new DbType("type-01", null, null, null, null));
+        set.add(new DbType("type-02", null, null, null, null));
+        set.add(new DbType("type-02", 1, null, null, null));
+        set.add(new DbType("type-02", 2, null, null, null));
+        set.add(new DbType("type-02", 2, null, null, true));
+        set.add(new DbType("type-02", 2, null, null, false));
+        set.add(new DbType("type-02", 2, null, 5, null));
+        set.add(new DbType("type-02", 2, null, 5, false));
+        set.add(new DbType("type-02", 2, null, 5, true));
+        set.add(new DbType("type-02", null, 8, 5, true));
+        set.add(new DbType("type-02", null, 9, 5, true));
+
+        Iterator<DbType> iterator = set.iterator();
+        assertEquals(new DbType("type-02", 2, null, 5, true), iterator.next());
+        assertEquals(new DbType("type-02", 2, null, 5, false), iterator.next());
+        assertEquals(new DbType("type-02", null, 9, 5, true), iterator.next());
+        assertEquals(new DbType("type-02", null, 8, 5, true), iterator.next());
+        assertEquals(new DbType("type-02", 2, null, 5, null), iterator.next());
+        assertEquals(new DbType("type-02", 2, null, null, true), iterator.next());
+        assertEquals(new DbType("type-02", 2, null, null, false), iterator.next());
+        assertEquals(new DbType("type-02", 2, null, null, null), iterator.next());
+        assertEquals(new DbType("type-02", 1, null, null, null), iterator.next());
+        assertEquals(new DbType("type-02", null, null, null, null), iterator.next());
+        assertEquals(new DbType("type-01", null, null, null, null), iterator.next());
+    }
+
+    @Test
+    public void testCover() throws Exception {
+        DbType typeJava = new DbType("java");
+        assertTrue(typeJava.isCover(typeJava));
+        assertTrue(typeJava.isCover(new DbType("java", 1, 1, 1, null)));
+        assertTrue(typeJava.isCover(new DbType("java", 1, null, null, null)));
+        assertTrue(typeJava.isCover(new DbType("java", null, 1, null, null)));
+        assertTrue(typeJava.isCover(new DbType("java", null, null, 1, null)));
+        assertTrue(typeJava.isCover(new DbType("java", null, null, null, true)));
+        assertTrue(typeJava.isCover(new DbType("java", null, null, null, false)));
+        assertFalse(typeJava.isCover(new DbType("java1", null, null, null, null)));
+
+        DbType typeWithLength = new DbType("java", 1, null, null, null);
+        assertTrue(typeWithLength.isCover(typeWithLength));
+        assertTrue(typeWithLength.isCover(new DbType("java", 1, null, 1, null)));
+        assertTrue(typeWithLength.isCover(new DbType("java", 1, null, 1, true)));
+        assertTrue(typeWithLength.isCover(new DbType("java", 1, null, null, true)));
+        assertTrue(typeWithLength.isCover(new DbType("java", 1, 1, null, true)));
+        assertFalse(typeWithLength.isCover(new DbType("java", 2, null, null, null)));
+        assertFalse(typeWithLength.isCover(new DbType("java", null, null, null, true)));
+        assertFalse(typeWithLength.isCover(new DbType("java1", 2, null, null, null)));
+
+        DbType typeWithLengthAndNotNull = new DbType("java", 1, null, null, true);
+        assertTrue(typeWithLength.isCover(typeWithLengthAndNotNull));
+        assertTrue(typeWithLength.isCover(new DbType("java", 1, null, 1, true)));
+        assertTrue(typeWithLength.isCover(new DbType("java", 1, 1, 1, true)));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java
index dc8a349..1305229 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
 import java.util.List;
 
 import org.apache.cayenne.access.DataNode;
+import org.apache.cayenne.access.loader.DbLoaderConfiguration;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.di.Inject;
@@ -98,7 +99,7 @@ public abstract class MergeCase extends ServerCase {
     }
 
     protected DbMerger createMerger(MergerFactory mergerFactory, ValueForNullProvider valueForNullProvider) {
-        return new DbMerger(mergerFactory, valueForNullProvider, null) {
+        return new DbMerger(mergerFactory, valueForNullProvider) {
 
             @Override
             public boolean includeTableName(String tableName) {
@@ -108,7 +109,7 @@ public abstract class MergeCase extends ServerCase {
     }
 
     protected List<MergerToken> createMergeTokens() {
-        return createMerger(node.getAdapter().mergerFactory()).createMergeTokens(node, map);
+        return createMerger(node.getAdapter().mergerFactory()).createMergeTokens(node, map, new DbLoaderConfiguration());
     }
 
     /**

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

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

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/pom.xml b/cayenne-tools/pom.xml
index 835b909..d48a654 100644
--- a/cayenne-tools/pom.xml
+++ b/cayenne-tools/pom.xml
@@ -66,6 +66,12 @@
 			<groupId>org.apache.ant</groupId>
 			<artifactId>ant</artifactId>
 		</dependency>
+        <dependency>
+            <groupId>org.apache.ant</groupId>
+            <artifactId>ant-testutil</artifactId>
+            <version>1.9.4</version>
+            <scope>test</scope>
+        </dependency>
 
 		<dependency>
 			<groupId>commons-collections</groupId>
@@ -115,6 +121,16 @@
 			<groupId>net.java.dev.inflector</groupId>
 			<artifactId>inflector</artifactId>
 		</dependency>
+        <dependency>
+            <groupId>org.apache.derby</groupId>
+            <artifactId>derby</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>xmlunit</groupId>
+            <artifactId>xmlunit</artifactId>
+            <scope>test</scope>
+        </dependency>
 
 	</dependencies>
 	
@@ -131,6 +147,16 @@
 				</executions>
 			</plugin>
             <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
                 <artifactId>maven-checkstyle-plugin</artifactId>
                 <!--<configuration>
                     <suppressionsLocation>${project.basedir}/cayenne-checkstyle-suppression.xml</suppressionsLocation>


[6/7] CAY-1946 CDbimport improvements

Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NamePatternMatcher.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NamePatternMatcher.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NamePatternMatcher.java
new file mode 100644
index 0000000..6faa7e4
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NamePatternMatcher.java
@@ -0,0 +1,225 @@
+/*****************************************************************
+ *   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.access.loader;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.cayenne.util.CayenneMapEntry;
+import org.apache.commons.logging.Log;
+
+/**
+ * Provides name pattern matching functionality.
+ * 
+ * @since 1.2
+ */
+public class NamePatternMatcher implements NameFilter {
+
+    private static final String[] EMPTY_ARRAY = new String[0];
+    private static final Pattern COMMA = Pattern.compile(",");
+
+    private final Pattern[] itemIncludeFilters;
+    private final Pattern[] itemExcludeFilters;
+
+    public static NamePatternMatcher build(Log logger, String includePattern, String excludePattern) {
+        return new NamePatternMatcher(createPatterns(logger, includePattern), createPatterns(logger, excludePattern));
+    }
+
+    public NamePatternMatcher(Pattern[] itemIncludeFilters, Pattern[] itemExcludeFilters) {
+        this.itemIncludeFilters = itemIncludeFilters;
+        this.itemExcludeFilters = itemExcludeFilters;
+    }
+
+    /**
+     * Applies preconfigured list of filters to the list, removing entities that do not
+     * pass the filter.
+     * 
+     * @deprecated since 3.0 still used by AntDataPortDelegate, which itself should
+     *             probably be deprecated
+     */
+    @Deprecated
+    public List<?> filter(List<?> items) {
+        if (items == null || items.isEmpty()) {
+            return items;
+        }
+
+        if (itemIncludeFilters.length == 0 && itemExcludeFilters.length == 0) {
+            return items;
+        }
+
+        Iterator<?> it = items.iterator();
+        while (it.hasNext()) {
+            CayenneMapEntry entity = (CayenneMapEntry) it.next();
+
+            if (!passedIncludeFilter(entity.getName())) {
+                it.remove();
+                continue;
+            }
+
+            if (!passedExcludeFilter(entity.getName())) {
+                it.remove();
+            }
+        }
+
+        return items;
+    }
+
+    /**
+     * Returns an array of Patterns. Takes a comma-separated list of patterns, attempting
+     * to convert them to the java.util.regex.Pattern syntax. E.g.
+     * <p>
+     * <code>"billing_*,user?"</code> will become an array of two expressions:
+     * <p>
+     * <code>^billing_.*$</code><br>
+     * <code>^user.?$</code><br>
+     */
+    public static Pattern[] createPatterns(Log logger, String patternString) {
+        if (patternString == null) {
+            return new Pattern[0];
+        }
+        String[] patternStrings = tokenizePattern(patternString);
+        List<Pattern> patterns = new ArrayList<Pattern>(patternStrings.length);
+
+        for (String patternString1 : patternStrings) {
+
+            // test the pattern
+            try {
+                patterns.add(Pattern.compile(patternString1));
+            } catch (PatternSyntaxException e) {
+
+                if (logger != null) {
+                    logger.warn("Ignoring invalid pattern [" + patternString1 + "], reason: " + e.getMessage());
+                }
+            }
+        }
+
+        return patterns.toArray(new Pattern[patterns.size()]);
+    }
+
+    /**
+     * Returns an array of valid regular expressions. Takes a comma-separated list of
+     * patterns, attempting to convert them to the java.util.regex.Pattern syntax. E.g.
+     * <p>
+     * <code>"billing_*,user?"</code> will become an array of two expressions:
+     * <p>
+     * <code>^billing_.*$</code><br>
+     * <code>^user.?$</code><br>
+     */
+    public static String[] tokenizePattern(String pattern) {
+        if (pattern == null || pattern.isEmpty()) {
+            return EMPTY_ARRAY;
+        }
+
+        String[] patterns = COMMA.split(pattern);
+        if (patterns.length == 0) {
+            return EMPTY_ARRAY;
+        }
+
+        for (int i = 0; i < patterns.length; i++) {
+            // convert * into regex syntax
+            // e.g. abc*x becomes ^abc.*x$
+            // or abc?x becomes ^abc.?x$
+            patterns[i] = "^" + patterns[i].replaceAll("[*?]", ".$0") + "$";
+        }
+
+        return patterns;
+    }
+
+    /**
+     * Returns true if a given object property satisfies the include/exclude patterns.
+     * 
+     * @since 3.0
+     */
+    @Override
+    public boolean isIncluded(String string) {
+        return passedIncludeFilter(string) && passedExcludeFilter(string);
+    }
+
+    /**
+     * Returns true if an object matches any one of the "include" patterns, or if there is
+     * no "include" patterns defined.
+     * 
+     * @since 3.0
+     */
+    private boolean passedIncludeFilter(String item) {
+        if (itemIncludeFilters.length == 0) {
+            return true;
+        }
+
+        for (Pattern itemIncludeFilter : itemIncludeFilters) {
+            if (itemIncludeFilter.matcher(item).find()) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns true if an object does not match any one of the "exclude" patterns, or if
+     * there is no "exclude" patterns defined.
+     * 
+     * @since 3.0
+     */
+    private boolean passedExcludeFilter(String item) {
+        if (itemExcludeFilters.length == 0) {
+            return true;
+        }
+
+        for (Pattern itemExcludeFilter : itemExcludeFilters) {
+            if (itemExcludeFilter.matcher(item).find()) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public static String replaceWildcardInStringWithString(
+            String wildcard,
+            String pattern,
+            String replacement) {
+
+        if (pattern == null || wildcard == null) {
+            return pattern;
+        }
+
+        StringBuilder buffer = new StringBuilder();
+        int lastPos = 0;
+        int wildCardPos = pattern.indexOf(wildcard);
+        while (wildCardPos != -1) {
+            if (lastPos != wildCardPos) {
+                buffer.append(pattern.substring(lastPos, wildCardPos));
+            }
+            buffer.append(replacement);
+            lastPos += wildCardPos + wildcard.length();
+            wildCardPos = pattern.indexOf(wildcard, lastPos);
+        }
+
+        if (lastPos < pattern.length()) {
+            buffer.append(pattern.substring(lastPos));
+        }
+
+        return buffer.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/DbPath.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/DbPath.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/DbPath.java
new file mode 100644
index 0000000..b9db92d
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/DbPath.java
@@ -0,0 +1,154 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.access.loader.filters;
+
+import java.util.regex.Pattern;
+
+/**
+* @since 3.2.
+* @Immutable
+*/
+public class DbPath implements Comparable<DbPath> {
+
+    public static final DbPath EMPTY = new DbPath();
+
+    public static final String SEPARATOR = "/";
+    public final String catalog;
+    public final String schema;
+    public final String tablePattern;
+
+    private final String path;
+
+    public DbPath() {
+        this(null, null, null);
+    }
+
+    public DbPath(String catalog) {
+        this(catalog, null, null);
+    }
+
+    public DbPath(String catalog, String schema) {
+        this(catalog, schema, null);
+    }
+
+    public DbPath(String catalog, String schema, String tablePattern) {
+        this.catalog = prepareValue(catalog);
+        this.schema = prepareValue(schema);
+        this.tablePattern = prepareValue(tablePattern);
+
+        this.path = join(this.catalog, this.schema, this.tablePattern);
+    }
+
+    private static String join(String first, String second) {
+        if (second == null || second.equals("%")) {
+            return first;
+        } else {
+            return escapeNull(first) + SEPARATOR + second;
+        }
+    }
+
+    private static String join(String catalog, String schema, String table) {
+        String join = join(catalog, join(schema, table));
+        return escapeNull(join);
+    }
+
+    private static String escapeNull(String join) {
+        return join == null ? "%" : join;
+    }
+
+    private String prepareValue(String value) {
+        return value == null ? null : value.trim();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        DbPath dbPath = (DbPath) o;
+
+        return path.equals(dbPath.path);
+    }
+
+
+    @Override
+    public int hashCode() {
+        return path.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return path;
+    }
+
+    @Override
+    public int compareTo(DbPath o) {
+        return path.compareTo(o.path);
+    }
+
+    public boolean isCover(String catalog, String schema) {
+        return isCover(catalog, schema, null);
+    }
+
+    public boolean isCover(String catalog, String schema, String table) {
+        if (this.catalog == null && catalog == null) {
+            return schemaCover(schema, table);
+        } else if (this.catalog == null) {
+            return schemaCover(schema, table);
+        } else {
+            return this.catalog.equalsIgnoreCase(catalog) && schemaCover(schema, table);
+        }
+    }
+
+    private boolean schemaCover(String schema, String table) {
+        if (this.schema == null && schema == null) {
+            return tableCover(table);
+        } else if (this.schema == null) {
+            return tableCover(table);
+        } else {
+            return this.schema.equalsIgnoreCase(schema) && tableCover(table);
+        }
+    }
+
+    private boolean tableCover(String table) {
+        return this.tablePattern == null
+                || table != null && Pattern.compile(this.tablePattern, Pattern.CASE_INSENSITIVE).matcher(table).matches();
+    }
+
+    public boolean isCover(DbPath dbPath) {
+        if (dbPath == null) {
+            throw new IllegalArgumentException("dbPath can't be null");
+        }
+        return isCover(dbPath.catalog, dbPath.schema, dbPath.tablePattern);
+    }
+
+    public DbPath merge(DbPath path) {
+        if (this.isCover(path)) {
+            return this;
+        } else if (path.isCover(this)) {
+            return path;
+        } else {
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/EntityFilters.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/EntityFilters.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/EntityFilters.java
new file mode 100644
index 0000000..5fde570
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/EntityFilters.java
@@ -0,0 +1,399 @@
+/*****************************************************************
+ *   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.access.loader.filters;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.util.EqualsBuilder;
+import org.apache.cayenne.util.HashCodeBuilder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import static org.apache.cayenne.access.loader.filters.FilterFactory.*;
+
+/**
+ * @since 3.2.
+ * @Immutable
+ */
+public class EntityFilters {
+
+    private static final Log LOG = LogFactory.getLog(Filter.class);
+
+    private final DbPath dbPath;
+
+    private final Filter<String> tableFilters;
+    private final Filter<String> columnFilters;
+    private final Filter<String> proceduresFilters;
+
+
+    public EntityFilters(DbPath dbPath) {
+        this(dbPath, NULL, NULL, NULL);
+    }
+    public EntityFilters(DbPath dbPath, Filter<String> tableFilters, Filter<String> columnFilters, Filter<String> proceduresFilters) {
+        this.dbPath = dbPath;
+        this.tableFilters = set(tableFilters);
+        this.columnFilters = set(columnFilters);
+        this.proceduresFilters = set(proceduresFilters);
+    }
+
+    public boolean isEmpty() {
+        return (tableFilters == null || NULL.equals(tableFilters))
+                && (columnFilters == null || NULL.equals(columnFilters))
+                && (proceduresFilters == null || NULL.equals(proceduresFilters));
+    }
+
+    public DbPath getDbPath() {
+        return dbPath;
+    }
+
+    private Filter<String> set(Filter<String> tableFilters) {
+        return tableFilters == null ? NULL : tableFilters;
+    }
+
+    public Filter<DbEntity> tableFilter() {
+        return new DbEntityFilter(dbPath, tableFilters);
+    }
+
+    public Filter<DbAttribute> columnFilter() {
+        return new DbAttributeFilter(dbPath, columnFilters);
+    }
+
+    public Filter<Procedure> procedureFilter() {
+        return new ProcedureFilter(dbPath, proceduresFilters);
+    }
+
+    public EntityFilters join(EntityFilters filter) {
+        if (filter == null) {
+            return this;
+        }
+
+        DbPath path;
+        if (this.dbPath == null) {
+            path = filter.dbPath;
+        } else if (filter.dbPath == null) {
+            path = this.dbPath;
+        } else {
+            path = this.dbPath.merge(filter.dbPath);
+        }
+
+        return new EntityFilters(path,
+                this.tableFilters.join(filter.tableFilters),
+                this.columnFilters.join(filter.columnFilters),
+                this.proceduresFilters.join(filter.proceduresFilters));
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder res = new StringBuilder();
+        res.append(dbPath).append(":\n");
+        if (tableFilters != null) {
+            res.append("    Table: ").append(tableFilters).append("\n");
+        }
+
+        if (columnFilters != null) {
+            res.append("    Column: ").append(columnFilters).append("\n");
+        }
+
+        if (proceduresFilters != null) {
+            res.append("    Procedures: ").append(proceduresFilters).append("\n");
+        }
+
+        return res.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (obj == this) {
+            return true;
+        }
+        if (obj.getClass() != getClass()) {
+            return false;
+        }
+
+        EntityFilters rhs = (EntityFilters) obj;
+        return new EqualsBuilder()
+                .append(this.dbPath, rhs.dbPath)
+                .append(this.tableFilters, rhs.tableFilters)
+                .append(this.columnFilters, rhs.columnFilters)
+                .append(this.proceduresFilters, rhs.proceduresFilters)
+                .isEquals();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder()
+                .append(dbPath)
+                .append(tableFilters)
+                .append(columnFilters)
+                .append(proceduresFilters)
+                .toHashCode();
+    }
+
+    /**
+     * @Immutable
+     * @param <T>
+     */
+    private abstract static class EntityFilter<T> implements Filter<T> {
+
+        private final DbPath dbPath;
+        private final Filter<String> filter;
+
+        protected EntityFilter(DbPath dbPath, Filter<String> filter) {
+            this.dbPath = dbPath;
+            this.filter = filter;
+        }
+
+        DbPath getDbPath() {
+            return dbPath;
+        }
+
+        Filter<String> getFilter() {
+            return filter;
+        }
+
+        @Override
+        public EntityFilter<T> join(Filter<T> filter) {
+            if (!(filter instanceof EntityFilter)) {
+                throw new IllegalArgumentException("Unexpected filter join '" + this + "' and '" + filter + "'");
+            }
+
+            EntityFilter<T> entityFilter = (EntityFilter<T>) filter;
+            DbPath dbPath;
+            if (entityFilter.dbPath.isCover(this.dbPath)) {
+                dbPath = entityFilter.dbPath;
+            } else if (this.dbPath.isCover(entityFilter.dbPath)) {
+                dbPath = this.dbPath;
+            } else {
+                throw new IllegalArgumentException("Attempt to merge filter with incompatible tuples: '" + entityFilter.dbPath + "'");
+            }
+
+            return create(dbPath, this.filter.join(entityFilter.filter));
+        }
+
+        @Override
+        public String toString() {
+            return getClass().getSimpleName() + " (" + dbPath + " -> " + filter + ")";
+        }
+
+        public abstract EntityFilter<T> create(DbPath dbPath, Filter<String> filter);
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+
+            if (o == null) {
+                return false;
+            }
+
+            if (o instanceof Filter) { // TODO
+                return filter.equals(o);
+            }
+
+            if (getClass() != o.getClass()) {
+                return false;
+            }
+
+            return filter.equals(((EntityFilter) o).filter);
+
+        }
+
+        @Override
+        public int hashCode() {
+            return filter.hashCode();
+        }
+    }
+
+    private static class DbEntityFilter extends EntityFilter<DbEntity> {
+
+        public DbEntityFilter(DbPath dbPath, Filter<String> filter) {
+            super(dbPath, filter);
+        }
+
+        @Override
+        public boolean isInclude(DbEntity obj) {
+            if (LOG.isTraceEnabled()
+                    && this.getDbPath().isCover(obj.getCatalog(), obj.getSchema())) {
+
+                LOG.warn("Attempt to apply inconvenient filter '" + this + "' for dbEntity '" + obj + "'");
+            }
+
+            return this.getFilter().isInclude(obj.getName());
+        }
+
+        @Override
+        public EntityFilter<DbEntity> create(DbPath dbPath, Filter<String> filter) {
+            return new DbEntityFilter(dbPath, filter);
+        }
+    }
+
+    private static class DbAttributeFilter extends EntityFilter<DbAttribute> {
+
+        public DbAttributeFilter(DbPath dbPath, Filter<String> filter) {
+            super(dbPath, filter);
+        }
+
+        @Override
+        public boolean isInclude(DbAttribute obj) {
+            DbEntity entity = obj.getEntity();
+            if (LOG.isTraceEnabled()
+                    && this.getDbPath().isCover(entity.getCatalog(), entity.getSchema(), entity.getName())) {
+
+                LOG.warn("Attempt to apply inconvenient filter '" + this + "' for attribute '" + obj + "'");
+            }
+
+            return this.getFilter().isInclude(obj.getName());
+        }
+
+        @Override
+        public EntityFilter<DbAttribute> create(DbPath dbPath, Filter<String> filter) {
+            return new DbAttributeFilter(dbPath, filter);
+        }
+    }
+
+    private static class ProcedureFilter extends EntityFilter<Procedure> {
+
+        public ProcedureFilter(DbPath dbPath, Filter<String> filter) {
+            super(dbPath, filter);
+        }
+
+        @Override
+        public boolean isInclude(Procedure obj) {
+            if (LOG.isTraceEnabled()
+                    && this.getDbPath().isCover(obj.getCatalog(), obj.getSchema())) {
+
+                LOG.warn("Attempt to apply inconvenient filter '" + this + "' for procedure '" + obj + "'");
+            }
+            return this.getFilter().isInclude(obj.getName());
+        }
+
+        @Override
+        public EntityFilter<Procedure> create(DbPath dbPath, Filter<String> filter) {
+            return new ProcedureFilter(dbPath, filter);
+        }
+    }
+
+
+    public static final class Builder {
+        private String catalog;
+        private String schema;
+
+        private Filter<String> tableFilters = NULL;
+        private Filter<String> columnFilters = NULL;
+        private Filter<String> proceduresFilters = NULL;
+
+        public Builder() {
+        }
+
+        public Builder catalog(String catalog) {
+            this.catalog = catalog;
+            return this;
+        }
+
+        public Builder schema(String schema) {
+            this.schema = schema;
+            return this;
+        }
+
+        public String schema() {
+            return schema;
+        }
+
+        public Builder includeTables(String tableFilters) {
+            for (String pattern : tableFilters.split(",")) {
+                this.tableFilters = this.tableFilters.join(include(pattern));
+            }
+
+            return this;
+        }
+
+        public Builder includeColumns(String columnFilters) {
+            for (String pattern : columnFilters.split(",")) {
+                this.columnFilters = this.columnFilters.join(include(pattern));
+            }
+
+            return this;
+        }
+
+        public Builder includeProcedures(String proceduresFilters) {
+            for (String pattern : proceduresFilters.split(",")) {
+                this.proceduresFilters = this.proceduresFilters.join(include(pattern));
+            }
+
+            return this;
+        }
+
+        public Builder excludeTables(String tableFilters) {
+            for (String pattern : tableFilters.split(",")) {
+                this.tableFilters = this.tableFilters.join(exclude(pattern));
+            }
+
+            return this;
+        }
+
+        public Builder excludeColumns(String columnFilters) {
+            for (String pattern : columnFilters.split(",")) {
+                this.columnFilters = this.columnFilters.join(exclude(pattern));
+            }
+
+            return this;
+        }
+
+        public Builder excludeProcedures(String proceduresFilters) {
+            for (String pattern : proceduresFilters.split(",")) {
+                this.proceduresFilters = this.proceduresFilters.join(exclude(pattern));
+            }
+
+            return this;
+        }
+
+        public Filter<String> tableFilters() {
+            return tableFilters;
+        }
+
+        public Filter<String> columnFilters() {
+            return columnFilters;
+        }
+
+        public Filter<String> proceduresFilters() {
+            return proceduresFilters;
+        }
+
+        public void setTableFilters(Filter<String> tableFilters) {
+            this.tableFilters = tableFilters;
+        }
+
+        public void setColumnFilters(Filter<String> columnFilters) {
+            this.columnFilters = columnFilters;
+        }
+
+        public void setProceduresFilters(Filter<String> proceduresFilters) {
+            this.proceduresFilters = proceduresFilters;
+        }
+
+        public EntityFilters build() {
+            return new EntityFilters(new DbPath(catalog, schema), tableFilters, columnFilters, proceduresFilters);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/ExcludeFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/ExcludeFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/ExcludeFilter.java
new file mode 100644
index 0000000..5bc794a
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/ExcludeFilter.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.access.loader.filters;
+
+import java.util.regex.Pattern;
+
+/**
+ * @since 3.2.
+ * @Immutable
+ */
+public class ExcludeFilter extends IncludeFilter {
+
+    ExcludeFilter(Pattern pattern) {
+        super(pattern);
+    }
+
+    @Override
+    public boolean isInclude(String obj) {
+        return !super.isInclude(obj);
+    }
+
+    @Override
+    public String toString() {
+        return "-(" + super.getPattern() + ')';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/Filter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/Filter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/Filter.java
new file mode 100644
index 0000000..c499276
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/Filter.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.access.loader.filters;
+
+/**
+ * @since 3.2.
+ * @Immutable
+ */
+public interface Filter<T> {
+
+    boolean isInclude(T obj);
+
+    Filter<T> join(Filter<T> filter);
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/FilterFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/FilterFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/FilterFactory.java
new file mode 100644
index 0000000..88f3d8d
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/FilterFactory.java
@@ -0,0 +1,94 @@
+/*****************************************************************
+ *   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.access.loader.filters;
+
+import java.util.regex.Pattern;
+
+/**
+ * @since 3.2.
+ */
+public class FilterFactory {
+
+    public static Filter<String> TRUE = new Filter<String>() {
+        @Override
+        public boolean isInclude(String obj) {
+            return true;
+        }
+
+        @Override
+        public Filter<String> join(Filter<String> filter) {
+            return filter == null || NULL.equals(filter) ? this : filter;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            return this == o || o != null && getClass() == o.getClass();
+        }
+
+        @Override
+        public String toString() {
+            return "true";
+        }
+    };
+
+    public static Filter<String> NULL = new Filter<String>() {
+
+        @Override
+        public boolean isInclude(String obj) {
+            return false;
+        }
+
+        @Override
+        public Filter<String> join(Filter<String> filter) {
+            return filter == null ? this : filter;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            return this == o || o != null && getClass() == o.getClass();
+        }
+
+        @Override
+        public String toString() {
+            return "null";
+        }
+    };
+
+    public static Filter<String> include(String tablePattern) {
+        return new IncludeFilter(pattern(tablePattern));
+    }
+
+    public static Filter<String> exclude(String tablePattern) {
+        return new ExcludeFilter(pattern(tablePattern));
+    }
+
+    public static Filter<String> list(Filter<String> ... filters) {
+        Filter<String> res = NULL;
+        for (Filter<String> filter : filters) {
+            res = res.join(filter);
+        }
+        return res;
+    }
+
+    public static Pattern pattern(String tablePattern) {
+        return Pattern.compile(tablePattern, Pattern.CASE_INSENSITIVE);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/FiltersConfig.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/FiltersConfig.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/FiltersConfig.java
new file mode 100644
index 0000000..4e79811
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/FiltersConfig.java
@@ -0,0 +1,180 @@
+/*****************************************************************
+ *   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.access.loader.filters;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @since 3.2.
+ * @Immutable
+ */
+public class FiltersConfig {
+
+    private final List<DbPath> dbPaths;
+    private final Map<DbPath, EntityFilters> filters;
+
+    private List<DbPath> pathsForQueries;
+
+    public FiltersConfig(EntityFilters ... filters) {
+        this(Arrays.asList(filters));
+    }
+
+    public FiltersConfig(Collection<EntityFilters> filters) {
+        this.dbPaths = new LinkedList<DbPath>();
+        this.filters = new HashMap<DbPath, EntityFilters>();
+        for (EntityFilters filter : filters) {
+            if (filter == null) {
+                continue;
+            }
+
+            DbPath path = filter.getDbPath();
+            if (this.dbPaths.contains(path)) {
+                this.filters.put(path, this.filters.get(path).join(filter));
+                continue;
+            }
+
+            this.dbPaths.add(path);
+            this.filters.put(path, filter);
+        }
+
+        Collections.sort(this.dbPaths);
+    }
+
+    /**
+     * Used for loading tables and procedures, it's aim avoid unnecessary queries by compacting pairs of
+     * (Catalog, Schema)
+     *
+     * Example:
+     * <ul>
+     *      <li>"aaa", null</li>
+     *      <li>"aaa", "11"</li>
+     *      <li>"aa", null</li>
+     *      <li>"aa", "a"</li>
+     *      <li>"aa", "aa"</li>
+     *      <li>"aa", "aa"</li>
+     * </ul>
+     *
+     * Should return
+     * <ul>
+     *      <li>"aa", null</li>
+     *      <li>"aaa", null</li>
+     * </ul>
+     * For more examples please see tests.
+     *
+     * @return list of pairs (Catalog, Schema) for which getTables and getProcedures should be called
+     *
+     **/
+    public List<DbPath> pathsForQueries() {
+        if (pathsForQueries != null) {
+            return pathsForQueries;
+        }
+
+        pathsForQueries = new LinkedList<DbPath>();
+        if (filters.isEmpty()) {
+            return pathsForQueries;
+        }
+
+        boolean save = true;
+        String catalog = null;
+        String schema = null;
+        for (DbPath path : dbPaths) {
+            if (save || catalog != null && !catalog.equals(path.catalog)) {
+                catalog = path.catalog;
+                schema = null;
+                save = true;
+            }
+
+            if (save || schema != null && !schema.equals(path.schema)) {
+                schema = path.schema;
+                save = true;
+            }
+
+            if (save) {
+                save = false;
+                pathsForQueries.add(new DbPath(catalog, schema));
+            }
+        }
+
+        return pathsForQueries;
+    }
+
+    /**
+     * TODO comment
+     *
+     * Return filters that applicable for path (filters which path covering path passed in method)
+     * */
+    public EntityFilters filter(DbPath path) {
+        EntityFilters res = new EntityFilters(path);
+        for (Map.Entry<DbPath, EntityFilters> entry : filters.entrySet()) {
+            if (entry.getKey().isCover(path)) {
+                res = res.join(entry.getValue());
+            }
+        }
+
+        return res;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        Map<DbPath, EntityFilters> filters = ((FiltersConfig) o).filters;
+        if (this.filters.size() != filters.size()) {
+            return false;
+        }
+
+        for (Map.Entry<DbPath, EntityFilters> entry : this.filters.entrySet()) {
+            EntityFilters f = filters.get(entry.getKey());
+            if (f == null || !f.equals(entry.getValue())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder res = new StringBuilder();
+        for (DbPath dbPath : dbPaths) {
+            res.append("    ").append(dbPath).append(" -> ").append(filters.get(dbPath)).append("\n");
+        }
+
+        return res.toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return filters.hashCode();
+    }
+
+    public List<DbPath> getDbPaths() {
+        return dbPaths;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/IncludeFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/IncludeFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/IncludeFilter.java
new file mode 100644
index 0000000..eeb90dc
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/IncludeFilter.java
@@ -0,0 +1,76 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.access.loader.filters;
+
+import java.util.regex.Pattern;
+
+/**
+ * @since 3.2.
+ * @Immutable
+ */
+public class IncludeFilter implements Filter<String> {
+
+    private final Pattern pattern;
+
+    IncludeFilter(Pattern pattern) {
+        this.pattern = pattern;
+    }
+
+    @Override
+    public boolean isInclude(String obj) {
+        return pattern.matcher(obj).matches();
+    }
+
+    @Override
+    public Filter join(Filter filter) {
+        return ListFilter.create(this, filter);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (o instanceof ListFilter) {
+            return o.equals(this);
+        }
+
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        return pattern.toString().equals(((IncludeFilter) o).pattern.toString());
+
+    }
+
+    @Override
+    public int hashCode() {
+        return pattern.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "+(" + pattern + ')';
+    }
+
+    protected Pattern getPattern() {
+        return pattern;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/ListFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/ListFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/ListFilter.java
new file mode 100644
index 0000000..49fdb38
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/ListFilter.java
@@ -0,0 +1,123 @@
+/*****************************************************************
+ *   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.access.loader.filters;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+
+import static org.apache.cayenne.access.loader.filters.FilterFactory.NULL;
+import static org.apache.cayenne.access.loader.filters.FilterFactory.TRUE;
+
+/**
+ * @since 3.2.
+ * @Immutable
+ */
+public class ListFilter<T> implements Filter<T> {
+
+    private final Collection<Filter<T>> filters;
+
+    public ListFilter(Collection<Filter<T>> filters) {
+        this.filters = filters;
+    }
+
+    @Override
+    public boolean isInclude(T obj) {
+        for (Filter<T> filter : filters) {
+            if (!filter.isInclude(obj)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public Filter<T> join(Filter<T> filter) {
+        LinkedList<Filter<T>> list = new LinkedList<Filter<T>>(filters);
+        if (TRUE.equals(filter) || NULL.equals(filter)) {
+            // Do nothing.
+        } else if (filter instanceof ListFilter) {
+            list.addAll(((ListFilter<T>) filter).filters);
+        } else {
+            list.add(filter);
+        }
+
+        return new ListFilter<T>(list);
+    }
+
+    public static <T> Filter<T> create(Filter<T> filter1, Filter<T> filter2) {
+        if (filter1 == null || TRUE.equals(filter1) || NULL.equals(filter1)) {
+            return filter2;
+        }
+
+        if (filter2 == null || TRUE.equals(filter2) || NULL.equals(filter2)) {
+            return filter1;
+        }
+
+        if (filter1 instanceof ListFilter) {
+            return filter1.join(filter2);
+        }
+
+        if (filter2 instanceof ListFilter) {
+            return filter2.join(filter1);
+        }
+
+        if (filter1.equals(filter2)) {
+            return filter1;
+        }
+
+        return new ListFilter<T>(Arrays.asList(filter1, filter2));
+    }
+
+    @Override
+    public String toString() {
+        return StringUtils.join(filters, " & ");
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        if (getClass() != o.getClass()) {
+            if (o instanceof Filter && filters.size() == 1) {
+                return o.equals(filters.iterator().next());
+            } else {
+                return false;
+            }
+        }
+
+        ListFilter that = (ListFilter) o;
+        return filters != null ? filters.equals(that.filters) : that.filters == null;
+
+    }
+
+    @Override
+    public int hashCode() {
+        return filters != null ? filters.hashCode() : 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DbType.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DbType.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DbType.java
new file mode 100644
index 0000000..731f824
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DbType.java
@@ -0,0 +1,195 @@
+/*****************************************************************
+ *   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.access.loader.mapper;
+
+import org.apache.cayenne.util.EqualsBuilder;
+import org.apache.cayenne.util.HashCodeBuilder;
+import org.apache.commons.lang.builder.CompareToBuilder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import static org.apache.commons.lang.StringUtils.isBlank;
+
+/**
+ * @since 3.2.
+ * @Immutable
+ */
+public class DbType implements Comparable<DbType> {
+
+    private static final Log LOG = LogFactory.getLog(DbType.class);
+
+    public final String jdbc;
+
+    public final Integer length;
+    public final Integer precision;
+    public final Integer scale;
+    public final Boolean notNull;
+
+    public DbType(String jdbc) {
+        this(jdbc, null, null, null, null);
+    }
+
+    public DbType(String jdbc, Integer length, Integer precision, Integer scale, Boolean notNull) {
+        if (isBlank(jdbc)) {
+            throw new IllegalArgumentException("Jdbc type can't be null");
+        }
+        this.jdbc = jdbc;
+
+        this.length = getValidInt(length);
+        this.precision = getValidInt(precision);
+        this.scale = getValidInt(scale);
+        this.notNull = notNull;
+    }
+
+    public String getJdbc() {
+        return jdbc;
+    }
+
+    public Integer getLength() {
+        return length;
+    }
+
+    public Integer getPrecision() {
+        return precision;
+    }
+
+    public Integer getScale() {
+        return scale;
+    }
+
+    public Boolean getNotNull() {
+        return notNull;
+    }
+
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (obj == this) {
+            return true;
+        }
+        if (obj.getClass() != getClass()) {
+            return false;
+        }
+        DbType rhs = (DbType) obj;
+        return new EqualsBuilder()
+                .append(this.jdbc, rhs.jdbc)
+                .append(this.length, rhs.length)
+                .append(this.precision, rhs.precision)
+                .append(this.scale, rhs.scale)
+                .append(this.notNull, rhs.notNull)
+                .isEquals();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder()
+                .append(jdbc)
+                .append(length)
+                .append(precision)
+                .append(scale)
+                .append(notNull)
+                .toHashCode();
+    }
+
+
+    @Override
+    public String toString() {
+        String res = jdbc;
+
+        String len = "*";
+        if (isPositive(length)) {
+            len = length.toString();
+        }
+        if (isPositive(precision)) {
+            len = precision.toString();
+        }
+
+        res += " (" + len;
+        if (isPositive(scale)) {
+            res += ", " + scale;
+        }
+        res += ")";
+
+        if (notNull != null && notNull) {
+            res += " NOT NULL";
+        }
+
+        return res;
+    }
+
+    private boolean isPositive(Integer num) {
+        return num != null && num > 0;
+    }
+
+    private Integer getValidInt(Integer num) {
+        if (num == null || num > 0) {
+            return num;
+        }
+
+        LOG.warn("Invalid int value '" + num + "'");
+        return null;
+    }
+
+    /**
+     * Compare by specificity the most specific DbPath should be first in ordered list
+     */
+    @Override
+    public int compareTo(DbType dbType) {
+        return new CompareToBuilder()
+                .append(dbType.jdbc, jdbc)
+                .append(dbType.getSpecificity(), getSpecificity())
+                .append(dbType.length, length)
+                .append(dbType.precision, precision)
+                .append(dbType.scale, scale)
+                .append(dbType.notNull, notNull)
+                .toComparison();
+    }
+
+    private int getSpecificity() {
+        int res = 0;
+        if (isPositive(length)) {
+            res += 100;
+        }
+        if (isPositive(precision)) {
+            res += 100;
+        }
+        if (isPositive(scale)) {
+            res += 10;
+        }
+        if (this.notNull != null) {
+            res += 5;
+        }
+
+        return res;
+    }
+
+    public boolean isCover(DbType type) {
+        return this.jdbc.equals(type.jdbc)
+            && (isCover(length, type.length) || length == null && type.length == null && isCover(precision, type.precision))
+            && isCover(scale, type.scale)
+            && isCover(notNull, type.notNull);
+    }
+
+    private boolean isCover(Object a, Object b) {
+        return a == null || a.equals(b);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java
new file mode 100644
index 0000000..7f37eb7
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java
@@ -0,0 +1,282 @@
+/*****************************************************************
+ *   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.access.loader.mapper;
+
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.util.Util;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.sql.Types;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * @since 3.2.
+ */
+public class DefaultJdbc2JavaTypeMapper implements Jdbc2JavaTypeMapper {
+
+    // Never use "-1" or any other normal integer, since there
+    // is a big chance it is being reserved in java.sql.Types
+    public static final int NOT_DEFINED = Integer.MAX_VALUE;
+
+    // char constants for Java data types
+    public static final String JAVA_LONG = "java.lang.Long";
+    public static final String JAVA_BYTES = "byte[]";
+    public static final String JAVA_BOOLEAN = "java.lang.Boolean";
+    public static final String JAVA_STRING = "java.lang.String";
+    public static final String JAVA_SQLDATE = "java.sql.Date";
+    public static final String JAVA_UTILDATE = "java.util.Date";
+    public static final String JAVA_BIGDECIMAL = "java.math.BigDecimal";
+    public static final String JAVA_DOUBLE = "java.lang.Double";
+    public static final String JAVA_FLOAT = "java.lang.Float";
+    public static final String JAVA_INTEGER = "java.lang.Integer";
+    public static final String JAVA_SHORT = "java.lang.Short";
+    public static final String JAVA_BYTE = "java.lang.Byte";
+    public static final String JAVA_TIME = "java.sql.Time";
+    public static final String JAVA_TIMESTAMP = "java.sql.Timestamp";
+    public static final String JAVA_BLOB = "java.sql.Blob";
+
+    /**
+     * Keys: java class names, Values: SQL int type definitions from java.sql.Types
+     */
+    private final Map<String, Integer> javaSqlEnum = new HashMap<String, Integer>();
+
+    private final Map<DbType, String> mapping = new HashMap<DbType, String>();
+    private final SortedSet<DbType> dbTypes = new TreeSet<DbType>();
+
+    private Map<String, String> classToPrimitive;
+
+    {
+        add(Types.BIGINT, JAVA_LONG);
+        add(Types.BINARY, JAVA_BYTES);
+        add(Types.BIT, JAVA_BOOLEAN);
+        add(Types.BOOLEAN, JAVA_BOOLEAN);
+        add(Types.BLOB, JAVA_BYTES);
+        add(Types.CLOB, JAVA_STRING);
+        add(Types.CHAR, JAVA_STRING);
+        add(Types.DATE, JAVA_UTILDATE);
+        add(Types.DECIMAL, JAVA_BIGDECIMAL);
+        add(Types.DOUBLE, JAVA_DOUBLE);
+        add(Types.FLOAT, JAVA_FLOAT);
+        add(Types.INTEGER, JAVA_INTEGER);
+        add(Types.LONGVARCHAR, JAVA_STRING);
+        add(Types.LONGVARBINARY, JAVA_BYTES);
+        add(Types.NUMERIC, JAVA_BIGDECIMAL);
+        add(Types.REAL, JAVA_FLOAT);
+        add(Types.SMALLINT, JAVA_SHORT);
+        add(Types.TINYINT, JAVA_SHORT);
+        add(Types.TIME, JAVA_UTILDATE);
+        add(Types.TIMESTAMP, JAVA_UTILDATE);
+        add(Types.VARBINARY, JAVA_BYTES);
+        add(Types.VARCHAR, JAVA_STRING);
+
+        javaSqlEnum.put(JAVA_LONG, Types.BIGINT);
+        javaSqlEnum.put(JAVA_BYTES, Types.BINARY);
+        javaSqlEnum.put(JAVA_BOOLEAN, Types.BIT);
+        javaSqlEnum.put(JAVA_STRING, Types.VARCHAR);
+        javaSqlEnum.put(JAVA_SQLDATE, Types.DATE);
+        javaSqlEnum.put(JAVA_UTILDATE, Types.DATE);
+        javaSqlEnum.put(JAVA_TIMESTAMP, Types.TIMESTAMP);
+        javaSqlEnum.put(JAVA_BIGDECIMAL, Types.DECIMAL);
+        javaSqlEnum.put(JAVA_DOUBLE, Types.DOUBLE);
+        javaSqlEnum.put(JAVA_FLOAT, Types.FLOAT);
+        javaSqlEnum.put(JAVA_INTEGER, Types.INTEGER);
+        javaSqlEnum.put(JAVA_SHORT, Types.SMALLINT);
+        javaSqlEnum.put(JAVA_BYTE, Types.SMALLINT);
+        javaSqlEnum.put(JAVA_TIME, Types.TIME);
+        javaSqlEnum.put(JAVA_TIMESTAMP, Types.TIMESTAMP);
+
+        // add primitives
+        javaSqlEnum.put("byte", Types.TINYINT);
+        javaSqlEnum.put("int", Types.INTEGER);
+        javaSqlEnum.put("short", Types.SMALLINT);
+        javaSqlEnum.put("char", Types.CHAR);
+        javaSqlEnum.put("double", Types.DOUBLE);
+        javaSqlEnum.put("long", Types.BIGINT);
+        javaSqlEnum.put("float", Types.FLOAT);
+        javaSqlEnum.put("boolean", Types.BIT);
+
+        classToPrimitive = new HashMap<String, String>();
+        classToPrimitive.put(Byte.class.getName(), "byte");
+        classToPrimitive.put(Long.class.getName(), "long");
+        classToPrimitive.put(Double.class.getName(), "double");
+        classToPrimitive.put(Boolean.class.getName(), "boolean");
+        classToPrimitive.put(Float.class.getName(), "float");
+        classToPrimitive.put(Short.class.getName(), "short");
+        classToPrimitive.put(Integer.class.getName(), "int");
+    }
+
+    private Boolean usePrimitives;
+
+
+    /**
+     * Returns default java.sql.Types type by the Java type name.
+     *
+     * @param className Fully qualified Java Class name.
+     * @return The SQL type or NOT_DEFINED if no type found.
+     */
+    public int getJdbcTypeByJava(DbAttribute attribute, String className) {
+        if (className == null) {
+            return NOT_DEFINED;
+        }
+
+        Integer type = javaSqlEnum.get(className);
+        if (type != null) {
+            return type;
+        }
+
+        // try to load a Java class - some nonstandard mappings may work
+        try {
+            return getSqlTypeByJava(attribute, Util.getJavaClass(className));
+        } catch (Throwable th) {
+            return NOT_DEFINED;
+        }
+    }
+
+
+    public void add(int jdbcType, String java) {
+        add(new DbType(TypesMapping.getSqlNameByType(jdbcType)), java);
+    }
+
+    @Override
+    public void add(DbType type, String java) {
+        mapping.put(type, java);
+        dbTypes.add(type);
+    }
+
+    /**
+     * Guesses a default JDBC type for the Java class.
+     *
+     * @since 1.1
+     */
+    protected int getSqlTypeByJava(DbAttribute attribute, Class<?> javaClass) {
+        if (javaClass == null) {
+            return NOT_DEFINED;
+        }
+
+        // check standard mapping of class and superclasses
+        Class<?> aClass = javaClass;
+        while (aClass != null) {
+
+            String name;
+
+            if (aClass.isArray()) {
+                name = aClass.getComponentType().getName() + "[]";
+            }  else {
+                name = aClass.getName();
+            }
+
+            Object type = javaSqlEnum.get(name);
+            if (type != null) {
+                return ((Number) type).intValue();
+            }
+
+            aClass = aClass.getSuperclass();
+        }
+
+        // check non-standard JDBC types that are still supported by JPA
+        if (javaClass.isArray()) {
+
+            Class<?> elementType = javaClass.getComponentType();
+            if (Character.class.isAssignableFrom(elementType)
+                    || Character.TYPE.isAssignableFrom(elementType)) {
+                return Types.VARCHAR;
+            }
+            else if (Byte.class.isAssignableFrom(elementType)
+                    || Byte.TYPE.isAssignableFrom(elementType)) {
+                return Types.VARBINARY;
+            }
+        }
+
+        if (Calendar.class.isAssignableFrom(javaClass)) {
+            return Types.TIMESTAMP;
+        }
+
+        if (BigInteger.class.isAssignableFrom(javaClass)) {
+            return Types.BIGINT;
+        }
+
+        if (Serializable.class.isAssignableFrom(javaClass)) {
+            // serializable check should be the last one when all other mapping attempts failed
+            return Types.VARBINARY;
+        }
+
+        return NOT_DEFINED;
+    }
+
+    /**
+     * Get the corresponding Java type by its java.sql.Types counterpart. Note that this
+     * method should be used as a last resort, with explicit mapping provided by user used
+     * as a first choice, as it can only guess how to map certain types, such as NUMERIC,
+     * etc.
+     *
+     * @return Fully qualified Java type name or null if not found.
+     */
+    @Override
+    public String getJavaByJdbcType(DbAttribute attribute, int type) {
+        String jdbcType = TypesMapping.getSqlNameByType(type);
+        DbType dbType;
+        if (attribute != null) {
+            dbType = new DbType(
+                    jdbcType,
+                    attribute.getMaxLength(),
+                    attribute.getAttributePrecision(),
+                    attribute.getScale(),
+                    attribute.isMandatory());
+        } else {
+            dbType = new DbType(jdbcType);
+        }
+
+        String typeName = getJavaByJdbcType(dbType);
+
+        if (usePrimitives != null && usePrimitives) {
+            String primitive = classToPrimitive.get(typeName);
+            if (primitive != null) {
+                return primitive;
+            }
+        }
+
+        return typeName;
+    }
+
+    public String getJavaByJdbcType(DbType type) {
+        for (DbType t : dbTypes) {
+            if (t.isCover(type)) {
+                // because dbTypes sorted by specificity we will take first and the most specific matching
+                // that applicable for attribute
+                return mapping.get(t);
+            }
+        }
+
+        return null;
+    }
+
+    public Boolean getUsePrimitives() {
+        return usePrimitives;
+    }
+
+    public void setUsePrimitives(Boolean usePrimitives) {
+        this.usePrimitives = usePrimitives;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/Jdbc2JavaTypeMapper.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/Jdbc2JavaTypeMapper.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/Jdbc2JavaTypeMapper.java
new file mode 100644
index 0000000..8e4510c
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/Jdbc2JavaTypeMapper.java
@@ -0,0 +1,33 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.access.loader.mapper;
+
+import org.apache.cayenne.map.DbAttribute;
+
+/**
+ * @since 3.2.
+ */
+public interface Jdbc2JavaTypeMapper {
+
+    String getJavaByJdbcType(DbAttribute attribute, int type);
+
+    int getJdbcTypeByJava(DbAttribute attribute, String className);
+
+    void add(DbType type, String java);
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/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 ba7dcd4..08bf584 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
@@ -1,21 +1,21 @@
-/*****************************************************************
- *   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
+/*
+ * 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
+ *      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.
- ****************************************************************/
+ *    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.configuration;
 
 import org.apache.cayenne.map.DataMap;
@@ -31,7 +31,7 @@ public class DefaultConfigurationNameMapper implements ConfigurationNameMapper {
 
     private static final String DATA_MAP_SUFFIX = ".map.xml";
 
-    protected ConfigurationNodeVisitor<String> nameMapper;
+    private final ConfigurationNodeVisitor<String> nameMapper;
 
     public DefaultConfigurationNameMapper() {
         nameMapper = new NameMapper();
@@ -41,23 +41,18 @@ public class DefaultConfigurationNameMapper implements ConfigurationNameMapper {
         return node.acceptVisitor(nameMapper);
     }
 
-    public String configurationLocation(
-            Class<? extends ConfigurationNode> type,
-            String name) {
+    public String configurationLocation(Class<? extends ConfigurationNode> type, String name) {
         if (DataChannelDescriptor.class.isAssignableFrom(type)) {
             return getDataChannelName(name);
         }
-        else if (DataMap.class.isAssignableFrom(type)) {
+        if (DataMap.class.isAssignableFrom(type)) {
             return getDataMapName(name);
         }
 
-        throw new IllegalArgumentException("Unrecognized configuration type: "
-                + type.getName());
+        throw new IllegalArgumentException("Unrecognized configuration type: " + type.getName());
     }
 
-    public String configurationNodeName(
-            Class<? extends ConfigurationNode> type,
-            Resource resource) {
+    public String configurationNodeName(Class<? extends ConfigurationNode> type, Resource resource) {
 
         String path = resource.getURL().getPath();
         if (path == null || path.length() == 0) {
@@ -80,37 +75,36 @@ public class DefaultConfigurationNameMapper implements ConfigurationNameMapper {
                 return null;
             }
 
-            return path.substring(CAYENNE_PREFIX.length(), path.length()
-                    - CAYENNE_SUFFIX.length());
+            return path.substring(CAYENNE_PREFIX.length(), path.length() - CAYENNE_SUFFIX.length());
         }
-        else if (DataMap.class.isAssignableFrom(type)) {
+
+        if (DataMap.class.isAssignableFrom(type)) {
             if (!path.endsWith(DATA_MAP_SUFFIX)) {
                 return null;
             }
             return path.substring(0, path.length() - DATA_MAP_SUFFIX.length());
         }
 
-        throw new IllegalArgumentException("Unrecognized configuration type: "
-                + type.getName());
+        throw new IllegalArgumentException("Unrecognized configuration type: " + type.getName());
     }
 
-    protected String getDataChannelName(String name) {
+    protected static String getDataChannelName(String name) {
         if (name == null) {
-            throw new NullPointerException("Null DataChannelDescriptor name");
+            throw new IllegalArgumentException("Null DataChannelDescriptor name");
         }
 
         return CAYENNE_PREFIX + name + CAYENNE_SUFFIX;
     }
 
-    protected String getDataMapName(String name) {
+    protected static String getDataMapName(String name) {
         if (name == null) {
-            throw new NullPointerException("Null DataMap name");
+            throw new IllegalArgumentException("Null DataMap name");
         }
 
         return name + DATA_MAP_SUFFIX;
     }
 
-    final class NameMapper extends BaseConfigurationNodeVisitor<String> {
+    private final class NameMapper extends BaseConfigurationNodeVisitor<String> {
 
         @Override
         public String visitDataChannelDescriptor(DataChannelDescriptor descriptor) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
index 5d6a372..4764b69 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
@@ -1,21 +1,21 @@
-/*****************************************************************
- *   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
+/*
+ * 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
+ *      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.
- ****************************************************************/
+ *    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.dba;
 
@@ -335,10 +335,11 @@ public class JdbcAdapter implements DbAdapter {
             boolean firstPk = true;
 
             while (pkit.hasNext()) {
-                if (firstPk)
+                if (firstPk) {
                     firstPk = false;
-                else
+                } else {
                     sqlBuffer.append(", ");
+                }
 
                 DbAttribute at = pkit.next();
 
@@ -355,43 +356,41 @@ public class JdbcAdapter implements DbAdapter {
      */
     @Override
     public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) {
-
-        String[] types = externalTypesForJdbcType(column.getType());
-        if (types == null || types.length == 0) {
-            String entityName = column.getEntity() != null ? ((DbEntity) column.getEntity()).getFullyQualifiedName()
-                    : "<null>";
-            throw new CayenneRuntimeException("Undefined type for attribute '" + entityName + "." + column.getName()
-                    + "': " + column.getType());
-        }
-
-        String type = types[0];
         sqlBuffer.append(quotingStrategy.quotedName(column));
-        sqlBuffer.append(' ').append(type);
-
-        // append size and precision (if applicable)s
-        if (typeSupportsLength(column.getType())) {
-            int len = column.getMaxLength();
+        sqlBuffer.append(' ').append(getType(this, column));
 
-            int scale = (TypesMapping.isDecimal(column.getType()) && column.getType() != Types.FLOAT) ? column
-                    .getScale() : -1;
+        sqlBuffer.append(sizeAndPrecision(this, column));
+        sqlBuffer.append(column.isMandatory() ? " NOT NULL" : " NULL");
+    }
 
-            // sanity check
-            if (scale > len) {
-                scale = -1;
-            }
+    public static String sizeAndPrecision(DbAdapter adapter, DbAttribute column) {
+        if (!adapter.typeSupportsLength(column.getType())) {
+            return "";
+        }
 
-            if (len > 0) {
-                sqlBuffer.append('(').append(len);
+        int len = column.getMaxLength();
+        int scale = TypesMapping.isDecimal(column.getType()) && column.getType() != Types.FLOAT ? column.getScale() : -1;
 
-                if (scale >= 0) {
-                    sqlBuffer.append(", ").append(scale);
-                }
+        // sanity check
+        if (scale > len) {
+            scale = -1;
+        }
 
-                sqlBuffer.append(')');
-            }
+        if (len > 0) {
+            return "(" + len + (scale >= 0 ? ", " + scale : "") + ")";
         }
 
-        sqlBuffer.append(column.isMandatory() ? " NOT NULL" : " NULL");
+        return "";
+    }
+
+    public static String getType(DbAdapter adapter, DbAttribute column) {
+        String[] types = adapter.externalTypesForJdbcType(column.getType());
+        if (types == null || types.length == 0) {
+            String entityName = column.getEntity() != null ? column.getEntity().getFullyQualifiedName() : "<null>";
+            throw new CayenneRuntimeException("Undefined type for attribute '"
+                    + entityName + "." + column.getName() + "': " + column.getType());
+        }
+        return types[0];
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java
index 5f1f10c..6441070 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java
@@ -1356,4 +1356,39 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable
 		clearQueries();
 		clearResultSets();
 	}
+
+    /**
+     *
+     * @return package + "." + name when it is possible otherwise just name
+     *
+     * @since 3.2
+     */
+    public String getNameWithDefaultPackage(String name) {
+        return getNameWithPackage(defaultPackage, name);
+    }
+
+    /**
+     *
+     * @return package + "." + name when it is possible otherwise just name
+     *
+     * @since 3.2
+     */
+    public static String getNameWithPackage(String pack, String name) {
+        if (Util.isEmptyString(pack)) {
+            return name;
+        } else {
+            return pack + (pack.endsWith(".") ? ""  : ".") + name;
+        }
+    }
+
+    /**
+     *
+     * @param name
+     * @return package + "." + name when it is possible otherwise just name
+     *
+     * @since 3.2
+     */
+    public String getNameWithDefaultClientPackage(String name) {
+        return getNameWithPackage(defaultClientPackage, name);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
index e84a5a8..69f661a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
@@ -196,8 +196,9 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
 
         TestJoin testJoin = new TestJoin(this);
         for (DbRelationship rel : target.getRelationships()) {
-            if (rel.getTargetEntity() != src)
+            if (rel.getTargetEntity() != src) {
                 continue;
+            }
 
             List<DbJoin> otherJoins = rel.getJoins();
             if (otherJoins.size() != joins.size()) {
@@ -273,7 +274,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
         }
 
         DbRelationship revRel = getReverseRelationship();
-        return (revRel != null) ? revRel.isToDependentPK() : false;
+        return revRel != null && revRel.isToDependentPK();
     }
     
     /**
@@ -315,7 +316,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
             DbAttribute target = join.getTarget();
             DbAttribute source = join.getSource();
 
-            if ((target != null && !target.isPrimaryKey()) || (source != null && !source.isPrimaryKey())) {
+            if (target != null && !target.isPrimaryKey() || source != null && !source.isPrimaryKey()) {
                 return false;
             }
         }
@@ -390,8 +391,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
         // handle generic case: numJoins > 1
         else {
             idMap = new HashMap<String, Object>(numJoins * 2);
-            for (int i = 0; i < numJoins; i++) {
-                DbJoin join = joins.get(i);
+            for (DbJoin join : joins) {
                 DbAttribute source = join.getSource();
                 Object val = srcSnapshot.get(join.getSourceName());
 
@@ -437,8 +437,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
 
         // general case
         Map<String, Object> idMap = new HashMap<String, Object>(len * 2);
-        for (int i = 0; i < len; i++) {
-            DbJoin join = joins.get(i);
+        for (DbJoin join : joins) {
             Object val = targetSnapshot.get(join.getTargetName());
             idMap.put(join.getSourceName(), val);
         }
@@ -468,8 +467,10 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
      * relationship is "to one".
      */
     public Map<String, Object> srcPkSnapshotWithTargetSnapshot(Map<String, Object> targetSnapshot) {
-        if (!isToMany())
+        if (!isToMany()) {
             throw new CayenneRuntimeException("Only 'to many' relationships support this method.");
+        }
+
         return srcSnapshotWithTargetSnapshot(targetSnapshot);
     }
 
@@ -491,7 +492,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
         return false;
     }
 
-    final static class JoinTransformers {
+    static final class JoinTransformers {
 
         static final Transformer targetExtractor = new Transformer() {
 
@@ -509,7 +510,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
     }
 
     // a join used for comparison
-    final static class TestJoin extends DbJoin {
+    static final class TestJoin extends DbJoin {
 
         TestJoin(DbRelationship relationship) {
             super(relationship);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java
index 6fb47de..67317e3 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java
@@ -55,8 +55,8 @@ import org.apache.commons.collections.Transformer;
  */
 public class ObjEntity extends Entity implements ObjEntityListener, ConfigurationNode {
 
-    final public static int LOCK_TYPE_NONE = 0;
-    final public static int LOCK_TYPE_OPTIMISTIC = 1;
+    public static final int LOCK_TYPE_NONE = 0;
+    public static final int LOCK_TYPE_OPTIMISTIC = 1;
 
     // do not import CayenneDataObject as it introduces unneeded client
     // dependency
@@ -320,7 +320,7 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
         try {
             return Util.getJavaClass(name);
         } catch (ClassNotFoundException e) {
-            throw new CayenneRuntimeException("Failed to load class " + name + ": " + e.getMessage(), e);
+            throw new CayenneRuntimeException("Failed to doLoad class " + name + ": " + e.getMessage(), e);
         }
     }
 
@@ -461,7 +461,7 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
      * @since 1.2
      */
     public boolean isClientAllowed() {
-        return (getDataMap() == null || isServerOnly()) ? false : getDataMap().isClientSupported();
+        return getDataMap() != null && !isServerOnly() && getDataMap().isClientSupported();
     }
 
     public boolean isAbstract() {
@@ -948,12 +948,13 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
      * Clears mapping between entities, attributes and relationships.
      */
     public void clearDbMapping() {
-        if (dbEntityName == null)
+        if (dbEntityName == null) {
             return;
+        }
 
         for (ObjAttribute attribute : getAttributeMap().values()) {
             DbAttribute dbAttr = attribute.getDbAttribute();
-            if (null != dbAttr) {
+            if (dbAttr != null) {
                 attribute.setDbAttributePath(null);
             }
         }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/map/naming/DefaultUniqueNameGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/DefaultUniqueNameGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/DefaultUniqueNameGenerator.java
index c9989d4..95ab877 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/DefaultUniqueNameGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/DefaultUniqueNameGenerator.java
@@ -49,12 +49,7 @@ public class DefaultUniqueNameGenerator implements UniqueNameGenerator {
             generator = new DefaultUniqueNameGenerator(NameCheckers.embeddable, pattern) {
                 @Override
                 public String generate(Object namingContext, String nameBase) {
-                    String name = super.generate(namingContext, nameBase);
-                    DataMap map = (DataMap) namingContext;
-                    if (map.getDefaultPackage() != null) {
-                        return map.getDefaultPackage() + "." + name;
-                    }
-                    return name;
+                    return ((DataMap) namingContext).getNameWithDefaultPackage(super.generate(namingContext, nameBase));
                 }
             };
         } else {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-server/src/main/java/org/apache/cayenne/map/naming/NameCheckers.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/NameCheckers.java b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/NameCheckers.java
index ea8f393..f86f043 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/NameCheckers.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/NameCheckers.java
@@ -75,11 +75,7 @@ public enum NameCheckers implements NameChecker {
 		@Override
 		public boolean isNameInUse(Object namingContext, String name) {
 			DataMap map = (DataMap) namingContext;
-			if (map.getDefaultPackage() != null) {
-				return map
-						.getEmbeddable((map.getDefaultPackage() + "." + name)) != null;
-			}
-			return map.getEmbeddable(name) != null;
+            return map.getEmbeddable(map.getNameWithDefaultPackage(name)) != null;
 		}
 	},
 


[4/7] CAY-1946 CDbimport improvements

Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
index d53af89..0d97aa9 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
@@ -33,7 +33,7 @@ import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.Embeddable;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.query.Query;
-import org.apache.cayenne.tools.NamePatternMatcher;
+import org.apache.cayenne.access.loader.NamePatternMatcher;
 import org.apache.commons.logging.Log;
 import org.apache.velocity.Template;
 import org.apache.velocity.VelocityContext;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClientDataMapArtifact.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClientDataMapArtifact.java b/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClientDataMapArtifact.java
index 129f2d3..7ba22e4 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClientDataMapArtifact.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClientDataMapArtifact.java
@@ -42,22 +42,11 @@ public class ClientDataMapArtifact extends DataMapArtifact {
     @Override
     public String getQualifiedClassName() {
         String clientPrefix = "";
-
-        if (Util.nullSafeEquals(dataMap.getDefaultClientPackage(), dataMap
-                .getDefaultPackage())) {
+        if (Util.nullSafeEquals(dataMap.getDefaultClientPackage(), dataMap.getDefaultPackage())) {
             clientPrefix = "Client_";
         }
 
-        String pkg = dataMap.getDefaultClientPackage();
-        if (pkg == null) {
-            pkg = "";
-        }
-        else {
-            pkg = pkg + '.';
-        }
-
-        return pkg
-                + NameConverter.underscoredToJava(clientPrefix
-                        + NameConverter.specialCharsToJava(dataMap.getName()), true);
+        return dataMap.getNameWithDefaultClientPackage(NameConverter
+                .underscoredToJava(clientPrefix + NameConverter.specialCharsToJava(dataMap.getName()), true));
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/gen/DataMapArtifact.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/gen/DataMapArtifact.java b/cayenne-tools/src/main/java/org/apache/cayenne/gen/DataMapArtifact.java
index a9d5d6a..818b213 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/gen/DataMapArtifact.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/gen/DataMapArtifact.java
@@ -62,17 +62,8 @@ public class DataMapArtifact implements Artifact {
     }
 
     public String getQualifiedClassName() {
-        String pkg = dataMap.getDefaultPackage();
-        if (pkg == null) {
-            pkg = "";
-        }
-        else {
-            pkg = pkg + '.';
-        }
-
-        return pkg
-                + NameConverter.underscoredToJava(NameConverter
-                        .specialCharsToJava(dataMap.getName()), true);
+        return dataMap.getNameWithDefaultPackage(NameConverter
+                .underscoredToJava(NameConverter.specialCharsToJava(dataMap.getName()), true));
     }
 
     public Object getObject() {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java
index b63ce32..1b9f38a 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java
@@ -25,6 +25,7 @@ import java.util.regex.Pattern;
 
 import org.apache.cayenne.access.DataPort;
 import org.apache.cayenne.access.DataPortDelegate;
+import org.apache.cayenne.access.loader.NamePatternMatcher;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.query.Query;
@@ -60,10 +61,10 @@ class AntDataPortDelegate implements DataPortDelegate {
             String includeEntitiesPattern, String excludeEntitiesPattern) {
         this.parentTask = parentTask;
 
-        this.namePatternMatcher = new NamePatternMatcher(new AntLogger(
-                parentTask), includeEntitiesPattern, excludeEntitiesPattern);
+        AntLogger logger = new AntLogger(parentTask);
 
-        this.mapFilters = namePatternMatcher.createPatterns(mapsPattern);
+        this.namePatternMatcher = NamePatternMatcher.build(logger, includeEntitiesPattern, excludeEntitiesPattern);
+        this.mapFilters = NamePatternMatcher.createPatterns(logger, mapsPattern);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
index fd297fc..49329a7 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
@@ -22,8 +22,8 @@ import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
-import java.util.List;
 
+import org.apache.cayenne.access.loader.NameFilter;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.Embeddable;
 import org.apache.cayenne.map.ObjEntity;
@@ -36,12 +36,11 @@ import org.apache.cayenne.map.ObjEntity;
  */
 class CayenneGeneratorEntityFilterAction {
 
-    private NamePatternMatcher nameFilter;
+    private NameFilter nameFilter;
     private boolean client;
 
     Collection<Embeddable> getFilteredEmbeddables(DataMap mainDataMap) {
-        List<Embeddable> embeddables = new ArrayList<Embeddable>(mainDataMap
-                .getEmbeddables());
+        Collection<Embeddable> embeddables = new ArrayList<Embeddable>(mainDataMap.getEmbeddables());
 
         // filter out excluded entities...
         Iterator<Embeddable> it = embeddables.iterator();
@@ -62,20 +61,13 @@ class CayenneGeneratorEntityFilterAction {
     Collection<ObjEntity> getFilteredEntities(DataMap mainDataMap)
             throws MalformedURLException {
 
-        List<ObjEntity> entities = new ArrayList<ObjEntity>(mainDataMap.getObjEntities());
+        Collection<ObjEntity> entities = new ArrayList<ObjEntity>(mainDataMap.getObjEntities());
 
         // filter out excluded entities...
         Iterator<ObjEntity> it = entities.iterator();
-
         while (it.hasNext()) {
             ObjEntity e = it.next();
-            if (e.isGeneric()) {
-                it.remove();
-            }
-            else if (client && !e.isClientAllowed()) {
-                it.remove();
-            }
-            else if (!nameFilter.isIncluded(e.getName())) {
+            if (e.isGeneric() || client && !e.isClientAllowed() || !nameFilter.isIncluded(e.getName())) {
                 it.remove();
             }
         }
@@ -87,7 +79,7 @@ class CayenneGeneratorEntityFilterAction {
         this.client = client;
     }
 
-    public void setNameFilter(NamePatternMatcher nameFilter) {
+    public void setNameFilter(NameFilter nameFilter) {
         this.nameFilter = nameFilter;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
index e4e3787..dcd36e6 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
@@ -20,6 +20,7 @@ package org.apache.cayenne.tools;
 
 import java.io.File;
 
+import org.apache.cayenne.access.loader.NamePatternMatcher;
 import org.apache.cayenne.gen.ArtifactsGenerationMode;
 import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.gen.ClientClassGenerationAction;
@@ -115,10 +116,7 @@ public class CayenneGeneratorTask extends CayenneTask {
 
         CayenneGeneratorEntityFilterAction filterAction = new CayenneGeneratorEntityFilterAction();
         filterAction.setClient(client);
-        filterAction.setNameFilter(new NamePatternMatcher(
-                logger,
-                includeEntitiesPattern,
-                excludeEntitiesPattern));
+        filterAction.setNameFilter(NamePatternMatcher.build(logger, includeEntitiesPattern, excludeEntitiesPattern));
 
         try {
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
index 530f8f9..0407649 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
@@ -1,26 +1,40 @@
-/*****************************************************************
- *   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
+/*
+ * 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
+ *      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.
- ****************************************************************/
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ */
 
 package org.apache.cayenne.tools;
 
 import java.io.File;
 
+import org.apache.cayenne.access.loader.filters.EntityFilters;
+import org.apache.cayenne.access.loader.filters.FilterFactory;
+import org.apache.cayenne.conn.DataSourceInfo;
+import org.apache.cayenne.tools.dbimport.config.Catalog;
+import org.apache.cayenne.tools.dbimport.config.ExcludeColumn;
+import org.apache.cayenne.tools.dbimport.config.ExcludeProcedure;
+import org.apache.cayenne.tools.dbimport.config.ExcludeTable;
+import org.apache.cayenne.tools.dbimport.config.FilterContainer;
+import org.apache.cayenne.tools.dbimport.config.FiltersConfigBuilder;
+import org.apache.cayenne.tools.dbimport.config.IncludeColumn;
+import org.apache.cayenne.tools.dbimport.config.IncludeProcedure;
+import org.apache.cayenne.tools.dbimport.config.IncludeTable;
+import org.apache.cayenne.tools.dbimport.config.ReverseEngineering;
+import org.apache.cayenne.tools.dbimport.config.Schema;
 import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.map.naming.DefaultNameGenerator;
@@ -36,42 +50,34 @@ import org.apache.tools.ant.Task;
 
 public class DbImporterTask extends Task {
 
-    private final DbImportConfiguration parameters;
+    private final DbImportConfiguration config;
 
-    /**
-     * @deprecated since 3.2 in favor of "schema"
-     */
-    @Deprecated
-    private String schemaName;
+    private final ReverseEngineering reverseEngineering = new ReverseEngineering();
 
-    /**
-     * @deprecated since 3.2 in favor of "meaningfulPkTable"
-     */
-    @Deprecated
-    private boolean meaningfulPk;
+    private final EntityFilters.Builder filterBuilder = new EntityFilters.Builder();
 
     public DbImporterTask() {
-        parameters = new DbImportConfiguration();
-        parameters.setOverwrite(true);
-        parameters.setImportProcedures(false);
-        parameters.setUsePrimitives(true);
-        parameters.setNamingStrategy(DefaultNameGenerator.class.getName());
+        config = new DbImportConfiguration();
+        config.setOverwrite(true);
+        config.setUsePrimitives(true);
+        config.setNamingStrategy(DefaultNameGenerator.class.getName());
     }
 
     @Override
     public void execute() {
 
-        initSchema();
-        initMeaningfulPkTables();
+        config.setFiltersConfig(new FiltersConfigBuilder(reverseEngineering)
+                .add(filterBuilder.build())
+                .filtersConfig());
 
         validateAttributes();
 
         Log logger = new AntLogger(this);
-        parameters.setLogger(logger);
+        config.setLogger(logger);
         Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule());
 
         try {
-            injector.getInstance(DbImportAction.class).execute(parameters);
+            injector.getInstance(DbImportAction.class).execute(config);
         } catch (Exception ex) {
             Throwable th = Util.unwindException(ex);
 
@@ -96,16 +102,17 @@ public class DbImporterTask extends Task {
     protected void validateAttributes() throws BuildException {
         StringBuilder error = new StringBuilder("");
 
-        if (parameters.getDataMapFile() == null) {
+        if (config.getDataMapFile() == null) {
             error.append("The 'map' attribute must be set.\n");
         }
 
-        if (parameters.getDriver() == null) {
+        DataSourceInfo dataSourceInfo = config.getDataSourceInfo();
+        if (dataSourceInfo.getJdbcDriver() == null) {
             error.append("The 'driver' attribute must be set.\n");
         }
 
-        if (parameters.getUrl() == null) {
-            error.append("The 'adapter' attribute must be set.\n");
+        if (dataSourceInfo.getDataSourceUrl() == null) {
+            error.append("The 'url' attribute must be set.\n");
         }
 
         if (error.length() > 0) {
@@ -117,122 +124,151 @@ public class DbImporterTask extends Task {
      * @since 3.2
      */
     public void setOverwrite(boolean overwrite) {
-        parameters.setOverwrite(overwrite);
+        config.setOverwrite(overwrite);
     }
 
     /**
      * @deprecated since 3.2 use {@link #setSchema(String)}
      */
+    @Deprecated
     public void setSchemaName(String schemaName) {
-        this.schemaName = schemaName;
+        this.setSchema(schemaName);
     }
 
     /**
      * @since 3.2
      */
     public void setSchema(String schema) {
-        parameters.setSchema(schema);
+        filterBuilder.schema(schema);
     }
 
     /**
      * @since 3.2
      */
     public void setDefaultPackage(String defaultPackage) {
-        parameters.setDefaultPackage(defaultPackage);
+        config.setDefaultPackage(defaultPackage);
     }
 
     public void setTablePattern(String tablePattern) {
-        parameters.setTablePattern(tablePattern);
+        filterBuilder.includeTables(tablePattern);
     }
 
     public void setImportProcedures(boolean importProcedures) {
-        parameters.setImportProcedures(importProcedures);
+        filterBuilder.setProceduresFilters(importProcedures ? FilterFactory.TRUE : FilterFactory.NULL);
     }
 
     public void setProcedurePattern(String procedurePattern) {
-        parameters.setProcedurePattern(procedurePattern);
+        filterBuilder.includeProcedures(procedurePattern);
     }
 
     /**
      * @deprecated since 3.2 use {@link #setMeaningfulPkTables(String)}
      */
     public void setMeaningfulPk(boolean meaningfulPk) {
-        this.meaningfulPk = meaningfulPk;
+        log("'meaningfulPk' property is deprecated. Use 'meaningfulPkTables' pattern instead", Project.MSG_WARN);
+
+        if (meaningfulPk) {
+            setMeaningfulPkTables("*");
+        }
     }
 
     /**
      * @since 3.2
      */
     public void setMeaningfulPkTables(String meaningfulPkTables) {
-        parameters.setMeaningfulPkTables(meaningfulPkTables);
+        config.setMeaningfulPkTables(meaningfulPkTables);
     }
 
     public void setNamingStrategy(String namingStrategy) {
-        parameters.setNamingStrategy(namingStrategy);
+        config.setNamingStrategy(namingStrategy);
     }
 
     public void setAdapter(String adapter) {
-        parameters.setAdapter(adapter);
+        config.setAdapter(adapter);
     }
 
     public void setDriver(String driver) {
-        parameters.setDriver(driver);
+        config.setDriver(driver);
     }
 
     public void setMap(File map) {
-        parameters.setDataMapFile(map);
+        config.setDataMapFile(map);
     }
 
     public void setPassword(String password) {
-        parameters.setPassword(password);
+        config.setPassword(password);
     }
 
     public void setUrl(String url) {
-        parameters.setUrl(url);
+        config.setUrl(url);
     }
 
     public void setUserName(String username) {
-        parameters.setUsername(username);
+        config.setUsername(username);
     }
 
     /**
      * @since 3.2
      */
     public void setIncludeTables(String includeTables) {
-        parameters.setIncludeTables(includeTables);
+        filterBuilder.includeTables(includeTables);
     }
 
     /**
      * @since 3.2
      */
     public void setExcludeTables(String excludeTables) {
-        parameters.setExcludeTables(excludeTables);
+        filterBuilder.excludeTables(excludeTables);
     }
 
     /**
      * @since 3.2
      */
     public void setUsePrimitives(boolean usePrimitives) {
-        parameters.setUsePrimitives(usePrimitives);
+        config.setUsePrimitives(usePrimitives);
     }
 
-    private void initSchema() {
-        if (schemaName != null) {
-            log("'schemaName' property is deprecated. Use 'schema' instead", Project.MSG_WARN);
-        }
+    public void addConfiguredIncludeColumn(IncludeColumn includeColumn) {
+        reverseEngineering.addIncludeColumn(includeColumn);
+    }
 
-        if (parameters.getSchema() == null) {
-            parameters.setSchema(schemaName);
-        }
+    public void addConfiguredExcludeColumn(ExcludeColumn excludeColumn) {
+        reverseEngineering.addExcludeColumn(excludeColumn);
     }
 
-    private void initMeaningfulPkTables() {
-        if (meaningfulPk) {
-            log("'meaningfulPk' property is deprecated. Use 'meaningfulPkTables' pattern instead", Project.MSG_WARN);
-        }
+    public void addConfiguredIncludeTable(IncludeTable includeTable) {
+        reverseEngineering.addIncludeTable(includeTable);
+    }
 
-        if (parameters.getMeaningfulPkTables() == null && meaningfulPk) {
-            parameters.setMeaningfulPkTables("*");
-        }
+    public void addConfiguredExcludeTable(ExcludeTable excludeTable) {
+        reverseEngineering.addExcludeTable(excludeTable);
+    }
+
+    public void addConfiguredIncludeProcedure(IncludeProcedure includeProcedure) {
+        reverseEngineering.addIncludeProcedure(includeProcedure);
+    }
+
+    public void addConfiguredExcludeProcedure(ExcludeProcedure excludeProcedure) {
+        reverseEngineering.addExcludeProcedure(excludeProcedure);
+    }
+
+    public void addConfiguredSchema(Schema schema) {
+        reverseEngineering.addSchema(schema);
+    }
+
+    public void addConfiguredCatalog(Catalog catalog) {
+        reverseEngineering.addCatalog(catalog);
+    }
+
+    public ReverseEngineering getReverseEngineering() {
+        return reverseEngineering;
+    }
+
+    public File getMap() {
+        return config.getDataMapFile();
+    }
+
+    public DbImportConfiguration toParameters() {
+        return config;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/NamePatternMatcher.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/NamePatternMatcher.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/NamePatternMatcher.java
deleted file mode 100644
index a567fb3..0000000
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/NamePatternMatcher.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-
-package org.apache.cayenne.tools;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.StringTokenizer;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-import org.apache.cayenne.util.CayenneMapEntry;
-import org.apache.commons.logging.Log;
-
-/**
- * Provides name pattern matching functionality.
- * 
- * @since 1.2
- */
-public class NamePatternMatcher {
-
-    protected Log logger;
-
-    protected Pattern[] itemIncludeFilters;
-    protected Pattern[] itemExcludeFilters;
-
-    public NamePatternMatcher(Log logger, String includePattern, String excludePattern) {
-        this.logger = logger;
-        this.itemIncludeFilters = createPatterns(includePattern);
-        this.itemExcludeFilters = createPatterns(excludePattern);
-    }
-
-    /**
-     * Applies preconfigured list of filters to the list, removing entities that do not
-     * pass the filter.
-     * 
-     * @deprecated since 3.0 still used by AntDataPortDelegate, which itself should
-     *             probably be deprecated
-     */
-    @Deprecated
-    List<?> filter(List<?> items) {
-        if (items == null || items.isEmpty()) {
-            return items;
-        }
-
-        if ((itemIncludeFilters.length == 0) && (itemExcludeFilters.length == 0)) {
-            return items;
-        }
-
-        Iterator<?> it = items.iterator();
-        while (it.hasNext()) {
-            CayenneMapEntry entity = (CayenneMapEntry) it.next();
-
-            if (!passedIncludeFilter(entity)) {
-                it.remove();
-                continue;
-            }
-
-            if (!passedExcludeFilter(entity)) {
-                it.remove();
-            }
-        }
-
-        return items;
-    }
-
-    /**
-     * Returns true if the entity matches any one of the "include" patterns, or if there
-     * is no "include" patterns defined.
-     * 
-     * @deprecated since 3.0. still used by AntDataPortDelegate, which itself should
-     *             probably be deprecated
-     */
-    @Deprecated
-    private boolean passedIncludeFilter(CayenneMapEntry item) {
-        if (itemIncludeFilters.length == 0) {
-            return true;
-        }
-
-        String itemName = item.getName();
-        for (Pattern itemIncludeFilter : itemIncludeFilters) {
-            if (itemIncludeFilter.matcher(itemName).find()) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Returns true if the entity does not match any one of the "exclude" patterns, or if
-     * there is no "exclude" patterns defined.
-     * 
-     * @deprecated since 3.0
-     */
-    @Deprecated
-    private boolean passedExcludeFilter(CayenneMapEntry item) {
-        if (itemExcludeFilters.length == 0) {
-            return true;
-        }
-
-        String itemName = item.getName();
-        for (Pattern itemExcludeFilter : itemExcludeFilters) {
-            if (itemExcludeFilter.matcher(itemName).find()) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Returns an array of Patterns. Takes a comma-separated list of patterns, attempting
-     * to convert them to the java.util.regex.Pattern syntax. E.g.
-     * <p>
-     * <code>"billing_*,user?"</code> will become an array of two expressions:
-     * <p>
-     * <code>^billing_.*$</code><br>
-     * <code>^user.?$</code><br>
-     */
-    public Pattern[] createPatterns(String patternString) {
-        String[] patternStrings = tokenizePattern(patternString);
-        List<Pattern> patterns = new ArrayList<Pattern>(patternStrings.length);
-
-        for (int i = 0; i < patternStrings.length; i++) {
-
-            // test the pattern
-            try {
-                patterns.add(Pattern.compile(patternStrings[i]));
-            }
-            catch (PatternSyntaxException e) {
-
-                if (logger != null) {
-                    logger.warn("Ignoring invalid pattern ["
-                            + patternStrings[i]
-                            + "], reason: "
-                            + e.getMessage());
-                }
-            }
-        }
-
-        return patterns.toArray(new Pattern[patterns.size()]);
-    }
-
-    /**
-     * Returns an array of valid regular expressions. Takes a comma-separated list of
-     * patterns, attempting to convert them to the java.util.regex.Pattern syntax. E.g.
-     * <p>
-     * <code>"billing_*,user?"</code> will become an array of two expressions:
-     * <p>
-     * <code>^billing_.*$</code><br>
-     * <code>^user.?$</code><br>
-     */
-    public String[] tokenizePattern(String pattern) {
-        if (pattern != null && pattern.length() > 0) {
-            StringTokenizer toks = new StringTokenizer(pattern, ",");
-
-            int len = toks.countTokens();
-            if (len == 0) {
-                return new String[0];
-            }
-
-            List<String> patterns = new ArrayList<String>(len);
-            for (int i = 0; i < len; i++) {
-                String nextPattern = toks.nextToken();
-                StringBuilder buffer = new StringBuilder();
-
-                // convert * into regex syntax
-                // e.g. abc*x becomes ^abc.*x$
-                // or abc?x becomes ^abc.?x$
-                buffer.append("^");
-                for (int j = 0; j < nextPattern.length(); j++) {
-                    char nextChar = nextPattern.charAt(j);
-                    if (nextChar == '*' || nextChar == '?') {
-                        buffer.append('.');
-                    }
-                    buffer.append(nextChar);
-                }
-                buffer.append("$");
-                patterns.add(buffer.toString());
-            }
-
-            return patterns.toArray(new String[patterns.size()]);
-        }
-        else {
-            return new String[0];
-        }
-    }
-
-    /**
-     * Returns true if a given object property satisfies the include/exclude patterns.
-     * 
-     * @since 3.0
-     */
-    public boolean isIncluded(String string) {
-
-        if ((itemIncludeFilters.length == 0) && (itemExcludeFilters.length == 0)) {
-            return true;
-        }
-
-        if (!passedIncludeFilter(string)) {
-            return false;
-        }
-
-        if (!passedExcludeFilter(string)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Returns true if an object matches any one of the "include" patterns, or if there is
-     * no "include" patterns defined.
-     * 
-     * @since 3.0
-     */
-    boolean passedIncludeFilter(String item) {
-        if (itemIncludeFilters.length == 0) {
-            return true;
-        }
-
-        for (Pattern itemIncludeFilter : itemIncludeFilters) {
-            if (itemIncludeFilter.matcher(item).find()) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Returns true if an object does not match any one of the "exclude" patterns, or if
-     * there is no "exclude" patterns defined.
-     * 
-     * @since 3.0
-     */
-    boolean passedExcludeFilter(String item) {
-        if (itemExcludeFilters.length == 0) {
-            return true;
-        }
-
-        for (Pattern itemExcludeFilter : itemExcludeFilters) {
-            if (itemExcludeFilter.matcher(item).find()) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    public static String replaceWildcardInStringWithString(
-            String wildcard,
-            String pattern,
-            String replacement) {
-        if (null == pattern || null == wildcard)
-            return pattern;
-
-        StringBuilder buffer = new StringBuilder();
-        int lastPos = 0;
-        int wildCardPos = pattern.indexOf(wildcard);
-        while (-1 != wildCardPos) {
-            if (lastPos != wildCardPos) {
-                buffer.append(pattern.substring(lastPos, wildCardPos));
-            }
-            buffer.append(replacement);
-            lastPos += wildCardPos + wildcard.length();
-            wildCardPos = pattern.indexOf(wildcard, lastPos);
-        }
-
-        if (lastPos < pattern.length()) {
-            buffer.append(pattern.substring(lastPos));
-        }
-
-        return buffer.toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
index a90881f..cb2aac6 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
@@ -1,21 +1,21 @@
-/*****************************************************************
- *   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
+/*
+ * 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
+ *      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.
- ****************************************************************/
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ */
 package org.apache.cayenne.tools.dbimport;
 
 import org.apache.cayenne.access.DbLoader;
@@ -67,7 +67,8 @@ public class DbImportAction {
     private final DbAdapterFactory adapterFactory;
     private final MapLoader mapLoader;
 
-    public DbImportAction(@Inject Log logger, @Inject ProjectSaver projectSaver,
+    public DbImportAction(@Inject Log logger,
+                          @Inject ProjectSaver projectSaver,
                           @Inject DataSourceFactory dataSourceFactory,
                           @Inject DbAdapterFactory adapterFactory,
                           @Inject MapLoader mapLoader) {
@@ -78,30 +79,29 @@ public class DbImportAction {
         this.mapLoader = mapLoader;
     }
 
-    public void execute(DbImportConfiguration parameters) throws Exception {
+    public void execute(DbImportConfiguration config) throws Exception {
 
         if (logger.isInfoEnabled()) {
-            logger.debug(String.format("DB connection - [driver: %s, url: %s, username: %s, password: %s]",
-                    parameters.getDriver(), parameters.getUrl(), parameters.getUsername(), "XXXXX"));
+            logger.debug("DB connection: " + config.getDataSourceInfo());
         }
 
         if (logger.isDebugEnabled()) {
-            parameters.log();
+            logger.debug(config);
         }
 
-        DataNodeDescriptor dataNodeDescriptor = parameters.createDataNodeDescriptor();
+        DataNodeDescriptor dataNodeDescriptor = config.createDataNodeDescriptor();
         DataSource dataSource = dataSourceFactory.getDataSource(dataNodeDescriptor);
         DbAdapter adapter = adapterFactory.createAdapter(dataNodeDescriptor, dataSource);
 
-        DataMap loadedFomDb = load(parameters, adapter, dataSource.getConnection());
+        DataMap loadedFomDb = load(config, adapter, dataSource.getConnection());
         if (loadedFomDb == null) {
             logger.info("Nothing was loaded from db.");
             return;
         }
 
-        DataMap existing = loadExistingDataMap(parameters.getDataMapFile());
+        DataMap existing = loadExistingDataMap(config.getDataMapFile());
         if (existing == null) {
-            saveLoaded(loadedFomDb);
+            saveLoaded(config.initializeDataMap(loadedFomDb));
         } else {
             MergerFactory mergerFactory = adapter.mergerFactory();
 
@@ -111,7 +111,7 @@ public class DbImportAction {
                 return;
             }
 
-            saveLoaded(execute(parameters.createMergeDelegate(), existing, log(reverse(mergerFactory, mergeTokens))));
+            saveLoaded(execute(config.createMergeDelegate(), existing, log(reverse(mergerFactory, mergeTokens))));
         }
     }
 
@@ -184,18 +184,13 @@ public class DbImportAction {
         projectSaver.save(project);
     }
 
-    private DataMap load(DbImportConfiguration parameters, DbAdapter adapter, Connection connection) throws Exception {
-        DataMap dataMap = parameters.createDataMap();
+    private DataMap load(DbImportConfiguration config, DbAdapter adapter, Connection connection) throws Exception {
+        DataMap dataMap = config.createDataMap();
 
         try {
-            DbLoader loader = parameters.createLoader(adapter, connection, parameters.createLoaderDelegate());
-
-            String[] types = loader.getDefaultTableTypes();
-            loader.load(dataMap, parameters.getCatalog(), parameters.getSchema(), parameters.getTablePattern(), types);
+            DbLoader loader = config.createLoader(adapter, connection, config.createLoaderDelegate());
 
-            if (parameters.isImportProcedures()) {
-                loader.loadProcedures(dataMap, parameters.getCatalog(), parameters.getSchema(), parameters.getProcedurePattern());
-            }
+            dataMap = loader.load(config.getDbLoaderConfig());
         } finally {
             if (connection != null) {
                 connection.close();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java
index b7e780a..3092bb2 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java
@@ -1,49 +1,51 @@
-/*****************************************************************
- *   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
+/*
+ * 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
+ *      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.
- ****************************************************************/
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ */
 package org.apache.cayenne.tools.dbimport;
 
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.access.DbLoader;
-import org.apache.cayenne.access.DbLoaderConfiguration;
+import org.apache.cayenne.access.loader.DbLoaderConfiguration;
 import org.apache.cayenne.access.DbLoaderDelegate;
-import org.apache.cayenne.access.DefaultDbLoaderDelegate;
+import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate;
+import org.apache.cayenne.access.loader.NameFilter;
+import org.apache.cayenne.access.loader.filters.DbPath;
+import org.apache.cayenne.access.loader.filters.FiltersConfig;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.conn.DataSourceInfo;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.map.naming.ObjectNameGenerator;
 import org.apache.cayenne.merge.DefaultModelMergeDelegate;
 import org.apache.cayenne.merge.ModelMergeDelegate;
 import org.apache.cayenne.resource.URLResource;
-import org.apache.cayenne.tools.NamePatternMatcher;
+import org.apache.cayenne.access.loader.NamePatternMatcher;
 import org.apache.cayenne.util.EntityMergeSupport;
 import org.apache.commons.logging.Log;
-import org.xml.sax.InputSource;
 
 import java.io.File;
 import java.io.IOException;
-import java.net.URL;
+import java.net.MalformedURLException;
 import java.sql.Connection;
 import java.util.Collections;
+import java.util.List;
 
 import static org.apache.commons.lang.StringUtils.isNotEmpty;
 
@@ -70,69 +72,25 @@ public class DbImportConfiguration {
      */
     private boolean overwrite;
 
-    /**
-     * DB schema to use for DB importing.
-     */
-    private DbLoaderConfiguration dbLoaderConfiguration = new DbLoaderConfiguration();
-
-    /**
-     * Pattern for tables to import from DB
-     */
-    private String tablePattern;
-
-    /**
-     * Indicates whether stored procedures should be imported.
-     */
-    private boolean importProcedures;
-
-    /**
-     * Pattern for stored procedures to import from DB. This is only meaningful
-     * if <code>importProcedures</code> is set to <code>true</code>.
-     */
-    private String procedurePattern;
-
     private String meaningfulPkTables;
 
     /**
-     * Java class implementing org.apache.cayenne.map.naming.NamingStrategy.
-     * This is used to specify how ObjEntities will be mapped from the imported
-     * DB schema.
-     */
-    private String namingStrategy;
-
-    /**
      * Java class implementing org.apache.cayenne.dba.DbAdapter. This attribute
      * is optional, the default is AutoAdapter, i.e. Cayenne would try to guess
      * the DB type.
      */
     private String adapter;
 
-    /**
-     * A class of JDBC driver to use for the target database.
-     */
-    private String driver;
+    private boolean usePrimitives;
 
-    /**
-     * JDBC connection URL of a target database.
-     */
-    private String url;
+    private Log logger;
 
-    /**
-     * Database user name.
-     */
-    private String username;
+    private final DataSourceInfo dataSourceInfo = new DataSourceInfo();
 
     /**
-     * Database user password.
+     * DB schema to use for DB importing.
      */
-    private String password;
-
-    private String includeTables;
-    private String excludeTables;
-
-    private boolean usePrimitives;
-
-    private Log logger;
+    private final DbLoaderConfiguration dbLoaderConfiguration = new DbLoaderConfiguration();
 
     public Log getLogger() {
         return logger;
@@ -166,52 +124,12 @@ public class DbImportConfiguration {
         this.overwrite = overwrite;
     }
 
-    public String getCatalog() {
-        return dbLoaderConfiguration.getCatalog();
-    }
-
-    public void setCatalog(String catalog) {
-        this.dbLoaderConfiguration.setCatalog(catalog);
-    }
-
-    public void setSchema(String schema) {
-        dbLoaderConfiguration.setSchema(schema);
-    }
-
-    public String getSchema() {
-        return dbLoaderConfiguration.getSchema();
-    }
-
-    public String getTablePattern() {
-        return tablePattern;
-    }
-
-    public void setTablePattern(String tablePattern) {
-        this.tablePattern = tablePattern;
-    }
-
-    public boolean isImportProcedures() {
-        return importProcedures;
-    }
-
-    public void setImportProcedures(boolean importProcedures) {
-        this.importProcedures = importProcedures;
-    }
-
-    public String getProcedurePattern() {
-        return procedurePattern;
-    }
-
-    public void setProcedurePattern(String procedurePattern) {
-        this.procedurePattern = procedurePattern;
-    }
-
     public String getNamingStrategy() {
-        return namingStrategy;
+        return dbLoaderConfiguration.getNamingStrategy();
     }
 
     public void setNamingStrategy(String namingStrategy) {
-        this.namingStrategy = namingStrategy;
+        dbLoaderConfiguration.setNamingStrategy(namingStrategy);
     }
 
     public String getAdapter() {
@@ -222,54 +140,6 @@ public class DbImportConfiguration {
         this.adapter = adapter;
     }
 
-    public String getDriver() {
-        return driver;
-    }
-
-    public void setDriver(String driver) {
-        this.driver = driver;
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    public void setUrl(String url) {
-        this.url = url;
-    }
-
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
-
-    public String getPassword() {
-        return password;
-    }
-
-    public void setPassword(String password) {
-        this.password = password;
-    }
-
-    public String getIncludeTables() {
-        return includeTables;
-    }
-
-    public void setIncludeTables(String includeTables) {
-        this.includeTables = includeTables;
-    }
-
-    public String getExcludeTables() {
-        return excludeTables;
-    }
-
-    public void setExcludeTables(String excludeTables) {
-        this.excludeTables = excludeTables;
-    }
-
     /**
      * Returns a comma-separated list of Perl5 regular expressions that match
      * table names for which {@link DbImportAction} should include ObjAttribute
@@ -294,19 +164,14 @@ public class DbImportConfiguration {
     public DbLoader createLoader(DbAdapter adapter, Connection connection, DbLoaderDelegate loaderDelegate)
             throws InstantiationException, IllegalAccessException, ClassNotFoundException {
 
-        final NamePatternMatcher nameFilter = new NamePatternMatcher(logger, getIncludeTables(), getExcludeTables());
-        final NamePatternMatcher meaningfulPkFilter = new NamePatternMatcher(logger, getMeaningfulPkTables(),
+        final NameFilter meaningfulPkFilter = NamePatternMatcher.build(logger, getMeaningfulPkTables(),
                 getMeaningfulPkTables() != null ? null : "*");
 
         DbLoader loader = new DbLoader(connection, adapter, loaderDelegate) {
-            @Override
-            public boolean includeTableName(String tableName) {
-                return nameFilter.isIncluded(tableName);
-            }
 
             @Override
             protected EntityMergeSupport createEntityMerger(DataMap map) {
-                EntityMergeSupport emSupport = new EntityMergeSupport(map, nameGenerator, true) {
+                EntityMergeSupport emSupport = new EntityMergeSupport(map, getNameGenerator(), true) {
 
                     @Override
                     protected boolean removePK(DbEntity dbEntity) {
@@ -329,20 +194,42 @@ public class DbImportConfiguration {
         return loader;
     }
 
-    public DataSourceInfo createDataSourceInfo() {
-        DataSourceInfo dataSourceInfo = new DataSourceInfo();
-        dataSourceInfo.setDataSourceUrl(getUrl());
-        dataSourceInfo.setJdbcDriver(getDriver());
-        dataSourceInfo.setUserName(getUsername());
-        dataSourceInfo.setPassword(getPassword());
+    public void setDriver(String jdbcDriver) {
+        dataSourceInfo.setJdbcDriver(jdbcDriver);
+    }
+
+    public String getDriver() {
+        return dataSourceInfo.getJdbcDriver();
+    }
 
-        return dataSourceInfo;
+    public void setPassword(String password) {
+        dataSourceInfo.setPassword(password);
+    }
+
+    public String getPassword() {
+        return dataSourceInfo.getPassword();
+    }
+
+    public void setUsername(String userName) {
+        dataSourceInfo.setUserName(userName);
+    }
+
+    public String getUsername() {
+        return dataSourceInfo.getUserName();
+    }
+
+    public void setUrl(String dataSourceUrl) {
+        dataSourceInfo.setDataSourceUrl(dataSourceUrl);
+    }
+
+    public String getUrl() {
+        return dataSourceInfo.getDataSourceUrl();
     }
 
     public DataNodeDescriptor createDataNodeDescriptor() {
         DataNodeDescriptor nodeDescriptor = new DataNodeDescriptor();
         nodeDescriptor.setAdapterType(getAdapter());
-        nodeDescriptor.setDataSourceDescriptor(createDataSourceInfo());
+        nodeDescriptor.setDataSourceDescriptor(dataSourceInfo);
 
         return nodeDescriptor;
     }
@@ -352,14 +239,11 @@ public class DbImportConfiguration {
             throw new NullPointerException("Null DataMap File.");
         }
 
-        String name = dataMapFile.getName();
-        if (!name.endsWith(DATA_MAP_LOCATION_SUFFIX)) {
-            throw new CayenneRuntimeException("DataMap file name must end with '%s': '%s'", DATA_MAP_LOCATION_SUFFIX,
-                    name);
-        }
+        return initializeDataMap(new DataMap());
+    }
 
-        String dataMapName = name.substring(0, name.length() - DATA_MAP_LOCATION_SUFFIX.length());
-        DataMap dataMap = new DataMap(dataMapName);
+    public DataMap initializeDataMap(DataMap dataMap) throws MalformedURLException {
+        dataMap.setName(getDataMapName());
         dataMap.setConfigurationSource(new URLResource(dataMapFile.toURI().toURL()));
         dataMap.setNamespace(new EntityResolver(Collections.singleton(dataMap)));
 
@@ -372,25 +256,37 @@ public class DbImportConfiguration {
             dataMap.setDefaultPackage(defaultPackage);
         }
 
-        // do not override default catalog of existing DataMap unless it is
-        // explicitly requested by the plugin caller, and the provided catalog is
-        // not a pattern
-        String catalog = getCatalog();
-        if (isNotEmpty(catalog) && catalog.indexOf('%') < 0) {
-            dataMap.setDefaultCatalog(catalog);
-        }
+        List<DbPath> dbPaths = dbLoaderConfiguration.getFiltersConfig().getDbPaths();
+        if (!dbPaths.isEmpty()) {
+            // do not override default catalog of existing DataMap unless it is
+            // explicitly requested by the plugin caller, and the provided catalog is
+            // not a pattern
+            String catalog = dbPaths.get(0).catalog;
+            if (isNotEmpty(catalog) && catalog.indexOf('%') < 0) {
+                dataMap.setDefaultCatalog(catalog);
+            }
 
-        // do not override default schema of existing DataMap unless it is
-        // explicitly requested by the plugin caller, and the provided schema is
-        // not a pattern
-        String schema = getSchema();
-        if (isNotEmpty(schema) && schema.indexOf('%') < 0) {
-            dataMap.setDefaultSchema(schema);
+            // do not override default schema of existing DataMap unless it is
+            // explicitly requested by the plugin caller, and the provided schema is
+            // not a pattern
+            String schema = dbPaths.get(0).schema;
+            if (isNotEmpty(schema) && schema.indexOf('%') < 0) {
+                dataMap.setDefaultSchema(schema);
+            }
         }
 
         return dataMap;
     }
 
+    public String getDataMapName() {
+        String name = dataMapFile.getName();
+        if (!name.endsWith(DATA_MAP_LOCATION_SUFFIX)) {
+            throw new CayenneRuntimeException("DataMap file name must end with '%s': '%s'", DATA_MAP_LOCATION_SUFFIX,
+                    name);
+        }
+        return name.substring(0, name.length() - DATA_MAP_LOCATION_SUFFIX.length());
+    }
+
     public ModelMergeDelegate createMergeDelegate() {
         return new DefaultModelMergeDelegate();
     }
@@ -399,19 +295,25 @@ public class DbImportConfiguration {
         return new DefaultDbLoaderDelegate();
     }
 
-    public void log() {
-        logger.debug("Importer options - map: " + getDataMapFile());
-        logger.debug("Importer options - overwrite: " + isOverwrite());
-        logger.debug("Importer options - adapter: " + getAdapter());
-        logger.debug("Importer options - catalog: " + getCatalog());
-        logger.debug("Importer options - schema: " + getSchema());
-        logger.debug("Importer options - defaultPackage: " + getDefaultPackage());
-        logger.debug("Importer options - tablePattern: " + getTablePattern());
-        logger.debug("Importer options - importProcedures: " + isImportProcedures());
-        logger.debug("Importer options - procedurePattern: " + getProcedurePattern());
-        logger.debug("Importer options - meaningfulPkTables: " + getMeaningfulPkTables());
-        logger.debug("Importer options - namingStrategy: " + getNamingStrategy());
-        logger.debug("Importer options - includeTables: " + getIncludeTables());
-        logger.debug("Importer options - excludeTables: " + getExcludeTables());
+    public DbLoaderConfiguration getDbLoaderConfig() {
+        return dbLoaderConfiguration;
+    }
+
+    public void setFiltersConfig(FiltersConfig filtersConfig) {
+        dbLoaderConfiguration.setFiltersConfig(filtersConfig);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder res = new StringBuilder("Importer options:");
+        for (String line : dbLoaderConfiguration.toString().split("\n")) {
+            res.append("    ").append(line).append("\n");
+        }
+
+        return res.toString();
+    }
+
+    public DataSourceInfo getDataSourceInfo() {
+        return dataSourceInfo;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/AntNestedElement.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/AntNestedElement.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/AntNestedElement.java
new file mode 100644
index 0000000..fad83d1
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/AntNestedElement.java
@@ -0,0 +1,38 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.tools.dbimport.config;
+
+/**
+ * Additional class to handle <name> element under <catalog> and <schema>
+ *      required for ant configuration
+ *
+ * @since 3.2.
+ */
+public class AntNestedElement {
+
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    public void addText(String str) {
+        name = str;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Catalog.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Catalog.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Catalog.java
new file mode 100644
index 0000000..f6b4690
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Catalog.java
@@ -0,0 +1,82 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.tools.dbimport.config;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * @since 3.2.
+ */
+public class Catalog extends FilterContainer {
+
+    private String name;
+
+    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;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoader.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoader.java
new file mode 100644
index 0000000..b69c118
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoader.java
@@ -0,0 +1,211 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.tools.dbimport.config;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.resource.Resource;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @since 3.2.
+ */
+public class DefaultReverseEngineeringLoader implements ReverseEngineeringLoader {
+
+    private static final Log LOG = LogFactory.getLog(ReverseEngineeringLoader.class);
+
+    @Override
+    public ReverseEngineering load(Resource configurationResource) throws CayenneRuntimeException {
+        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+
+        try {
+            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+            Document doc = dBuilder.parse(configurationResource.getURL().openStream());
+
+            ReverseEngineering engineering = new ReverseEngineering();
+
+            Element root = doc.getDocumentElement();
+            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) {
+            LOG.info(e.getMessage(), e);
+        } catch (SAXException e) {
+            LOG.info(e.getMessage(), e);
+        } catch (IOException e) {
+            LOG.info(e.getMessage(), e);
+        }
+
+
+        return null;
+    }
+
+    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 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/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultTypeMapperBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultTypeMapperBuilder.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultTypeMapperBuilder.java
new file mode 100644
index 0000000..df51c97
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultTypeMapperBuilder.java
@@ -0,0 +1,82 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.tools.dbimport.config;
+
+import org.apache.cayenne.access.loader.mapper.DbType;
+import org.apache.cayenne.access.loader.mapper.DefaultJdbc2JavaTypeMapper;
+import org.apache.cayenne.access.loader.mapper.Jdbc2JavaTypeMapper;
+import org.apache.commons.lang.ClassUtils;
+import org.apache.commons.logging.Log;
+
+import static org.apache.commons.lang.StringUtils.isBlank;
+
+/**
+ * @since 3.2.
+ */
+public class DefaultTypeMapperBuilder {
+
+    private final DefaultJdbc2JavaTypeMapper mapper;
+    private final Log logger;
+
+    public DefaultTypeMapperBuilder(Log logger, TypeMapper typeMapper) {
+        this.logger = logger;
+        this.mapper = createMapper(typeMapper.getMapperClassName());
+
+        for (Type type : typeMapper.getTypes()) {
+            this.mapper.add(buildType(type), type.getJava());
+        }
+    }
+
+    private DbType buildType(Type type) {
+        return new DbType(
+                type.getJdbc(),
+                type.getLength(),
+                type.getPrecision(),
+                type.getScale(),
+                type.getNotNull()
+        );
+    }
+
+    private DefaultJdbc2JavaTypeMapper createMapper(String className) {
+        if (!isBlank(className)) {
+            try {
+                return (DefaultJdbc2JavaTypeMapper) ClassUtils.getClass(Thread.currentThread()
+                        .getContextClassLoader(), className).newInstance();
+            } catch (ClassNotFoundException e) {
+                logger.error("Can't load class '" + className + "': ", e);
+            } catch (InstantiationException e) {
+                logger.error("Can't instantiate '" + className + "' make sure it has default constructor.", e);
+            } catch (IllegalAccessException e) {
+                logger.error("Can't instantiate '" + className + "' make sure it has default constructor.", e);
+            }
+        }
+
+        return new DefaultJdbc2JavaTypeMapper();
+    }
+
+    public DefaultTypeMapperBuilder setUsePrimitives(Boolean usePrimitives) {
+        mapper.setUsePrimitives(usePrimitives);
+
+        return this;
+    }
+
+    public Jdbc2JavaTypeMapper build() {
+        return mapper;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeColumn.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeColumn.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeColumn.java
new file mode 100644
index 0000000..648645f
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/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.tools.dbimport.config;
+
+/**
+ * @since 3.2.
+ */
+public class ExcludeColumn extends PatternParam {
+    public ExcludeColumn() {
+    }
+
+    public ExcludeColumn(String pattern) {
+        super(pattern);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeProcedure.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeProcedure.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeProcedure.java
new file mode 100644
index 0000000..ec8d5aa
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/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.tools.dbimport.config;
+
+/**
+ * @since 3.2.
+ */
+public class ExcludeProcedure extends PatternParam {
+    public ExcludeProcedure() {
+    }
+
+    public ExcludeProcedure(String pattern) {
+        super(pattern);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeTable.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeTable.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeTable.java
new file mode 100644
index 0000000..3618540
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/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.tools.dbimport.config;
+
+/**
+ * @since 3.2.
+ */
+public class ExcludeTable extends PatternParam {
+    public ExcludeTable() {
+    }
+
+    public ExcludeTable(String pattern) {
+        super(pattern);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/FilterContainer.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/FilterContainer.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/FilterContainer.java
new file mode 100644
index 0000000..db461ed
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/FilterContainer.java
@@ -0,0 +1,109 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.tools.dbimport.config;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * @since 3.2.
+ */
+public class FilterContainer {
+
+    private Collection<IncludeTable> includeTables = new LinkedList<IncludeTable>();
+    private Collection<ExcludeTable> excludeTables = new LinkedList<ExcludeTable>();
+    private Collection<IncludeColumn> includeColumns = new LinkedList<IncludeColumn>();
+    private Collection<ExcludeColumn> excludeColumns = new LinkedList<ExcludeColumn>();
+    private Collection<IncludeProcedure> includeProcedures = new LinkedList<IncludeProcedure>();
+    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);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fde7761f/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/FiltersConfigBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/FiltersConfigBuilder.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/FiltersConfigBuilder.java
new file mode 100644
index 0000000..8ccbe7a
--- /dev/null
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/FiltersConfigBuilder.java
@@ -0,0 +1,169 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.tools.dbimport.config;
+
+import static org.apache.cayenne.access.loader.filters.FilterFactory.NULL;
+import static org.apache.cayenne.access.loader.filters.FilterFactory.TRUE;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.cayenne.access.loader.filters.DbPath;
+import org.apache.cayenne.access.loader.filters.EntityFilters;
+import org.apache.cayenne.access.loader.filters.Filter;
+import org.apache.cayenne.access.loader.filters.FilterFactory;
+import org.apache.cayenne.access.loader.filters.FiltersConfig;
+import org.apache.cayenne.access.loader.filters.ListFilter;
+
+/**
+* @since 3.2.
+*/
+public final class FiltersConfigBuilder {
+
+    private final ReverseEngineering engineering;
+    private final List<EntityFilters> filters = new LinkedList<EntityFilters>();
+
+    public FiltersConfigBuilder(ReverseEngineering engineering) {
+        this.engineering = engineering;
+    }
+
+    public FiltersConfigBuilder add(EntityFilters filter) {
+        if (!filter.getDbPath().equals(new DbPath()) && !filter.isEmpty()) {
+            this.filters.add(filter);
+        }
+
+        return this;
+    }
+
+    public FiltersConfig filtersConfig() {
+        DbPath path = new DbPath();
+
+        filters.addAll(processFilters(path, engineering));
+        filters.addAll(processSchemas(path, engineering.getSchemas()));
+        filters.addAll(processCatalog(path, engineering.getCatalogs()));
+
+        if (filters.isEmpty()) {
+            filters.add(defaultFilter(path));
+        }
+        return new FiltersConfig(filters);
+    }
+
+    private EntityFilters defaultFilter(DbPath path) {
+        return new EntityFilters(path, TRUE, TRUE, NULL);
+    }
+
+    private Collection<? extends EntityFilters> processSchemas(DbPath root, Collection<Schema> schemas) {
+        List<EntityFilters> filters = new LinkedList<EntityFilters>();
+        for (Schema schema : schemas) {
+            DbPath path = new DbPath(root.catalog, schema.getName());
+            List<EntityFilters> schemaFilters = processFilters(path, schema);
+            if (schemaFilters.isEmpty()) {
+                schemaFilters.add(defaultFilter(path));
+            }
+
+            filters.addAll(schemaFilters);
+        }
+
+        return filters;
+    }
+
+    private Collection<? extends EntityFilters> processCatalog(DbPath root, Collection<Catalog> catalogs) {
+        List<EntityFilters> filters = new LinkedList<EntityFilters>();
+        for (Catalog catalog: catalogs) {
+            DbPath path = new DbPath(catalog.getName());
+
+            List<EntityFilters> catalogFilters = new LinkedList<EntityFilters>();
+            catalogFilters.addAll(processFilters(path, catalog));
+            catalogFilters.addAll(processSchemas(path, catalog.getSchemas()));
+
+            if (catalogFilters.isEmpty()) {
+                catalogFilters.add(defaultFilter(path));
+            }
+
+            filters.addAll(catalogFilters);
+        }
+
+        return filters;
+    }
+
+    private List<EntityFilters> processFilters(DbPath root, FilterContainer container) {
+        LinkedList<EntityFilters> res = new LinkedList<EntityFilters>();
+        res.addAll(processTableFilters(root, container.getIncludeTables()));
+
+        EntityFilters filter = new EntityFilters(
+                root,
+                processIncludes(container.getIncludeTables()).join(processExcludes(container.getExcludeTables())),
+                processIncludes(container.getIncludeColumns()).join(processExcludes(container.getExcludeColumns())),
+                processIncludes(container.getIncludeProcedures()).join(processExcludes(container.getExcludeProcedures()))
+        );
+
+        if (!filter.isEmpty()) {
+            res.add(filter);
+        }
+
+        return res;
+    }
+
+    private List<EntityFilters> processTableFilters(DbPath root, Collection<IncludeTable> tables) {
+        List<EntityFilters> list = new LinkedList<EntityFilters>();
+        for (IncludeTable includeTable : tables) {
+            Filter<String> filter = TRUE
+                    .join(processIncludes(includeTable.getIncludeColumns()))
+                    .join(processExcludes(includeTable.getExcludeColumns()));
+
+            DbPath dbPath = new DbPath(root.catalog, root.schema, includeTable.getPattern());
+            list.add(new EntityFilters(dbPath, NULL, filter, NULL));
+        }
+        return list;
+    }
+
+    private Filter<String> processIncludes(Collection<? extends PatternParam> filters) {
+        return processFilters("include", filters);
+    }
+
+    private Filter<String> processExcludes(Collection<? extends PatternParam> excludeProcedures) {
+        return processFilters("exclude", excludeProcedures);
+    }
+
+    private Filter<String> processFilters(String factoryMethodName, Collection<? extends PatternParam> includeProcedures) {
+        Method factoryMethod;
+        try {
+            factoryMethod = FilterFactory.class.getMethod(factoryMethodName, String.class);
+        } catch (NoSuchMethodException e) {
+            throw new IllegalStateException(e);
+        }
+
+        Collection<Filter<String>> filters = new LinkedList<Filter<String>>();
+        for (PatternParam includeProcedure : includeProcedures) {
+            try {
+                filters.add((Filter<String>) factoryMethod.invoke(FilterFactory.class, includeProcedure.getPattern()));
+            } catch (Exception e) {
+                // TODO log / process exact parsing exception
+                e.printStackTrace();
+            }
+        }
+
+        if (filters.isEmpty()) {
+            return NULL;
+        }
+        return new ListFilter<String>(filters);
+    }
+}