You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2017/07/25 12:25:16 UTC

[01/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - new XML loader for DataMap - new project version - updated test projects

Repository: cayenne
Updated Branches:
  refs/heads/master 2c9896cae -> d608777a9


http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/relationships-to-one-fk.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/relationships-to-one-fk.map.xml b/cayenne-server/src/test/resources/relationships-to-one-fk.map.xml
index fbb7bec..cb7c147 100644
--- a/cayenne-server/src/test/resources/relationships-to-one-fk.map.xml
+++ b/cayenne-server/src/test/resources/relationships-to-one-fk.map.xml
@@ -1,26 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_to_one_fk"/>
-    <db-entity name="TO_ONE_FK1">
-        <db-attribute name="TO_ONE_FK1_FK" type="INTEGER" isMandatory="true"/>
-        <db-attribute name="TO_ONE_FK1_PK" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="TO_ONE_FK2">
-        <db-attribute name="TO_ONE_FK2_PK" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <obj-entity name="ToOneFK1" className="org.apache.cayenne.testdo.relationships_to_one_fk.ToOneFK1" dbEntityName="TO_ONE_FK1">
-    </obj-entity>
-    <obj-entity name="ToOneFK2" className="org.apache.cayenne.testdo.relationships_to_one_fk.ToOneFK2" dbEntityName="TO_ONE_FK2">
-    </obj-entity>
-    <db-relationship name="toPK" source="TO_ONE_FK1" target="TO_ONE_FK2" toMany="false">
-        <db-attribute-pair source="TO_ONE_FK1_FK" target="TO_ONE_FK2_PK"/>
-    </db-relationship>
-    <db-relationship name="toOneToFK" source="TO_ONE_FK2" target="TO_ONE_FK1" toMany="false">
-        <db-attribute-pair source="TO_ONE_FK2_PK" target="TO_ONE_FK1_FK"/>
-    </db-relationship>
-    <obj-relationship name="toPK" source="ToOneFK1" target="ToOneFK2" db-relationship-path="toPK"/>
-    <obj-relationship name="toOneToFK" source="ToOneFK2" target="ToOneFK1" db-relationship-path="toOneToFK"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_to_one_fk"/>
+	<db-entity name="TO_ONE_FK1">
+		<db-attribute name="TO_ONE_FK1_FK" type="INTEGER" isMandatory="true"/>
+		<db-attribute name="TO_ONE_FK1_PK" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="TO_ONE_FK2">
+		<db-attribute name="TO_ONE_FK2_PK" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<obj-entity name="ToOneFK1" className="org.apache.cayenne.testdo.relationships_to_one_fk.ToOneFK1" dbEntityName="TO_ONE_FK1"/>
+	<obj-entity name="ToOneFK2" className="org.apache.cayenne.testdo.relationships_to_one_fk.ToOneFK2" dbEntityName="TO_ONE_FK2"/>
+	<db-relationship name="toPK" source="TO_ONE_FK1" target="TO_ONE_FK2">
+		<db-attribute-pair source="TO_ONE_FK1_FK" target="TO_ONE_FK2_PK"/>
+	</db-relationship>
+	<db-relationship name="toOneToFK" source="TO_ONE_FK2" target="TO_ONE_FK1">
+		<db-attribute-pair source="TO_ONE_FK2_PK" target="TO_ONE_FK1_FK"/>
+	</db-relationship>
+	<obj-relationship name="toPK" source="ToOneFK1" target="ToOneFK2" db-relationship-path="toPK"/>
+	<obj-relationship name="toOneToFK" source="ToOneFK2" target="ToOneFK1" db-relationship-path="toOneToFK"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/relationships.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/relationships.map.xml b/cayenne-server/src/test/resources/relationships.map.xml
index 305b42b..55b9fda 100644
--- a/cayenne-server/src/test/resources/relationships.map.xml
+++ b/cayenne-server/src/test/resources/relationships.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.relationships"/>
 	<db-entity name="FK_OF_DIFFERENT_TYPE">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
@@ -22,8 +22,7 @@
 		<db-attribute name="NAME" type="VARCHAR" length="100"/>
 		<db-attribute name="RELATIONSHIP_HELPER_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 	</db-entity>
-	<obj-entity name="FkOfDifferentType" className="org.apache.cayenne.testdo.relationships.FkOfDifferentType" dbEntityName="FK_OF_DIFFERENT_TYPE">
-	</obj-entity>
+	<obj-entity name="FkOfDifferentType" className="org.apache.cayenne.testdo.relationships.FkOfDifferentType" dbEntityName="FK_OF_DIFFERENT_TYPE"/>
 	<obj-entity name="MeaningfulFK" className="org.apache.cayenne.testdo.relationships.MeaningfulFK" dbEntityName="MEANINGFUL_FK">
 		<obj-attribute name="relationshipHelperID" type="java.lang.Integer" db-attribute-path="RELATIONSHIP_HELPER_ID"/>
 	</obj-entity>
@@ -33,19 +32,19 @@
 	<obj-entity name="RelationshipHelper" className="org.apache.cayenne.testdo.relationships.RelationshipHelper" dbEntityName="RELATIONSHIP_HELPER">
 		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
 	</obj-entity>
-	<db-relationship name="relationshipHelper" source="FK_OF_DIFFERENT_TYPE" target="RELATIONSHIP_HELPER" toMany="false">
+	<db-relationship name="relationshipHelper" source="FK_OF_DIFFERENT_TYPE" target="RELATIONSHIP_HELPER">
 		<db-attribute-pair source="RELATIONSHIP_HELPER_FK" target="RELATIONSHIP_HELPER_ID"/>
 	</db-relationship>
-	<db-relationship name="toRelationshipHelper" source="MEANINGFUL_FK" target="RELATIONSHIP_HELPER" toMany="false">
+	<db-relationship name="toRelationshipHelper" source="MEANINGFUL_FK" target="RELATIONSHIP_HELPER">
 		<db-attribute-pair source="RELATIONSHIP_HELPER_ID" target="RELATIONSHIP_HELPER_ID"/>
 	</db-relationship>
 	<db-relationship name="children" source="REFLEXIVE_AND_TO_ONE" target="REFLEXIVE_AND_TO_ONE" toMany="true">
 		<db-attribute-pair source="REFLEXIVE_AND_TO_ONE_ID" target="PARENT_ID"/>
 	</db-relationship>
-	<db-relationship name="toHelper" source="REFLEXIVE_AND_TO_ONE" target="RELATIONSHIP_HELPER" toMany="false">
+	<db-relationship name="toHelper" source="REFLEXIVE_AND_TO_ONE" target="RELATIONSHIP_HELPER">
 		<db-attribute-pair source="RELATIONSHIP_HELPER_ID" target="RELATIONSHIP_HELPER_ID"/>
 	</db-relationship>
-	<db-relationship name="toParent" source="REFLEXIVE_AND_TO_ONE" target="REFLEXIVE_AND_TO_ONE" toMany="false">
+	<db-relationship name="toParent" source="REFLEXIVE_AND_TO_ONE" target="REFLEXIVE_AND_TO_ONE">
 		<db-attribute-pair source="PARENT_ID" target="REFLEXIVE_AND_TO_ONE_ID"/>
 	</db-relationship>
 	<db-relationship name="fksOfDifferentType" source="RELATIONSHIP_HELPER" target="FK_OF_DIFFERENT_TYPE" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/return-types.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/return-types.map.xml b/cayenne-server/src/test/resources/return-types.map.xml
index 61e9eb1..b0ba1a3 100644
--- a/cayenne-server/src/test/resources/return-types.map.xml
+++ b/cayenne-server/src/test/resources/return-types.map.xml
@@ -1,92 +1,92 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.return_types"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="TYPES_MAPPING_LOBS_TEST1">
-        <db-attribute name="AAAID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="CLOB_COLUMN" type="CLOB"/>
-        <db-attribute name="NCLOB_COLUMN" type="NCLOB"/>
-    </db-entity>
-    <db-entity name="TYPES_MAPPING_TEST1">
-        <db-attribute name="AAAID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="BIGINT_COLUMN" type="BIGINT"/>
-        <db-attribute name="BIT_COLUMN" type="BIT"/>
-        <db-attribute name="BOOLEAN_COLUMN" type="BOOLEAN"/>
-        <db-attribute name="CHAR_COLUMN" type="CHAR" length="254"/>
-        <db-attribute name="NCHAR_COLUMN" type="NCHAR" length="254"/>
-        <db-attribute name="DATE_COLUMN" type="DATE"/>
-        <db-attribute name="DECIMAL_COLUMN" type="DECIMAL" length="12" scale="5"/>
-        <db-attribute name="DOUBLE_COLUMN" type="DOUBLE" scale="7"/>
-        <db-attribute name="FLOAT_COLUMN" type="FLOAT" scale="3"/>
-        <db-attribute name="INTEGER_COLUMN" type="INTEGER"/>
-        <db-attribute name="LONGVARCHAR_COLUMN" type="LONGVARCHAR"/>
-        <db-attribute name="LONGNVARCHAR_COLUMN" type="LONGNVARCHAR"/>
-        <db-attribute name="NUMERIC_COLUMN" type="NUMERIC" length="12" scale="5"/>
-        <db-attribute name="REAL_COLUMN" type="REAL" scale="5"/>
-        <db-attribute name="SMALLINT_COLUMN" type="SMALLINT"/>
-        <db-attribute name="TIMESTAMP_COLUMN" type="TIMESTAMP"/>
-        <db-attribute name="TIME_COLUMN" type="TIME"/>
-        <db-attribute name="TINYINT_COLUMN" type="TINYINT"/>
-        <db-attribute name="VARCHAR_COLUMN" type="VARCHAR" length="255"/>
-        <db-attribute name="NVARCHAR_COLUMN" type="NVARCHAR" length="255"/>
-    </db-entity>
-    <db-entity name="TYPES_MAPPING_TEST2">
-        <db-attribute name="AAAID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="BINARY_COLUMN" type="BINARY" length="14"/>
-        <db-attribute name="BLOB_COLUMN" type="BLOB"/>
-        <db-attribute name="LONGVARBINARY_COLUMN" type="LONGVARBINARY"/>
-        <db-attribute name="VARBINARY_COLUMN" type="VARBINARY" length="1000"/>
-    </db-entity>
-    <obj-entity name="ReturnTypesMap1" className="org.apache.cayenne.testdo.return_types.ReturnTypesMap1" clientClassName="test.client.ReturnTypesMap1" dbEntityName="TYPES_MAPPING_TEST1" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
-        <obj-attribute name="bigintColumn" type="java.lang.Long" db-attribute-path="BIGINT_COLUMN"/>
-        <obj-attribute name="bitColumn" type="java.lang.Boolean" db-attribute-path="BIT_COLUMN"/>
-        <obj-attribute name="booleanColumn" type="java.lang.Boolean" db-attribute-path="BOOLEAN_COLUMN"/>
-        <obj-attribute name="charColumn" type="java.lang.String" db-attribute-path="CHAR_COLUMN"/>
-        <obj-attribute name="ncharColumn" type="java.lang.String" db-attribute-path="NCHAR_COLUMN"/>
-        <obj-attribute name="dateColumn" type="java.util.Date" db-attribute-path="DATE_COLUMN"/>
-        <obj-attribute name="decimalColumn" type="java.math.BigDecimal" db-attribute-path="DECIMAL_COLUMN"/>
-        <obj-attribute name="doubleColumn" type="java.lang.Double" db-attribute-path="DOUBLE_COLUMN"/>
-        <obj-attribute name="floatColumn" type="java.lang.Float" db-attribute-path="FLOAT_COLUMN"/>
-        <obj-attribute name="integerColumn" type="java.lang.Integer" db-attribute-path="INTEGER_COLUMN"/>
-        <obj-attribute name="longvarcharColumn" type="java.lang.String" db-attribute-path="LONGVARCHAR_COLUMN"/>
-        <obj-attribute name="longnvarcharColumn" type="java.lang.String" db-attribute-path="LONGNVARCHAR_COLUMN"/>
-        <obj-attribute name="numericColumn" type="java.math.BigDecimal" db-attribute-path="NUMERIC_COLUMN"/>
-        <obj-attribute name="realColumn" type="java.lang.Float" db-attribute-path="REAL_COLUMN"/>
-        <obj-attribute name="smallintColumn" type="java.lang.Short" db-attribute-path="SMALLINT_COLUMN"/>
-        <obj-attribute name="timeColumn" type="java.util.Date" db-attribute-path="TIME_COLUMN"/>
-        <obj-attribute name="timestampColumn" type="java.util.Date" db-attribute-path="TIMESTAMP_COLUMN"/>
-        <obj-attribute name="tinyintColumn" type="java.lang.Byte" db-attribute-path="TINYINT_COLUMN"/>
-        <obj-attribute name="varcharColumn" type="java.lang.String" db-attribute-path="VARCHAR_COLUMN"/>
-        <obj-attribute name="nvarcharColumn" type="java.lang.String" db-attribute-path="NVARCHAR_COLUMN"/>
-    </obj-entity>
-    <obj-entity name="ReturnTypesMap2" className="org.apache.cayenne.testdo.return_types.ReturnTypesMap2" clientClassName="test.client.ReturnTypesMap2" dbEntityName="TYPES_MAPPING_TEST2" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
-        <obj-attribute name="binaryColumn" type="byte[]" db-attribute-path="BINARY_COLUMN"/>
-        <obj-attribute name="blobColumn" type="byte[]" db-attribute-path="BLOB_COLUMN"/>
-        <obj-attribute name="longvarbinaryColumn" type="byte[]" db-attribute-path="LONGVARBINARY_COLUMN"/>
-        <obj-attribute name="varbinaryColumn" type="byte[]" db-attribute-path="VARBINARY_COLUMN"/>
-    </obj-entity>
-    <obj-entity name="ReturnTypesMapLobs1" className="org.apache.cayenne.testdo.return_types.ReturnTypesMapLobs1" clientClassName="test.client.ReturnTypesMapLobs1" dbEntityName="TYPES_MAPPING_LOBS_TEST1" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
-        <obj-attribute name="clobColumn" type="java.lang.String" db-attribute-path="CLOB_COLUMN"/>
-        <obj-attribute name="nclobColumn" type="java.lang.String" db-attribute-path="NCLOB_COLUMN"/>
-    </obj-entity>
-    <query name="SelectReturnTypesLobsMap1" type="SQLTemplate" root="data-map" root-name="return-types">
-        <property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
-        <sql><![CDATA[SELECT * FROM TYPES_MAPPING_LOBS_TEST1]]></sql>
-    </query>
-    <query name="SelectReturnTypesMap1" type="SQLTemplate" root="data-map" root-name="return-types">
-        <property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
-        <property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
-        <sql><![CDATA[SELECT * FROM TYPES_MAPPING_TEST1]]></sql>
-    </query>
-    <query name="SelectReturnTypesMap2" type="SQLTemplate" root="data-map" root-name="return-types">
-        <property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
-        <property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
-        <sql><![CDATA[SELECT * FROM TYPES_MAPPING_TEST2]]></sql>
-    </query>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.return_types"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="TYPES_MAPPING_LOBS_TEST1">
+		<db-attribute name="AAAID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="CLOB_COLUMN" type="CLOB"/>
+		<db-attribute name="NCLOB_COLUMN" type="NCLOB"/>
+	</db-entity>
+	<db-entity name="TYPES_MAPPING_TEST1">
+		<db-attribute name="AAAID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="BIGINT_COLUMN" type="BIGINT"/>
+		<db-attribute name="BIT_COLUMN" type="BIT"/>
+		<db-attribute name="BOOLEAN_COLUMN" type="BOOLEAN"/>
+		<db-attribute name="CHAR_COLUMN" type="CHAR" length="254"/>
+		<db-attribute name="DATE_COLUMN" type="DATE"/>
+		<db-attribute name="DECIMAL_COLUMN" type="DECIMAL" length="12" scale="5"/>
+		<db-attribute name="DOUBLE_COLUMN" type="DOUBLE" scale="7"/>
+		<db-attribute name="FLOAT_COLUMN" type="FLOAT" scale="3"/>
+		<db-attribute name="INTEGER_COLUMN" type="INTEGER"/>
+		<db-attribute name="LONGNVARCHAR_COLUMN" type="LONGNVARCHAR"/>
+		<db-attribute name="LONGVARCHAR_COLUMN" type="LONGVARCHAR"/>
+		<db-attribute name="NCHAR_COLUMN" type="NCHAR" length="254"/>
+		<db-attribute name="NUMERIC_COLUMN" type="NUMERIC" length="12" scale="5"/>
+		<db-attribute name="NVARCHAR_COLUMN" type="NVARCHAR" length="255"/>
+		<db-attribute name="REAL_COLUMN" type="REAL" scale="5"/>
+		<db-attribute name="SMALLINT_COLUMN" type="SMALLINT"/>
+		<db-attribute name="TIMESTAMP_COLUMN" type="TIMESTAMP"/>
+		<db-attribute name="TIME_COLUMN" type="TIME"/>
+		<db-attribute name="TINYINT_COLUMN" type="TINYINT"/>
+		<db-attribute name="VARCHAR_COLUMN" type="VARCHAR" length="255"/>
+	</db-entity>
+	<db-entity name="TYPES_MAPPING_TEST2">
+		<db-attribute name="AAAID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="BINARY_COLUMN" type="BINARY" length="14"/>
+		<db-attribute name="BLOB_COLUMN" type="BLOB"/>
+		<db-attribute name="LONGVARBINARY_COLUMN" type="LONGVARBINARY"/>
+		<db-attribute name="VARBINARY_COLUMN" type="VARBINARY" length="1000"/>
+	</db-entity>
+	<obj-entity name="ReturnTypesMap1" className="org.apache.cayenne.testdo.return_types.ReturnTypesMap1" clientClassName="test.client.ReturnTypesMap1" dbEntityName="TYPES_MAPPING_TEST1" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
+		<obj-attribute name="bigintColumn" type="java.lang.Long" db-attribute-path="BIGINT_COLUMN"/>
+		<obj-attribute name="bitColumn" type="java.lang.Boolean" db-attribute-path="BIT_COLUMN"/>
+		<obj-attribute name="booleanColumn" type="java.lang.Boolean" db-attribute-path="BOOLEAN_COLUMN"/>
+		<obj-attribute name="charColumn" type="java.lang.String" db-attribute-path="CHAR_COLUMN"/>
+		<obj-attribute name="dateColumn" type="java.util.Date" db-attribute-path="DATE_COLUMN"/>
+		<obj-attribute name="decimalColumn" type="java.math.BigDecimal" db-attribute-path="DECIMAL_COLUMN"/>
+		<obj-attribute name="doubleColumn" type="java.lang.Double" db-attribute-path="DOUBLE_COLUMN"/>
+		<obj-attribute name="floatColumn" type="java.lang.Float" db-attribute-path="FLOAT_COLUMN"/>
+		<obj-attribute name="integerColumn" type="java.lang.Integer" db-attribute-path="INTEGER_COLUMN"/>
+		<obj-attribute name="longnvarcharColumn" type="java.lang.String" db-attribute-path="LONGNVARCHAR_COLUMN"/>
+		<obj-attribute name="longvarcharColumn" type="java.lang.String" db-attribute-path="LONGVARCHAR_COLUMN"/>
+		<obj-attribute name="ncharColumn" type="java.lang.String" db-attribute-path="NCHAR_COLUMN"/>
+		<obj-attribute name="numericColumn" type="java.math.BigDecimal" db-attribute-path="NUMERIC_COLUMN"/>
+		<obj-attribute name="nvarcharColumn" type="java.lang.String" db-attribute-path="NVARCHAR_COLUMN"/>
+		<obj-attribute name="realColumn" type="java.lang.Float" db-attribute-path="REAL_COLUMN"/>
+		<obj-attribute name="smallintColumn" type="java.lang.Short" db-attribute-path="SMALLINT_COLUMN"/>
+		<obj-attribute name="timeColumn" type="java.util.Date" db-attribute-path="TIME_COLUMN"/>
+		<obj-attribute name="timestampColumn" type="java.util.Date" db-attribute-path="TIMESTAMP_COLUMN"/>
+		<obj-attribute name="tinyintColumn" type="java.lang.Byte" db-attribute-path="TINYINT_COLUMN"/>
+		<obj-attribute name="varcharColumn" type="java.lang.String" db-attribute-path="VARCHAR_COLUMN"/>
+	</obj-entity>
+	<obj-entity name="ReturnTypesMap2" className="org.apache.cayenne.testdo.return_types.ReturnTypesMap2" clientClassName="test.client.ReturnTypesMap2" dbEntityName="TYPES_MAPPING_TEST2" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
+		<obj-attribute name="binaryColumn" type="byte[]" db-attribute-path="BINARY_COLUMN"/>
+		<obj-attribute name="blobColumn" type="byte[]" db-attribute-path="BLOB_COLUMN"/>
+		<obj-attribute name="longvarbinaryColumn" type="byte[]" db-attribute-path="LONGVARBINARY_COLUMN"/>
+		<obj-attribute name="varbinaryColumn" type="byte[]" db-attribute-path="VARBINARY_COLUMN"/>
+	</obj-entity>
+	<obj-entity name="ReturnTypesMapLobs1" className="org.apache.cayenne.testdo.return_types.ReturnTypesMapLobs1" clientClassName="test.client.ReturnTypesMapLobs1" dbEntityName="TYPES_MAPPING_LOBS_TEST1" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
+		<obj-attribute name="clobColumn" type="java.lang.String" db-attribute-path="CLOB_COLUMN"/>
+		<obj-attribute name="nclobColumn" type="java.lang.String" db-attribute-path="NCLOB_COLUMN"/>
+	</obj-entity>
+	<query name="SelectReturnTypesLobsMap1" type="SQLTemplate" root="data-map" root-name="return-types">
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
+		<sql><![CDATA[SELECT * FROM TYPES_MAPPING_LOBS_TEST1]]></sql>
+	</query>
+	<query name="SelectReturnTypesMap1" type="SQLTemplate" root="data-map" root-name="return-types">
+		<property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
+		<sql><![CDATA[SELECT * FROM TYPES_MAPPING_TEST1]]></sql>
+	</query>
+	<query name="SelectReturnTypesMap2" type="SQLTemplate" root="data-map" root-name="return-types">
+		<property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
+		<sql><![CDATA[SELECT * FROM TYPES_MAPPING_TEST2]]></sql>
+	</query>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/soft-delete.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/soft-delete.map.xml b/cayenne-server/src/test/resources/soft-delete.map.xml
index dbd91c8..64a443b 100644
--- a/cayenne-server/src/test/resources/soft-delete.map.xml
+++ b/cayenne-server/src/test/resources/soft-delete.map.xml
@@ -1,18 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.soft_delete"/>
-    <db-entity name="SOFT_DELETE">
-        <db-attribute name="DELETED" type="BOOLEAN"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="100"/>
-        <qualifier><![CDATA[DELETED = false]]></qualifier>
-    </db-entity>
-    <obj-entity name="SoftDelete" className="org.apache.cayenne.testdo.soft_delete.SoftDelete" dbEntityName="SOFT_DELETE">
-        <obj-attribute name="deleted" type="java.lang.Boolean" db-attribute-path="DELETED"/>
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-        <post-add method-name="onPrePersist"/>
-    </obj-entity>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.soft_delete"/>
+	<db-entity name="SOFT_DELETE">
+		<db-attribute name="DELETED" type="BOOLEAN"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+		<qualifier><![CDATA[DELETED = false]]></qualifier>
+	</db-entity>
+	<obj-entity name="SoftDelete" className="org.apache.cayenne.testdo.soft_delete.SoftDelete" dbEntityName="SOFT_DELETE">
+		<obj-attribute name="deleted" type="java.lang.Boolean" db-attribute-path="DELETED"/>
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+		<post-add method-name="onPrePersist"/>
+	</obj-entity>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/sus-map.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/sus-map.map.xml b/cayenne-server/src/test/resources/sus-map.map.xml
index 6889dfa..cf4f5ea 100644
--- a/cayenne-server/src/test/resources/sus-map.map.xml
+++ b/cayenne-server/src/test/resources/sus-map.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<db-entity name="SUS1">
 		<db-attribute name="id" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="strNoMandatory" type="VARCHAR" length="200"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/table-primitives.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/table-primitives.map.xml b/cayenne-server/src/test/resources/table-primitives.map.xml
index e09d406..75d82a9 100644
--- a/cayenne-server/src/test/resources/table-primitives.map.xml
+++ b/cayenne-server/src/test/resources/table-primitives.map.xml
@@ -1,18 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.table_primitives"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="org.apache.cayenne.testdo.table_primitives"/>
-    <db-entity name="TABLE_PRIMITIVES">
-        <db-attribute name="BOOLEAN_COLUMN" type="BOOLEAN"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="INT_COLUMN" type="INTEGER"/>
-    </db-entity>
-    <obj-entity name="TablePrimitives" className="org.apache.cayenne.testdo.table_primitives.TablePrimitives" clientClassName="org.apache.cayenne.testdo.table_primitives.ClientTablePrimitives" dbEntityName="TABLE_PRIMITIVES">
-        <obj-attribute name="booleanColumn" type="boolean" db-attribute-path="BOOLEAN_COLUMN"/>
-        <obj-attribute name="intColumn" type="int" db-attribute-path="INT_COLUMN"/>
-    </obj-entity>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.table_primitives"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="org.apache.cayenne.testdo.table_primitives"/>
+	<db-entity name="TABLE_PRIMITIVES">
+		<db-attribute name="BOOLEAN_COLUMN" type="BOOLEAN"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="INT_COLUMN" type="INTEGER"/>
+	</db-entity>
+	<obj-entity name="TablePrimitives" className="org.apache.cayenne.testdo.table_primitives.TablePrimitives" clientClassName="org.apache.cayenne.testdo.table_primitives.ClientTablePrimitives" dbEntityName="TABLE_PRIMITIVES">
+		<obj-attribute name="booleanColumn" type="boolean" db-attribute-path="BOOLEAN_COLUMN"/>
+		<obj-attribute name="intColumn" type="int" db-attribute-path="INT_COLUMN"/>
+	</obj-entity>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/testmap.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/testmap.map.xml b/cayenne-server/src/test/resources/testmap.map.xml
index 8e082d9..1ce62c2 100644
--- a/cayenne-server/src/test/resources/testmap.map.xml
+++ b/cayenne-server/src/test/resources/testmap.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.testmap"/>
 	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
 	<property name="clientSupported" value="true"/>
@@ -19,8 +19,7 @@
 	<procedure name="cayenne_tst_upd_proc">
 		<procedure-parameter name="paintingPrice" type="INTEGER" direction="in"/>
 	</procedure>
-	<procedure name="cayenne_tst_upd_proc2">
-	</procedure>
+	<procedure name="cayenne_tst_upd_proc2"/>
 	<db-entity name="ARTGROUP">
 		<db-attribute name="GROUP_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="NAME" type="VARCHAR" isMandatory="true" length="100"/>
@@ -89,7 +88,7 @@
 		<obj-attribute name="artistName" type="java.lang.String" db-attribute-path="ARTIST_NAME"/>
 		<obj-attribute name="dateOfBirth" type="java.util.Date" db-attribute-path="DATE_OF_BIRTH"/>
 	</obj-entity>
-	<obj-entity name="ArtistCallback" className="org.apache.cayenne.testdo.testmap.ArtistCallback" dbEntityName="ARTIST_CT" exclude-superclass-listeners="true" exclude-default-listeners="true">
+	<obj-entity name="ArtistCallback" className="org.apache.cayenne.testdo.testmap.ArtistCallback" dbEntityName="ARTIST_CT">
 		<obj-attribute name="artistName" type="java.lang.String"/>
 		<obj-attribute name="dateOfBirth" type="java.util.Date"/>
 		<post-add method-name="prePersistEntityObjEntity"/>
@@ -100,8 +99,7 @@
 		<post-remove method-name="postRemoveEntityObjEntity"/>
 		<post-load method-name="postLoadEntityObjEntity"/>
 	</obj-entity>
-	<obj-entity name="ArtistExhibit" className="org.apache.cayenne.testdo.testmap.ArtistExhibit" dbEntityName="ARTIST_EXHIBIT">
-	</obj-entity>
+	<obj-entity name="ArtistExhibit" className="org.apache.cayenne.testdo.testmap.ArtistExhibit" dbEntityName="ARTIST_EXHIBIT"/>
 	<obj-entity name="CompoundPainting" className="org.apache.cayenne.testdo.testmap.CompoundPainting" dbEntityName="PAINTING">
 		<obj-attribute name="artistName" type="java.lang.String" db-attribute-path="toArtist.ARTIST_NAME"/>
 		<obj-attribute name="estimatedPrice" type="java.math.BigDecimal" db-attribute-path="ESTIMATED_PRICE"/>
@@ -166,7 +164,7 @@
 	<db-relationship name="toChildGroups" source="ARTGROUP" target="ARTGROUP" toMany="true">
 		<db-attribute-pair source="GROUP_ID" target="PARENT_GROUP_ID"/>
 	</db-relationship>
-	<db-relationship name="toParentGroup" source="ARTGROUP" target="ARTGROUP" toMany="false">
+	<db-relationship name="toParentGroup" source="ARTGROUP" target="ARTGROUP">
 		<db-attribute-pair source="PARENT_GROUP_ID" target="GROUP_ID"/>
 	</db-relationship>
 	<db-relationship name="artistExhibitArray" source="ARTIST" target="ARTIST_EXHIBIT" toDependentPK="true" toMany="true">
@@ -178,22 +176,22 @@
 	<db-relationship name="paintingArray" source="ARTIST" target="PAINTING" toMany="true">
 		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
 	</db-relationship>
-	<db-relationship name="toArtist" source="ARTIST_EXHIBIT" target="ARTIST" toMany="false">
+	<db-relationship name="toArtist" source="ARTIST_EXHIBIT" target="ARTIST">
 		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
 	</db-relationship>
-	<db-relationship name="toExhibit" source="ARTIST_EXHIBIT" target="EXHIBIT" toMany="false">
+	<db-relationship name="toExhibit" source="ARTIST_EXHIBIT" target="EXHIBIT">
 		<db-attribute-pair source="EXHIBIT_ID" target="EXHIBIT_ID"/>
 	</db-relationship>
-	<db-relationship name="toArtist" source="ARTIST_GROUP" target="ARTIST" toMany="false">
+	<db-relationship name="toArtist" source="ARTIST_GROUP" target="ARTIST">
 		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
 	</db-relationship>
-	<db-relationship name="toGroup" source="ARTIST_GROUP" target="ARTGROUP" toMany="false">
+	<db-relationship name="toGroup" source="ARTIST_GROUP" target="ARTGROUP">
 		<db-attribute-pair source="GROUP_ID" target="GROUP_ID"/>
 	</db-relationship>
 	<db-relationship name="artistExhibitArray" source="EXHIBIT" target="ARTIST_EXHIBIT" toDependentPK="true" toMany="true">
 		<db-attribute-pair source="EXHIBIT_ID" target="EXHIBIT_ID"/>
 	</db-relationship>
-	<db-relationship name="toGallery" source="EXHIBIT" target="GALLERY" toMany="false">
+	<db-relationship name="toGallery" source="EXHIBIT" target="GALLERY">
 		<db-attribute-pair source="GALLERY_ID" target="GALLERY_ID"/>
 	</db-relationship>
 	<db-relationship name="exhibitArray" source="GALLERY" target="EXHIBIT" toMany="true">
@@ -202,19 +200,19 @@
 	<db-relationship name="paintingArray" source="GALLERY" target="PAINTING" toMany="true">
 		<db-attribute-pair source="GALLERY_ID" target="GALLERY_ID"/>
 	</db-relationship>
-	<db-relationship name="toArtist" source="PAINTING" target="ARTIST" toMany="false">
+	<db-relationship name="toArtist" source="PAINTING" target="ARTIST">
 		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
 	</db-relationship>
-	<db-relationship name="toGallery" source="PAINTING" target="GALLERY" toMany="false">
+	<db-relationship name="toGallery" source="PAINTING" target="GALLERY">
 		<db-attribute-pair source="GALLERY_ID" target="GALLERY_ID"/>
 	</db-relationship>
-	<db-relationship name="toPaintingInfo" source="PAINTING" target="PAINTING_INFO" toDependentPK="true" toMany="false">
+	<db-relationship name="toPaintingInfo" source="PAINTING" target="PAINTING_INFO" toDependentPK="true">
 		<db-attribute-pair source="PAINTING_ID" target="PAINTING_ID"/>
 	</db-relationship>
-	<db-relationship name="toArtist" source="PAINTING1" target="ARTIST" toMany="false">
+	<db-relationship name="toArtist" source="PAINTING1" target="ARTIST">
 		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
 	</db-relationship>
-	<db-relationship name="painting" source="PAINTING_INFO" target="PAINTING" toMany="false">
+	<db-relationship name="painting" source="PAINTING_INFO" target="PAINTING">
 		<db-attribute-pair source="PAINTING_ID" target="PAINTING_ID"/>
 	</db-relationship>
 	<obj-relationship name="artistArray" source="ArtGroup" target="Artist" deleteRule="Nullify" db-relationship-path="artistGroupArray.toArtist"/>
@@ -271,8 +269,7 @@ VALUES (#bind($id), #bind($title), #bind($price))]]></sql>
 		<property name="cayenne.GenericSelectQuery.cacheStrategy" value="SHARED_CACHE"/>
 		<qualifier><![CDATA[artistName like $name]]></qualifier>
 	</query>
-	<query name="ProcedureQuery" type="ProcedureQuery" root="procedure" root-name="cayenne_tst_select_proc" result-entity="Artist">
-	</query>
+	<query name="ProcedureQuery" type="ProcedureQuery" root="procedure" root-name="cayenne_tst_select_proc" result-entity="Artist"/>
 	<query name="QueryWithLocalCache" type="SelectQuery" root="obj-entity" root-name="Artist">
 		<property name="cayenne.GenericSelectQuery.cacheStrategy" value="LOCAL_CACHE"/>
 	</query>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/things.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/things.map.xml b/cayenne-server/src/test/resources/things.map.xml
index 3212d70..fc6158f 100644
--- a/cayenne-server/src/test/resources/things.map.xml
+++ b/cayenne-server/src/test/resources/things.map.xml
@@ -1,110 +1,110 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.things"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="BAG">
-        <db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="200"/>
-    </db-entity>
-    <db-entity name="BALL">
-        <db-attribute name="BOX_ID" type="BIGINT" isMandatory="true"/>
-        <db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="THING_VOLUME" type="INTEGER" isMandatory="true"/>
-        <db-attribute name="THING_WEIGHT" type="INTEGER" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="BOX">
-        <db-attribute name="BAG_ID" type="BIGINT" isMandatory="true"/>
-        <db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="200"/>
-    </db-entity>
-    <db-entity name="BOX_INFO">
-        <db-attribute name="BOX_ID" type="BIGINT" isMandatory="true"/>
-        <db-attribute name="COLOR" type="VARCHAR" isMandatory="true" length="200"/>
-        <db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="BOX_THING">
-        <db-attribute name="BOX_ID" type="BIGINT" isMandatory="true"/>
-        <db-attribute name="THING_VOLUME" type="INTEGER" isMandatory="true"/>
-        <db-attribute name="THING_WEIGHT" type="INTEGER" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="THING">
-        <db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="VOLUME" type="INTEGER" isMandatory="true"/>
-        <db-attribute name="WEIGHT" type="INTEGER" isMandatory="true"/>
-    </db-entity>
-    <obj-entity name="Bag" className="org.apache.cayenne.testdo.things.Bag" clientClassName="test.client.Bag" dbEntityName="BAG" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="Ball" className="org.apache.cayenne.testdo.things.Ball" clientClassName="test.client.Ball" dbEntityName="BALL" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
-        <obj-attribute name="thingVolume" type="java.lang.Integer" db-attribute-path="THING_VOLUME"/>
-        <obj-attribute name="thingWeight" type="java.lang.Integer" db-attribute-path="THING_WEIGHT"/>
-    </obj-entity>
-    <obj-entity name="Box" className="org.apache.cayenne.testdo.things.Box" clientClassName="test.client.Box" dbEntityName="BOX" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="BoxInfo" className="org.apache.cayenne.testdo.things.BoxInfo" clientClassName="test.client.BoxInfo" dbEntityName="BOX_INFO" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
-        <obj-attribute name="color" type="java.lang.String" db-attribute-path="COLOR"/>
-    </obj-entity>
-    <obj-entity name="Thing" className="org.apache.cayenne.testdo.things.Thing" clientClassName="test.client.Thing" dbEntityName="THING" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
-        <obj-attribute name="volume" type="java.lang.Integer" db-attribute-path="VOLUME"/>
-        <obj-attribute name="weight" type="java.lang.Integer" db-attribute-path="WEIGHT"/>
-    </obj-entity>
-    <db-relationship name="BOXES" source="BAG" target="BOX" toMany="true">
-        <db-attribute-pair source="ID" target="BAG_ID"/>
-    </db-relationship>
-    <db-relationship name="BOX" source="BALL" target="BOX" toMany="false">
-        <db-attribute-pair source="BOX_ID" target="ID"/>
-    </db-relationship>
-    <db-relationship name="THING" source="BALL" target="THING" toMany="false">
-        <db-attribute-pair source="THING_VOLUME" target="VOLUME"/>
-        <db-attribute-pair source="THING_WEIGHT" target="WEIGHT"/>
-    </db-relationship>
-    <db-relationship name="BAG" source="BOX" target="BAG" toMany="false">
-        <db-attribute-pair source="BAG_ID" target="ID"/>
-    </db-relationship>
-    <db-relationship name="BALLS" source="BOX" target="BALL" toMany="true">
-        <db-attribute-pair source="ID" target="BOX_ID"/>
-    </db-relationship>
-    <db-relationship name="BOX_INFO" source="BOX" target="BOX_INFO" toMany="false">
-        <db-attribute-pair source="ID" target="BOX_ID"/>
-    </db-relationship>
-    <db-relationship name="BOX_THING" source="BOX" target="BOX_THING" toMany="true">
-        <db-attribute-pair source="ID" target="BOX_ID"/>
-    </db-relationship>
-    <db-relationship name="BOX" source="BOX_INFO" target="BOX" toMany="false">
-        <db-attribute-pair source="BOX_ID" target="ID"/>
-    </db-relationship>
-    <db-relationship name="BOX" source="BOX_THING" target="BOX" toMany="false">
-        <db-attribute-pair source="BOX_ID" target="ID"/>
-    </db-relationship>
-    <db-relationship name="THING" source="BOX_THING" target="THING" toMany="false">
-        <db-attribute-pair source="THING_VOLUME" target="VOLUME"/>
-        <db-attribute-pair source="THING_WEIGHT" target="WEIGHT"/>
-    </db-relationship>
-    <db-relationship name="BALL" source="THING" target="BALL" toMany="false">
-        <db-attribute-pair source="VOLUME" target="THING_VOLUME"/>
-        <db-attribute-pair source="WEIGHT" target="THING_WEIGHT"/>
-    </db-relationship>
-    <db-relationship name="BOX_THING" source="THING" target="BOX_THING" toMany="true">
-        <db-attribute-pair source="VOLUME" target="THING_VOLUME"/>
-        <db-attribute-pair source="WEIGHT" target="THING_WEIGHT"/>
-    </db-relationship>
-    <obj-relationship name="balls" source="Bag" target="Ball" deleteRule="Deny" db-relationship-path="BOXES.BALLS"/>
-    <obj-relationship name="boxes" source="Bag" target="Box" deleteRule="Deny" db-relationship-path="BOXES"/>
-    <obj-relationship name="things" source="Bag" target="Thing" deleteRule="Deny" db-relationship-path="BOXES.BOX_THING.THING"/>
-    <obj-relationship name="box" source="Ball" target="Box" deleteRule="Nullify" db-relationship-path="BOX"/>
-    <obj-relationship name="thing" source="Ball" target="Thing" deleteRule="Nullify" db-relationship-path="THING"/>
-    <obj-relationship name="bag" source="Box" target="Bag" deleteRule="Nullify" db-relationship-path="BAG"/>
-    <obj-relationship name="balls" source="Box" target="Ball" deleteRule="Deny" db-relationship-path="BALLS"/>
-    <obj-relationship name="boxInfo" source="Box" target="BoxInfo" deleteRule="Deny" db-relationship-path="BOX_INFO"/>
-    <obj-relationship name="things" source="Box" target="Thing" deleteRule="Deny" db-relationship-path="BOX_THING.THING"/>
-    <obj-relationship name="box" source="BoxInfo" target="Box" deleteRule="Nullify" db-relationship-path="BOX"/>
-    <obj-relationship name="ball" source="Thing" target="Ball" deleteRule="Nullify" db-relationship-path="BALL"/>
-    <obj-relationship name="box" source="Thing" target="Box" deleteRule="Deny" db-relationship-path="BOX_THING.BOX"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.things"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="BAG">
+		<db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="200"/>
+	</db-entity>
+	<db-entity name="BALL">
+		<db-attribute name="BOX_ID" type="BIGINT" isMandatory="true"/>
+		<db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="THING_VOLUME" type="INTEGER" isMandatory="true"/>
+		<db-attribute name="THING_WEIGHT" type="INTEGER" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="BOX">
+		<db-attribute name="BAG_ID" type="BIGINT" isMandatory="true"/>
+		<db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="200"/>
+	</db-entity>
+	<db-entity name="BOX_INFO">
+		<db-attribute name="BOX_ID" type="BIGINT" isMandatory="true"/>
+		<db-attribute name="COLOR" type="VARCHAR" isMandatory="true" length="200"/>
+		<db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="BOX_THING">
+		<db-attribute name="BOX_ID" type="BIGINT" isMandatory="true"/>
+		<db-attribute name="THING_VOLUME" type="INTEGER" isMandatory="true"/>
+		<db-attribute name="THING_WEIGHT" type="INTEGER" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="THING">
+		<db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="VOLUME" type="INTEGER" isMandatory="true"/>
+		<db-attribute name="WEIGHT" type="INTEGER" isMandatory="true"/>
+	</db-entity>
+	<obj-entity name="Bag" className="org.apache.cayenne.testdo.things.Bag" clientClassName="test.client.Bag" dbEntityName="BAG" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="Ball" className="org.apache.cayenne.testdo.things.Ball" clientClassName="test.client.Ball" dbEntityName="BALL" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
+		<obj-attribute name="thingVolume" type="java.lang.Integer" db-attribute-path="THING_VOLUME"/>
+		<obj-attribute name="thingWeight" type="java.lang.Integer" db-attribute-path="THING_WEIGHT"/>
+	</obj-entity>
+	<obj-entity name="Box" className="org.apache.cayenne.testdo.things.Box" clientClassName="test.client.Box" dbEntityName="BOX" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="BoxInfo" className="org.apache.cayenne.testdo.things.BoxInfo" clientClassName="test.client.BoxInfo" dbEntityName="BOX_INFO" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
+		<obj-attribute name="color" type="java.lang.String" db-attribute-path="COLOR"/>
+	</obj-entity>
+	<obj-entity name="Thing" className="org.apache.cayenne.testdo.things.Thing" clientClassName="test.client.Thing" dbEntityName="THING" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
+		<obj-attribute name="volume" type="java.lang.Integer" db-attribute-path="VOLUME"/>
+		<obj-attribute name="weight" type="java.lang.Integer" db-attribute-path="WEIGHT"/>
+	</obj-entity>
+	<db-relationship name="BOXES" source="BAG" target="BOX" toMany="true">
+		<db-attribute-pair source="ID" target="BAG_ID"/>
+	</db-relationship>
+	<db-relationship name="BOX" source="BALL" target="BOX">
+		<db-attribute-pair source="BOX_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="THING" source="BALL" target="THING">
+		<db-attribute-pair source="THING_VOLUME" target="VOLUME"/>
+		<db-attribute-pair source="THING_WEIGHT" target="WEIGHT"/>
+	</db-relationship>
+	<db-relationship name="BAG" source="BOX" target="BAG">
+		<db-attribute-pair source="BAG_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="BALLS" source="BOX" target="BALL" toMany="true">
+		<db-attribute-pair source="ID" target="BOX_ID"/>
+	</db-relationship>
+	<db-relationship name="BOX_INFO" source="BOX" target="BOX_INFO">
+		<db-attribute-pair source="ID" target="BOX_ID"/>
+	</db-relationship>
+	<db-relationship name="BOX_THING" source="BOX" target="BOX_THING" toMany="true">
+		<db-attribute-pair source="ID" target="BOX_ID"/>
+	</db-relationship>
+	<db-relationship name="BOX" source="BOX_INFO" target="BOX">
+		<db-attribute-pair source="BOX_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="BOX" source="BOX_THING" target="BOX">
+		<db-attribute-pair source="BOX_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="THING" source="BOX_THING" target="THING">
+		<db-attribute-pair source="THING_VOLUME" target="VOLUME"/>
+		<db-attribute-pair source="THING_WEIGHT" target="WEIGHT"/>
+	</db-relationship>
+	<db-relationship name="BALL" source="THING" target="BALL">
+		<db-attribute-pair source="VOLUME" target="THING_VOLUME"/>
+		<db-attribute-pair source="WEIGHT" target="THING_WEIGHT"/>
+	</db-relationship>
+	<db-relationship name="BOX_THING" source="THING" target="BOX_THING" toMany="true">
+		<db-attribute-pair source="VOLUME" target="THING_VOLUME"/>
+		<db-attribute-pair source="WEIGHT" target="THING_WEIGHT"/>
+	</db-relationship>
+	<obj-relationship name="balls" source="Bag" target="Ball" deleteRule="Deny" db-relationship-path="BOXES.BALLS"/>
+	<obj-relationship name="boxes" source="Bag" target="Box" deleteRule="Deny" db-relationship-path="BOXES"/>
+	<obj-relationship name="things" source="Bag" target="Thing" deleteRule="Deny" db-relationship-path="BOXES.BOX_THING.THING"/>
+	<obj-relationship name="box" source="Ball" target="Box" deleteRule="Nullify" db-relationship-path="BOX"/>
+	<obj-relationship name="thing" source="Ball" target="Thing" deleteRule="Nullify" db-relationship-path="THING"/>
+	<obj-relationship name="bag" source="Box" target="Bag" deleteRule="Nullify" db-relationship-path="BAG"/>
+	<obj-relationship name="balls" source="Box" target="Ball" deleteRule="Deny" db-relationship-path="BALLS"/>
+	<obj-relationship name="boxInfo" source="Box" target="BoxInfo" deleteRule="Deny" db-relationship-path="BOX_INFO"/>
+	<obj-relationship name="things" source="Box" target="Thing" deleteRule="Deny" db-relationship-path="BOX_THING.THING"/>
+	<obj-relationship name="box" source="BoxInfo" target="Box" deleteRule="Nullify" db-relationship-path="BOX"/>
+	<obj-relationship name="ball" source="Thing" target="Ball" deleteRule="Nullify" db-relationship-path="BALL"/>
+	<obj-relationship name="box" source="Thing" target="Box" deleteRule="Deny" db-relationship-path="BOX_THING.BOX"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/toone.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/toone.map.xml b/cayenne-server/src/test/resources/toone.map.xml
index f206e6e..ba31399 100644
--- a/cayenne-server/src/test/resources/toone.map.xml
+++ b/cayenne-server/src/test/resources/toone.map.xml
@@ -1,27 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.toone"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="org.apache.cayenne.testdo.toone"/>
-    <db-entity name="TOONE_DEP">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="TOONE_MASTER">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <obj-entity name="TooneDep" className="org.apache.cayenne.testdo.toone.TooneDep" clientClassName="org.apache.cayenne.testdo.toone.ClientTooneDep" dbEntityName="TOONE_DEP">
-    </obj-entity>
-    <obj-entity name="TooneMaster" className="org.apache.cayenne.testdo.toone.TooneMaster" clientClassName="org.apache.cayenne.testdo.toone.ClientTooneMaster" dbEntityName="TOONE_MASTER">
-    </obj-entity>
-    <db-relationship name="toMaster" source="TOONE_DEP" target="TOONE_MASTER" toMany="false">
-        <db-attribute-pair source="ID" target="ID"/>
-    </db-relationship>
-    <db-relationship name="toDependent" source="TOONE_MASTER" target="TOONE_DEP" toDependentPK="true" toMany="false">
-        <db-attribute-pair source="ID" target="ID"/>
-    </db-relationship>
-    <obj-relationship name="toMaster" source="TooneDep" target="TooneMaster" deleteRule="Nullify" db-relationship-path="toMaster"/>
-    <obj-relationship name="toDependent" source="TooneMaster" target="TooneDep" deleteRule="Cascade" db-relationship-path="toDependent"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.toone"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="org.apache.cayenne.testdo.toone"/>
+	<db-entity name="TOONE_DEP">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="TOONE_MASTER">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<obj-entity name="TooneDep" className="org.apache.cayenne.testdo.toone.TooneDep" clientClassName="org.apache.cayenne.testdo.toone.ClientTooneDep" dbEntityName="TOONE_DEP"/>
+	<obj-entity name="TooneMaster" className="org.apache.cayenne.testdo.toone.TooneMaster" clientClassName="org.apache.cayenne.testdo.toone.ClientTooneMaster" dbEntityName="TOONE_MASTER"/>
+	<db-relationship name="toMaster" source="TOONE_DEP" target="TOONE_MASTER">
+		<db-attribute-pair source="ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="toDependent" source="TOONE_MASTER" target="TOONE_DEP" toDependentPK="true">
+		<db-attribute-pair source="ID" target="ID"/>
+	</db-relationship>
+	<obj-relationship name="toMaster" source="TooneDep" target="TooneMaster" deleteRule="Nullify" db-relationship-path="toMaster"/>
+	<obj-relationship name="toDependent" source="TooneMaster" target="TooneDep" deleteRule="Cascade" db-relationship-path="toDependent"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/unsupported-distinct-types.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/unsupported-distinct-types.map.xml b/cayenne-server/src/test/resources/unsupported-distinct-types.map.xml
index 0280918..0452f5c 100644
--- a/cayenne-server/src/test/resources/unsupported-distinct-types.map.xml
+++ b/cayenne-server/src/test/resources/unsupported-distinct-types.map.xml
@@ -1,57 +1,57 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.unsupported_distinct_types"/>
 	<db-entity name="COMPOSITION">
 		<db-attribute name="BASE_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="CONTAINED_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 	</db-entity>
-	<db-entity name="ORDERS">
-		<db-attribute name="CUSTOMER_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-		<db-attribute name="PRODUCT_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-	</db-entity>
 	<db-entity name="CUSTOMER">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="LONGVARCHAR_COL" type="LONGVARCHAR"/>
 	</db-entity>
+	<db-entity name="ORDERS">
+		<db-attribute name="CUSTOMER_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="PRODUCT_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
 	<db-entity name="PRODUCT">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="LONGVARCHAR_COL" type="LONGVARCHAR"/>
 	</db-entity>
-	<obj-entity name="Product" className="org.apache.cayenne.testdo.unsupported_distinct_types.Product" dbEntityName="PRODUCT">
+	<obj-entity name="Customer" className="org.apache.cayenne.testdo.unsupported_distinct_types.Customer" dbEntityName="CUSTOMER">
 		<obj-attribute name="longvarcharCol" type="java.lang.String" db-attribute-path="LONGVARCHAR_COL"/>
 	</obj-entity>
-	<obj-entity name="Customer" className="org.apache.cayenne.testdo.unsupported_distinct_types.Customer" dbEntityName="CUSTOMER">
+	<obj-entity name="Product" className="org.apache.cayenne.testdo.unsupported_distinct_types.Product" dbEntityName="PRODUCT">
 		<obj-attribute name="longvarcharCol" type="java.lang.String" db-attribute-path="LONGVARCHAR_COL"/>
 	</obj-entity>
-	<db-relationship name="base" source="COMPOSITION" target="PRODUCT" toMany="false">
+	<db-relationship name="base" source="COMPOSITION" target="PRODUCT">
 		<db-attribute-pair source="BASE_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="contained" source="COMPOSITION" target="PRODUCT" toMany="false">
+	<db-relationship name="contained" source="COMPOSITION" target="PRODUCT">
 		<db-attribute-pair source="CONTAINED_ID" target="ID"/>
 	</db-relationship>
+	<db-relationship name="orderBy" source="CUSTOMER" target="ORDERS" toDependentPK="true" toMany="true">
+		<db-attribute-pair source="ID" target="CUSTOMER_ID"/>
+	</db-relationship>
+	<db-relationship name="order" source="ORDERS" target="PRODUCT">
+		<db-attribute-pair source="PRODUCT_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="orderBy" source="ORDERS" target="CUSTOMER">
+		<db-attribute-pair source="CUSTOMER_ID" target="ID"/>
+	</db-relationship>
 	<db-relationship name="base" source="PRODUCT" target="COMPOSITION" toDependentPK="true" toMany="true">
 		<db-attribute-pair source="ID" target="BASE_ID"/>
 	</db-relationship>
 	<db-relationship name="contained" source="PRODUCT" target="COMPOSITION" toDependentPK="true" toMany="true">
 		<db-attribute-pair source="ID" target="CONTAINED_ID"/>
 	</db-relationship>
-	<db-relationship name="order" source="ORDERS" target="PRODUCT" toMany="false">
-		<db-attribute-pair source="PRODUCT_ID" target="ID"/>
-	</db-relationship>
-	<db-relationship name="orderBy" source="ORDERS" target="CUSTOMER" toMany="false">
-		<db-attribute-pair source="CUSTOMER_ID" target="ID"/>
-	</db-relationship>
 	<db-relationship name="order" source="PRODUCT" target="ORDERS" toDependentPK="true" toMany="true">
 		<db-attribute-pair source="ID" target="PRODUCT_ID"/>
 	</db-relationship>
-	<db-relationship name="orderBy" source="CUSTOMER" target="ORDERS" toDependentPK="true" toMany="true">
-		<db-attribute-pair source="ID" target="CUSTOMER_ID"/>
-	</db-relationship>
+	<obj-relationship name="order" source="Customer" target="Product" deleteRule="Deny" db-relationship-path="orderBy.order"/>
 	<obj-relationship name="base" source="Product" target="Product" deleteRule="Deny" db-relationship-path="contained.base"/>
 	<obj-relationship name="contained" source="Product" target="Product" deleteRule="Deny" db-relationship-path="base.contained"/>
 	<obj-relationship name="orderBy" source="Product" target="Customer" deleteRule="Deny" db-relationship-path="order.orderBy"/>
-	<obj-relationship name="order" source="Customer" target="Product" deleteRule="Deny" db-relationship-path="orderBy.order"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/url conversion/cayenne-empty.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/url conversion/cayenne-empty.xml b/cayenne-server/src/test/resources/url conversion/cayenne-empty.xml
new file mode 100644
index 0000000..3ee43c4
--- /dev/null
+++ b/cayenne-server/src/test/resources/url conversion/cayenne-empty.xml	
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain project-version="9">
+    <map name="empty"/>
+</domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/url conversion/empty.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/url conversion/empty.map.xml b/cayenne-server/src/test/resources/url conversion/empty.map.xml
new file mode 100644
index 0000000..89734f3
--- /dev/null
+++ b/cayenne-server/src/test/resources/url conversion/empty.map.xml	
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
+          project-version="9">
+    <db-entity name="EMPTY">
+        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+    </db-entity>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/uuid.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/uuid.map.xml b/cayenne-server/src/test/resources/uuid.map.xml
index 1f38102..2622564 100644
--- a/cayenne-server/src/test/resources/uuid.map.xml
+++ b/cayenne-server/src/test/resources/uuid.map.xml
@@ -1,24 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.uuid"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="UUID_PK_ENTITY">
-        <db-attribute name="ID" type="VARCHAR" isPrimaryKey="true" isMandatory="true" length="100"/>
-    </db-entity>
-    <db-entity name="UUID_TEST">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="UUID" type="VARCHAR" length="100"/>
-    </db-entity>
-    <obj-entity name="UuidPkEntity" className="org.apache.cayenne.testdo.uuid.UuidPkEntity" dbEntityName="UUID_PK_ENTITY">
-        <obj-attribute name="id" type="java.util.UUID" db-attribute-path="ID"/>
-    </obj-entity>
-    <obj-entity name="UuidTestEntity" className="org.apache.cayenne.testdo.uuid.UuidTestEntity" dbEntityName="UUID_TEST">
-        <obj-attribute name="uuid" type="java.util.UUID" db-attribute-path="UUID"/>
-    </obj-entity>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.uuid"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="UUID_PK_ENTITY">
+		<db-attribute name="ID" type="VARCHAR" isPrimaryKey="true" isMandatory="true" length="100"/>
+	</db-entity>
+	<db-entity name="UUID_TEST">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="UUID" type="VARCHAR" length="100"/>
+	</db-entity>
+	<obj-entity name="UuidPkEntity" className="org.apache.cayenne.testdo.uuid.UuidPkEntity" dbEntityName="UUID_PK_ENTITY">
+		<obj-attribute name="id" type="java.util.UUID" db-attribute-path="ID"/>
+	</obj-entity>
+	<obj-entity name="UuidTestEntity" className="org.apache.cayenne.testdo.uuid.UuidTestEntity" dbEntityName="UUID_TEST">
+		<obj-attribute name="uuid" type="java.util.UUID" db-attribute-path="UUID"/>
+	</obj-entity>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/weighted-sort.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/weighted-sort.map.xml b/cayenne-server/src/test/resources/weighted-sort.map.xml
index ac01ec5..25684af 100644
--- a/cayenne-server/src/test/resources/weighted-sort.map.xml
+++ b/cayenne-server/src/test/resources/weighted-sort.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.weighted_sort"/>
 	<db-entity name="SORT_DEP">
 		<db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
@@ -11,11 +11,9 @@
 	<db-entity name="SORT_ROOT">
 		<db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
 	</db-entity>
-	<obj-entity name="SortDep" className="org.apache.cayenne.testdo.weighted_sort.SortDep" dbEntityName="SORT_DEP">
-	</obj-entity>
-	<obj-entity name="SortRoot" className="org.apache.cayenne.testdo.weighted_sort.SortRoot" dbEntityName="SORT_ROOT">
-	</obj-entity>
-	<db-relationship name="root" source="SORT_DEP" target="SORT_ROOT" toMany="false">
+	<obj-entity name="SortDep" className="org.apache.cayenne.testdo.weighted_sort.SortDep" dbEntityName="SORT_DEP"/>
+	<obj-entity name="SortRoot" className="org.apache.cayenne.testdo.weighted_sort.SortRoot" dbEntityName="SORT_ROOT"/>
+	<db-relationship name="root" source="SORT_DEP" target="SORT_ROOT">
 		<db-attribute-pair source="ROOT_ID" target="ID"/>
 	</db-relationship>
 	<db-relationship name="deps" source="SORT_ROOT" target="SORT_DEP" toMany="true">

[08/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - new XML loader for DataMap - new project version - updated test projects

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DbEntityHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DbEntityHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DbEntityHandler.java
new file mode 100644
index 0000000..8de6bb1
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DbEntityHandler.java
@@ -0,0 +1,146 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+public class DbEntityHandler extends NamespaceAwareNestedTagHandler {
+
+    private static final String DB_ENTITY_TAG = "db-entity";
+    private static final String DB_ATTRIBUTE_TAG = "db-attribute";
+    private static final String DB_KEY_GENERATOR_TAG = "db-key-generator";
+    private static final String QUALIFIER_TAG = "qualifier";
+
+    private DataMap dataMap;
+    private DbEntity entity;
+    private DbAttribute lastAttribute;
+
+    public DbEntityHandler(NamespaceAwareNestedTagHandler parentHandler, DataMap dataMap) {
+        super(parentHandler);
+        this.dataMap = dataMap;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        switch (localName) {
+            case DB_ENTITY_TAG:
+                createDbEntity(attributes);
+                return true;
+
+            case DB_ATTRIBUTE_TAG:
+                createDbAttribute(attributes);
+                return true;
+
+            case QUALIFIER_TAG:
+                return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    protected void processCharData(String localName, String data) {
+        switch (localName) {
+            case QUALIFIER_TAG:
+                createQualifier(data);
+                break;
+        }
+    }
+
+    @Override
+    protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String qName, Attributes attributes) {
+        switch (localName) {
+            case DB_KEY_GENERATOR_TAG:
+                return new DbKeyGeneratorHandler(this, entity);
+        }
+        return super.createChildTagHandler(namespaceURI, localName, qName, attributes);
+    }
+
+    private void createDbEntity(Attributes attributes) {
+        String name = attributes.getValue("name");
+        entity = new DbEntity(name);
+        entity.setSchema(attributes.getValue("schema"));
+        entity.setCatalog(attributes.getValue("catalog"));
+        dataMap.addDbEntity(entity);
+    }
+
+    private void createDbAttribute(Attributes attributes) {
+        String name = attributes.getValue("name");
+        String type = attributes.getValue("type");
+
+        lastAttribute = new DbAttribute(name);
+        lastAttribute.setType(TypesMapping.getSqlTypeByName(type));
+        entity.addAttribute(lastAttribute);
+
+        String length = attributes.getValue("length");
+        if (length != null) {
+            lastAttribute.setMaxLength(Integer.parseInt(length));
+        }
+
+        String precision = attributes.getValue("attributePrecision");
+        if (precision != null) {
+            lastAttribute.setAttributePrecision(Integer.parseInt(precision));
+        }
+
+        // this is an obsolete 1.2 'precision' attribute that really meant 'scale'
+        String pseudoPrecision = attributes.getValue("precision");
+        if (pseudoPrecision != null) {
+            lastAttribute.setScale(Integer.parseInt(pseudoPrecision));
+        }
+
+        String scale = attributes.getValue("scale");
+        if (scale != null) {
+            lastAttribute.setScale(Integer.parseInt(scale));
+        }
+
+        lastAttribute.setPrimaryKey(DataMapHandler.TRUE.equalsIgnoreCase(attributes.getValue("isPrimaryKey")));
+        lastAttribute.setMandatory(DataMapHandler.TRUE.equalsIgnoreCase(attributes.getValue("isMandatory")));
+        lastAttribute.setGenerated(DataMapHandler.TRUE.equalsIgnoreCase(attributes.getValue("isGenerated")));
+    }
+
+    private void createQualifier(String qualifier) {
+        if (qualifier.trim().length() == 0) {
+            return;
+        }
+
+        // qualifier can belong to ObjEntity, DbEntity or a query
+        if (entity != null) {
+            entity.setQualifier(ExpressionFactory.exp(qualifier));
+        }
+    }
+
+    public DbEntity getEntity() {
+        return entity;
+    }
+
+    public DbAttribute getLastAttribute() {
+        return lastAttribute;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DbKeyGeneratorHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DbKeyGeneratorHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DbKeyGeneratorHandler.java
new file mode 100644
index 0000000..e76c4c3
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DbKeyGeneratorHandler.java
@@ -0,0 +1,117 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbKeyGenerator;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+public class DbKeyGeneratorHandler extends NamespaceAwareNestedTagHandler {
+
+    private static final String DB_KEY_GENERATOR_TAG = "db-key-generator";
+    private static final String DB_GENERATOR_TYPE_TAG = "db-generator-type";
+    private static final String DB_GENERATOR_NAME_TAG = "db-generator-name";
+    private static final String DB_KEY_CACHE_SIZE_TAG = "db-key-cache-size";
+
+    DbEntity entity;
+
+    public DbKeyGeneratorHandler(NamespaceAwareNestedTagHandler parentHandler, DbEntity entity) {
+        super(parentHandler);
+        this.entity = entity;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        switch (localName) {
+            case DB_KEY_GENERATOR_TAG:
+                createDbKeyGenerator();
+                return true;
+
+            case DB_GENERATOR_NAME_TAG:
+            case DB_GENERATOR_TYPE_TAG:
+            case DB_KEY_CACHE_SIZE_TAG:
+                return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    protected void processCharData(String localName, String data) {
+        switch (localName) {
+            case DB_GENERATOR_TYPE_TAG:
+                setDbGeneratorType(data);
+                break;
+
+            case DB_GENERATOR_NAME_TAG:
+                setDbGeneratorName(data);
+                break;
+
+            case DB_KEY_CACHE_SIZE_TAG:
+                setDbKeyCacheSize(data);
+                break;
+        }
+    }
+
+    private void createDbKeyGenerator() {
+        entity.setPrimaryKeyGenerator(new DbKeyGenerator());
+    }
+
+    private void setDbGeneratorType(String type) {
+        if (entity == null) {
+            return;
+        }
+        DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator();
+        pkGenerator.setGeneratorType(type);
+        if (pkGenerator.getGeneratorType() == null) {
+            entity.setPrimaryKeyGenerator(null);
+        }
+    }
+
+    private void setDbGeneratorName(String name) {
+        if (entity == null) {
+            return;
+        }
+        DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator();
+        if (pkGenerator == null) {
+            return;
+        }
+        pkGenerator.setGeneratorName(name);
+    }
+
+    private void setDbKeyCacheSize(String size) {
+        if (entity == null) {
+            return;
+        }
+        DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator();
+        if (pkGenerator == null) {
+            return;
+        }
+        try {
+            pkGenerator.setKeyCacheSize(new Integer(size.trim()));
+        } catch (Exception ex) {
+            pkGenerator.setKeyCacheSize(null);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DbRelationshipHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DbRelationshipHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DbRelationshipHandler.java
new file mode 100644
index 0000000..b4730e5
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DbRelationshipHandler.java
@@ -0,0 +1,97 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+public class DbRelationshipHandler extends NamespaceAwareNestedTagHandler {
+
+    private static final String DB_RELATIONSHIP_TAG = "db-relationship";
+    public static final String DB_ATTRIBUTE_PAIR_TAG = "db-attribute-pair";
+
+    private DataMap map;
+
+    private DbRelationship dbRelationship;
+
+    public DbRelationshipHandler(NamespaceAwareNestedTagHandler parentHandler, DataMap map) {
+        super(parentHandler);
+        this.map = map;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+
+        switch (localName) {
+            case DB_RELATIONSHIP_TAG:
+                createRelationship(attributes);
+                return true;
+
+            case DB_ATTRIBUTE_PAIR_TAG:
+                createDbAttributePair(attributes);
+                return true;
+        }
+
+        return false;
+    }
+
+    private void createRelationship(Attributes attributes) throws SAXException {
+        String name = attributes.getValue("name");
+        if (name == null) {
+            throw new SAXException("DbRelationshipHandler::createRelationship() - missing \"name\" attribute.");
+        }
+
+        String sourceName = attributes.getValue("source");
+        if (sourceName == null) {
+            throw new SAXException("DbRelationshipHandler::createRelationship() - null source entity");
+        }
+
+        DbEntity source = map.getDbEntity(sourceName);
+        if (source == null) {
+            return;
+        }
+
+        dbRelationship = new DbRelationship(name);
+        dbRelationship.setSourceEntity(source);
+        dbRelationship.setTargetEntityName(attributes.getValue("target"));
+        dbRelationship.setToMany(DataMapHandler.TRUE.equalsIgnoreCase(attributes.getValue("toMany")));
+        dbRelationship.setToDependentPK(DataMapHandler.TRUE.equalsIgnoreCase(attributes.getValue("toDependentPK")));
+
+        source.addRelationship(dbRelationship);
+    }
+
+    private void createDbAttributePair(Attributes attributes) {
+        DbJoin join = new DbJoin(dbRelationship);
+        join.setSourceName(attributes.getValue("source"));
+        join.setTargetName(attributes.getValue("target"));
+        dbRelationship.addJoin(join);
+    }
+
+    public DbRelationship getDbRelationship() {
+        return dbRelationship;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DefaultDataChannelMetaData.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DefaultDataChannelMetaData.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DefaultDataChannelMetaData.java
new file mode 100644
index 0000000..869abed
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DefaultDataChannelMetaData.java
@@ -0,0 +1,91 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.cayenne.configuration.ConfigurationNode;
+
+/**
+ * <p>
+ *     Default implementation of {@link DataChannelMetaData} that stores data in Map.
+ * </p>
+ * <p>
+ *     This implementation is thread safe.
+ * </p>
+ *
+ * @see NoopDataChannelMetaData
+ * @since 4.1
+ */
+public class DefaultDataChannelMetaData implements DataChannelMetaData {
+
+    private Map<ConfigurationNode, Map<Class<?>, Object>> map;
+
+    public DefaultDataChannelMetaData() {
+        map = new ConcurrentHashMap<>();
+    }
+
+    /**
+     * value.getClass() will be used under the hood to associate data with the key object.
+     *
+     * @param key object for which we want to store data
+     * @param value data to store
+     */
+    @Override
+    public void add(ConfigurationNode key, Object value) {
+        if(key == null || value == null) {
+            return;
+        }
+
+        Map<Class<?>, Object> data = map.get(key);
+        if(data == null) {
+            data = new ConcurrentHashMap<>();
+            Map<Class<?>, Object> old = map.put(key, data);
+            // extra check in case if someone was fast enough
+            if(old != null) {
+                data.putAll(old);
+            }
+        }
+        data.put(value.getClass(), value);
+    }
+
+    /**
+     * If either key or value is {@code null} then {@code null} will be returned.
+     *
+     * @param key object for wich we want meta data
+     * @param type meta data type class
+     * @param <T> data type
+     * @return value or {@code null}
+     */
+    @Override
+    public <T> T get(ConfigurationNode key, Class<T> type) {
+        if(key == null || type == null) {
+            return null;
+        }
+
+        Map<Class<?>, Object> data = map.get(key);
+        if(data == null) {
+            return null;
+        }
+
+        return type.cast(data.get(type));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DefaultHandlerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DefaultHandlerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DefaultHandlerFactory.java
new file mode 100644
index 0000000..5fd2293
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DefaultHandlerFactory.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.configuration.xml;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+
+/**
+ * @since 4.1
+ */
+public class DefaultHandlerFactory implements HandlerFactory {
+
+    private static Logger logger = LoggerFactory.getLogger(XMLDataChannelDescriptorLoader.class);
+
+    @Override
+    public NamespaceAwareNestedTagHandler createHandler(String namespace, String localName, NamespaceAwareNestedTagHandler parent) {
+        return new NamespaceAwareNestedTagHandler(parent, namespace) {
+            @Override
+            protected boolean processElement(String namespaceURI, String localName, Attributes attributes) {
+                logger.debug("Skipping unknown tag <{}:{}>", namespaceURI, localName);
+                return true;
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/EmbeddableAttributeHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/EmbeddableAttributeHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/EmbeddableAttributeHandler.java
new file mode 100644
index 0000000..d0d4ae9
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/EmbeddableAttributeHandler.java
@@ -0,0 +1,69 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.map.EmbeddedAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+public class EmbeddableAttributeHandler extends NamespaceAwareNestedTagHandler {
+
+    private static final String EMBEDDED_ATTRIBUTE_TAG = "embedded-attribute";
+    private static final String EMBEDDABLE_ATTRIBUTE_OVERRIDE_TAG = "embeddable-attribute-override";
+
+    private ObjEntity entity;
+
+    private EmbeddedAttribute embeddedAttribute;
+
+    public EmbeddableAttributeHandler(NamespaceAwareNestedTagHandler parentHandler, ObjEntity entity) {
+        super(parentHandler);
+        this.entity = entity;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        switch (localName) {
+            case EMBEDDED_ATTRIBUTE_TAG:
+                createEmbeddableAttribute(attributes);
+                return true;
+
+            case EMBEDDABLE_ATTRIBUTE_OVERRIDE_TAG:
+                createEmbeddableAttributeOverride(attributes);
+                return true;
+        }
+
+        return false;
+    }
+
+    private void createEmbeddableAttribute(Attributes attributes) {
+        embeddedAttribute = new EmbeddedAttribute(attributes.getValue("name"));
+        embeddedAttribute.setType(attributes.getValue("type"));
+        entity.addAttribute(embeddedAttribute);
+    }
+
+    private void createEmbeddableAttributeOverride(Attributes attributes) {
+        embeddedAttribute.addAttributeOverride(attributes.getValue("name"),
+                attributes.getValue("db-attribute-path"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/EmbeddableHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/EmbeddableHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/EmbeddableHandler.java
new file mode 100644
index 0000000..648474e
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/EmbeddableHandler.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.configuration.xml;
+
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Embeddable;
+import org.apache.cayenne.map.EmbeddableAttribute;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+public class EmbeddableHandler extends NamespaceAwareNestedTagHandler {
+
+    private static final String EMBEDDABLE_TAG = "embeddable";
+    private static final String EMBEDDABLE_ATTRIBUTE_TAG = "embeddable-attribute";
+
+    private DataMap map;
+
+    private Embeddable embeddable;
+
+    public EmbeddableHandler(NamespaceAwareNestedTagHandler parentHandler, DataMap map) {
+        super(parentHandler);
+        this.map = map;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        switch (localName) {
+            case EMBEDDABLE_TAG:
+                createEmbeddable(attributes);
+                return true;
+
+            case EMBEDDABLE_ATTRIBUTE_TAG:
+                createEmbeddableAttribute(attributes);
+                return true;
+        }
+
+        return false;
+    }
+
+    private void createEmbeddable(Attributes attributes) {
+        embeddable = new Embeddable(attributes.getValue("className"));
+        map.addEmbeddable(embeddable);
+    }
+
+    private void createEmbeddableAttribute(Attributes attributes) {
+        EmbeddableAttribute ea = new EmbeddableAttribute(attributes.getValue("name"));
+        ea.setType(attributes.getValue("type"));
+        ea.setDbAttributeName(attributes.getValue("db-attribute-name"));
+        embeddable.addAttribute(ea);
+    }
+
+    public Embeddable getEmbeddable() {
+        return embeddable;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/HandlerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/HandlerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/HandlerFactory.java
new file mode 100644
index 0000000..d02be06
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/HandlerFactory.java
@@ -0,0 +1,30 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.configuration.xml;
+
+/**
+ * Factory that creates handlers for unparsed elements.
+ *
+ * @since 4.1
+ */
+public interface HandlerFactory {
+
+    NamespaceAwareNestedTagHandler createHandler(String namespace, String localName, NamespaceAwareNestedTagHandler parent);
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/LoaderContext.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/LoaderContext.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/LoaderContext.java
new file mode 100644
index 0000000..9507e4f
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/LoaderContext.java
@@ -0,0 +1,63 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.cayenne.map.DataMap;
+import org.xml.sax.XMLReader;
+
+/**
+ * @since 4.1
+ */
+public class LoaderContext {
+
+    Collection<DataMapLoaderListener> dataMapListeners;
+
+    private XMLReader xmlReader;
+
+    private HandlerFactory factory;
+
+    public LoaderContext(XMLReader reader, HandlerFactory factory) {
+        this.xmlReader = reader;
+        this.factory = factory;
+        dataMapListeners = new ArrayList<>();
+    }
+
+    public HandlerFactory getFactory() {
+        return factory;
+    }
+
+    public XMLReader getXmlReader() {
+        return xmlReader;
+    }
+
+    public void addDataMapListener(DataMapLoaderListener dataMapLoaderListener) {
+        dataMapListeners.add(dataMapLoaderListener);
+    }
+
+    public void dataMapLoaded(DataMap dataMap) {
+        for(DataMapLoaderListener listener : dataMapListeners) {
+            listener.onDataMapLoaded(dataMap);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/NamespaceAwareNestedTagHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/NamespaceAwareNestedTagHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/NamespaceAwareNestedTagHandler.java
new file mode 100644
index 0000000..ec332e5
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/NamespaceAwareNestedTagHandler.java
@@ -0,0 +1,97 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import java.util.Objects;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * Base class for handlers that can delegate execution of unknown tags to
+ * handlers produced by factory.
+ *
+ * @since 4.1
+ */
+abstract public class NamespaceAwareNestedTagHandler extends SAXNestedTagHandler {
+
+    protected String targetNamespace;
+
+    private StringBuilder charactersBuffer = new StringBuilder();
+
+    public NamespaceAwareNestedTagHandler(LoaderContext loaderContext) {
+        super(loaderContext);
+    }
+
+    public NamespaceAwareNestedTagHandler(SAXNestedTagHandler parentHandler, String targetNamespace) {
+        super(parentHandler);
+        this.targetNamespace = Objects.requireNonNull(targetNamespace);
+    }
+
+    public NamespaceAwareNestedTagHandler(NamespaceAwareNestedTagHandler parentHandler) {
+        this(parentHandler, parentHandler.targetNamespace);
+    }
+
+    abstract protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException;
+
+    protected void processCharData(String localName, String data) {
+    }
+
+    @Override
+    public void characters(char[] ch, int start, int length) throws SAXException {
+        charactersBuffer.append(ch, start, length);
+    }
+
+    @Override
+    public final void startElement(String namespaceURI, String localName,
+                                   String qName, Attributes attributes) throws SAXException {
+
+        ContentHandler childHandler = createChildTagHandler(namespaceURI, localName, qName, attributes);
+
+        if(!namespaceURI.equals(targetNamespace) || !processElement(namespaceURI, localName, attributes)) {
+            // recursively pass element down into child handlers
+            childHandler.startElement(namespaceURI, localName, qName, attributes);
+        }
+
+        // push child handler to the stack...
+        loaderContext.getXmlReader().setContentHandler(childHandler);
+        charactersBuffer.delete(0, charactersBuffer.length());
+    }
+
+    @Override
+    public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
+        super.endElement(namespaceURI, localName, qName);
+        if(namespaceURI.equals(targetNamespace) && parentHandler instanceof NamespaceAwareNestedTagHandler) {
+            ((NamespaceAwareNestedTagHandler)parentHandler).processCharData(localName, charactersBuffer.toString());
+        }
+    }
+
+    @Override
+    protected ContentHandler createChildTagHandler(String namespaceURI, String localName,
+                                                   String qName, Attributes attributes) {
+        // try to pass unknown tags to someone else
+        return loaderContext.getFactory().createHandler(namespaceURI, localName, this);
+    }
+
+    public void setTargetNamespace(String targetNamespace) {
+        this.targetNamespace = targetNamespace;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/NoopDataChannelMetaData.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/NoopDataChannelMetaData.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/NoopDataChannelMetaData.java
new file mode 100644
index 0000000..cbcb696
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/NoopDataChannelMetaData.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.configuration.xml;
+
+import org.apache.cayenne.configuration.ConfigurationNode;
+
+/**
+ * Noop implementation of {@link DataChannelMetaData}.
+ * Used by Cayenne runtime by default as it doesn't need this information.
+ *
+ * @see DefaultDataChannelMetaData
+ * @since 4.1
+ */
+public class NoopDataChannelMetaData implements DataChannelMetaData {
+
+    @Override
+    public void add(ConfigurationNode key, Object value) {
+        // noop
+    }
+
+    @Override
+    public <T> T get(ConfigurationNode key, Class<T> type) {
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/ObjEntityHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/ObjEntityHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/ObjEntityHandler.java
new file mode 100644
index 0000000..e9ee9aa
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/ObjEntityHandler.java
@@ -0,0 +1,210 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.configuration.xml;
+
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.map.CallbackDescriptor;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+public class ObjEntityHandler extends NamespaceAwareNestedTagHandler {
+
+    private static final String OBJ_ENTITY_TAG = "obj-entity";
+    private static final String OBJ_ATTRIBUTE_TAG = "obj-attribute";
+    private static final String OBJ_ATTRIBUTE_OVERRIDE_TAG = "attribute-override";
+    private static final String EMBEDDED_ATTRIBUTE_TAG = "embedded-attribute";
+    private static final String QUALIFIER_TAG = "qualifier";
+
+    // lifecycle listeners and callbacks related
+    private static final String POST_ADD_TAG = "post-add";
+    private static final String PRE_PERSIST_TAG = "pre-persist";
+    private static final String POST_PERSIST_TAG = "post-persist";
+    private static final String PRE_UPDATE_TAG = "pre-update";
+    private static final String POST_UPDATE_TAG = "post-update";
+    private static final String PRE_REMOVE_TAG = "pre-remove";
+    private static final String POST_REMOVE_TAG = "post-remove";
+    private static final String POST_LOAD_TAG = "post-load";
+
+    private DataMap map;
+
+    private ObjEntity entity;
+
+    private ObjAttribute lastAttribute;
+
+    public ObjEntityHandler(NamespaceAwareNestedTagHandler parentHandler, DataMap map) {
+        super(parentHandler);
+        this.map = map;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        switch (localName) {
+            case OBJ_ENTITY_TAG:
+                createObjEntity(attributes);
+                return true;
+
+            case OBJ_ATTRIBUTE_TAG:
+                createObjAttribute(attributes);
+                return true;
+
+            case OBJ_ATTRIBUTE_OVERRIDE_TAG:
+                processStartAttributeOverride(attributes);
+                return true;
+
+            case QUALIFIER_TAG:
+                return true;
+
+            case POST_ADD_TAG:
+            case PRE_PERSIST_TAG:
+            case POST_PERSIST_TAG:
+            case PRE_UPDATE_TAG:
+            case POST_UPDATE_TAG:
+            case PRE_REMOVE_TAG:
+            case POST_REMOVE_TAG:
+            case POST_LOAD_TAG:
+                createCallback(localName, attributes);
+                return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String qName, Attributes attributes) {
+        if(namespaceURI.equals(targetNamespace)) {
+            switch (localName) {
+                case EMBEDDED_ATTRIBUTE_TAG:
+                    return new EmbeddableAttributeHandler(this, entity);
+            }
+        }
+
+        return super.createChildTagHandler(namespaceURI, localName, qName, attributes);
+    }
+
+    @Override
+    protected void processCharData(String localName, String data) {
+        switch (localName) {
+            case QUALIFIER_TAG:
+                createQualifier(data);
+                break;
+        }
+    }
+
+    private void createObjEntity(Attributes attributes) {
+        entity = new ObjEntity(attributes.getValue("name"));
+        entity.setClassName(attributes.getValue("className"));
+        entity.setClientClassName(attributes.getValue("clientClassName"));
+        entity.setAbstract(DataMapHandler.TRUE.equalsIgnoreCase(attributes.getValue("abstract")));
+        entity.setReadOnly(DataMapHandler.TRUE.equalsIgnoreCase(attributes.getValue("readOnly")));
+        entity.setServerOnly(DataMapHandler.TRUE.equalsIgnoreCase(attributes.getValue("serverOnly")));
+        if ("optimistic".equals(attributes.getValue("", "lock-type"))) {
+            entity.setDeclaredLockType(ObjEntity.LOCK_TYPE_OPTIMISTIC);
+        }
+
+        String superEntityName = attributes.getValue("superEntityName");
+        if (superEntityName != null) {
+            entity.setSuperEntityName(superEntityName);
+        } else {
+            entity.setSuperClassName(attributes.getValue("superClassName"));
+            entity.setClientSuperClassName(attributes.getValue("clientSuperClassName"));
+        }
+        entity.setDbEntityName(attributes.getValue("dbEntityName"));
+
+        map.addObjEntity(entity);
+    }
+
+    private void createObjAttribute(Attributes attributes) {
+        String dbPath = attributes.getValue("db-attribute-path");
+        if (dbPath == null) {
+            dbPath = attributes.getValue("db-attribute-name");
+        }
+
+        lastAttribute = new ObjAttribute(attributes.getValue("name"));
+        lastAttribute.setType(attributes.getValue("type"));
+        lastAttribute.setUsedForLocking(DataMapHandler.TRUE.equalsIgnoreCase(attributes.getValue("lock")));
+        lastAttribute.setDbAttributePath(dbPath);
+        entity.addAttribute(lastAttribute);
+    }
+
+    private void processStartAttributeOverride(Attributes attributes) {
+        entity.addAttributeOverride(attributes.getValue("name"),
+                attributes.getValue("db-attribute-path"));
+    }
+
+    private CallbackDescriptor getCallbackDescriptor(String type) {
+        if (entity == null) {
+            return null;
+        }
+
+        switch (type) {
+            case POST_ADD_TAG:
+                return entity.getCallbackMap().getPostAdd();
+            case PRE_PERSIST_TAG:
+                return entity.getCallbackMap().getPrePersist();
+            case POST_PERSIST_TAG:
+                return entity.getCallbackMap().getPostPersist();
+            case PRE_UPDATE_TAG:
+                return entity.getCallbackMap().getPreUpdate();
+            case POST_UPDATE_TAG:
+                return entity.getCallbackMap().getPostUpdate();
+            case PRE_REMOVE_TAG:
+                return entity.getCallbackMap().getPreRemove();
+            case POST_REMOVE_TAG:
+                return entity.getCallbackMap().getPostRemove();
+            case POST_LOAD_TAG:
+                return entity.getCallbackMap().getPostLoad();
+        }
+
+        return null;
+    }
+
+    private void createCallback(String type, Attributes attributes) {
+        String methodName = attributes.getValue("method-name");
+        CallbackDescriptor descriptor = getCallbackDescriptor(type);
+        if(descriptor != null) {
+            descriptor.addCallbackMethod(methodName);
+        }
+    }
+
+    private void createQualifier(String qualifier) {
+        if (qualifier.trim().length() == 0) {
+            return;
+        }
+
+        if (entity != null) {
+            entity.setDeclaredQualifier(ExpressionFactory.exp(qualifier));
+        }
+    }
+
+    public ObjEntity getEntity() {
+        return entity;
+    }
+
+    public ObjAttribute getLastAttribute() {
+        return lastAttribute;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/ObjRelationshipHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/ObjRelationshipHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/ObjRelationshipHandler.java
new file mode 100644
index 0000000..63be65d
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/ObjRelationshipHandler.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.configuration.xml;
+
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DeleteRule;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+public class ObjRelationshipHandler extends NamespaceAwareNestedTagHandler {
+
+    public static final String OBJ_RELATIONSHIP_TAG = "obj-relationship";
+
+    @Deprecated
+    public static final String DB_RELATIONSHIP_REF_TAG = "db-relationship-ref";
+
+    private DataMap map;
+
+    private ObjRelationship objRelationship;
+
+    public ObjRelationshipHandler(NamespaceAwareNestedTagHandler parentHandler, DataMap map) {
+        super(parentHandler);
+        this.map = map;
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        switch (localName) {
+            case OBJ_RELATIONSHIP_TAG:
+                addObjRelationship(attributes);
+                return true;
+
+            case DB_RELATIONSHIP_REF_TAG:
+                addDbRelationshipRef(attributes);
+                return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * <db-relationship-ref> tag deprecated
+     */
+    @Deprecated
+    private void addDbRelationshipRef(Attributes attributes) throws SAXException {
+        String name = attributes.getValue("name");
+        if (name == null) {
+            throw new SAXException("ObjRelationshipHandler::addDbRelationshipRef() - null DbRelationship name for "
+                    + objRelationship.getName());
+        }
+
+        String path = objRelationship.getDbRelationshipPath();
+        objRelationship.setDbRelationshipPath((path != null) ? path + "." + name : name);
+    }
+
+    private void addObjRelationship(Attributes attributes) throws SAXException {
+        String name = attributes.getValue("name");
+        if (null == name) {
+            throw new SAXException("ObjRelationshipHandler::addObjRelationship() - unable to parse target.");
+        }
+
+        String sourceName = attributes.getValue("source");
+        if (sourceName == null) {
+            throw new SAXException("ObjRelationshipHandler::addObjRelationship() - unable to parse source.");
+        }
+
+        ObjEntity source = map.getObjEntity(sourceName);
+        if (source == null) {
+            throw new SAXException("ObjRelationshipHandler::addObjRelationship() - unable to find source " + sourceName);
+        }
+
+        objRelationship = new ObjRelationship(name);
+        objRelationship.setSourceEntity(source);
+        objRelationship.setTargetEntityName(attributes.getValue("target"));
+        objRelationship.setDeleteRule(DeleteRule.deleteRuleForName(attributes.getValue("deleteRule")));
+        objRelationship.setUsedForLocking(DataMapHandler.TRUE.equalsIgnoreCase(attributes.getValue("lock")));
+        objRelationship.setDeferredDbRelationshipPath((attributes.getValue("db-relationship-path")));
+        objRelationship.setCollectionType(attributes.getValue("collection-type"));
+        objRelationship.setMapKey(attributes.getValue("map-key"));
+        source.addRelationship(objRelationship);
+    }
+
+    public ObjRelationship getObjRelationship() {
+        return objRelationship;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/ProcedureHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/ProcedureHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/ProcedureHandler.java
new file mode 100644
index 0000000..72e6a53
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/ProcedureHandler.java
@@ -0,0 +1,114 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.configuration.xml;
+
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.ProcedureParameter;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+public class ProcedureHandler extends NamespaceAwareNestedTagHandler {
+
+    private static final String PROCEDURE_TAG = "procedure";
+    private static final String PROCEDURE_PARAMETER_TAG = "procedure-parameter";
+
+    private DataMap map;
+
+    private Procedure procedure;
+
+    public ProcedureHandler(NamespaceAwareNestedTagHandler parentHandler, DataMap map) {
+        super(parentHandler);
+        this.map = map;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        switch (localName) {
+            case PROCEDURE_TAG:
+                addProcedure(attributes);
+                return true;
+
+            case PROCEDURE_PARAMETER_TAG:
+                addProcedureParameter(attributes);
+                return true;
+        }
+
+        return false;
+    }
+
+    private void addProcedure(Attributes attributes) throws SAXException{
+        String name = attributes.getValue("name");
+        String returningValue = attributes.getValue("returningValue");
+        if (null == name) {
+            throw new SAXException("ProcedureHandler::addProcedure() - no procedure name.");
+        }
+
+        procedure = new Procedure(name);
+        procedure.setReturningValue(returningValue != null && returningValue.equalsIgnoreCase(DataMapHandler.TRUE));
+        procedure.setSchema(attributes.getValue("schema"));
+        procedure.setCatalog(attributes.getValue("catalog"));
+        map.addProcedure(procedure);
+    }
+
+    private void addProcedureParameter(Attributes attributes) throws SAXException {
+
+        String name = attributes.getValue("name");
+        if (name == null) {
+            throw new SAXException("ProcedureHandler::addProcedureParameter() - no procedure parameter name.");
+        }
+
+        ProcedureParameter parameter = new ProcedureParameter(name);
+
+        String type = attributes.getValue("type");
+        if (type != null) {
+            parameter.setType(TypesMapping.getSqlTypeByName(type));
+        }
+
+        String length = attributes.getValue("length");
+        if (length != null) {
+            parameter.setMaxLength(Integer.parseInt(length));
+        }
+
+        String precision = attributes.getValue("precision");
+        if (precision != null) {
+            parameter.setPrecision(Integer.parseInt(precision));
+        }
+
+        String direction = attributes.getValue("direction");
+        if ("in".equals(direction)) {
+            parameter.setDirection(ProcedureParameter.IN_PARAMETER);
+        } else if ("out".equals(direction)) {
+            parameter.setDirection(ProcedureParameter.OUT_PARAMETER);
+        } else if ("in_out".equals(direction)) {
+            parameter.setDirection(ProcedureParameter.IN_OUT_PARAMETER);
+        }
+
+        procedure.addCallParameter(parameter);
+    }
+
+    public Procedure getProcedure() {
+        return procedure;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/QueryDescriptorHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/QueryDescriptorHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/QueryDescriptorHandler.java
new file mode 100644
index 0000000..4034184
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/QueryDescriptorHandler.java
@@ -0,0 +1,191 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.QueryDescriptor;
+import org.apache.cayenne.map.QueryDescriptorLoader;
+import org.apache.cayenne.util.Util;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+public class QueryDescriptorHandler extends NamespaceAwareNestedTagHandler {
+
+    private static final String QUERY_DESCRIPTOR_TAG = "query";
+    private static final String QUERY_SQL_TAG = "sql";
+    private static final String QUERY_EJBQL_TAG = "ejbql";
+    private static final String QUERY_QUALIFIER_TAG = "qualifier";
+    private static final String QUERY_ORDERING_TAG = "ordering";
+    private static final String QUERY_PREFETCH_TAG = "prefetch";
+
+    public static final String PROPERTY_TAG = "property";
+
+    private DataMap map;
+
+    private QueryDescriptorLoader queryBuilder;
+    private QueryDescriptor descriptor;
+    private boolean changed;
+
+    private String sqlKey;
+    private String descending;
+    private String ignoreCase;
+
+    public QueryDescriptorHandler(NamespaceAwareNestedTagHandler parentHandler, DataMap map) {
+        super(parentHandler);
+        this.map = map;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+
+        switch (localName) {
+            case QUERY_DESCRIPTOR_TAG:
+                addQueryDescriptor(attributes);
+                return true;
+
+            case PROPERTY_TAG:
+                addQueryDescriptorProperty(attributes);
+                return true;
+
+            case QUERY_SQL_TAG:
+                this.sqlKey = attributes.getValue("adapter-class");
+                return true;
+
+            case QUERY_ORDERING_TAG:
+                createQueryOrdering(attributes);
+                return true;
+
+            case QUERY_EJBQL_TAG:
+            case QUERY_QUALIFIER_TAG:
+            case QUERY_PREFETCH_TAG:
+                return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    protected void processCharData(String localName, String data) {
+        switch (localName) {
+            case QUERY_SQL_TAG:
+                queryBuilder.addSql(data, sqlKey);
+                break;
+
+            case QUERY_EJBQL_TAG:
+                queryBuilder.setEjbql(data);
+                break;
+
+            case QUERY_QUALIFIER_TAG:
+                createQualifier(data);
+                break;
+
+            case QUERY_ORDERING_TAG:
+                addQueryOrdering(data);
+                break;
+
+            case QUERY_PREFETCH_TAG:
+                queryBuilder.addPrefetch(data);
+                break;
+        }
+    }
+
+    @Override
+    protected void beforeScopeEnd() {
+        map.addQueryDescriptor(getQueryDescriptor());
+    }
+
+    private void addQueryDescriptor(Attributes attributes) throws SAXException {
+        String name = attributes.getValue("name");
+        if (null == name) {
+            throw new SAXException("QueryDescriptorHandler::addQueryDescriptor() - no query name.");
+        }
+
+        queryBuilder = new QueryDescriptorLoader();
+        queryBuilder.setName(name);
+
+        String type = attributes.getValue("type");
+        // Legacy format support (v7 and older)
+        if(type == null) {
+            queryBuilder.setLegacyFactory(attributes.getValue("factory"));
+        } else {
+            queryBuilder.setQueryType(type);
+        }
+
+        String rootName = attributes.getValue("root-name");
+        queryBuilder.setRoot(map, attributes.getValue("root"), rootName);
+
+        // TODO: Andrus, 2/13/2006 'result-type' is only used in ProcedureQuery
+        // and is deprecated in 1.2
+        String resultEntity = attributes.getValue("result-entity");
+        if (!Util.isEmptyString(resultEntity)) {
+            queryBuilder.setResultEntity(resultEntity);
+        }
+
+        changed = true;
+    }
+
+    private void addQueryDescriptorProperty(Attributes attributes) throws SAXException {
+        String name = attributes.getValue("name");
+        if (null == name) {
+            throw new SAXException("QueryDescriptorHandler::addQueryDescriptorProperty() - no property name.");
+        }
+
+        String value = attributes.getValue("value");
+        if (null == value) {
+            throw new SAXException("QueryDescriptorHandler::addQueryDescriptorProperty() - no property value.");
+        }
+
+        queryBuilder.addProperty(name, value);
+        changed = true;
+    }
+
+    private void createQualifier(String qualifier) {
+        if (qualifier.trim().length() == 0) {
+            return;
+        }
+
+        queryBuilder.setQualifier(qualifier);
+        changed = true;
+    }
+
+    private void createQueryOrdering(Attributes attributes) {
+        descending = attributes.getValue("descending");
+        ignoreCase = attributes.getValue("ignore-case");
+    }
+
+    private void addQueryOrdering(String path) {
+        queryBuilder.addOrdering(path, descending, ignoreCase);
+        changed = true;
+    }
+
+    public QueryDescriptor getQueryDescriptor() {
+        if(queryBuilder == null) {
+            return null;
+        }
+        if(descriptor == null || changed) {
+            descriptor = queryBuilder.buildQueryDescriptor();
+            changed = false;
+        }
+        return descriptor;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/RootDataMapHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/RootDataMapHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/RootDataMapHandler.java
new file mode 100644
index 0000000..dba5022
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/RootDataMapHandler.java
@@ -0,0 +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
+ *
+ *    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.configuration.xml;
+
+import org.apache.cayenne.map.DataMap;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+public class RootDataMapHandler extends NamespaceAwareNestedTagHandler {
+
+    public RootDataMapHandler(LoaderContext loaderContext) {
+        super(loaderContext);
+        setTargetNamespace(DataMap.SCHEMA_XSD);
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        return false;
+    }
+
+    @Override
+    protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String qName, Attributes attributes) {
+        if(targetNamespace.equals(namespaceURI) && "data-map".equals(localName)) {
+            return new DataMapHandler(this);
+        }
+
+        return super.createChildTagHandler(namespaceURI, localName, qName, attributes);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/SAXNestedTagHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/SAXNestedTagHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/SAXNestedTagHandler.java
new file mode 100644
index 0000000..d2d4e04
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/SAXNestedTagHandler.java
@@ -0,0 +1,175 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A superclass of nested tag handlers for parsing of XML documents with SAX.
+ * This class is not namespace aware, i.e. tags like &lt;info:property/> and &lt;property/>
+ * will be treated as equal.
+ * Use {@link NamespaceAwareNestedTagHandler} if you need to process namespaces.
+ *
+ * @see NamespaceAwareNestedTagHandler
+ * @since 3.1
+ * @since 4.1 redesigned and moved from {@link org.apache.cayenne.configuration} package
+ */
+public class SAXNestedTagHandler extends DefaultHandler {
+
+    private final static Locator NOOP_LOCATOR = new Locator() {
+
+        public int getColumnNumber() {
+            return -1;
+        }
+
+        public int getLineNumber() {
+            return -1;
+        }
+
+        public String getPublicId() {
+            return "<unknown>";
+        }
+
+        public String getSystemId() {
+            return "<unknown>";
+        }
+    };
+
+    protected LoaderContext loaderContext;
+    protected ContentHandler parentHandler;
+    protected Locator locator;
+
+    public SAXNestedTagHandler(LoaderContext loaderContext) {
+        this.loaderContext = Objects.requireNonNull(loaderContext);
+        this.locator = NOOP_LOCATOR;
+    }
+
+    public SAXNestedTagHandler(SAXNestedTagHandler parentHandler) {
+        this.parentHandler = Objects.requireNonNull(parentHandler);
+        this.loaderContext = Objects.requireNonNull(parentHandler.loaderContext);
+
+        locator = parentHandler.locator;
+        if (locator == null) {
+            locator = NOOP_LOCATOR;
+        }
+    }
+
+    protected String unexpectedTagMessage(String tagFound, String... tagsExpected) {
+
+        List<String> expected = tagsExpected != null
+                ? Arrays.asList(tagsExpected)
+                : Collections.<String> emptyList();
+
+        return String.format("tag <%s> is unexpected at [%d,%d]. The following tags are allowed here: %s",
+                tagFound,
+                locator.getColumnNumber(),
+                locator.getLineNumber(),
+                expected);
+    }
+
+    /**
+     * Main method to process XML content.
+     * Should be override in subclasses, by default do nothing.
+     * Return value should be true if tag was fully processed and shouldn't be passed down to child handler.
+     *
+     * @param namespaceURI namespace for tag
+     * @param localName tag local name (i.e. w/o namespace prefix)
+     * @param attributes tag attributes
+     *
+     * @return true if tag was processed
+     *
+     * @throws SAXException can be thrown to abort parsing
+     *
+     * @see #createChildTagHandler(String, String, String, Attributes)
+     */
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        return true;
+    }
+
+    /**
+     * Callback method that is called before this handler pushed out of parsers stack.
+     * Can be used to flush some aggregate state.
+     */
+    protected void beforeScopeEnd() {
+    }
+
+    /**
+     * This method should be used to create nested handlers to process children elements.
+     * This method should never return {@code null}.
+     *
+     * @param namespaceURI namespace for tag
+     * @param localName tag local name (i.e. w/o namespace prefix)
+     * @param qName tag full name (i.e. with namespace prefix)
+     * @param attributes tag attributes
+     * @return new handler to process child tag
+     */
+    protected ContentHandler createChildTagHandler(String namespaceURI, String localName,
+                                                   String qName, Attributes attributes) {
+        // loose handling of unrecognized tags - just ignore them
+        return new SAXNestedTagHandler(this);
+    }
+
+    protected void stop() {
+        beforeScopeEnd();
+        // pop self from the handler stack
+        loaderContext.getXmlReader().setContentHandler(parentHandler);
+    }
+
+    /**
+     * This method directly called by SAX parser, do not override it directly,
+     * use {@link #processElement(String, String, Attributes)} method instead to process content.
+     *
+     * @see #createChildTagHandler(String, String, String, Attributes)
+     */
+    @Override
+    public void startElement(String namespaceURI, String localName,
+                             String qName, Attributes attributes) throws SAXException {
+        ContentHandler childHandler = createChildTagHandler(namespaceURI, localName, qName, attributes);
+
+        if(!processElement(namespaceURI, localName, attributes)) {
+            childHandler.startElement(namespaceURI, localName, qName, attributes);
+        }
+
+        // push child handler to the stack...
+        loaderContext.getXmlReader().setContentHandler(childHandler);
+    }
+
+    @Override
+    public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
+        stop();
+    }
+
+    @Override
+    public void setDocumentLocator(Locator locator) {
+        this.locator = locator;
+    }
+
+    public ContentHandler getParentHandler() {
+        return parentHandler;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoader.java
new file mode 100644
index 0000000..e9d104e
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoader.java
@@ -0,0 +1,149 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.configuration.ConfigurationNameMapper;
+import org.apache.cayenne.configuration.ConfigurationTree;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
+import org.apache.cayenne.configuration.DataMapLoader;
+import org.apache.cayenne.di.AdhocObjectFactory;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.resource.Resource;
+import org.apache.cayenne.util.Util;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+/**
+ * @since 3.1
+ * @since 4.1 moved from org.apache.cayenne.configuration package
+ */
+public class XMLDataChannelDescriptorLoader implements DataChannelDescriptorLoader {
+
+	private static Logger logger = LoggerFactory.getLogger(XMLDataChannelDescriptorLoader.class);
+
+	static final String CURRENT_PROJECT_VERSION = "10";
+
+	/**
+	 * @deprecated the caller should use password resolving strategy instead of
+	 *             resolving the password on the spot. For one thing this can be
+	 *             used in the Modeler and no password may be available.
+	 */
+	@Deprecated
+	static String passwordFromURL(URL url) {
+		InputStream inputStream;
+		String password = null;
+
+		try {
+			inputStream = url.openStream();
+			password = passwordFromInputStream(inputStream);
+		} catch (IOException exception) {
+			// Log the error while trying to open the stream. A null
+			// password will be returned as a result.
+			logger.warn(exception.getMessage(), exception);
+		}
+
+		return password;
+	}
+
+	/**
+	 * @deprecated the caller should use password resolving strategy instead of
+	 *             resolving the password on the spot. For one thing this can be
+	 *             used in the Modeler and no password may be available.
+	 */
+	@Deprecated
+	static String passwordFromInputStream(InputStream inputStream) {
+		String password = null;
+
+		try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));) {
+
+			password = bufferedReader.readLine();
+		} catch (IOException exception) {
+			logger.warn(exception.getMessage(), exception);
+		} finally {
+
+			try {
+				inputStream.close();
+			} catch (IOException ignored) {
+			}
+		}
+
+		return password;
+	}
+
+	@Inject
+	protected DataMapLoader dataMapLoader;
+
+	@Inject
+	protected ConfigurationNameMapper nameMapper;
+
+	@Inject
+	protected AdhocObjectFactory objectFactory;
+
+	@Inject
+	protected HandlerFactory handlerFactory;
+
+	@Override
+	public ConfigurationTree<DataChannelDescriptor> load(Resource configurationResource) throws ConfigurationException {
+
+		if (configurationResource == null) {
+			throw new NullPointerException("Null configurationResource");
+		}
+
+		URL configurationURL = configurationResource.getURL();
+
+		logger.info("Loading XML configuration resource from " + configurationURL);
+
+		final DataChannelDescriptor descriptor = new DataChannelDescriptor();
+		descriptor.setConfigurationSource(configurationResource);
+		descriptor.setName(nameMapper.configurationNodeName(DataChannelDescriptor.class, configurationResource));
+
+		try(InputStream in = configurationURL.openStream()) {
+			XMLReader parser = Util.createXmlReader();
+			LoaderContext loaderContext = new LoaderContext(parser, handlerFactory);
+			loaderContext.addDataMapListener(new DataMapLoaderListener() {
+				@Override
+				public void onDataMapLoaded(DataMap dataMap) {
+					descriptor.getDataMaps().add(dataMap);
+				}
+			});
+
+			DataChannelHandler rootHandler = new DataChannelHandler(this, descriptor, loaderContext);
+			parser.setContentHandler(rootHandler);
+			parser.setErrorHandler(rootHandler);
+			parser.parse(new InputSource(in));
+		} catch (Exception e) {
+			throw new ConfigurationException("Error loading configuration from %s", e, configurationURL);
+		}
+
+		// TODO: andrus 03/10/2010 - actually provide load failures here...
+		return new ConfigurationTree<>(descriptor, null);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/XMLDataMapLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/XMLDataMapLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/XMLDataMapLoader.java
new file mode 100644
index 0000000..eb82d32
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/XMLDataMapLoader.java
@@ -0,0 +1,102 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.DataMapLoader;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.resource.Resource;
+import org.apache.cayenne.util.Util;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+import java.io.InputStream;
+
+/**
+ * @since 3.1
+ * @since 4.1 moved from org.apache.cayenne.configuration package
+ */
+public class XMLDataMapLoader implements DataMapLoader {
+
+    private static final String DATA_MAP_LOCATION_SUFFIX = ".map.xml";
+
+    @Inject
+    protected HandlerFactory handlerFactory;
+
+    private DataMap map;
+
+    public synchronized DataMap load(Resource configurationResource) throws CayenneRuntimeException {
+        try(InputStream in = configurationResource.getURL().openStream()) {
+            XMLReader parser = Util.createXmlReader();
+            LoaderContext loaderContext = new LoaderContext(parser, handlerFactory);
+            loaderContext.addDataMapListener(new DataMapLoaderListener() {
+                @Override
+                public void onDataMapLoaded(DataMap dataMap) {
+                    map = dataMap;
+                }
+            });
+            RootDataMapHandler rootHandler = new RootDataMapHandler(loaderContext);
+
+            parser.setContentHandler(rootHandler);
+            parser.setErrorHandler(rootHandler);
+            parser.parse(new InputSource(in));
+        } catch (Exception e) {
+            throw new CayenneRuntimeException("Error loading configuration from %s", e, configurationResource.getURL());
+        }
+
+        if(map == null) {
+            throw new CayenneRuntimeException("Unable to load data map from %s", configurationResource.getURL());
+        }
+
+        if(map.getName() == null) {
+            // set name based on location if no name provided by map itself
+            map.setName(mapNameFromLocation(configurationResource.getURL().getFile()));
+        }
+        return map;
+    }
+
+    /**
+     * Helper method to guess the map name from its location.
+     */
+    protected String mapNameFromLocation(String location) {
+        if (location == null) {
+            return "Untitled";
+        }
+
+        int lastSlash = location.lastIndexOf('/');
+        if (lastSlash < 0) {
+            lastSlash = location.lastIndexOf('\\');
+        }
+
+        if (lastSlash >= 0 && lastSlash + 1 < location.length()) {
+            location = location.substring(lastSlash + 1);
+        }
+
+        if (location.endsWith(DATA_MAP_LOCATION_SUFFIX)) {
+            location = location.substring(0, location.length() - DATA_MAP_LOCATION_SUFFIX.length());
+        }
+
+        return location;
+    }
+
+    public void setHandlerFactory(HandlerFactory handlerFactory) {
+        this.handlerFactory = handlerFactory;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java b/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java
index f51c8f0..0647fbc 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java
@@ -21,6 +21,7 @@ package org.apache.cayenne.conn;
 
 import java.io.Serializable;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.PasswordEncoding;
 import org.apache.cayenne.configuration.PlainTextPasswordEncoder;
 import org.apache.cayenne.di.DIRuntimeException;
@@ -134,58 +135,46 @@ public class DataSourceInfo implements Cloneable, Serializable, XMLSerializable
 	/**
 	 * @since 3.1
 	 */
-	public void encodeAsXML(XMLEncoder encoder) {
-		encoder.println("<data-source>");
-		encoder.indent(1);
-
-		encoder.print("<driver");
-		encoder.printAttribute("value", jdbcDriver);
-		encoder.println("/>");
+	@Override
+	public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+		encoder.start("data-source");
 
-		encoder.print("<url");
-		encoder.printAttribute("value", dataSourceUrl);
-		encoder.println("/>");
+		encoder.start("driver").attribute("value", jdbcDriver).end();
+		encoder.start("url").attribute("value", dataSourceUrl).end();
 
-		encoder.print("<connectionPool");
-		encoder.printAttribute("min", String.valueOf(minConnections));
-		encoder.printAttribute("max", String.valueOf(maxConnections));
-		encoder.println("/>");
+		encoder.start("connectionPool")
+				.attribute("min", minConnections)
+				.attribute("max", String.valueOf(maxConnections))
+				.end();
 
-		encoder.print("<login");
-		encoder.printAttribute("userName", userName);
+		encoder.start("login").attribute("userName", userName);
 
 		if (DataSourceInfo.PASSWORD_LOCATION_MODEL.equals(passwordLocation)) {
-
 			PasswordEncoding passwordEncoder = getPasswordEncoder();
-
 			if (passwordEncoder != null) {
 				String passwordEncoded = passwordEncoder.encodePassword(password, passwordEncoderKey);
-				encoder.printAttribute("password", passwordEncoded);
+				encoder.attribute("password", passwordEncoded);
 			}
 		}
 
 		if (!PlainTextPasswordEncoder.class.getName().equals(passwordEncoderClass)) {
-			encoder.printAttribute("encoderClass", passwordEncoderClass);
+			encoder.attribute("encoderClass", passwordEncoderClass);
 		}
 
-		encoder.printAttribute("encoderKey", passwordEncoderKey);
+		encoder.attribute("encoderKey", passwordEncoderKey);
 
 		if (!DataSourceInfo.PASSWORD_LOCATION_MODEL.equals(passwordLocation)) {
-			encoder.printAttribute("passwordLocation", passwordLocation);
+			encoder.attribute("passwordLocation", passwordLocation);
 		}
 
 		// TODO: this is very not nice... we need to clean up the whole
-		// DataSourceInfo
-		// to avoid returning arbitrary labels...
+		// DataSourceInfo to avoid returning arbitrary labels...
 		String passwordSource = getPasswordSource();
 		if (!"Not Applicable".equals(passwordSource)) {
-			encoder.printAttribute("passwordSource", passwordSource);
+			encoder.attribute("passwordSource", passwordSource);
 		}
 
-		encoder.println("/>");
-
-		encoder.indent(-1);
-		encoder.println("</data-source>");
+		encoder.end().end();
 	}
 
 	public DataSourceInfo cloneInfo() {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/exp/Expression.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/Expression.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/Expression.java
index 0d35cea..77a8cdf 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/Expression.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/Expression.java
@@ -31,6 +31,7 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.exp.parser.ASTScalar;
 import org.apache.cayenne.util.ConversionUtil;
 import org.apache.cayenne.util.HashCodeBuilder;
@@ -679,14 +680,15 @@ public abstract class Expression implements Serializable, XMLSerializable {
 	 * 
 	 * @since 1.1
 	 */
-	public void encodeAsXML(XMLEncoder encoder) {
-		encoder.print("<![CDATA[");
+	@Override
+	public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+		StringBuilder sb = new StringBuilder();
 		try {
-			appendAsString(encoder.getPrintWriter());
+			appendAsString(sb);
 		} catch (IOException e) {
 			throw new CayenneRuntimeException("Unexpected IO exception appending to PrintWriter", e);
 		}
-		encoder.print("]]>");
+		encoder.cdata(sb.toString(), true);
 	}
 
 	/**


[10/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - ProjectExtension - new upgrade handlers

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V8Test.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V8Test.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V8Test.java
new file mode 100644
index 0000000..1201654
--- /dev/null
+++ b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V8Test.java
@@ -0,0 +1,97 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.upgrade.handlers;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+/**
+ * @since 4.1
+ */
+public class UpgradeHandler_V8Test extends BaseUpgradeHandlerTest {
+
+    @Override
+    UpgradeHandler newHandler() {
+        return new UpgradeHandler_V8();
+    }
+
+    @Test
+    public void testProjectDomUpgrade() throws Exception {
+        Document document = processProjectDom("cayenne-project-v7.xml");
+
+        Element root = document.getDocumentElement();
+        assertEquals("8", root.getAttribute("project-version"));
+        assertEquals("", root.getAttribute("xmlns"));
+        assertEquals(2, root.getElementsByTagName("map").getLength());
+    }
+
+    @Test
+    public void testDataMapDomUpgrade() throws Exception {
+        Document document = processDataMapDom("test-map-v7.map.xml");
+
+        Element root = document.getDocumentElement();
+        assertEquals("8", root.getAttribute("project-version"));
+        assertEquals("http://cayenne.apache.org/schema/8/modelMap", root.getAttribute("xmlns"));
+        assertEquals(2, root.getElementsByTagName("db-attribute").getLength());
+
+        NodeList nodeList = root.getElementsByTagName("query");
+        for(int i=0; i<nodeList.getLength(); i++) {
+            NamedNodeMap attributes = nodeList.item(i).getAttributes();
+
+            // should change factory to type
+            assertNull(attributes.getNamedItem("factory"));
+
+            String type = attributes.getNamedItem("type").getNodeValue();
+            switch (attributes.getNamedItem("name").getNodeValue()) {
+                case "EjbqlQueryTest":
+                    assertEquals("EJBQLQuery", type);
+                    break;
+
+                case "SQLTemplateTest":
+                    assertEquals("SQLTemplate", type);
+                    break;
+
+                case "SelectQueryTest":
+                    assertEquals("SelectQuery", type);
+                    break;
+
+                case "ProcedureQueryTest":
+                    assertEquals("ProcedureQuery", type);
+                    break;
+            }
+        }
+    }
+
+    @Test
+    public void testModelUpgrade() throws Exception {
+        DataChannelDescriptor descriptor = mock(DataChannelDescriptor.class);
+        handler.processModel(descriptor);
+        verifyZeroInteractions(descriptor);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V9Test.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V9Test.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V9Test.java
new file mode 100644
index 0000000..1affb2c
--- /dev/null
+++ b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V9Test.java
@@ -0,0 +1,69 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.upgrade.handlers;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+/**
+ * @since 4.1
+ */
+public class UpgradeHandler_V9Test extends BaseUpgradeHandlerTest {
+
+
+    @Override
+    UpgradeHandler newHandler() {
+        return new UpgradeHandler_V9();
+    }
+
+    @Test
+    public void testProjectDomUpgrade() throws Exception {
+        Document document = processProjectDom("cayenne-project-v8.xml");
+
+        Element root = document.getDocumentElement();
+        assertEquals("9", root.getAttribute("project-version"));
+        assertEquals("", root.getAttribute("xmlns"));
+        assertEquals(2, root.getElementsByTagName("map").getLength());
+    }
+
+    @Test
+    public void testDataMapDomUpgrade() throws Exception {
+        Document document = processDataMapDom("test-map-v8.map.xml");
+
+        Element root = document.getDocumentElement();
+        assertEquals("9", root.getAttribute("project-version"));
+        assertEquals("http://cayenne.apache.org/schema/9/modelMap", root.getAttribute("xmlns"));
+        assertEquals(0, root.getElementsByTagName("reverse-engineering-config").getLength());
+        assertEquals(2, root.getElementsByTagName("db-attribute").getLength());
+    }
+
+    @Test
+    public void testModelUpgrade() throws Exception {
+        DataChannelDescriptor descriptor = mock(DataChannelDescriptor.class);
+        handler.processModel(descriptor);
+        verifyZeroInteractions(descriptor);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/v7/ProjectUpgrader_V7Test.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/v7/ProjectUpgrader_V7Test.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/v7/ProjectUpgrader_V7Test.java
deleted file mode 100644
index 8dd51a2..0000000
--- a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/v7/ProjectUpgrader_V7Test.java
+++ /dev/null
@@ -1,499 +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.project.upgrade.v7;
-
-import org.apache.cayenne.configuration.ConfigurationNameMapper;
-import org.apache.cayenne.configuration.DataMapLoader;
-import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
-import org.apache.cayenne.configuration.XMLDataMapLoader;
-import org.apache.cayenne.configuration.server.JNDIDataSourceFactory;
-import org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory;
-import org.apache.cayenne.di.*;
-import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
-import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
-import org.apache.cayenne.project.FileProjectSaver;
-import org.apache.cayenne.project.ProjectSaver;
-import org.apache.cayenne.project.unit.Project2Case;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
-import org.apache.cayenne.project.upgrade.UpgradeMetaData;
-import org.apache.cayenne.project.upgrade.UpgradeType;
-import org.apache.cayenne.resource.Resource;
-import org.apache.cayenne.resource.URLResource;
-import org.apache.cayenne.test.resource.ResourceUtil;
-import org.junit.Test;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
-import javax.xml.xpath.XPathFactory;
-import java.io.File;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.junit.Assert.*;
-
-public class ProjectUpgrader_V7Test extends Project2Case {
-
-	@Test
-	public void testMetadata_3_0_0_1() {
-
-		String baseUrl = getClass().getPackage().getName().replace('.', '/');
-		URL url = getClass().getClassLoader().getResource(baseUrl + "/3_0_0_1a/cayenne.xml");
-		assertNotNull(url);
-
-		Module testModule = new Module() {
-
-			public void configure(Binder binder) {
-				binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
-				binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-			}
-		};
-
-		ProjectUpgrader_V7 upgrader = new ProjectUpgrader_V7();
-		Injector injector = DIBootstrap.createInjector(testModule);
-		injector.injectMembers(upgrader);
-
-		Resource source = new URLResource(url);
-		UpgradeHandler handler = upgrader.getUpgradeHandler(source);
-
-		assertNotNull(handler);
-		assertSame(source, handler.getProjectSource());
-
-		UpgradeMetaData md = handler.getUpgradeMetaData();
-		assertNotNull(md);
-
-		assertSame(UpgradeType.UPGRADE_NEEDED, md.getUpgradeType());
-		assertNull(md.getIntermediateUpgradeVersion());
-		assertEquals("3.0.0.1", md.getProjectVersion());
-		assertEquals("7", md.getSupportedVersion());
-	}
-
-	@Test
-	public void testMetadata_Type2_0() {
-		String baseUrl = getClass().getPackage().getName().replace('.', '/');
-		URL url = getClass().getClassLoader().getResource(baseUrl + "/2_0a/cayenne.xml");
-		assertNotNull(url);
-
-		Module testModule = new Module() {
-
-			public void configure(Binder binder) {
-				binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
-				binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-			}
-		};
-
-		ProjectUpgrader_V7 upgrader = new ProjectUpgrader_V7();
-		Injector injector = DIBootstrap.createInjector(testModule);
-		injector.injectMembers(upgrader);
-
-		Resource source = new URLResource(url);
-		UpgradeHandler handler = upgrader.getUpgradeHandler(source);
-
-		assertNotNull(handler);
-		assertSame(source, handler.getProjectSource());
-
-		UpgradeMetaData md = handler.getUpgradeMetaData();
-		assertNotNull(md);
-		assertSame(UpgradeType.INTERMEDIATE_UPGRADE_NEEDED, md.getUpgradeType());
-		assertEquals("3.0.0.1", md.getIntermediateUpgradeVersion());
-		assertEquals("2.0", md.getProjectVersion());
-		assertEquals("7", md.getSupportedVersion());
-	}
-
-	@Test
-	public void testMetadata_Type6() {
-		String baseUrl = getClass().getPackage().getName().replace('.', '/');
-		URL url = getClass().getClassLoader().getResource(baseUrl + "/6a/cayenne-PROJECT1.xml");
-		assertNotNull(url);
-
-		Module testModule = new Module() {
-
-			public void configure(Binder binder) {
-				binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
-				binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-			}
-		};
-
-		ProjectUpgrader_V7 upgrader = new ProjectUpgrader_V7();
-		Injector injector = DIBootstrap.createInjector(testModule);
-		injector.injectMembers(upgrader);
-
-		Resource source = new URLResource(url);
-		UpgradeHandler handler = upgrader.getUpgradeHandler(source);
-
-		assertNotNull(handler);
-		assertSame(source, handler.getProjectSource());
-
-		UpgradeMetaData md = handler.getUpgradeMetaData();
-		assertNotNull(md);
-		assertSame(UpgradeType.UPGRADE_NEEDED, md.getUpgradeType());
-		assertNull(md.getIntermediateUpgradeVersion());
-		assertEquals("6", md.getProjectVersion());
-		assertEquals("7", md.getSupportedVersion());
-	}
-
-	@Test
-	public void testMetadata_Type7() {
-		String baseUrl = getClass().getPackage().getName().replace('.', '/');
-		URL url = getClass().getClassLoader().getResource(baseUrl + "/7a/cayenne-PROJECT1.xml");
-		assertNotNull(url);
-
-		Module testModule = new Module() {
-
-			public void configure(Binder binder) {
-				binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
-				binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-			}
-		};
-
-		ProjectUpgrader_V7 upgrader = new ProjectUpgrader_V7();
-		Injector injector = DIBootstrap.createInjector(testModule);
-		injector.injectMembers(upgrader);
-
-		Resource source = new URLResource(url);
-		UpgradeHandler handler = upgrader.getUpgradeHandler(source);
-
-		assertNotNull(handler);
-		assertSame(source, handler.getProjectSource());
-
-		UpgradeMetaData md = handler.getUpgradeMetaData();
-		assertNotNull(md);
-		assertSame(UpgradeType.UPGRADE_NOT_NEEDED, md.getUpgradeType());
-		assertNull(md.getIntermediateUpgradeVersion());
-		assertEquals("7", md.getProjectVersion());
-		assertEquals("7", md.getSupportedVersion());
-	}
-
-	@Test
-	public void testPerformUpgradeFrom3() throws Exception {
-
-		File testFolder = setupTestDirectory("testPerformUpgrade_3_0_0_1");
-		String sourceUrl = getClass().getPackage().getName().replace('.', '/') + "/3_0_0_1a/";
-
-		List<String> sources = new ArrayList<String>();
-
-		sources.add("cayenne.xml");
-		sources.add("d1Map1.map.xml");
-		sources.add("d1Map2.map.xml");
-		sources.add("d1NodeDriver.driver.xml");
-
-		// upgrades are done in-place, so copy it first
-		List<File> targetsBefore = new ArrayList<File>();
-		for (String source : sources) {
-
-			URL url = getClass().getClassLoader().getResource(sourceUrl + source);
-			File target = new File(testFolder, source);
-			assertNotNull(source);
-			ResourceUtil.copyResourceToFile(url, target);
-			targetsBefore.add(target);
-		}
-
-		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(ProjectSaver.class).to(FileProjectSaver.class);
-				binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-				binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
-			}
-		};
-
-		ProjectUpgrader_V7 upgrader = new ProjectUpgrader_V7();
-		Injector injector = DIBootstrap.createInjector(testModule);
-		injector.injectMembers(upgrader);
-
-		Resource source = new URLResource(targetsBefore.get(0).toURI().toURL());
-		UpgradeHandler handler = upgrader.getUpgradeHandler(source);
-
-		Resource upgraded = handler.performUpgrade();
-		assertNotNull(upgraded);
-		assertNotSame(source, upgrader);
-
-		// check that all the new files are created...
-		String[] targetsAfterNames = new String[] { "cayenne-d1.xml", "cayenne-d2.xml", "d1Map1.map.xml",
-				"d1Map2.map.xml" };
-
-		File[] targetsAfter = new File[targetsAfterNames.length];
-		for (int i = 0; i < targetsAfter.length; i++) {
-			targetsAfter[i] = new File(testFolder, targetsAfterNames[i]);
-			assertTrue("File was not created: " + targetsAfter[i].getAbsolutePath(), targetsAfter[i].exists());
-		}
-
-		// DataMap files should remain the same; all others need to be deleted
-		for (File file : targetsBefore) {
-			if (file.getName().endsWith(".map.xml")) {
-				assertTrue("DataMap file disappeared: " + file.getAbsolutePath(), file.exists());
-			} else {
-				assertFalse("File expected to be deleted: " + file.getAbsolutePath(), file.exists());
-			}
-		}
-
-		// assert XML structure of the generated files
-		assertPerformUpgrade_3_0_0_1_cayenne_d1(targetsAfter[0]);
-		assertPerformUpgrade_3_0_0_1_cayenne_d2(targetsAfter[1]);
-		assertPerformUpgrade_3_0_0_1_d1Map1(targetsAfter[2]);
-		assertPerformUpgrade_3_0_0_1_d1Map2(targetsAfter[3]);
-	}
-
-	private void assertPerformUpgrade_3_0_0_1_cayenne_d1(File file) throws Exception {
-		Document document = toDOMTree(file);
-
-		XPath xpath = XPathFactory.newInstance().newXPath();
-		assertEquals("", xpath.evaluate("/domain/@name", document));
-		assertEquals("9", xpath.evaluate("/domain/@project-version", document));
-
-		NodeList maps = (NodeList) xpath.evaluate("/domain/map", document, XPathConstants.NODESET);
-		assertNotNull(maps);
-		assertEquals(2, maps.getLength());
-
-		Node map1 = maps.item(0);
-		Node map2 = maps.item(1);
-
-		assertEquals("d1Map1", xpath.evaluate("@name", map1));
-		assertEquals("d1Map2", xpath.evaluate("@name", map2));
-
-		NodeList nodes = (NodeList) xpath.evaluate("/domain/node", document, XPathConstants.NODESET);
-		assertNotNull(nodes);
-		assertEquals(1, nodes.getLength());
-
-		Node node1 = nodes.item(0);
-
-		assertEquals("d1NodeDriver", xpath.evaluate("@name", node1));
-		assertEquals(XMLPoolingDataSourceFactory.class.getName(), xpath.evaluate("@factory", node1));
-
-		NodeList mapRefs = (NodeList) xpath.evaluate("map-ref", node1, XPathConstants.NODESET);
-		assertNotNull(mapRefs);
-		assertEquals(2, mapRefs.getLength());
-
-		assertEquals("d1Map1", xpath.evaluate("@name", mapRefs.item(0)));
-		assertEquals("d1Map2", xpath.evaluate("@name", mapRefs.item(1)));
-
-		NodeList dataSources = (NodeList) xpath.evaluate("data-source", node1, XPathConstants.NODESET);
-		assertNotNull(dataSources);
-		assertEquals(1, dataSources.getLength());
-
-		Node ds = dataSources.item(0);
-		assertEquals("org.hsqldb.jdbcDriver", xpath.evaluate("driver/@value", ds));
-		assertEquals("jdbc:hsqldb:mem:xdb", xpath.evaluate("url/@value", ds));
-	}
-
-	private void assertPerformUpgrade_3_0_0_1_cayenne_d2(File file) throws Exception {
-		Document document = toDOMTree(file);
-
-		XPath xpath = XPathFactory.newInstance().newXPath();
-		assertEquals("", xpath.evaluate("/domain/@name", document));
-		assertEquals("9", xpath.evaluate("/domain/@project-version", document));
-
-		NodeList maps = (NodeList) xpath.evaluate("/domain/map", document, XPathConstants.NODESET);
-		assertNotNull(maps);
-		assertEquals(0, maps.getLength());
-
-		NodeList nodes = (NodeList) xpath.evaluate("/domain/node", document, XPathConstants.NODESET);
-		assertNotNull(nodes);
-		assertEquals(2, nodes.getLength());
-
-		Node node1 = nodes.item(0);
-		Node node2 = nodes.item(1);
-
-		assertEquals("d2NodeDBCP", xpath.evaluate("@name", node1));
-		assertEquals("dbcpx", xpath.evaluate("@parameters", node1));
-		assertEquals("org.apache.cayenne.configuration.server.DBCPDataSourceFactory", xpath.evaluate("@factory", node1));
-
-		NodeList dataSources1 = (NodeList) xpath.evaluate("data-source", node1, XPathConstants.NODESET);
-		assertNotNull(dataSources1);
-		assertEquals(0, dataSources1.getLength());
-
-		assertEquals("d2NodeJNDI", xpath.evaluate("@name", node2));
-		assertEquals("jndi/x", xpath.evaluate("@parameters", node2));
-		assertEquals(JNDIDataSourceFactory.class.getName(), xpath.evaluate("@factory", node2));
-
-		NodeList dataSources2 = (NodeList) xpath.evaluate("data-source", node2, XPathConstants.NODESET);
-		assertNotNull(dataSources2);
-		assertEquals(0, dataSources2.getLength());
-	}
-
-	private void assertPerformUpgrade_3_0_0_1_d1Map1(File file) throws Exception {
-		Document document = toDOMTree(file);
-
-		XPath xpath = XPathFactory.newInstance().newXPath();
-		assertEquals("9", xpath.evaluate("/data-map/@project-version", document));
-	}
-
-	private void assertPerformUpgrade_3_0_0_1_d1Map2(File file) throws Exception {
-		Document document = toDOMTree(file);
-
-		XPath xpath = XPathFactory.newInstance().newXPath();
-		assertEquals("9", xpath.evaluate("/data-map/@project-version", document));
-	}
-
-	@Test
-	public void testPerformUpgradeFrom6() throws Exception {
-		File testFolder = setupTestDirectory("testUpgrade6a");
-		String sourceUrl = getClass().getPackage().getName().replace('.', '/') + "/6a/";
-		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(ProjectSaver.class).to(FileProjectSaver.class);
-				binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-				binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
-			}
-		};
-
-		String[] resources = { "cayenne-PROJECT1.xml", "testProjectMap1_1.map.xml", "testProjectMap1_2.map.xml" };
-		List<File> files = new ArrayList<File>();
-
-		for (String name : resources) {
-			URL xmlUrl = getClass().getClassLoader().getResource(sourceUrl + name);
-			File target = new File(testFolder, name);
-			ResourceUtil.copyResourceToFile(xmlUrl, target);
-			files.add(target);
-		}
-
-		Injector injector = DIBootstrap.createInjector(testModule);
-		ProjectUpgrader_V7 upgrader = new ProjectUpgrader_V7();
-		injector.injectMembers(upgrader);
-
-		Resource source = new URLResource(files.get(0).toURI().toURL());
-		assertNotNull(source);
-		UpgradeHandler handler = upgrader.getUpgradeHandler(source);
-		assertNotNull(handler);
-
-		Resource upgraded = handler.performUpgrade();
-		assertNotNull(upgraded);
-		assertNotSame(source, upgraded);
-
-		assertPerformUpgrade6Cayenne(files.get(0));
-		assertPerformUpgrade6Map1(files.get(1));
-		assertPerformUpgradeMap2(files.get(2));
-	}
-
-	private void assertPerformUpgrade6Map1(File file) throws Exception {
-		Document document = toDOMTree(file);
-
-		XPath xpath = XPathFactory.newInstance().newXPath();
-		assertEquals("9", xpath.evaluate("/data-map/@project-version", document));
-
-		NodeList maps = (NodeList) xpath.evaluate("/data-map/obj-entity/entity-listener", document,
-				XPathConstants.NODESET);
-		assertNotNull(maps);
-		assertEquals(0, maps.getLength());
-	}
-
-	private void assertPerformUpgrade6Cayenne(File file) throws Exception {
-		Document document = toDOMTree(file);
-
-		XPath xpath = XPathFactory.newInstance().newXPath();
-		assertEquals("9", xpath.evaluate("/domain/@project-version", document));
-	}
-
-	private void assertPerformUpgradeMap2(File file) throws Exception {
-		Document document = toDOMTree(file);
-
-		XPath xpath = XPathFactory.newInstance().newXPath();
-		assertEquals("9", xpath.evaluate("/data-map/@project-version", document));
-	}
-
-	@Test
-	public void testObjAttributeDelete() throws Exception {
-
-		File testFolder = setupTestDirectory("testObjAttribute");
-		String sourceUrl = getClass().getPackage().getName().replace('.', '/') + "/6a/delete_shadow_attributes/";
-
-		Module testModule = new Module() {
-
-			public void configure(Binder binder) {
-				binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
-				binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-				binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
-				binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
-				binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
-			}
-		};
-
-		ArrayList<String> source = new ArrayList<String>();
-		source.add("cayenne-TestProject.xml");
-		source.add("testProjectMap1.map.xml");
-		source.add("testProjectMap2.map.xml");
-
-		ArrayList<File> file = new ArrayList<File>();
-
-		for (String name : source) {
-			URL xmlUrl = getClass().getClassLoader().getResource(sourceUrl + name);
-			File target = new File(testFolder, name);
-			ResourceUtil.copyResourceToFile(xmlUrl, target);
-			file.add(target);
-		}
-
-		Injector injector = DIBootstrap.createInjector(testModule);
-		ProjectUpgrader_V7 upgrader = new ProjectUpgrader_V7();
-		injector.injectMembers(upgrader);
-
-		Resource resource = new URLResource(file.get(0).toURI().toURL());
-		assertNotNull(resource);
-		UpgradeHandler handler = upgrader.getUpgradeHandler(resource);
-		assertNotNull(handler);
-
-		Resource upgraded = handler.performUpgrade();
-		assertNotNull(upgraded);
-		assertNotSame(resource, upgraded);
-
-		assertPerformUpgrade6Cayenne(file.get(0));
-		assertObjAttributeMap1(file.get(1));
-		assertObjAttributeMap2(file.get(2));
-	}
-
-	private void assertObjAttributeMap1(File file) throws Exception {
-		Document document = toDOMTree(file);
-
-		XPath xpath = XPathFactory.newInstance().newXPath();
-		assertEquals("9", xpath.evaluate("/data-map/@project-version", document));
-
-		String xpathValue = "/data-map/obj-entity[@name='GreatArtist']/obj-attribute";
-		XPathExpression expr = xpath.compile(xpathValue);
-		Node node = (Node) expr.evaluate(document, XPathConstants.NODE);
-
-		assertEquals("attribute2", xpath.evaluate("@name", node));
-	}
-
-	private void assertObjAttributeMap2(File file) throws Exception {
-		Document document = toDOMTree(file);
-
-		XPath xpath = XPathFactory.newInstance().newXPath();
-		assertEquals("9", xpath.evaluate("/data-map/@project-version", document));
-
-		String xpath_1 = "/data-map/obj-entity[@name='House']/obj-attribute/@name";
-		String xpath_2 = "/data-map/obj-entity[@name='Penthouse']/obj-attribute/@name";
-		XPathExpression expr = xpath.compile(xpath_1);
-		String houseAttr = (String) expr.evaluate(document, XPathConstants.STRING);
-		expr = xpath.compile(xpath_2);
-		String penthouseAttr = (String) expr.evaluate(document, XPathConstants.STRING);
-
-		assertEquals("attribute2", houseAttr);
-		assertEquals("attribute3", penthouseAttr);
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/v8/ProjectUpgrader_V8Test.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/v8/ProjectUpgrader_V8Test.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/v8/ProjectUpgrader_V8Test.java
deleted file mode 100644
index 610d77c..0000000
--- a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/v8/ProjectUpgrader_V8Test.java
+++ /dev/null
@@ -1,197 +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.project.upgrade.v8;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.configuration.ConfigurationNameMapper;
-import org.apache.cayenne.configuration.DataMapLoader;
-import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
-import org.apache.cayenne.configuration.XMLDataMapLoader;
-import org.apache.cayenne.di.*;
-import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
-import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
-import org.apache.cayenne.project.FileProjectSaver;
-import org.apache.cayenne.project.ProjectSaver;
-import org.apache.cayenne.project.unit.Project2Case;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
-import org.apache.cayenne.resource.Resource;
-import org.apache.cayenne.resource.URLResource;
-import org.apache.cayenne.test.file.FileUtil;
-import org.apache.cayenne.test.resource.ResourceUtil;
-import org.junit.Test;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathFactory;
-import java.io.File;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.junit.Assert.*;
-
-public class ProjectUpgrader_V8Test extends Project2Case {
-
-    protected File setupTestDirectory(String subfolder) {
-        String classPath = getClass().getName().replace('.', '/');
-        String location = "target/testrun/" + classPath + "/" + subfolder;
-        File testDirectory = new File(location);
-
-        // delete old tests
-        if (testDirectory.exists()) {
-            if (!FileUtil.delete(location, true)) {
-                throw new CayenneRuntimeException(
-                        "Error deleting test directory '%s'",
-                        location);
-            }
-        }
-
-        if (!testDirectory.mkdirs()) {
-            throw new CayenneRuntimeException(
-                    "Error creating test directory '%s'",
-                    location);
-        }
-
-        return testDirectory;
-    }
-
-    @Test
-    public void testPerformUpgrade() throws Exception {
-
-        File testFolder = setupTestDirectory("testPerformUpgrade_7");
-        String sourceUrl = getClass().getPackage().getName().replace('.', '/') + "/7a/";
-
-        List<String> sources = new ArrayList<>();
-
-        sources.add("cayenne-PROJECT1.xml");
-        sources.add("testProjectMap1_1.map.xml");
-        sources.add("testProjectMap1_2.map.xml");
-
-        // upgrades are done in-place, so copy it first
-        List<File> targetsBefore = new ArrayList<>();
-        for (String source : sources) {
-
-            URL url = getClass().getClassLoader().getResource(sourceUrl + source);
-            File target = new File(testFolder, source);
-            assertNotNull(source);
-            ResourceUtil.copyResourceToFile(url, target);
-            targetsBefore.add(target);
-        }
-
-        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(ProjectSaver.class).to(FileProjectSaver.class);
-                binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-                binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
-            }
-        };
-
-        ProjectUpgrader_V8 upgrader = new ProjectUpgrader_V8();
-        Injector injector = DIBootstrap.createInjector(testModule);
-        injector.injectMembers(upgrader);
-
-        Resource source = new URLResource(targetsBefore.get(0).toURL());
-        UpgradeHandler handler = upgrader.getUpgradeHandler(source);
-
-        Resource upgraded = handler.performUpgrade();
-        assertNotNull(upgraded);
-        assertNotSame(source, upgrader);
-
-        // check that all the new files are created...
-        String[] targetsAfterNames = new String[] {
-                "cayenne-PROJECT1.xml", "testProjectMap1_1.map.xml", "testProjectMap1_2.map.xml"
-        };
-
-        File[] targetsAfter = new File[targetsAfterNames.length];
-        for (int i = 0; i < targetsAfter.length; i++) {
-            targetsAfter[i] = new File(testFolder, targetsAfterNames[i]);
-            assertTrue("File was not created: " + targetsAfter[i].getAbsolutePath(), targetsAfter[i].exists());
-        }
-
-        // assert XML structure of the generated files
-        assertPerformUpgrade_7_cayenne(targetsAfter[0]);
-        assertPerformUpgrade_map1_1(targetsAfter[1]);
-        assertPerformUpgrade_map1_2(targetsAfter[2]);
-    }
-
-    private void assertPerformUpgrade_7_cayenne(File file) throws Exception {
-        Document document = toDOMTree(file);
-
-        XPath xpath = XPathFactory.newInstance().newXPath();
-        assertEquals("", xpath.evaluate("/domain/@name", document));
-        assertEquals("9", xpath.evaluate("/domain/@project-version", document));
-
-        NodeList maps = (NodeList) xpath.evaluate("/domain/map", document, XPathConstants.NODESET);
-        assertNotNull(maps);
-        assertEquals(2, maps.getLength());
-
-        Node map1 = maps.item(0);
-        Node map2 = maps.item(1);
-
-        assertEquals("testProjectMap1_1", xpath.evaluate("@name", map1));
-        assertEquals("testProjectMap1_2", xpath.evaluate("@name", map2));
-
-        NodeList nodes = (NodeList) xpath.evaluate("/domain/node", document, XPathConstants.NODESET);
-        assertNotNull(nodes);
-        assertEquals(1, nodes.getLength());
-    }
-
-    private void assertPerformUpgrade_map1_1(File file) throws Exception {
-        Document document = toDOMTree(file);
-
-        XPath xpath = XPathFactory.newInstance().newXPath();
-        assertEquals("9", xpath.evaluate("/data-map/@project-version", document));
-
-        NodeList queryNodes = (NodeList) xpath.evaluate("/data-map/query", document, XPathConstants.NODESET);
-        assertNotNull(queryNodes);
-
-        Map<String, Element> queries = new HashMap<>();
-
-        for (int i = 0; i < queryNodes.getLength(); i++) {
-            Element query = (Element) queryNodes.item(i);
-            queries.put(query.getAttribute("name"), query);
-        }
-
-        assertEquals("", queries.get("EjbqlQueryTest").getAttribute("factory"));
-        assertEquals("", queries.get("SQLTemplateTest").getAttribute("factory"));
-        assertEquals("", queries.get("SelectQueryTest").getAttribute("factory"));
-        assertEquals("", queries.get("ProcedureQueryTest").getAttribute("factory"));
-
-        assertEquals("EJBQLQuery", queries.get("EjbqlQueryTest").getAttribute("type"));
-        assertEquals("SQLTemplate", queries.get("SQLTemplateTest").getAttribute("type"));
-        assertEquals("SelectQuery", queries.get("SelectQueryTest").getAttribute("type"));
-        assertEquals("ProcedureQuery", queries.get("ProcedureQueryTest").getAttribute("type"));
-    }
-
-    private void assertPerformUpgrade_map1_2(File file) throws Exception {
-        Document document = toDOMTree(file);
-
-        XPath xpath = XPathFactory.newInstance().newXPath();
-        assertEquals("9", xpath.evaluate("/data-map/@project-version", document));
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/v9/ProjectUpgrader_V9Test.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/v9/ProjectUpgrader_V9Test.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/v9/ProjectUpgrader_V9Test.java
deleted file mode 100644
index 3851a2e..0000000
--- a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/v9/ProjectUpgrader_V9Test.java
+++ /dev/null
@@ -1,249 +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.project.upgrade.v9;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.configuration.ConfigurationNameMapper;
-import org.apache.cayenne.configuration.DataMapLoader;
-import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
-import org.apache.cayenne.configuration.XMLDataMapLoader;
-import org.apache.cayenne.di.*;
-import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
-import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
-import org.apache.cayenne.project.FileProjectSaver;
-import org.apache.cayenne.project.ProjectSaver;
-import org.apache.cayenne.project.unit.Project2Case;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
-import org.apache.cayenne.project.upgrade.UpgradeMetaData;
-import org.apache.cayenne.project.upgrade.UpgradeType;
-import org.apache.cayenne.resource.Resource;
-import org.apache.cayenne.resource.URLResource;
-import org.apache.cayenne.test.file.FileUtil;
-import org.apache.cayenne.test.resource.ResourceUtil;
-import org.junit.Test;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathFactory;
-import java.io.File;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.junit.Assert.*;
-
-public class ProjectUpgrader_V9Test extends Project2Case {
-
-    @Test
-    public void testMetadata_3_0_0_1() {
-
-        String baseUrl = getClass().getPackage().getName().replace('.', '/');
-        URL url = getClass().getClassLoader().getResource(baseUrl + "/3_0_0_1a/cayenne.xml");
-        assertNotNull(url);
-
-        Module testModule = new Module() {
-
-            public void configure(Binder binder) {
-                binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
-                binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-            }
-        };
-
-        ProjectUpgrader_V9 upgrader = new ProjectUpgrader_V9();
-        Injector injector = DIBootstrap.createInjector(testModule);
-        injector.injectMembers(upgrader);
-
-        Resource source = new URLResource(url);
-        UpgradeHandler handler = upgrader.getUpgradeHandler(source);
-
-        assertNotNull(handler);
-        assertSame(source, handler.getProjectSource());
-
-        UpgradeMetaData md = handler.getUpgradeMetaData();
-        assertNotNull(md);
-
-        assertSame(UpgradeType.UPGRADE_NEEDED, md.getUpgradeType());
-        assertNull(md.getIntermediateUpgradeVersion());
-        assertEquals("3.0.0.1", md.getProjectVersion());
-        assertEquals("9", md.getSupportedVersion());
-    }
-
-    @Test
-    public void testMetadata_Type6() {
-        String baseUrl = getClass().getPackage().getName().replace('.', '/');
-        URL url = getClass().getClassLoader().getResource(baseUrl + "/6a/cayenne-PROJECT1.xml");
-        assertNotNull(url);
-
-        Module testModule = new Module() {
-
-            public void configure(Binder binder) {
-                binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
-                binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-            }
-        };
-
-        ProjectUpgrader_V9 upgrader = new ProjectUpgrader_V9();
-        Injector injector = DIBootstrap.createInjector(testModule);
-        injector.injectMembers(upgrader);
-
-        Resource source = new URLResource(url);
-        UpgradeHandler handler = upgrader.getUpgradeHandler(source);
-
-        assertNotNull(handler);
-        assertSame(source, handler.getProjectSource());
-
-        UpgradeMetaData md = handler.getUpgradeMetaData();
-        assertNotNull(md);
-        assertSame(UpgradeType.UPGRADE_NEEDED, md.getUpgradeType());
-        assertNull(md.getIntermediateUpgradeVersion());
-        assertEquals("6", md.getProjectVersion());
-        assertEquals("9", md.getSupportedVersion());
-    }
-
-    protected File setupTestDirectory(String subfolder) {
-        String classPath = getClass().getName().replace('.', '/');
-        String location = "target/testrun/" + classPath + "/" + subfolder;
-        File testDirectory = new File(location);
-
-        // delete old tests
-        if (testDirectory.exists()) {
-            if (!FileUtil.delete(location, true)) {
-                throw new CayenneRuntimeException(
-                        "Error deleting test directory '%s'",
-                        location);
-            }
-        }
-
-        if (!testDirectory.mkdirs()) {
-            throw new CayenneRuntimeException(
-                    "Error creating test directory '%s'",
-                    location);
-        }
-
-        return testDirectory;
-    }
-
-    @Test
-    public void testPerformUpgradeFrom8() throws Exception {
-
-        File testFolder = setupTestDirectory("testPerformUpgradeFrom8");
-        String sourceUrl = getClass().getPackage().getName().replace('.', '/') + "/";
-
-        List<String> sources = new ArrayList<>();
-
-        sources.add("cayenne-PROJECT1.xml");
-        sources.add("testProjectMap1_1.map.xml");
-        sources.add("testProjectMap1_2.map.xml");
-        sources.add("reverseEngineering.xml");
-
-        // upgrades are done in-place, so copy it first
-        List<File> targetsBefore = new ArrayList<>();
-        for (String source : sources) {
-
-            URL url = getClass().getClassLoader().getResource(sourceUrl + source);
-            File target = new File(testFolder, source);
-            assertNotNull(source);
-            ResourceUtil.copyResourceToFile(url, target);
-            targetsBefore.add(target);
-        }
-
-        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(ProjectSaver.class).to(FileProjectSaver.class);
-                binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-                binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
-            }
-        };
-
-        ProjectUpgrader_V9 upgrader = new ProjectUpgrader_V9();
-        Injector injector = DIBootstrap.createInjector(testModule);
-        injector.injectMembers(upgrader);
-
-        Resource source = new URLResource(targetsBefore.get(0).toURI().toURL());
-        UpgradeHandler handler = upgrader.getUpgradeHandler(source);
-
-        Resource upgraded = handler.performUpgrade();
-        assertNotNull(upgraded);
-        assertNotSame(source, upgrader);
-
-        // check that all the new files are created...
-        String[] targetsAfterNames = new String[] {
-                "cayenne-PROJECT1.xml", "testProjectMap1_1.map.xml", "testProjectMap1_2.map.xml"
-        };
-
-        File[] targetsAfter = new File[targetsAfterNames.length];
-        for (int i = 0; i < targetsAfter.length; i++) {
-            targetsAfter[i] = new File(testFolder, targetsAfterNames[i]);
-            assertTrue("File was not created: " + targetsAfter[i].getAbsolutePath(), targetsAfter[i].exists());
-        }
-
-        // assert XML structure of the generated files
-        assertPerformUpgradeFrom8_cayenne(targetsAfter[0]);
-        assertPerformUpgradeFrom8_map1_1(targetsAfter[1]);
-        assertPerformUpgradeFrom8_map1_2(targetsAfter[2]);
-        assertFalse(new File(testFolder, "reverseEngineering.xml").exists());
-    }
-
-    private void assertPerformUpgradeFrom8_cayenne(File file) throws Exception {
-        Document document = toDOMTree(file);
-
-        XPath xpath = XPathFactory.newInstance().newXPath();
-        assertEquals("", xpath.evaluate("/domain/@name", document));
-        assertEquals("9", xpath.evaluate("/domain/@project-version", document));
-
-        NodeList maps = (NodeList) xpath.evaluate("/domain/map", document, XPathConstants.NODESET);
-        assertNotNull(maps);
-        assertEquals(2, maps.getLength());
-
-        Node map1 = maps.item(0);
-        Node map2 = maps.item(1);
-
-        assertEquals("testProjectMap1_1", xpath.evaluate("@name", map1));
-        assertEquals("testProjectMap1_2", xpath.evaluate("@name", map2));
-
-        NodeList nodes = (NodeList) xpath.evaluate("/domain/node", document, XPathConstants.NODESET);
-        assertNotNull(nodes);
-        assertEquals(1, nodes.getLength());
-    }
-
-    private void assertPerformUpgradeFrom8_map1_1(File file) throws Exception {
-        Document document = toDOMTree(file);
-
-        XPath xpath = XPathFactory.newInstance().newXPath();
-        assertEquals("9", xpath.evaluate("/data-map/@project-version", document));
-
-        NodeList reverseEngineeringNodes = (NodeList) xpath.evaluate("/data-map/reverse-engineering-config",
-                document, XPathConstants.NODESET);
-        assertEquals(0, reverseEngineeringNodes.getLength());
-    }
-
-    private void assertPerformUpgradeFrom8_map1_2(File file) throws Exception {
-        Document document = toDOMTree(file);
-
-        XPath xpath = XPathFactory.newInstance().newXPath();
-        assertEquals("9", xpath.evaluate("/data-map/@project-version", document));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/cayenne-PROJECT1.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/cayenne-PROJECT1.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/cayenne-PROJECT1.xml
index 31fb0d3..5b27d93 100644
--- a/cayenne-project/src/test/resources/org/apache/cayenne/project/cayenne-PROJECT1.xml
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/cayenne-PROJECT1.xml
@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain name="DefaultDomain" project-version="6">
-
-	<map name="testProjectMap1_1" />
-	<map name="testProjectMap1_2" />
-
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="testProjectMap1_1"/>
+	<map name="testProjectMap1_2"/>
 	<node name="testProjectNode1"
-		adapter="org.example.test.Adapter" factory="org.example.test.DataSourceFactory">
+		 adapter="org.example.test.Adapter"
+		 factory="org.example.test.DataSourceFactory">
+		<map-ref name="testProjectMap1_1"/>
 		<data-source>
 			<connectionPool min="1" max="1" />
 			<login />
 		</data-source>
-		<map-ref name="testProjectMap1_1" />
 	</node>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/cayenne-PROJECT2.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/cayenne-PROJECT2.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/cayenne-PROJECT2.xml
index 7fba199..c83d807 100644
--- a/cayenne-project/src/test/resources/org/apache/cayenne/project/cayenne-PROJECT2.xml
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/cayenne-PROJECT2.xml
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain name="DefaultDomain" project-version="6">
-
-	<map name="testProjectMap2_1" />
-	<map name="testProjectMap2_2" />
-
-	<node name="testProjectNode2" adapter="org.example.test.Adapter"
-		factory="org.apache.cayenne.configuration.XMLPoolingDataSourceFactory">
-		<map-ref name="testProjectMap2_1" />
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="testProjectMap2_1"/>
+	<map name="testProjectMap2_2"/>
+	<node name="testProjectNode2"
+		 adapter="org.example.test.Adapter"
+		 factory="org.apache.cayenne.configuration.XMLPoolingDataSourceFactory">
+		<map-ref name="testProjectMap2_1"/>
 		<data-source>
 			<driver value="xyzDriver"/>
 			<url value="xyzUrl"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap1_1.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap1_1.map.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap1_1.map.xml
index 6b79eb5..abbaaf3 100644
--- a/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap1_1.map.xml
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap1_1.map.xml
@@ -1,7 +1,5 @@
 <?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">
-
-</data-map>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap1_2.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap1_2.map.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap1_2.map.xml
index 6b79eb5..abbaaf3 100644
--- a/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap1_2.map.xml
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap1_2.map.xml
@@ -1,7 +1,5 @@
 <?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">
-
-</data-map>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap2_1.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap2_1.map.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap2_1.map.xml
index 6b79eb5..abbaaf3 100644
--- a/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap2_1.map.xml
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap2_1.map.xml
@@ -1,7 +1,5 @@
 <?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">
-
-</data-map>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap2_2.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap2_2.map.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap2_2.map.xml
index 6b79eb5..abbaaf3 100644
--- a/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap2_2.map.xml
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/testProjectMap2_2.map.xml
@@ -1,7 +1,5 @@
 <?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">
-
-</data-map>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v10.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v10.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v10.xml
new file mode 100644
index 0000000..c3f0681
--- /dev/null
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v10.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Fake version to test DefaultUpgradeService -->
+<domain project-version="10"/>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v11.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v11.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v11.xml
new file mode 100644
index 0000000..51f7c4c
--- /dev/null
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v11.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Fake version to test DefaultUpgradeService -->
+<domain project-version="11"/>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v3.2.1.0.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v3.2.1.0.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v3.2.1.0.xml
new file mode 100644
index 0000000..b8c95e1
--- /dev/null
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v3.2.1.0.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Fake version to test DefaultUpgradeService -->
+<domain project-version="3.2.1.0"/>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v5.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v5.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v5.xml
new file mode 100644
index 0000000..0cb4160
--- /dev/null
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v5.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Fake version to test DefaultUpgradeService -->
+<domain project-version="5"/>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v6.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v6.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v6.xml
new file mode 100644
index 0000000..11735326
--- /dev/null
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v6.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain project-version="6">
+
+	<property name="cayenne.DataDomain.usingExternalTransactions" value="true"/>
+
+	<map name="testProjectMap1_1" />
+	<map name="testProjectMap1_2" />
+
+	<node name="testProjectNode1"
+		adapter="org.example.test.Adapter" factory="org.example.test.DataSourceFactory">
+		<data-source>
+			<connectionPool min="1" max="1" />
+			<login />
+		</data-source>
+		<map-ref name="testProjectMap1_1" />
+	</node>
+</domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v7.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v7.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v7.xml
new file mode 100644
index 0000000..7b4a247
--- /dev/null
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v7.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain project-version="7">
+
+	<map name="testProjectMap1_1" />
+	<map name="testProjectMap1_2" />
+
+	<node name="testProjectNode1"
+		adapter="org.example.test.Adapter" factory="org.example.test.DataSourceFactory">
+		<data-source>
+			<connectionPool min="1" max="1" />
+			<login />
+		</data-source>
+		<map-ref name="testProjectMap1_1" />
+	</node>
+</domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v8.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v8.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v8.xml
new file mode 100644
index 0000000..745ea3f
--- /dev/null
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v8.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain project-version="8">
+
+    <map name="testProjectMap1_1" />
+    <map name="testProjectMap1_2" />
+
+    <node name="testProjectNode1"
+          adapter="org.example.test.Adapter" factory="org.example.test.DataSourceFactory">
+        <data-source>
+            <connectionPool min="1" max="1" />
+            <login />
+        </data-source>
+        <map-ref name="testProjectMap1_1" />
+    </node>
+</domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v9.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v9.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v9.xml
new file mode 100644
index 0000000..52cf7b4
--- /dev/null
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v9.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain project-version="9">
+
+    <map name="testProjectMap1_1" />
+    <map name="testProjectMap1_2" />
+
+    <node name="testProjectNode1"
+          adapter="org.example.test.Adapter" factory="org.example.test.DataSourceFactory">
+        <data-source>
+            <connectionPool min="1" max="1" />
+            <login />
+        </data-source>
+        <map-ref name="testProjectMap1_1" />
+    </node>
+</domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v6.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v6.map.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v6.map.xml
new file mode 100644
index 0000000..25167f4
--- /dev/null
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v6.map.xml
@@ -0,0 +1,21 @@
+<?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">
+<db-entity name="Artist">
+        <db-attribute name="attributeOne" type="CHAR" isPrimaryKey="true" isMandatory="true" length="10"/>
+        <db-attribute name="attributeTwo" type="DATE"/>
+    </db-entity>
+    <obj-entity name="Artist" dbEntityName="Artist">
+        <entity-listener class="EntityListener">
+            <post-add method-name="prePersistEntityListener"/>
+			<post-persist method-name="postPersistEntityListener"/>
+			<pre-update method-name="preUpdateEntityListener"/>
+			<post-update method-name="postUpdateEntityListener"/>
+			<pre-remove method-name="preRemoveEntityListener"/>
+			<post-remove method-name="postRemoveEntityListener"/>
+			<post-load method-name="postLoadEntityListener"/>
+        </entity-listener>
+    </obj-entity>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v7.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v7.map.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v7.map.xml
new file mode 100644
index 0000000..dcc9580
--- /dev/null
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v7.map.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<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="Artist">
+        <db-attribute name="untitledAttr" type="CHAR" isPrimaryKey="true" isMandatory="true" length="10"/>
+        <db-attribute name="untitledAttr1" type="DATE"/>
+    </db-entity>
+    <obj-entity name="Artist" dbEntityName="Artist">
+        <entity-listener class="NowyListener">
+        </entity-listener>
+    </obj-entity>
+    <query name="EjbqlQueryTest" factory="org.apache.cayenne.map.EjbqlBuilder">
+        <property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
+        <property name="cayenne.GenericSelectQuery.cacheStrategy" value="SHARED_CACHE"/>
+        <ejbql><![CDATA[select a from Artist a]]></ejbql>
+    </query>
+    <query name="SQLTemplateTest" factory="org.apache.cayenne.map.SQLTemplateBuilder" root="data-map" root-name="testmap">
+        <property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
+        <sql><![CDATA[INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ESTIMATED_PRICE)
+VALUES (512, 'No Painting Like This', 12.5)]]></sql>
+        <sql adapter-class="org.apache.cayenne.dba.db2.DB2Adapter"><![CDATA[INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ESTIMATED_PRICE) VALUES (512, 'No Painting Like This', 12.5)]]></sql>
+    </query>
+    <query name="SelectQueryTest" factory="org.apache.cayenne.map.SelectQueryBuilder" root="obj-entity" root-name="Painting">
+        <qualifier><![CDATA[toArtist = $artist]]></qualifier>
+        <ordering><![CDATA[paintingTitle]]></ordering>
+    </query>
+    <query name="ProcedureQueryTest" factory="org.apache.cayenne.map.ProcedureQueryBuilder" root="procedure" root-name="cayenne_tst_select_proc" result-entity="Artist">
+    </query>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v8.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v8.map.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v8.map.xml
new file mode 100644
index 0000000..1464a49
--- /dev/null
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v8.map.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data-map xmlns="http://cayenne.apache.org/schema/8/modelMap"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://cayenne.apache.org/schema/8/modelMap http://cayenne.apache.org/schema/8/modelMap.xsd"
+          project-version="8">
+    <reverse-engineering-config name="reverseEngineering"/>
+    <db-entity name="Artist">
+        <db-attribute name="untitledAttr" type="CHAR" isPrimaryKey="true" isMandatory="true" length="10"/>
+        <db-attribute name="untitledAttr1" type="DATE"/>
+    </db-entity>
+    <obj-entity name="Artist" dbEntityName="Artist">
+    </obj-entity>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v9.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v9.map.xml b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v9.map.xml
new file mode 100644
index 0000000..1787bf0
--- /dev/null
+++ b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/test-map-v9.map.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
+          project-version="9">
+    <db-entity name="Artist">
+        <db-attribute name="untitledAttr" type="CHAR" isPrimaryKey="true" isMandatory="true" length="10"/>
+        <db-attribute name="untitledAttr1" type="DATE"/>
+    </db-entity>
+    <obj-entity name="Artist" dbEntityName="Artist">
+    </obj-entity>
+</data-map>

[11/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - ProjectExtension - new upgrade handlers

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V8.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V8.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V8.java
new file mode 100644
index 0000000..c2898bc
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V8.java
@@ -0,0 +1,99 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.upgrade.handlers;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.map.QueryDescriptor;
+import org.apache.cayenne.project.upgrade.UpgradeUnit;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * @since 4.1
+ */
+public class UpgradeHandler_V8 implements UpgradeHandler {
+
+    @Override
+    public String getVersion() {
+        return "8";
+    }
+
+    @Override
+    public void processProjectDom(UpgradeUnit upgradeUnit) {
+        Element domain = upgradeUnit.getDocument().getDocumentElement();
+        domain.setAttribute("project-version", getVersion());
+    }
+
+    @Override
+    public void processDataMapDom(UpgradeUnit upgradeUnit) {
+        Element dataMap = upgradeUnit.getDocument().getDocumentElement();
+        dataMap.setAttribute("xmlns","http://cayenne.apache.org/schema/8/modelMap");
+        dataMap.setAttribute("xsi:schemaLocation", "http://cayenne.apache.org/schema/8/modelMap " +
+                "http://cayenne.apache.org/schema/8/modelMap.xsd");
+        dataMap.setAttribute("project-version", getVersion());
+
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        NodeList queryNodes;
+        try {
+            queryNodes = (NodeList) xpath.evaluate("/data-map/query", upgradeUnit.getDocument(), XPathConstants.NODESET);
+        } catch (Exception ex) {
+            return;
+        }
+
+        for (int j = 0; j < queryNodes.getLength(); j++) {
+            Element queryElement = (Element) queryNodes.item(j);
+            String factory = queryElement.getAttribute("factory");
+            if(factory == null || factory.isEmpty()) {
+                continue;
+            }
+
+            String queryType;
+            switch (factory) {
+                case "org.apache.cayenne.map.SelectQueryBuilder":
+                    queryType = QueryDescriptor.SELECT_QUERY;
+                    break;
+                case "org.apache.cayenne.map.SQLTemplateBuilder":
+                    queryType = QueryDescriptor.SQL_TEMPLATE;
+                    break;
+                case "org.apache.cayenne.map.EjbqlBuilder":
+                    queryType = QueryDescriptor.EJBQL_QUERY;
+                    break;
+                case "org.apache.cayenne.map.ProcedureQueryBuilder":
+                    queryType = QueryDescriptor.PROCEDURE_QUERY;
+                    break;
+                default:
+                    throw new ConfigurationException("Unknown query factory: " + factory);
+            }
+
+            queryElement.setAttribute("type", queryType);
+            queryElement.removeAttribute("factory");
+        }
+    }
+
+    @Override
+    public void processModel(DataChannelDescriptor dataChannelDescriptor) {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V9.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V9.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V9.java
new file mode 100644
index 0000000..bc0d078
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V9.java
@@ -0,0 +1,81 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.upgrade.handlers;
+
+import java.io.File;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.project.upgrade.UpgradeUnit;
+import org.apache.cayenne.util.Util;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * @since 4.1
+ */
+public class UpgradeHandler_V9 implements UpgradeHandler {
+
+    @Override
+    public String getVersion() {
+        return "9";
+    }
+
+    @Override
+    public void processProjectDom(UpgradeUnit upgradeUnit) {
+        Element domain = upgradeUnit.getDocument().getDocumentElement();
+        domain.setAttribute("project-version", getVersion());
+    }
+
+    @Override
+    public void processDataMapDom(UpgradeUnit upgradeUnit) {
+        Document document = upgradeUnit.getDocument();
+        Element dataMap = document.getDocumentElement();
+        dataMap.setAttribute("xmlns","http://cayenne.apache.org/schema/9/modelMap");
+        dataMap.setAttribute("xsi:schemaLocation", "http://cayenne.apache.org/schema/9/modelMap " +
+                "http://cayenne.apache.org/schema/9/modelMap.xsd");
+        dataMap.setAttribute("project-version", getVersion());
+
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        try {
+            Node reNode = (Node) xpath.evaluate("/data-map/reverse-engineering-config", document, XPathConstants.NODE);
+
+            if (reNode != null) {
+                String reFileName = ((Element) reNode).getAttribute("name") + ".xml";
+                String directoryPath = Util.toFile(upgradeUnit.getResource().getURL()).getParent();
+
+                File file = new File(directoryPath + "/" + reFileName);
+                if (file.exists()) {
+                    file.delete();
+                }
+                dataMap.removeChild(reNode);
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    @Override
+    public void processModel(DataChannelDescriptor dataChannelDescriptor) {
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/ProjectUpgrader_V6.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/ProjectUpgrader_V6.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/ProjectUpgrader_V6.java
deleted file mode 100644
index 0a4a0a0..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/ProjectUpgrader_V6.java
+++ /dev/null
@@ -1,43 +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.project.upgrade.v6;
-
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.project.upgrade.ProjectUpgrader;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
-import org.apache.cayenne.resource.Resource;
-
-/**
- * A ProjectUpgrader that handles project upgrades to version 6.
- * 
- * @since 3.1
- */
-public class ProjectUpgrader_V6 implements ProjectUpgrader {
-
-    @Inject
-    protected Injector injector;
-
-    public UpgradeHandler getUpgradeHandler(Resource projectSource) {
-        UpgradeHandler_V6 handler = new UpgradeHandler_V6(projectSource);
-        injector.injectMembers(handler);
-        return handler;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/UpgradeHandler_V6.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/UpgradeHandler_V6.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/UpgradeHandler_V6.java
deleted file mode 100644
index f20553e..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/UpgradeHandler_V6.java
+++ /dev/null
@@ -1,118 +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.project.upgrade.v6;
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.configuration.ConfigurationTree;
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.project.Project;
-import org.apache.cayenne.project.ProjectSaver;
-import org.apache.cayenne.project.upgrade.BaseUpgradeHandler;
-import org.apache.cayenne.project.upgrade.UpgradeMetaData;
-import org.apache.cayenne.resource.Resource;
-import org.apache.cayenne.util.Util;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * @since 3.1
- */
-class UpgradeHandler_V6 extends BaseUpgradeHandler {
-
-    static final String TO_VERSION = "6";
-
-    /**
-     * Notice that the loader is statically typed, intentionally not using DI to ensure
-     * predictable behavior on legacy upgrades.
-     */
-    private XMLDataChannelDescriptorLoader_V3_0_0_1 projectLoader;
-
-    /**
-     * Unlike loader, saver is injected, so that we can save dynamically with the latest
-     * version. This may change once this upgrade handler becomes an intermediate handler.
-     */
-    @Inject
-    private ProjectSaver projectSaver;
-
-    UpgradeHandler_V6(Resource source) {
-        super(source);
-        this.projectLoader = new XMLDataChannelDescriptorLoader_V3_0_0_1();
-    }
-
-    @Override
-    protected Resource doPerformUpgrade(UpgradeMetaData metaData) throws ConfigurationException {
-
-        List<DataChannelDescriptor> domains = projectLoader.load(projectSource);
-        if (domains.isEmpty()) {
-            // create a single domain dummy project if a noop config is being upgraded
-            DataChannelDescriptor descriptor = new DataChannelDescriptor();
-            descriptor.setName("DEFAULT");
-            domains.add(descriptor);
-        }
-
-        // collect resources to delete before the upgrade...
-        Collection<Resource> resourcesToDelete = new ArrayList<>();
-        for (DataChannelDescriptor descriptor : domains) {
-            for (DataNodeDescriptor node : descriptor.getNodeDescriptors()) {
-                Resource nodeResource = node.getConfigurationSource();
-                if (nodeResource != null) {
-                    resourcesToDelete.add(nodeResource);
-                }
-            }
-        }
-
-        // save in the new format
-        for (DataChannelDescriptor descriptor : domains) {
-            Project project = new Project(new ConfigurationTree<>(descriptor));
-            
-            attachToNamespace((DataChannelDescriptor) project.getRootNode());
-
-            // side effect of that is deletion of the common "cayenne.xml"
-            projectSaver.save(project);
-        }
-
-        // delete all .driver.xml files
-        for (Resource resource : resourcesToDelete) {
-            try {
-                File file = Util.toFile(resource.getURL());
-                if (file.exists() && file.getName().endsWith(".driver.xml")) {
-                    file.delete();
-                }
-            }
-            catch (Exception e) {
-                // ignore...
-            }
-        }
-
-        // returns the first domain configuration out of possibly multiple new
-        // configurations...
-        return domains.get(0).getConfigurationSource();
-    }
-
-    @Override
-    protected String getToVersion() {
-        return TO_VERSION;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java
deleted file mode 100644
index f0819ff..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java
+++ /dev/null
@@ -1,299 +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.project.upgrade.v6;
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.configuration.SAXNestedTagHandler;
-import org.apache.cayenne.configuration.server.JNDIDataSourceFactory;
-import org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory;
-import org.apache.cayenne.conn.DataSourceInfo;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.resource.Resource;
-import org.apache.cayenne.util.Util;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.XMLReader;
-
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A loader of Cayenne projects descriptor for version "3.0.0.1".
- */
-class XMLDataChannelDescriptorLoader_V3_0_0_1 {
-
-	static final String DBCP_DATA_SOURCE_FACTORY = "org.apache.cayenne.configuration.server.DBCPDataSourceFactory";
-
-	private static Logger logger = LoggerFactory.getLogger(XMLDataChannelDescriptorLoader_V3_0_0_1.class);
-
-	static final String DOMAINS_TAG = "domains";
-	static final String DOMAIN_TAG = "domain";
-	static final String MAP_TAG = "map";
-	static final String NODE_TAG = "node";
-	static final String PROPERTY_TAG = "property";
-	static final String MAP_REF_TAG = "map-ref";
-
-	private static final Map<String, String> dataSourceFactoryLegacyNameMapping;
-
-	static {
-		dataSourceFactoryLegacyNameMapping = new HashMap<>();
-		dataSourceFactoryLegacyNameMapping.put("org.apache.cayenne.conf.DriverDataSourceFactory",
-				XMLPoolingDataSourceFactory.class.getName());
-		dataSourceFactoryLegacyNameMapping.put("org.apache.cayenne.conf.JNDIDataSourceFactory",
-				JNDIDataSourceFactory.class.getName());
-		dataSourceFactoryLegacyNameMapping.put("org.apache.cayenne.conf.DBCPDataSourceFactory",
-				DBCP_DATA_SOURCE_FACTORY);
-	}
-
-	// implementation is statically typed and is intentionally not DI-provided
-	protected XMLDataMapLoader_V3_0_0_1 mapLoader;
-	protected XMLDataSourceInfoLoader_V3_0_0_1 dataSourceInfoLoader;
-
-	XMLDataChannelDescriptorLoader_V3_0_0_1() {
-		mapLoader = new XMLDataMapLoader_V3_0_0_1();
-		dataSourceInfoLoader = new XMLDataSourceInfoLoader_V3_0_0_1();
-	}
-
-	List<DataChannelDescriptor> load(Resource configurationSource) throws ConfigurationException {
-
-		if (configurationSource == null) {
-			throw new NullPointerException("Null configurationSource");
-		}
-
-		URL configurationURL = configurationSource.getURL();
-
-		List<DataChannelDescriptor> domains = new ArrayList<>();
-
-		try (InputStream in = configurationURL.openStream();) {
-
-			XMLReader parser = Util.createXmlReader();
-
-			DomainsHandler rootHandler = new DomainsHandler(configurationSource, domains, parser);
-			parser.setContentHandler(rootHandler);
-			parser.setErrorHandler(rootHandler);
-			parser.parse(new InputSource(in));
-		} catch (Exception e) {
-			throw new ConfigurationException("Error loading configuration from %s", e, configurationURL);
-		}
-
-		return domains;
-	}
-
-	/**
-	 * Make sure the domain name is only made up of Java-identifier-safe
-	 * characters.
-	 */
-	protected String scrubDomainName(String name) {
-		if (name == null || name.length() == 0) {
-			return name;
-		}
-
-		StringBuilder buffer = new StringBuilder(name.length());
-
-		for (int i = 0; i < name.length(); i++) {
-			char c = name.charAt(i);
-			if (i == 0 && !Character.isJavaIdentifierStart(c)) {
-				buffer.append('_');
-			} else if (i > 0 && !Character.isJavaIdentifierPart(c)) {
-				buffer.append('_');
-			} else {
-				buffer.append(c);
-			}
-		}
-
-		return buffer.toString();
-	}
-
-	/**
-	 * Converts the names of standard Cayenne-supplied DataSourceFactories from
-	 * the legacy names to the current names.
-	 */
-	private String convertDataSourceFactory(String dataSourceFactory) {
-
-		if (dataSourceFactory == null) {
-			return null;
-		}
-
-		String converted = dataSourceFactoryLegacyNameMapping.get(dataSourceFactory);
-		return converted != null ? converted : dataSourceFactory;
-	}
-
-	final class DomainsHandler extends SAXNestedTagHandler {
-
-		private Collection<DataChannelDescriptor> domains;
-		private Resource configurationSource;
-
-		DomainsHandler(Resource configurationSource, Collection<DataChannelDescriptor> domains, XMLReader parser) {
-			super(parser, null);
-			this.domains = domains;
-			this.configurationSource = configurationSource;
-		}
-
-		@Override
-		protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String qName,
-				Attributes attributes) {
-
-			if (localName.equals(DOMAINS_TAG)) {
-				return new DomainsChildrenHandler(parser, this);
-			}
-
-			return super.createChildTagHandler(namespaceURI, localName, qName, attributes);
-		}
-	}
-
-	final class DomainsChildrenHandler extends SAXNestedTagHandler {
-
-		private Collection<DataChannelDescriptor> domains;
-		private Resource configurationSource;
-
-		DomainsChildrenHandler(XMLReader parser, DomainsHandler parent) {
-			super(parser, parent);
-			this.domains = parent.domains;
-			this.configurationSource = parent.configurationSource;
-		}
-
-		@Override
-		protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name,
-				Attributes attributes) {
-
-			if (localName.equals(DOMAIN_TAG)) {
-
-				String domainName = attributes.getValue("", "name");
-				DataChannelDescriptor descriptor = new DataChannelDescriptor();
-				descriptor.setName(scrubDomainName(domainName));
-				descriptor.setConfigurationSource(configurationSource);
-
-				domains.add(descriptor);
-				return new DataChannelChildrenHandler(descriptor, parser, this);
-			}
-
-			logger.info(unexpectedTagMessage(localName, DOMAIN_TAG));
-			return super.createChildTagHandler(namespaceURI, localName, name, attributes);
-		}
-	}
-
-	final class DataChannelChildrenHandler extends SAXNestedTagHandler {
-
-		private DataChannelDescriptor descriptor;
-
-		DataChannelChildrenHandler(DataChannelDescriptor descriptor, XMLReader parser,
-				DomainsChildrenHandler parentHandler) {
-			super(parser, parentHandler);
-			this.descriptor = descriptor;
-		}
-
-		@Override
-		protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name,
-				Attributes attributes) {
-
-			if (localName.equals(PROPERTY_TAG)) {
-
-				String key = attributes.getValue("", "name");
-				String value = attributes.getValue("", "value");
-				if (key != null && value != null) {
-					descriptor.getProperties().put(key, value);
-				}
-			} else if (localName.equals(MAP_TAG)) {
-
-				String dataMapName = attributes.getValue("", "name");
-				Resource baseResource = descriptor.getConfigurationSource();
-
-				String dataMapLocation = attributes.getValue("", "location");
-				Resource dataMapResource = baseResource.getRelativeResource(dataMapLocation);
-
-				DataMap dataMap = mapLoader.load(dataMapResource);
-				dataMap.setName(dataMapName);
-				dataMap.setLocation(dataMapLocation);
-				dataMap.setConfigurationSource(dataMapResource);
-
-				descriptor.getDataMaps().add(dataMap);
-			} else if (localName.equals(NODE_TAG)) {
-
-				String nodeName = attributes.getValue("", "name");
-				if (nodeName == null) {
-					// TODO: assign dummy name?
-					throw new ConfigurationException("Error: <node> without 'name'.");
-				}
-
-				DataNodeDescriptor nodeDescriptor = new DataNodeDescriptor();
-				nodeDescriptor.setName(nodeName);
-
-				String dataSourceFactory = attributes.getValue("", "factory");
-				String dataSourceFactory6 = convertDataSourceFactory(dataSourceFactory);
-				nodeDescriptor.setDataSourceFactoryType(dataSourceFactory6);
-
-				// depending on the factory, "datasource" attribute is
-				// interpreted
-				// differently
-				String datasource = attributes.getValue("", "datasource");
-				if (XMLPoolingDataSourceFactory.class.getName().equals(dataSourceFactory6)) {
-					Resource baseResource = descriptor.getConfigurationSource();
-					Resource dataNodeResource = baseResource.getRelativeResource(datasource);
-					nodeDescriptor.setConfigurationSource(dataNodeResource);
-
-					DataSourceInfo dataSourceInfo = dataSourceInfoLoader.load(dataNodeResource);
-					nodeDescriptor.setDataSourceDescriptor(dataSourceInfo);
-				} else {
-					nodeDescriptor.setParameters(datasource);
-				}
-
-				descriptor.getNodeDescriptors().add(nodeDescriptor);
-				nodeDescriptor.setAdapterType(attributes.getValue("", "adapter"));
-				nodeDescriptor.setSchemaUpdateStrategyType(attributes.getValue("", "schema-update-strategy"));
-
-				return new DataNodeChildrenHandler(parser, this, nodeDescriptor);
-			}
-
-			return super.createChildTagHandler(namespaceURI, localName, name, attributes);
-		}
-	}
-
-	final class DataNodeChildrenHandler extends SAXNestedTagHandler {
-
-		private DataNodeDescriptor nodeDescriptor;
-
-		DataNodeChildrenHandler(XMLReader parser, SAXNestedTagHandler parentHandler, DataNodeDescriptor nodeDescriptor) {
-			super(parser, parentHandler);
-			this.nodeDescriptor = nodeDescriptor;
-		}
-
-		@Override
-		protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name,
-				Attributes attributes) {
-
-			if (localName.equals(MAP_REF_TAG)) {
-
-				String mapName = attributes.getValue("", "name");
-				nodeDescriptor.getDataMapNames().add(mapName);
-			}
-
-			return super.createChildTagHandler(namespaceURI, localName, name, attributes);
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataSourceInfoLoader_V3_0_0_1.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataSourceInfoLoader_V3_0_0_1.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataSourceInfoLoader_V3_0_0_1.java
deleted file mode 100644
index 188c6f8..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataSourceInfoLoader_V3_0_0_1.java
+++ /dev/null
@@ -1,300 +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.project.upgrade.v6;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.configuration.PasswordEncoding;
-import org.apache.cayenne.configuration.SAXNestedTagHandler;
-import org.apache.cayenne.conn.DataSourceInfo;
-import org.apache.cayenne.resource.Resource;
-import org.apache.cayenne.util.Util;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.XMLReader;
-
-/**
- * @since 3.1
- */
-class XMLDataSourceInfoLoader_V3_0_0_1 {
-
-    private static Logger logger = LoggerFactory.getLogger(XMLDataSourceInfoLoader_V3_0_0_1.class);
-
-    private static String passwordFromURL(URL url) {
-        InputStream inputStream = null;
-        String password = null;
-
-        try {
-            inputStream = url.openStream();
-            password = passwordFromInputStream(inputStream);
-        }
-        catch (IOException exception) {
-            // Log the error while trying to open the stream. A null
-            // password will be returned as a result.
-            logger.warn(exception.getMessage(), exception);
-        }
-
-        return password;
-    }
-
-    private static String passwordFromInputStream(InputStream inputStream) {
-        BufferedReader bufferedReader = null;
-        String password = null;
-
-        try {
-            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
-            password = bufferedReader.readLine();
-        }
-        catch (IOException exception) {
-            logger.warn(exception.getMessage(), exception);
-        }
-        finally {
-            try {
-                if (bufferedReader != null) {
-                    bufferedReader.close();
-                }
-            }
-            catch (Exception exception) {
-            }
-
-            try {
-                inputStream.close();
-            }
-            catch (IOException exception) {
-            }
-        }
-
-        return password;
-    }
-
-    DataSourceInfo load(Resource configurationSource) {
-        if (configurationSource == null) {
-            throw new NullPointerException("Null configurationSource");
-        }
-
-        URL configurationURL = configurationSource.getURL();
-
-        DataSourceInfo dataSourceInfo = new DataSourceInfo();
-
-        InputStream in = null;
-
-        try {
-            in = configurationURL.openStream();
-            XMLReader parser = Util.createXmlReader();
-
-            DriverHandler rootHandler = new DriverHandler(parser, dataSourceInfo);
-            parser.setContentHandler(rootHandler);
-            parser.setErrorHandler(rootHandler);
-            parser.parse(new InputSource(in));
-        }
-        catch (Exception e) {
-            throw new ConfigurationException(
-                    "Error loading configuration from %s",
-                    e,
-                    configurationURL);
-        }
-        finally {
-            try {
-                if (in != null) {
-                    in.close();
-                }
-            }
-            catch (IOException ioex) {
-                logger.info("failure closing input stream for "
-                        + configurationURL
-                        + ", ignoring", ioex);
-            }
-        }
-
-        return dataSourceInfo;
-    }
-
-    final class DriverHandler extends SAXNestedTagHandler {
-
-        private DataSourceInfo dataSourceDescriptor;
-
-        DriverHandler(XMLReader parser, DataSourceInfo dataSourceDescriptor) {
-            super(parser, null);
-            this.dataSourceDescriptor = dataSourceDescriptor;
-        }
-
-        @Override
-        protected ContentHandler createChildTagHandler(
-                String namespaceURI,
-                String localName,
-                String name,
-                Attributes attributes) {
-
-            if (localName.equals("driver")) {
-                String className = attributes.getValue("", "class");
-                dataSourceDescriptor.setJdbcDriver(className);
-
-                return new DataSourceChildrenHandler(parser, this);
-            }
-
-            return super.createChildTagHandler(namespaceURI, localName, name, attributes);
-        }
-    }
-
-    class DataSourceChildrenHandler extends SAXNestedTagHandler {
-
-        private DataSourceInfo dataSourceDescriptor;
-
-        DataSourceChildrenHandler(XMLReader parser, DriverHandler parentHandler) {
-            super(parser, parentHandler);
-            this.dataSourceDescriptor = parentHandler.dataSourceDescriptor;
-        }
-
-        @Override
-        protected ContentHandler createChildTagHandler(
-                String namespaceURI,
-                String localName,
-                String name,
-                Attributes attributes) {
-
-            if (localName.equals("login")) {
-
-                String encoderClass = attributes.getValue("encoderClass");
-
-                String encoderKey = attributes.getValue("encoderKey");
-                if (encoderKey == null) {
-                    encoderKey = attributes.getValue("encoderSalt");
-                }
-
-                String password = attributes.getValue("password");
-                String passwordLocation = attributes.getValue("passwordLocation");
-                String passwordSource = attributes.getValue("passwordSource");
-                if (passwordSource == null) {
-                    passwordSource = DataSourceInfo.PASSWORD_LOCATION_MODEL;
-                }
-
-                String username = attributes.getValue("userName");
-
-                dataSourceDescriptor.setPasswordEncoderClass(encoderClass);
-                dataSourceDescriptor.setPasswordEncoderKey(encoderKey);
-                dataSourceDescriptor.setPasswordLocation(passwordLocation);
-                dataSourceDescriptor.setPasswordSource(passwordSource);
-                dataSourceDescriptor.setUserName(username);
-
-                // Replace {} in passwordSource with encoderSalt -- useful for EXECUTABLE
-                // & URL options
-                if (encoderKey != null) {
-                    passwordSource = passwordSource.replaceAll("\\{\\}", encoderKey);
-                }
-
-                PasswordEncoding passwordEncoder = dataSourceDescriptor
-                        .getPasswordEncoder();
-
-                if (passwordLocation != null) {
-                    if (passwordLocation
-                            .equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH)) {
-
-                        ClassLoader classLoader = Thread
-                                .currentThread()
-                                .getContextClassLoader();
-                        URL url = classLoader.getResource(username);
-                        if (url != null) {
-                            password = passwordFromURL(url);
-                        }
-                        else {
-                            logger.error("Could not find resource in CLASSPATH: "
-                                    + passwordSource);
-                        }
-                    }
-                    else if (passwordLocation
-                            .equals(DataSourceInfo.PASSWORD_LOCATION_URL)) {
-                        try {
-                            password = passwordFromURL(new URL(passwordSource));
-                        }
-                        catch (MalformedURLException exception) {
-                            logger.warn(exception.getMessage(), exception);
-                        }
-                    }
-                    else if (passwordLocation
-                            .equals(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE)) {
-                        if (passwordSource != null) {
-                            try {
-                                Process process = Runtime.getRuntime().exec(
-                                        passwordSource);
-                                password = passwordFromInputStream(process
-                                        .getInputStream());
-                                process.waitFor();
-                            }
-                            catch (IOException exception) {
-                                logger.warn(exception.getMessage(), exception);
-                            }
-                            catch (InterruptedException exception) {
-                                logger.warn(exception.getMessage(), exception);
-                            }
-                        }
-                    }
-                }
-
-                if (password != null && passwordEncoder != null) {
-                    dataSourceDescriptor.setPassword(passwordEncoder.decodePassword(
-                            password,
-                            encoderKey));
-                }
-            }
-            else if (localName.equals("url")) {
-                dataSourceDescriptor.setDataSourceUrl(attributes.getValue("value"));
-            }
-            else if (localName.equals("connectionPool")) {
-                String min = attributes.getValue("min");
-                if (min != null) {
-                    try {
-                        dataSourceDescriptor.setMinConnections(Integer.parseInt(min));
-                    }
-                    catch (NumberFormatException nfex) {
-                        logger.info("Non-numeric 'min' attribute", nfex);
-                        throw new ConfigurationException(
-                                "Non-numeric 'min' attribute '%s'",
-                                nfex,
-                                min);
-                    }
-                }
-
-                String max = attributes.getValue("max");
-                if (max != null) {
-                    try {
-                        dataSourceDescriptor.setMaxConnections(Integer.parseInt(max));
-                    }
-                    catch (NumberFormatException nfex) {
-                        logger.info("Non-numeric 'max' attribute", nfex);
-                        throw new ConfigurationException(
-                                "Non-numeric 'max' attribute '%s'",
-                                nfex,
-                                max);
-                    }
-                }
-            }
-
-            return super.createChildTagHandler(namespaceURI, localName, name, attributes);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v7/UpgradeHandler_V7.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v7/UpgradeHandler_V7.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v7/UpgradeHandler_V7.java
deleted file mode 100644
index bd30381..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v7/UpgradeHandler_V7.java
+++ /dev/null
@@ -1,137 +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.project.upgrade.v7;
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.configuration.ConfigurationTree;
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.project.Project;
-import org.apache.cayenne.project.ProjectSaver;
-import org.apache.cayenne.project.upgrade.BaseUpgradeHandler;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
-import org.apache.cayenne.project.upgrade.UpgradeMetaData;
-import org.apache.cayenne.project.upgrade.v6.ProjectUpgrader_V6;
-import org.apache.cayenne.resource.Resource;
-
-import java.util.ArrayList;
-import java.util.List;
-
-class UpgradeHandler_V7 extends BaseUpgradeHandler {
-
-    static final String PREVIOUS_VERSION = "6";
-    static final String TO_VERSION = "7";
-
-    // this will be removed from DataDomain soon. So caching this property name
-    // in the upgrade handler
-    static final String USING_EXTERNAL_TRANSACTIONS_PROPERTY = "cayenne.DataDomain.usingExternalTransactions";
-
-    @Inject
-    protected Injector injector;
-
-    @Inject
-    private ProjectSaver projectSaver;
-
-    public UpgradeHandler_V7(Resource source) {
-        super(source);
-    }
-
-    @Override
-    protected Resource doPerformUpgrade(UpgradeMetaData metaData) throws ConfigurationException {
-        if (compareVersions(metaData.getProjectVersion(), PREVIOUS_VERSION) == -1) {
-            ProjectUpgrader_V6 upgraderV6 = new ProjectUpgrader_V6();
-            injector.injectMembers(upgraderV6);
-            UpgradeHandler handlerV6 = upgraderV6.getUpgradeHandler(projectSource);
-            projectSource = handlerV6.performUpgrade();
-        }
-
-        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
-        injector.injectMembers(loader);
-        ConfigurationTree<DataChannelDescriptor> tree = loader.load(projectSource);
-        Project project = new Project(tree);
-
-        attachToNamespace((DataChannelDescriptor) project.getRootNode());
-        
-        removeExternalTxProperty(project);
-
-        // remove "shadow" attributes per CAY-1795
-        removeShadowAttributes(project);
-
-        // load and safe cycle removes objects no longer supported, specifically
-        // listeners
-        projectSaver.save(project);
-        return project.getConfigurationResource();
-    }
-
-    private void removeExternalTxProperty(Project project) {
-        DataChannelDescriptor rootNode = (DataChannelDescriptor) project.getRootNode();
-        rootNode.getProperties().remove(USING_EXTERNAL_TRANSACTIONS_PROPERTY);
-    }
-
-    private void removeShadowAttributes(Project project) {
-        DataChannelDescriptor rootNode = (DataChannelDescriptor) project.getRootNode();
-
-        for (DataMap dataMap : rootNode.getDataMaps()) {
-
-            // if objEntity has super entity, then checks it
-            // for duplicated attributes
-            for (ObjEntity objEntity : dataMap.getObjEntities()) {
-                ObjEntity superEntity = objEntity.getSuperEntity();
-                if (superEntity != null) {
-                    removeShadowAttributes(objEntity, superEntity);
-                }
-            }
-        }
-    }
-
-    /**
-     * Remove attributes from objEntity, if superEntity has attributes with same
-     * names.
-     */
-    private void removeShadowAttributes(ObjEntity objEntity, ObjEntity superEntity) {
-
-        List<String> delList = new ArrayList<>();
-
-        // if subAttr and superAttr have same names, adds subAttr to delList
-        for (ObjAttribute subAttr : objEntity.getDeclaredAttributes()) {
-            for (ObjAttribute superAttr : superEntity.getAttributes()) {
-                if (subAttr.getName().equals(superAttr.getName())) {
-                    delList.add(subAttr.getName());
-                }
-            }
-        }
-
-        if (!delList.isEmpty()) {
-            for (String i : delList) {
-                objEntity.removeAttribute(i);
-            }
-        }
-    }
-
-    @Override
-    protected String getToVersion() {
-        return TO_VERSION;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v8/UpgradeHandler_V8.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v8/UpgradeHandler_V8.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v8/UpgradeHandler_V8.java
deleted file mode 100644
index 2e39599..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v8/UpgradeHandler_V8.java
+++ /dev/null
@@ -1,174 +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.project.upgrade.v8;
-
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.configuration.ConfigurationTree;
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.map.QueryDescriptor;
-import org.apache.cayenne.project.Project;
-import org.apache.cayenne.project.ProjectSaver;
-import org.apache.cayenne.project.upgrade.BaseUpgradeHandler;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
-import org.apache.cayenne.project.upgrade.UpgradeMetaData;
-import org.apache.cayenne.project.upgrade.v7.ProjectUpgrader_V7;
-import org.apache.cayenne.resource.Resource;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathFactory;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-
-public class UpgradeHandler_V8 extends BaseUpgradeHandler {
-
-    static final String PREVIOUS_VERSION = "7";
-    static final String TO_VERSION = "8";
-
-    @Inject
-    protected Injector injector;
-
-    @Inject
-    private ProjectSaver projectSaver;
-
-    public UpgradeHandler_V8(Resource source) {
-        super(source);
-    }
-
-    @Override
-    protected Resource doPerformUpgrade(UpgradeMetaData metaData) throws ConfigurationException {
-        if (compareVersions(metaData.getProjectVersion(), PREVIOUS_VERSION) == -1) {
-            ProjectUpgrader_V7 upgraderV7 = new ProjectUpgrader_V7();
-            injector.injectMembers(upgraderV7);
-            UpgradeHandler handlerV7 = upgraderV7.getUpgradeHandler(projectSource);
-            projectSource = handlerV7.performUpgrade();
-        }
-
-        upgradeFactories(projectSource);
-
-        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
-        injector.injectMembers(loader);
-        ConfigurationTree<DataChannelDescriptor> tree = loader.load(projectSource);
-        Project project = new Project(tree);
-
-        // load and safe cycle updates project version
-        projectSaver.save(project);
-        return project.getConfigurationResource();
-    }
-
-    private void upgradeFactories(Resource projectSource) {
-        Document projectDoc = readDOMDocument(projectSource);
-
-        try {
-            XPath xpath = XPathFactory.newInstance().newXPath();
-            NodeList nodes = (NodeList) xpath.evaluate("/domain/map/@name", projectDoc, XPathConstants.NODESET);
-
-            TransformerFactory transformerFactory = TransformerFactory.newInstance();
-            Transformer transformer = transformerFactory.newTransformer();
-
-            for (int i = 0; i < nodes.getLength(); i++) {
-                Node mapNode = nodes.item(i);
-
-                Resource mapResource = projectSource.getRelativeResource(mapNode.getNodeValue() + ".map.xml");
-
-                Document datamapDoc = readDOMDocument(mapResource);
-
-                NodeList queryNodes = (NodeList) xpath.evaluate("/data-map/query", datamapDoc, XPathConstants.NODESET);
-
-                for (int j = 0; j < queryNodes.getLength(); j++) {
-                    Element queryElement = (Element) queryNodes.item(j);
-                    String factory = queryElement.getAttribute("factory");
-                    if(factory == null || factory.isEmpty()) {
-                        continue;
-                    }
-
-                    String queryType;
-
-                    switch (factory) {
-                        case "org.apache.cayenne.map.SelectQueryBuilder":
-                            queryType = QueryDescriptor.SELECT_QUERY;
-                            break;
-                        case "org.apache.cayenne.map.SQLTemplateBuilder":
-                            queryType = QueryDescriptor.SQL_TEMPLATE;
-                            break;
-                        case "org.apache.cayenne.map.EjbqlBuilder":
-                            queryType = QueryDescriptor.EJBQL_QUERY;
-                            break;
-                        case "org.apache.cayenne.map.ProcedureQueryBuilder":
-                            queryType = QueryDescriptor.PROCEDURE_QUERY;
-                            break;
-                        default:
-                            throw new ConfigurationException("Unknown query factory: " + factory);
-                    }
-
-                    queryElement.setAttribute("type", queryType);
-                    queryElement.removeAttribute("factory");
-                }
-
-                DOMSource domSource = new DOMSource(datamapDoc);
-                StreamResult result = new StreamResult(
-                        new FileOutputStream(new File(mapResource.getURL().getPath())));
-                transformer.transform(domSource, result);
-            }
-
-        } catch (Exception e) {
-            throw new ConfigurationException("Unable to parse Cayenne XML configuration files.", e);
-        }
-    }
-
-    private Document readDOMDocument(Resource resource) {
-        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
-        try {
-            DocumentBuilder domBuilder = documentBuilderFactory.newDocumentBuilder();
-
-            try (InputStream inputStream = resource.getURL().openStream()) {
-                return domBuilder.parse(inputStream);
-            } catch (IOException | SAXException e) {
-                throw new ConfigurationException("Error loading configuration from %s", e, resource);
-            }
-        } catch (ParserConfigurationException e) {
-            throw new ConfigurationException(e);
-        }
-    }
-
-    @Override
-    protected String getToVersion() {
-        return TO_VERSION;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v9/UpgradeHandler_V9.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v9/UpgradeHandler_V9.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v9/UpgradeHandler_V9.java
deleted file mode 100644
index 92c2f0b..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v9/UpgradeHandler_V9.java
+++ /dev/null
@@ -1,145 +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.project.upgrade.v9;
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.configuration.ConfigurationTree;
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.project.Project;
-import org.apache.cayenne.project.ProjectSaver;
-import org.apache.cayenne.project.upgrade.BaseUpgradeHandler;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
-import org.apache.cayenne.project.upgrade.UpgradeMetaData;
-import org.apache.cayenne.project.upgrade.v8.ProjectUpgrader_V8;
-import org.apache.cayenne.resource.Resource;
-import org.apache.cayenne.util.Util;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathFactory;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-
-public class UpgradeHandler_V9 extends BaseUpgradeHandler {
-
-    static final String PREVIOUS_VERSION = "8";
-    static final String TO_VERSION = "9";
-
-    @Inject
-    protected Injector injector;
-
-    @Inject
-    private ProjectSaver projectSaver;
-
-    public UpgradeHandler_V9(Resource source) {
-        super(source);
-    }
-
-    @Override
-    protected Resource doPerformUpgrade(UpgradeMetaData metaData) throws ConfigurationException {
-        if (compareVersions(metaData.getProjectVersion(), PREVIOUS_VERSION) == -1) {
-            ProjectUpgrader_V8 upgraderV8 = new ProjectUpgrader_V8();
-            injector.injectMembers(upgraderV8);
-            UpgradeHandler handlerV8 = upgraderV8.getUpgradeHandler(projectSource);
-            projectSource = handlerV8.performUpgrade();
-        }
-
-        deleteReverseEngineeringFiles(projectSource);
-
-        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
-        injector.injectMembers(loader);
-        ConfigurationTree<DataChannelDescriptor> tree = loader.load(projectSource);
-        Project project = new Project(tree);
-
-        // load and safe cycle updates project version
-        projectSaver.save(project);
-        return project.getConfigurationResource();
-    }
-
-    private void deleteReverseEngineeringFiles(Resource projectSource) {
-        Document projectDoc = readDOMDocument(projectSource);
-
-        try {
-            XPath xpath = XPathFactory.newInstance().newXPath();
-            NodeList nodes = (NodeList) xpath.evaluate("/domain/map/@name", projectDoc, XPathConstants.NODESET);
-
-            for (int i = 0; i < nodes.getLength(); i++) {
-                Node mapNode = nodes.item(i);
-
-                Resource mapResource = projectSource.getRelativeResource(mapNode.getNodeValue() + ".map.xml");
-
-                Document datamapDoc = readDOMDocument(mapResource);
-
-                Node reNode = (Node) xpath.evaluate("/data-map/reverse-engineering-config",
-                        datamapDoc, XPathConstants.NODE);
-
-                if (reNode != null) {
-                    String reFileName = ((Element) reNode).getAttribute("name") + ".xml";
-
-                    try {
-                        String directoryPath = Util.toFile(projectSource.getURL()).getParent();
-
-                        File file = new File(directoryPath + "/" + reFileName);
-                        if (file.exists()) {
-                            file.delete();
-                        }
-                    } catch (Exception e) {
-                        // ignore...
-                    }
-                }
-            }
-
-        } catch (Exception e) {
-            throw new ConfigurationException("Unable to parse Cayenne XML configuration files.", e);
-        }
-    }
-
-    private Document readDOMDocument(Resource resource) {
-        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
-        try {
-            DocumentBuilder domBuilder = documentBuilderFactory.newDocumentBuilder();
-
-            try (InputStream inputStream = resource.getURL().openStream()) {
-                return domBuilder.parse(inputStream);
-            } catch (IOException | SAXException e) {
-                throw new ConfigurationException("Error loading configuration from %s", e, resource);
-            }
-        } catch (ParserConfigurationException e) {
-            throw new ConfigurationException(e);
-        }
-    }
-
-    @Override
-    protected String getToVersion() {
-        return TO_VERSION;
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/java/org/apache/cayenne/project/DataChannelProjectLoaderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/DataChannelProjectLoaderTest.java b/cayenne-project/src/test/java/org/apache/cayenne/project/DataChannelProjectLoaderTest.java
index 7159570..9e136f8 100644
--- a/cayenne-project/src/test/java/org/apache/cayenne/project/DataChannelProjectLoaderTest.java
+++ b/cayenne-project/src/test/java/org/apache/cayenne/project/DataChannelProjectLoaderTest.java
@@ -23,8 +23,12 @@ import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
 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.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
+import org.apache.cayenne.configuration.xml.HandlerFactory;
+import org.apache.cayenne.configuration.xml.NoopDataChannelMetaData;
+import org.apache.cayenne.configuration.xml.XMLDataChannelDescriptorLoader;
+import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.ClassLoaderManager;
@@ -58,10 +62,10 @@ public class DataChannelProjectLoaderTest {
                 binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
 
                 binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
-                binder.bind(DataChannelDescriptorLoader.class).to(
-                        XMLDataChannelDescriptorLoader.class);
-                binder.bind(ConfigurationNameMapper.class).to(
-                        DefaultConfigurationNameMapper.class);
+                binder.bind(DataChannelDescriptorLoader.class).to(XMLDataChannelDescriptorLoader.class);
+                binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
+                binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
+                binder.bind(DataChannelMetaData.class).to(NoopDataChannelMetaData.class);
             }
         };
 
@@ -70,8 +74,7 @@ public class DataChannelProjectLoaderTest {
 
         String testConfigName = "PROJECT1";
         String baseUrl = getClass().getPackage().getName().replace('.', '/');
-        URL url = getClass().getClassLoader().getResource(
-                baseUrl + "/cayenne-" + testConfigName + ".xml");
+        URL url = getClass().getClassLoader().getResource(baseUrl + "/cayenne-" + testConfigName + ".xml");
 
         Resource rootSource = new URLResource(url);
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/java/org/apache/cayenne/project/DataChannelProjectSaverTest.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/DataChannelProjectSaverTest.java b/cayenne-project/src/test/java/org/apache/cayenne/project/DataChannelProjectSaverTest.java
index 484c9ca..5e55221 100644
--- a/cayenne-project/src/test/java/org/apache/cayenne/project/DataChannelProjectSaverTest.java
+++ b/cayenne-project/src/test/java/org/apache/cayenne/project/DataChannelProjectSaverTest.java
@@ -23,8 +23,12 @@ import org.apache.cayenne.configuration.ConfigurationNameMapper;
 import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
 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.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
+import org.apache.cayenne.configuration.xml.HandlerFactory;
+import org.apache.cayenne.configuration.xml.NoopDataChannelMetaData;
+import org.apache.cayenne.configuration.xml.XMLDataChannelDescriptorLoader;
+import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.ClassLoaderManager;
@@ -33,6 +37,7 @@ 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.project.extension.ProjectExtension;
 import org.apache.cayenne.project.unit.Project2Case;
 import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.resource.URLResource;
@@ -41,6 +46,7 @@ import org.junit.Test;
 import java.io.File;
 import java.io.PrintWriter;
 import java.net.URL;
+import java.util.Collections;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -51,7 +57,7 @@ public class DataChannelProjectSaverTest extends Project2Case {
     @Test
     public void testSaveAs() throws Exception {
 
-        FileProjectSaver saver = new FileProjectSaver();
+        FileProjectSaver saver = new FileProjectSaver(Collections.<ProjectExtension>emptyList());
 
         Module testModule = new Module() {
 
@@ -61,11 +67,11 @@ public class DataChannelProjectSaverTest extends Project2Case {
                 binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
 
                 binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
-                binder.bind(DataChannelDescriptorLoader.class).to(
-                        XMLDataChannelDescriptorLoader.class);
+                binder.bind(DataChannelDescriptorLoader.class).to(XMLDataChannelDescriptorLoader.class);
                 binder.bind(ProjectLoader.class).to(DataChannelProjectLoader.class);
-                binder.bind(ConfigurationNameMapper.class).to(
-                        DefaultConfigurationNameMapper.class);
+                binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
+                binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
+                binder.bind(DataChannelMetaData.class).to(NoopDataChannelMetaData.class);
             }
         };
 
@@ -100,7 +106,7 @@ public class DataChannelProjectSaverTest extends Project2Case {
     @Test
     public void testSaveAs_RecoverFromSaveError() throws Exception {
 
-        FileProjectSaver saver = new FileProjectSaver() {
+        FileProjectSaver saver = new FileProjectSaver(Collections.<ProjectExtension>emptyList()) {
 
             @Override
             void saveToTempFile(SaveUnit unit, PrintWriter printWriter) {
@@ -115,11 +121,11 @@ public class DataChannelProjectSaverTest extends Project2Case {
                 binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
                 binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
                 binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
-                binder.bind(DataChannelDescriptorLoader.class).to(
-                        XMLDataChannelDescriptorLoader.class);
+                binder.bind(DataChannelDescriptorLoader.class).to(XMLDataChannelDescriptorLoader.class);
                 binder.bind(ProjectLoader.class).to(DataChannelProjectLoader.class);
-                binder.bind(ConfigurationNameMapper.class).to(
-                        DefaultConfigurationNameMapper.class);
+                binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
+                binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
+                binder.bind(DataChannelMetaData.class).to(NoopDataChannelMetaData.class);
             }
         };
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/java/org/apache/cayenne/project/FileProjectSaverTest.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/FileProjectSaverTest.java b/cayenne-project/src/test/java/org/apache/cayenne/project/FileProjectSaverTest.java
index a9a432d..747b101 100644
--- a/cayenne-project/src/test/java/org/apache/cayenne/project/FileProjectSaverTest.java
+++ b/cayenne-project/src/test/java/org/apache/cayenne/project/FileProjectSaverTest.java
@@ -28,6 +28,7 @@ import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.di.Module;
 import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.project.extension.ProjectExtension;
 import org.apache.cayenne.project.unit.Project2Case;
 import org.apache.cayenne.resource.URLResource;
 import org.junit.Before;
@@ -41,6 +42,7 @@ import javax.xml.xpath.XPathFactory;
 import java.io.File;
 import java.net.URL;
 import java.util.Arrays;
+import java.util.Collections;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -59,7 +61,7 @@ public class FileProjectSaverTest extends Project2Case {
             }
         };
 
-        saver = new FileProjectSaver();
+        saver = new FileProjectSaver(Collections.<ProjectExtension>emptyList());
         Injector injector = DIBootstrap.createInjector(testModule);
         injector.injectMembers(saver);
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultUpgradeServiceTest.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultUpgradeServiceTest.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultUpgradeServiceTest.java
new file mode 100644
index 0000000..e3a0342
--- /dev/null
+++ b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultUpgradeServiceTest.java
@@ -0,0 +1,163 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.upgrade;
+
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler;
+import org.apache.cayenne.resource.Resource;
+import org.apache.cayenne.resource.URLResource;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentMatchers;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
+import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+/**
+ * @since 4.1
+ */
+public class DefaultUpgradeServiceTest {
+
+    DefaultUpgradeService upgradeService;
+
+    List<UpgradeHandler> handlers;
+
+    @Before
+    public void createService() {
+        createHandlers();
+        upgradeService = new DefaultUpgradeService(handlers);
+    }
+
+    @Test
+    public void getUpgradeType() throws Exception {
+        UpgradeMetaData metaData = upgradeService.getUpgradeType(getResourceForVersion("5"));
+        assertEquals(UpgradeType.INTERMEDIATE_UPGRADE_NEEDED, metaData.getUpgradeType());
+
+        metaData = upgradeService.getUpgradeType(getResourceForVersion("6"));
+        assertEquals(UpgradeType.UPGRADE_NEEDED, metaData.getUpgradeType());
+
+        metaData = upgradeService.getUpgradeType(getResourceForVersion("10"));
+        assertEquals(UpgradeType.UPGRADE_NOT_NEEDED, metaData.getUpgradeType());
+
+        metaData = upgradeService.getUpgradeType(getResourceForVersion("11"));
+        assertEquals(UpgradeType.DOWNGRADE_NEEDED, metaData.getUpgradeType());
+    }
+
+    @Test
+    public void getHandlersForVersion() throws Exception {
+
+        List<UpgradeHandler> handlers = upgradeService.getHandlersForVersion("6");
+        assertEquals(4, handlers.size());
+
+        handlers = upgradeService.getHandlersForVersion("9");
+        assertEquals(1, handlers.size());
+        assertEquals("10", handlers.get(0).getVersion());
+    }
+
+    @Test
+    public void getAdditionalDatamapResources() throws Exception {
+        URL url = getClass().getResource("../cayenne-PROJECT1.xml");
+        Resource resource = new URLResource(url);
+        Document document = readDocument(url);
+        UpgradeUnit unit = new UpgradeUnit(resource, document);
+        List<Resource> resources = upgradeService.getAdditionalDatamapResources(unit);
+
+        assertEquals(2, resources.size());
+        assertTrue(resources.get(0).getURL().sameFile(getClass().getResource("../testProjectMap1_1.map.xml")));
+    }
+
+    @Test
+    public void loadProjectVersion() throws Exception {
+        assertEquals("3.2.1.0", upgradeService.loadProjectVersion(getResourceForVersion("3.2.1.0")));
+        assertEquals("10", upgradeService.loadProjectVersion(getResourceForVersion("10")));
+    }
+
+    @Test
+    public void decodeVersion() throws Exception {
+        assertEquals(1.2340, DefaultUpgradeService.decodeVersion("1.2.3.4"), 0.000001);
+        assertEquals(1.0004, DefaultUpgradeService.decodeVersion("1.0.0.0.4"), 0.000001);
+        assertEquals(10, DefaultUpgradeService.decodeVersion("10"), 0.000001);
+    }
+
+    @Test
+    public void upgradeDOM() throws Exception {
+        Resource resource = new URLResource(getClass().getResource("../cayenne-PROJECT1.xml"));
+
+        // Mock service so it will use actual reading but skip actual saving part
+        upgradeService = mock(DefaultUpgradeService.class);
+        when(upgradeService.upgradeDOM(any(Resource.class), ArgumentMatchers.<UpgradeHandler>anyList()))
+                .thenCallRealMethod();
+        when(upgradeService.readDocument(any(Resource.class)))
+                .thenCallRealMethod();
+        when(upgradeService.getAdditionalDatamapResources(any(UpgradeUnit.class)))
+                .thenCallRealMethod();
+
+        upgradeService.upgradeDOM(resource, handlers);
+
+        // one for project and two for data maps
+        verify(upgradeService, times(3)).saveDocument(any(UpgradeUnit.class));
+        for(UpgradeHandler handler : handlers) {
+            verify(handler).processProjectDom(any(UpgradeUnit.class));
+            // two data maps
+            verify(handler, times(2)).processDataMapDom(any(UpgradeUnit.class));
+        }
+    }
+
+    @Test
+    public void readDocument() throws Exception {
+        Document document = upgradeService
+                .readDocument(new URLResource(getClass().getResource("../cayenne-PROJECT1.xml")));
+        assertEquals("10", document.getDocumentElement().getAttribute("project-version"));
+    }
+
+    private Document readDocument(URL url) throws Exception {
+        DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+        return db.parse(new InputSource(new InputStreamReader(url.openStream())));
+    }
+
+    private void createHandlers() {
+        handlers = new ArrayList<>();
+        String[] versions = {"7", "8", "9", "10"};
+        for(String version : versions) {
+            handlers.add(createHandler(version));
+        }
+    }
+
+    private UpgradeHandler createHandler(String version) {
+        UpgradeHandler handler = mock(UpgradeHandler.class);
+        when(handler.getVersion()).thenReturn(version);
+        return handler;
+    }
+
+    private Resource getResourceForVersion(String version) {
+        return new URLResource(getClass().getResource("handlers/cayenne-project-v"+version+".xml"));
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/BaseUpgradeHandlerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/BaseUpgradeHandlerTest.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/BaseUpgradeHandlerTest.java
new file mode 100644
index 0000000..7595a88
--- /dev/null
+++ b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/BaseUpgradeHandlerTest.java
@@ -0,0 +1,71 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.upgrade.handlers;
+
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.cayenne.project.upgrade.UpgradeUnit;
+import org.apache.cayenne.resource.URLResource;
+import org.junit.Before;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
+/**
+ * @since 4.1
+ */
+abstract class BaseUpgradeHandlerTest {
+
+    UpgradeHandler handler;
+
+    @Before
+    public void createHandler() {
+        handler = newHandler();
+    }
+
+    abstract UpgradeHandler newHandler();
+
+    Document processProjectDom(String xmlResourceName) throws Exception {
+        UpgradeUnit unit = new UpgradeUnit(new URLResource(getClass().getResource(xmlResourceName)),
+                documentFromResource(xmlResourceName));
+        handler.processProjectDom(unit);
+        return unit.getDocument();
+    }
+
+    Document processDataMapDom(String xmlResourceName) throws Exception {
+        UpgradeUnit unit = new UpgradeUnit(new URLResource(getClass().getResource(xmlResourceName)),
+                documentFromResource(xmlResourceName));
+        handler.processDataMapDom(unit);
+        return unit.getDocument();
+    }
+
+    Document documentFromString(String xml) throws Exception {
+        DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+        return db.parse(new InputSource(new StringReader(xml)));
+    }
+
+    Document documentFromResource(String resource) throws Exception {
+        DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+        return db.parse(new InputSource(new InputStreamReader(getClass().getResourceAsStream(resource))));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V10Test.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V10Test.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V10Test.java
new file mode 100644
index 0000000..5413a92
--- /dev/null
+++ b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V10Test.java
@@ -0,0 +1,66 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.upgrade.handlers;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+/**
+ * @since 4.1
+ */
+public class UpgradeHandler_V10Test extends BaseUpgradeHandlerTest{
+
+    UpgradeHandler newHandler() {
+        return new UpgradeHandler_V10();
+    }
+
+    @Test
+    public void testProjectDomUpgrade() throws Exception {
+        Document document = processProjectDom("cayenne-project-v9.xml");
+
+        Element root = document.getDocumentElement();
+        assertEquals("10", root.getAttribute("project-version"));
+        assertEquals("http://cayenne.apache.org/schema/10/domain", root.getAttribute("xmlns"));
+        assertEquals(2, root.getElementsByTagName("map").getLength());
+    }
+
+    @Test
+    public void testDataMapDomUpgrade() throws Exception {
+        Document document = processDataMapDom("test-map-v9.map.xml");
+
+        Element root = document.getDocumentElement();
+        assertEquals("10", root.getAttribute("project-version"));
+        assertEquals("http://cayenne.apache.org/schema/10/modelMap", root.getAttribute("xmlns"));
+        assertEquals(2, root.getElementsByTagName("db-attribute").getLength());
+    }
+
+    @Test
+    public void testModelUpgrade() throws Exception {
+        DataChannelDescriptor descriptor = mock(DataChannelDescriptor.class);
+        handler.processModel(descriptor);
+        verifyZeroInteractions(descriptor);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V7Test.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V7Test.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V7Test.java
new file mode 100644
index 0000000..5464650
--- /dev/null
+++ b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V7Test.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.project.upgrade.handlers;
+
+import java.util.Collections;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * @since 4.1
+ */
+public class UpgradeHandler_V7Test extends BaseUpgradeHandlerTest {
+
+    @Override
+    UpgradeHandler newHandler() {
+        return new UpgradeHandler_V7();
+    }
+
+    @Test
+    public void testProjectDomUpgrade() throws Exception {
+        Document document = processProjectDom("cayenne-project-v6.xml");
+
+        Element root = document.getDocumentElement();
+        assertEquals("7", root.getAttribute("project-version"));
+        assertEquals("", root.getAttribute("xmlns"));
+        assertEquals(2, root.getElementsByTagName("map").getLength());
+        assertEquals(0, root.getElementsByTagName("property").getLength());
+    }
+
+    @Test
+    public void testDataMapDomUpgrade() throws Exception {
+        Document document = processDataMapDom("test-map-v6.map.xml");
+
+        Element root = document.getDocumentElement();
+        assertEquals("7", root.getAttribute("project-version"));
+        assertEquals("http://cayenne.apache.org/schema/7/modelMap", root.getAttribute("xmlns"));
+        assertEquals(2, root.getElementsByTagName("db-attribute").getLength());
+    }
+
+    @Test
+    public void testModelUpgrade() throws Exception {
+        DataChannelDescriptor descriptor = mock(DataChannelDescriptor.class);
+        DataMap map = new DataMap();
+        when(descriptor.getDataMaps()).thenReturn(Collections.singletonList(map));
+
+        ObjEntity superEntity = new ObjEntity("super");
+        superEntity.addAttribute(new ObjAttribute("super"));
+        superEntity.addAttribute(new ObjAttribute("simple"));
+        map.addObjEntity(superEntity);
+
+        ObjEntity subEntity = new ObjEntity("sub");
+        subEntity.setSuperEntityName("super");
+        subEntity.addAttribute(new ObjAttribute("super"));
+        subEntity.addAttribute(new ObjAttribute("simple_sub"));
+        map.addObjEntity(subEntity);
+
+        assertNotNull(superEntity.getDeclaredAttribute("super"));
+        assertNotNull(subEntity.getDeclaredAttribute("super"));
+
+        handler.processModel(descriptor);
+
+        assertNotNull(superEntity.getDeclaredAttribute("super"));
+        assertNull(subEntity.getDeclaredAttribute("super"));
+
+        verify(descriptor).getDataMaps();
+        verifyNoMoreInteractions(descriptor);
+    }
+}
\ No newline at end of file

[04/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - new XML loader for DataMap - new project version - updated test projects

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-enum.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-enum.xml b/cayenne-server/src/test/resources/cayenne-enum.xml
index 17eda24..84bdc40 100644
--- a/cayenne-server/src/test/resources/cayenne-enum.xml
+++ b/cayenne-server/src/test/resources/cayenne-enum.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="enum"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-extended-type.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-extended-type.xml b/cayenne-server/src/test/resources/cayenne-extended-type.xml
index 6c65720..bfaef17 100644
--- a/cayenne-server/src/test/resources/cayenne-extended-type.xml
+++ b/cayenne-server/src/test/resources/cayenne-extended-type.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="extended-type"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="extended-type"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-generated.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-generated.xml b/cayenne-server/src/test/resources/cayenne-generated.xml
index a880717..5742090 100644
--- a/cayenne-server/src/test/resources/cayenne-generated.xml
+++ b/cayenne-server/src/test/resources/cayenne-generated.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="generated"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="generated"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-generic.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-generic.xml b/cayenne-server/src/test/resources/cayenne-generic.xml
index 7dff2a3..36652f8 100644
--- a/cayenne-server/src/test/resources/cayenne-generic.xml
+++ b/cayenne-server/src/test/resources/cayenne-generic.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="generic"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="generic"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-inheritance-single-table1.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-inheritance-single-table1.xml b/cayenne-server/src/test/resources/cayenne-inheritance-single-table1.xml
index 04b98f6..415b79c 100644
--- a/cayenne-server/src/test/resources/cayenne-inheritance-single-table1.xml
+++ b/cayenne-server/src/test/resources/cayenne-inheritance-single-table1.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="inheritance-single-table1"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-inheritance-vertical.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-inheritance-vertical.xml b/cayenne-server/src/test/resources/cayenne-inheritance-vertical.xml
index 7edce8d..9d8da09 100644
--- a/cayenne-server/src/test/resources/cayenne-inheritance-vertical.xml
+++ b/cayenne-server/src/test/resources/cayenne-inheritance-vertical.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="inheritance-vertical"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-inheritance.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-inheritance.xml b/cayenne-server/src/test/resources/cayenne-inheritance.xml
index 818c9b2..affbae9 100644
--- a/cayenne-server/src/test/resources/cayenne-inheritance.xml
+++ b/cayenne-server/src/test/resources/cayenne-inheritance.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="inheritance"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="inheritance"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-lifecycle-callbacks-order.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-lifecycle-callbacks-order.xml b/cayenne-server/src/test/resources/cayenne-lifecycle-callbacks-order.xml
index 79900f9..4b4c9be 100644
--- a/cayenne-server/src/test/resources/cayenne-lifecycle-callbacks-order.xml
+++ b/cayenne-server/src/test/resources/cayenne-lifecycle-callbacks-order.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="lifecycle-callbacks-order"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="lifecycle-callbacks-order"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-lifecycles.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-lifecycles.xml b/cayenne-server/src/test/resources/cayenne-lifecycles.xml
index ba6fc19..6306561 100644
--- a/cayenne-server/src/test/resources/cayenne-lifecycles.xml
+++ b/cayenne-server/src/test/resources/cayenne-lifecycles.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="lifecycles"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="lifecycles"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-lob.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-lob.xml b/cayenne-server/src/test/resources/cayenne-lob.xml
index dde2a47..630bb15 100644
--- a/cayenne-server/src/test/resources/cayenne-lob.xml
+++ b/cayenne-server/src/test/resources/cayenne-lob.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="lob"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="lob"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-locking.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-locking.xml b/cayenne-server/src/test/resources/cayenne-locking.xml
index 1d4f2a5..7a12f1d 100644
--- a/cayenne-server/src/test/resources/cayenne-locking.xml
+++ b/cayenne-server/src/test/resources/cayenne-locking.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="locking"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-map-to-many.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-map-to-many.xml b/cayenne-server/src/test/resources/cayenne-map-to-many.xml
index 10709e0..117ab72 100644
--- a/cayenne-server/src/test/resources/cayenne-map-to-many.xml
+++ b/cayenne-server/src/test/resources/cayenne-map-to-many.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="map-to-many"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="map-to-many"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-meaningful-pk.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-meaningful-pk.xml b/cayenne-server/src/test/resources/cayenne-meaningful-pk.xml
index fe17e9e..feebe09 100644
--- a/cayenne-server/src/test/resources/cayenne-meaningful-pk.xml
+++ b/cayenne-server/src/test/resources/cayenne-meaningful-pk.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="meaningful-pk"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="meaningful-pk"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-misc-types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-misc-types.xml b/cayenne-server/src/test/resources/cayenne-misc-types.xml
index 46adeb2..0371c40 100644
--- a/cayenne-server/src/test/resources/cayenne-misc-types.xml
+++ b/cayenne-server/src/test/resources/cayenne-misc-types.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="misc-types"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="misc-types"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-mixed-persistence-strategy.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-mixed-persistence-strategy.xml b/cayenne-server/src/test/resources/cayenne-mixed-persistence-strategy.xml
index 0723809..2a2f901 100644
--- a/cayenne-server/src/test/resources/cayenne-mixed-persistence-strategy.xml
+++ b/cayenne-server/src/test/resources/cayenne-mixed-persistence-strategy.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="mixed-persistence-strategy"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="mixed-persistence-strategy"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-multi-tier.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-multi-tier.xml b/cayenne-server/src/test/resources/cayenne-multi-tier.xml
index 65f4f51..af46d6e 100644
--- a/cayenne-server/src/test/resources/cayenne-multi-tier.xml
+++ b/cayenne-server/src/test/resources/cayenne-multi-tier.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="multi-tier"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-multinode.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-multinode.xml b/cayenne-server/src/test/resources/cayenne-multinode.xml
index 7b23fb5..5554ac0 100644
--- a/cayenne-server/src/test/resources/cayenne-multinode.xml
+++ b/cayenne-server/src/test/resources/cayenne-multinode.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="map-db1"/>
 	<map name="map-db2"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-no-pk.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-no-pk.xml b/cayenne-server/src/test/resources/cayenne-no-pk.xml
index 2905c89..a153e9a 100644
--- a/cayenne-server/src/test/resources/cayenne-no-pk.xml
+++ b/cayenne-server/src/test/resources/cayenne-no-pk.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="no-pk"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="no-pk"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-numeric-types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-numeric-types.xml b/cayenne-server/src/test/resources/cayenne-numeric-types.xml
index 3376ad1..cb44482 100644
--- a/cayenne-server/src/test/resources/cayenne-numeric-types.xml
+++ b/cayenne-server/src/test/resources/cayenne-numeric-types.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="numeric-types"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="numeric-types"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-oneway-rels.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-oneway-rels.xml b/cayenne-server/src/test/resources/cayenne-oneway-rels.xml
index 1c23877..788d49e 100644
--- a/cayenne-server/src/test/resources/cayenne-oneway-rels.xml
+++ b/cayenne-server/src/test/resources/cayenne-oneway-rels.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="oneway-rels"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-org.apache.cayenne.configuration.rop.server.test-config.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-org.apache.cayenne.configuration.rop.server.test-config.xml b/cayenne-server/src/test/resources/cayenne-org.apache.cayenne.configuration.rop.server.test-config.xml
index 19c38f0..f76c39e 100644
--- a/cayenne-server/src/test/resources/cayenne-org.apache.cayenne.configuration.rop.server.test-config.xml
+++ b/cayenne-server/src/test/resources/cayenne-org.apache.cayenne.configuration.rop.server.test-config.xml
@@ -1,3 +1,3 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-</domain>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-people.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-people.xml b/cayenne-server/src/test/resources/cayenne-people.xml
index 26629b4..47d3cbb 100644
--- a/cayenne-server/src/test/resources/cayenne-people.xml
+++ b/cayenne-server/src/test/resources/cayenne-people.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="people"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-primitive.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-primitive.xml b/cayenne-server/src/test/resources/cayenne-primitive.xml
index 026c75c..35c4154 100644
--- a/cayenne-server/src/test/resources/cayenne-primitive.xml
+++ b/cayenne-server/src/test/resources/cayenne-primitive.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="primitive"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="primitive"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-qualified.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-qualified.xml b/cayenne-server/src/test/resources/cayenne-qualified.xml
index f930615..2f67cd9 100644
--- a/cayenne-server/src/test/resources/cayenne-qualified.xml
+++ b/cayenne-server/src/test/resources/cayenne-qualified.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="qualified"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-quoted-identifiers.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-quoted-identifiers.xml b/cayenne-server/src/test/resources/cayenne-quoted-identifiers.xml
index 91cfec5..0764d45 100644
--- a/cayenne-server/src/test/resources/cayenne-quoted-identifiers.xml
+++ b/cayenne-server/src/test/resources/cayenne-quoted-identifiers.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="quoted-identifiers"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-reflexive.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-reflexive.xml b/cayenne-server/src/test/resources/cayenne-reflexive.xml
index e178d26..2bd2113 100644
--- a/cayenne-server/src/test/resources/cayenne-reflexive.xml
+++ b/cayenne-server/src/test/resources/cayenne-reflexive.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="reflexive"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="reflexive"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-relationships-activity.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-relationships-activity.xml b/cayenne-server/src/test/resources/cayenne-relationships-activity.xml
index 4eb8f9a..f6a9e52 100644
--- a/cayenne-server/src/test/resources/cayenne-relationships-activity.xml
+++ b/cayenne-server/src/test/resources/cayenne-relationships-activity.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="relationships-activity"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-relationships-child-master.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-relationships-child-master.xml b/cayenne-server/src/test/resources/cayenne-relationships-child-master.xml
index d14f075..e50106a 100644
--- a/cayenne-server/src/test/resources/cayenne-relationships-child-master.xml
+++ b/cayenne-server/src/test/resources/cayenne-relationships-child-master.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="relationships-child-master"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="relationships-child-master"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-relationships-clob.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-relationships-clob.xml b/cayenne-server/src/test/resources/cayenne-relationships-clob.xml
index 2d736b4..99425f9 100644
--- a/cayenne-server/src/test/resources/cayenne-relationships-clob.xml
+++ b/cayenne-server/src/test/resources/cayenne-relationships-clob.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="relationships-clob"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-relationships-collection-to-many.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-relationships-collection-to-many.xml b/cayenne-server/src/test/resources/cayenne-relationships-collection-to-many.xml
index 6df5be0..712aa28 100644
--- a/cayenne-server/src/test/resources/cayenne-relationships-collection-to-many.xml
+++ b/cayenne-server/src/test/resources/cayenne-relationships-collection-to-many.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="relationships-collection-to-many"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="relationships-collection-to-many"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-relationships-delete-rules.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-relationships-delete-rules.xml b/cayenne-server/src/test/resources/cayenne-relationships-delete-rules.xml
index 0d9b1e8..a98b2c3 100644
--- a/cayenne-server/src/test/resources/cayenne-relationships-delete-rules.xml
+++ b/cayenne-server/src/test/resources/cayenne-relationships-delete-rules.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="relationships-delete-rules"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="relationships-delete-rules"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-relationships-flattened.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-relationships-flattened.xml b/cayenne-server/src/test/resources/cayenne-relationships-flattened.xml
index 499333a..c89d35e 100644
--- a/cayenne-server/src/test/resources/cayenne-relationships-flattened.xml
+++ b/cayenne-server/src/test/resources/cayenne-relationships-flattened.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="relationships-flattened"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-relationships-set-to-many.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-relationships-set-to-many.xml b/cayenne-server/src/test/resources/cayenne-relationships-set-to-many.xml
index a5331ce..6ece1ba 100644
--- a/cayenne-server/src/test/resources/cayenne-relationships-set-to-many.xml
+++ b/cayenne-server/src/test/resources/cayenne-relationships-set-to-many.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="relationships-set-to-many"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="relationships-set-to-many"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-relationships-to-many-fk.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-relationships-to-many-fk.xml b/cayenne-server/src/test/resources/cayenne-relationships-to-many-fk.xml
index b1e77d1..16f6835 100644
--- a/cayenne-server/src/test/resources/cayenne-relationships-to-many-fk.xml
+++ b/cayenne-server/src/test/resources/cayenne-relationships-to-many-fk.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="relationships-to-many-fk"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="relationships-to-many-fk"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-relationships-to-one-fk.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-relationships-to-one-fk.xml b/cayenne-server/src/test/resources/cayenne-relationships-to-one-fk.xml
index c6884b8..40a6818 100644
--- a/cayenne-server/src/test/resources/cayenne-relationships-to-one-fk.xml
+++ b/cayenne-server/src/test/resources/cayenne-relationships-to-one-fk.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="relationships-to-one-fk"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="relationships-to-one-fk"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-relationships.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-relationships.xml b/cayenne-server/src/test/resources/cayenne-relationships.xml
index a709d2b..90524b9 100644
--- a/cayenne-server/src/test/resources/cayenne-relationships.xml
+++ b/cayenne-server/src/test/resources/cayenne-relationships.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="relationships"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-return-types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-return-types.xml b/cayenne-server/src/test/resources/cayenne-return-types.xml
index b346de0..e5ef2d6 100644
--- a/cayenne-server/src/test/resources/cayenne-return-types.xml
+++ b/cayenne-server/src/test/resources/cayenne-return-types.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="return-types"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="return-types"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-soft-delete.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-soft-delete.xml b/cayenne-server/src/test/resources/cayenne-soft-delete.xml
index 860278a..074f163 100644
--- a/cayenne-server/src/test/resources/cayenne-soft-delete.xml
+++ b/cayenne-server/src/test/resources/cayenne-soft-delete.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="soft-delete"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="soft-delete"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-sus.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-sus.xml b/cayenne-server/src/test/resources/cayenne-sus.xml
index 7031593..87da094 100644
--- a/cayenne-server/src/test/resources/cayenne-sus.xml
+++ b/cayenne-server/src/test/resources/cayenne-sus.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="sus-map"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-table-primitives.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-table-primitives.xml b/cayenne-server/src/test/resources/cayenne-table-primitives.xml
index b03ffb9..23109fd 100644
--- a/cayenne-server/src/test/resources/cayenne-table-primitives.xml
+++ b/cayenne-server/src/test/resources/cayenne-table-primitives.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="table-primitives"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="table-primitives"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-testmap.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-testmap.xml b/cayenne-server/src/test/resources/cayenne-testmap.xml
index 3c44022..9d8918c 100644
--- a/cayenne-server/src/test/resources/cayenne-testmap.xml
+++ b/cayenne-server/src/test/resources/cayenne-testmap.xml
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain project-version="10">
 	<map name="testmap"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-things.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-things.xml b/cayenne-server/src/test/resources/cayenne-things.xml
index 10f6104..6b04b1f 100644
--- a/cayenne-server/src/test/resources/cayenne-things.xml
+++ b/cayenne-server/src/test/resources/cayenne-things.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="things"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="things"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-toone.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-toone.xml b/cayenne-server/src/test/resources/cayenne-toone.xml
index f71983a..ba524a1 100644
--- a/cayenne-server/src/test/resources/cayenne-toone.xml
+++ b/cayenne-server/src/test/resources/cayenne-toone.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="toone"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="toone"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-unsupported-distinct-types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-unsupported-distinct-types.xml b/cayenne-server/src/test/resources/cayenne-unsupported-distinct-types.xml
index 3a6ce3b..70734ff 100644
--- a/cayenne-server/src/test/resources/cayenne-unsupported-distinct-types.xml
+++ b/cayenne-server/src/test/resources/cayenne-unsupported-distinct-types.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="unsupported-distinct-types"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-uuid.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-uuid.xml b/cayenne-server/src/test/resources/cayenne-uuid.xml
index f654de9..8e35140 100644
--- a/cayenne-server/src/test/resources/cayenne-uuid.xml
+++ b/cayenne-server/src/test/resources/cayenne-uuid.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="uuid"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="uuid"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-weighted-sort.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-weighted-sort.xml b/cayenne-server/src/test/resources/cayenne-weighted-sort.xml
index cc939f7..78ce677 100644
--- a/cayenne-server/src/test/resources/cayenne-weighted-sort.xml
+++ b/cayenne-server/src/test/resources/cayenne-weighted-sort.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="weighted-sort"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/compound.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/compound.map.xml b/cayenne-server/src/test/resources/compound.map.xml
index d4210ab..616ffca 100644
--- a/cayenne-server/src/test/resources/compound.map.xml
+++ b/cayenne-server/src/test/resources/compound.map.xml
@@ -1,64 +1,64 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.compound"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="CHAR_FK_TEST">
-        <db-attribute name="FK_COL" type="CHAR" length="10"/>
-        <db-attribute name="NAME" type="VARCHAR" length="100"/>
-        <db-attribute name="PK" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="CHAR_PK_TEST">
-        <db-attribute name="OTHER_COL" type="CHAR" length="10"/>
-        <db-attribute name="PK_COL" type="CHAR" isPrimaryKey="true" isMandatory="true" length="10"/>
-    </db-entity>
-    <db-entity name="COMPOUND_FK_TEST">
-        <db-attribute name="F_KEY1" type="VARCHAR" length="20"/>
-        <db-attribute name="F_KEY2" type="VARCHAR" length="20"/>
-        <db-attribute name="NAME" type="VARCHAR" length="255"/>
-        <db-attribute name="PKEY" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="COMPOUND_PK_TEST">
-        <db-attribute name="KEY1" type="VARCHAR" isPrimaryKey="true" isMandatory="true" length="20"/>
-        <db-attribute name="KEY2" type="VARCHAR" isPrimaryKey="true" isMandatory="true" length="20"/>
-        <db-attribute name="NAME" type="VARCHAR" length="255"/>
-    </db-entity>
-    <obj-entity name="CharFkTestEntity" className="org.apache.cayenne.testdo.compound.CharFkTestEntity" dbEntityName="CHAR_FK_TEST">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="CharPkTestEntity" className="org.apache.cayenne.testdo.compound.CharPkTestEntity" dbEntityName="CHAR_PK_TEST">
-        <obj-attribute name="otherCol" type="java.lang.String" db-attribute-path="OTHER_COL"/>
-        <obj-attribute name="pkCol" type="java.lang.String" db-attribute-path="PK_COL"/>
-    </obj-entity>
-    <obj-entity name="CompoundFkTestEntity" className="org.apache.cayenne.testdo.compound.CompoundFkTestEntity" dbEntityName="COMPOUND_FK_TEST">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="CompoundPkTestEntity" className="org.apache.cayenne.testdo.compound.CompoundPkTestEntity" dbEntityName="COMPOUND_PK_TEST">
-        <obj-attribute name="key1" type="java.lang.String" db-attribute-path="KEY1"/>
-        <obj-attribute name="key2" type="java.lang.String" db-attribute-path="KEY2"/>
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <db-relationship name="toCharPK" source="CHAR_FK_TEST" target="CHAR_PK_TEST" toMany="false">
-        <db-attribute-pair source="FK_COL" target="PK_COL"/>
-    </db-relationship>
-    <db-relationship name="charFKs" source="CHAR_PK_TEST" target="CHAR_FK_TEST" toMany="true">
-        <db-attribute-pair source="PK_COL" target="FK_COL"/>
-    </db-relationship>
-    <db-relationship name="toCompoundPk" source="COMPOUND_FK_TEST" target="COMPOUND_PK_TEST" toMany="false">
-        <db-attribute-pair source="F_KEY1" target="KEY1"/>
-        <db-attribute-pair source="F_KEY2" target="KEY2"/>
-    </db-relationship>
-    <db-relationship name="compoundFkArray" source="COMPOUND_PK_TEST" target="COMPOUND_FK_TEST" toMany="true">
-        <db-attribute-pair source="KEY1" target="F_KEY1"/>
-        <db-attribute-pair source="KEY2" target="F_KEY2"/>
-    </db-relationship>
-    <obj-relationship name="toCharPK" source="CharFkTestEntity" target="CharPkTestEntity" db-relationship-path="toCharPK"/>
-    <obj-relationship name="charFKs" source="CharPkTestEntity" target="CharFkTestEntity" db-relationship-path="charFKs"/>
-    <obj-relationship name="toCompoundPk" source="CompoundFkTestEntity" target="CompoundPkTestEntity" db-relationship-path="toCompoundPk"/>
-    <obj-relationship name="compoundFkArray" source="CompoundPkTestEntity" target="CompoundFkTestEntity" db-relationship-path="compoundFkArray"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.compound"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="CHAR_FK_TEST">
+		<db-attribute name="FK_COL" type="CHAR" length="10"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+		<db-attribute name="PK" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="CHAR_PK_TEST">
+		<db-attribute name="OTHER_COL" type="CHAR" length="10"/>
+		<db-attribute name="PK_COL" type="CHAR" isPrimaryKey="true" isMandatory="true" length="10"/>
+	</db-entity>
+	<db-entity name="COMPOUND_FK_TEST">
+		<db-attribute name="F_KEY1" type="VARCHAR" length="20"/>
+		<db-attribute name="F_KEY2" type="VARCHAR" length="20"/>
+		<db-attribute name="NAME" type="VARCHAR" length="255"/>
+		<db-attribute name="PKEY" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="COMPOUND_PK_TEST">
+		<db-attribute name="KEY1" type="VARCHAR" isPrimaryKey="true" isMandatory="true" length="20"/>
+		<db-attribute name="KEY2" type="VARCHAR" isPrimaryKey="true" isMandatory="true" length="20"/>
+		<db-attribute name="NAME" type="VARCHAR" length="255"/>
+	</db-entity>
+	<obj-entity name="CharFkTestEntity" className="org.apache.cayenne.testdo.compound.CharFkTestEntity" dbEntityName="CHAR_FK_TEST">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="CharPkTestEntity" className="org.apache.cayenne.testdo.compound.CharPkTestEntity" dbEntityName="CHAR_PK_TEST">
+		<obj-attribute name="otherCol" type="java.lang.String" db-attribute-path="OTHER_COL"/>
+		<obj-attribute name="pkCol" type="java.lang.String" db-attribute-path="PK_COL"/>
+	</obj-entity>
+	<obj-entity name="CompoundFkTestEntity" className="org.apache.cayenne.testdo.compound.CompoundFkTestEntity" dbEntityName="COMPOUND_FK_TEST">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="CompoundPkTestEntity" className="org.apache.cayenne.testdo.compound.CompoundPkTestEntity" dbEntityName="COMPOUND_PK_TEST">
+		<obj-attribute name="key1" type="java.lang.String" db-attribute-path="KEY1"/>
+		<obj-attribute name="key2" type="java.lang.String" db-attribute-path="KEY2"/>
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<db-relationship name="toCharPK" source="CHAR_FK_TEST" target="CHAR_PK_TEST">
+		<db-attribute-pair source="FK_COL" target="PK_COL"/>
+	</db-relationship>
+	<db-relationship name="charFKs" source="CHAR_PK_TEST" target="CHAR_FK_TEST" toMany="true">
+		<db-attribute-pair source="PK_COL" target="FK_COL"/>
+	</db-relationship>
+	<db-relationship name="toCompoundPk" source="COMPOUND_FK_TEST" target="COMPOUND_PK_TEST">
+		<db-attribute-pair source="F_KEY1" target="KEY1"/>
+		<db-attribute-pair source="F_KEY2" target="KEY2"/>
+	</db-relationship>
+	<db-relationship name="compoundFkArray" source="COMPOUND_PK_TEST" target="COMPOUND_FK_TEST" toMany="true">
+		<db-attribute-pair source="KEY1" target="F_KEY1"/>
+		<db-attribute-pair source="KEY2" target="F_KEY2"/>
+	</db-relationship>
+	<obj-relationship name="toCharPK" source="CharFkTestEntity" target="CharPkTestEntity" db-relationship-path="toCharPK"/>
+	<obj-relationship name="charFKs" source="CharPkTestEntity" target="CharFkTestEntity" db-relationship-path="charFKs"/>
+	<obj-relationship name="toCompoundPk" source="CompoundFkTestEntity" target="CompoundPkTestEntity" db-relationship-path="toCompoundPk"/>
+	<obj-relationship name="compoundFkArray" source="CompoundPkTestEntity" target="CompoundFkTestEntity" db-relationship-path="compoundFkArray"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/custom-name-file.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/custom-name-file.xml b/cayenne-server/src/test/resources/custom-name-file.xml
index 867126e..29b3610 100644
--- a/cayenne-server/src/test/resources/custom-name-file.xml
+++ b/cayenne-server/src/test/resources/custom-name-file.xml
@@ -17,6 +17,6 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<domain project-version="9">
+<domain project-version="10">
 	<map name="testmap"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/date-time.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/date-time.map.xml b/cayenne-server/src/test/resources/date-time.map.xml
index b2d825d..7a9a06a 100644
--- a/cayenne-server/src/test/resources/date-time.map.xml
+++ b/cayenne-server/src/test/resources/date-time.map.xml
@@ -1,34 +1,34 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.date_time"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="CALENDAR_TEST">
-        <db-attribute name="CALENDAR_FIELD" type="TIMESTAMP"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="DATE_TEST">
-        <db-attribute name="DATE_COLUMN" type="DATE"/>
-        <db-attribute name="DATE_TEST_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="TIMESTAMP_COLUMN" type="TIMESTAMP"/>
-        <db-attribute name="TIME_COLUMN" type="TIME"/>
-    </db-entity>
-    <obj-entity name="CalendarEntity" className="org.apache.cayenne.testdo.date_time.CalendarEntity" dbEntityName="CALENDAR_TEST">
-        <obj-attribute name="calendarField" type="java.util.Calendar" db-attribute-path="CALENDAR_FIELD"/>
-    </obj-entity>
-    <obj-entity name="DateTestEntity" className="org.apache.cayenne.testdo.date_time.DateTestEntity" dbEntityName="DATE_TEST">
-        <obj-attribute name="dateColumn" type="java.util.Date" db-attribute-path="DATE_COLUMN"/>
-        <obj-attribute name="timeColumn" type="java.util.Date" db-attribute-path="TIME_COLUMN"/>
-        <obj-attribute name="timestampColumn" type="java.util.Date" db-attribute-path="TIMESTAMP_COLUMN"/>
-    </obj-entity>
-    <query name="SelectDateTest" type="SQLTemplate" root="data-map" root-name="date-time">
-        <property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
-        <property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
-        <sql><![CDATA[SELECT * FROM DATE_TEST]]></sql>
-    </query>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.date_time"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="CALENDAR_TEST">
+		<db-attribute name="CALENDAR_FIELD" type="TIMESTAMP"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="DATE_TEST">
+		<db-attribute name="DATE_COLUMN" type="DATE"/>
+		<db-attribute name="DATE_TEST_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="TIMESTAMP_COLUMN" type="TIMESTAMP"/>
+		<db-attribute name="TIME_COLUMN" type="TIME"/>
+	</db-entity>
+	<obj-entity name="CalendarEntity" className="org.apache.cayenne.testdo.date_time.CalendarEntity" dbEntityName="CALENDAR_TEST">
+		<obj-attribute name="calendarField" type="java.util.Calendar" db-attribute-path="CALENDAR_FIELD"/>
+	</obj-entity>
+	<obj-entity name="DateTestEntity" className="org.apache.cayenne.testdo.date_time.DateTestEntity" dbEntityName="DATE_TEST">
+		<obj-attribute name="dateColumn" type="java.util.Date" db-attribute-path="DATE_COLUMN"/>
+		<obj-attribute name="timeColumn" type="java.util.Date" db-attribute-path="TIME_COLUMN"/>
+		<obj-attribute name="timestampColumn" type="java.util.Date" db-attribute-path="TIMESTAMP_COLUMN"/>
+	</obj-entity>
+	<query name="SelectDateTest" type="SQLTemplate" root="data-map" root-name="date-time">
+		<property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
+		<sql><![CDATA[SELECT * FROM DATE_TEST]]></sql>
+	</query>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/delete-rules.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/delete-rules.map.xml b/cayenne-server/src/test/resources/delete-rules.map.xml
index 62f47aa..52080bf 100644
--- a/cayenne-server/src/test/resources/delete-rules.map.xml
+++ b/cayenne-server/src/test/resources/delete-rules.map.xml
@@ -1,64 +1,64 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.deleterules"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="org.apache.cayenne.testdo.deleterules"/>
-    <db-entity name="DELETE_CASCADE">
-        <db-attribute name="DELETE_CASCADE_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="DELETE_RULE_ID" type="INTEGER"/>
-        <db-attribute name="NAME" type="VARCHAR" length="200"/>
-    </db-entity>
-    <db-entity name="DELETE_DENY">
-        <db-attribute name="DELETE_DENY_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="DELETE_RULE_ID" type="INTEGER"/>
-        <db-attribute name="NAME" type="VARCHAR" length="200"/>
-    </db-entity>
-    <db-entity name="DELETE_NULLIFY">
-        <db-attribute name="DELETE_NULLIFY_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="DELETE_RULE_ID" type="INTEGER"/>
-        <db-attribute name="NAME" type="VARCHAR" length="200"/>
-    </db-entity>
-    <db-entity name="DELETE_RULE">
-        <db-attribute name="DELETE_RULE_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="200"/>
-    </db-entity>
-    <obj-entity name="DeleteCascade" className="org.apache.cayenne.testdo.deleterules.DeleteCascade" clientClassName="org.apache.cayenne.testdo.deleterules.ClientDeleteCascade" dbEntityName="DELETE_CASCADE">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="DeleteDeny" className="org.apache.cayenne.testdo.deleterules.DeleteDeny" clientClassName="org.apache.cayenne.testdo.deleterules.ClientDeleteDeny" dbEntityName="DELETE_DENY">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="DeleteNullify" className="org.apache.cayenne.testdo.deleterules.DeleteNullify" clientClassName="org.apache.cayenne.testdo.deleterules.ClientDeleteNullify" dbEntityName="DELETE_NULLIFY">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="DeleteRule" className="org.apache.cayenne.testdo.deleterules.DeleteRule" clientClassName="org.apache.cayenne.testdo.deleterules.ClientDeleteRule" dbEntityName="DELETE_RULE">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <db-relationship name="cascade" source="DELETE_CASCADE" target="DELETE_RULE" toMany="false">
-        <db-attribute-pair source="DELETE_RULE_ID" target="DELETE_RULE_ID"/>
-    </db-relationship>
-    <db-relationship name="deny" source="DELETE_DENY" target="DELETE_RULE" toMany="false">
-        <db-attribute-pair source="DELETE_RULE_ID" target="DELETE_RULE_ID"/>
-    </db-relationship>
-    <db-relationship name="nullify" source="DELETE_NULLIFY" target="DELETE_RULE" toMany="false">
-        <db-attribute-pair source="DELETE_RULE_ID" target="DELETE_RULE_ID"/>
-    </db-relationship>
-    <db-relationship name="fromCascade" source="DELETE_RULE" target="DELETE_CASCADE" toMany="true">
-        <db-attribute-pair source="DELETE_RULE_ID" target="DELETE_RULE_ID"/>
-    </db-relationship>
-    <db-relationship name="fromDeny" source="DELETE_RULE" target="DELETE_DENY" toMany="true">
-        <db-attribute-pair source="DELETE_RULE_ID" target="DELETE_RULE_ID"/>
-    </db-relationship>
-    <db-relationship name="fromNullify" source="DELETE_RULE" target="DELETE_NULLIFY" toMany="true">
-        <db-attribute-pair source="DELETE_RULE_ID" target="DELETE_RULE_ID"/>
-    </db-relationship>
-    <obj-relationship name="cascade" source="DeleteCascade" target="DeleteRule" deleteRule="Cascade" db-relationship-path="cascade"/>
-    <obj-relationship name="deny" source="DeleteDeny" target="DeleteRule" deleteRule="Deny" db-relationship-path="deny"/>
-    <obj-relationship name="nullify" source="DeleteNullify" target="DeleteRule" deleteRule="Nullify" db-relationship-path="nullify"/>
-    <obj-relationship name="fromCascade" source="DeleteRule" target="DeleteCascade" db-relationship-path="fromCascade"/>
-    <obj-relationship name="fromDeny" source="DeleteRule" target="DeleteDeny" db-relationship-path="fromDeny"/>
-    <obj-relationship name="fromNullify" source="DeleteRule" target="DeleteNullify" db-relationship-path="fromNullify"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.deleterules"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="org.apache.cayenne.testdo.deleterules"/>
+	<db-entity name="DELETE_CASCADE">
+		<db-attribute name="DELETE_CASCADE_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="DELETE_RULE_ID" type="INTEGER"/>
+		<db-attribute name="NAME" type="VARCHAR" length="200"/>
+	</db-entity>
+	<db-entity name="DELETE_DENY">
+		<db-attribute name="DELETE_DENY_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="DELETE_RULE_ID" type="INTEGER"/>
+		<db-attribute name="NAME" type="VARCHAR" length="200"/>
+	</db-entity>
+	<db-entity name="DELETE_NULLIFY">
+		<db-attribute name="DELETE_NULLIFY_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="DELETE_RULE_ID" type="INTEGER"/>
+		<db-attribute name="NAME" type="VARCHAR" length="200"/>
+	</db-entity>
+	<db-entity name="DELETE_RULE">
+		<db-attribute name="DELETE_RULE_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="200"/>
+	</db-entity>
+	<obj-entity name="DeleteCascade" className="org.apache.cayenne.testdo.deleterules.DeleteCascade" clientClassName="org.apache.cayenne.testdo.deleterules.ClientDeleteCascade" dbEntityName="DELETE_CASCADE">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="DeleteDeny" className="org.apache.cayenne.testdo.deleterules.DeleteDeny" clientClassName="org.apache.cayenne.testdo.deleterules.ClientDeleteDeny" dbEntityName="DELETE_DENY">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="DeleteNullify" className="org.apache.cayenne.testdo.deleterules.DeleteNullify" clientClassName="org.apache.cayenne.testdo.deleterules.ClientDeleteNullify" dbEntityName="DELETE_NULLIFY">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="DeleteRule" className="org.apache.cayenne.testdo.deleterules.DeleteRule" clientClassName="org.apache.cayenne.testdo.deleterules.ClientDeleteRule" dbEntityName="DELETE_RULE">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<db-relationship name="cascade" source="DELETE_CASCADE" target="DELETE_RULE">
+		<db-attribute-pair source="DELETE_RULE_ID" target="DELETE_RULE_ID"/>
+	</db-relationship>
+	<db-relationship name="deny" source="DELETE_DENY" target="DELETE_RULE">
+		<db-attribute-pair source="DELETE_RULE_ID" target="DELETE_RULE_ID"/>
+	</db-relationship>
+	<db-relationship name="nullify" source="DELETE_NULLIFY" target="DELETE_RULE">
+		<db-attribute-pair source="DELETE_RULE_ID" target="DELETE_RULE_ID"/>
+	</db-relationship>
+	<db-relationship name="fromCascade" source="DELETE_RULE" target="DELETE_CASCADE" toMany="true">
+		<db-attribute-pair source="DELETE_RULE_ID" target="DELETE_RULE_ID"/>
+	</db-relationship>
+	<db-relationship name="fromDeny" source="DELETE_RULE" target="DELETE_DENY" toMany="true">
+		<db-attribute-pair source="DELETE_RULE_ID" target="DELETE_RULE_ID"/>
+	</db-relationship>
+	<db-relationship name="fromNullify" source="DELETE_RULE" target="DELETE_NULLIFY" toMany="true">
+		<db-attribute-pair source="DELETE_RULE_ID" target="DELETE_RULE_ID"/>
+	</db-relationship>
+	<obj-relationship name="cascade" source="DeleteCascade" target="DeleteRule" deleteRule="Cascade" db-relationship-path="cascade"/>
+	<obj-relationship name="deny" source="DeleteDeny" target="DeleteRule" deleteRule="Deny" db-relationship-path="deny"/>
+	<obj-relationship name="nullify" source="DeleteNullify" target="DeleteRule" deleteRule="Nullify" db-relationship-path="nullify"/>
+	<obj-relationship name="fromCascade" source="DeleteRule" target="DeleteCascade" db-relationship-path="fromCascade"/>
+	<obj-relationship name="fromDeny" source="DeleteRule" target="DeleteDeny" db-relationship-path="fromDeny"/>
+	<obj-relationship name="fromNullify" source="DeleteRule" target="DeleteNullify" db-relationship-path="fromNullify"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/embeddable.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/embeddable.map.xml b/cayenne-server/src/test/resources/embeddable.map.xml
index 84bb4b0..10c4db6 100644
--- a/cayenne-server/src/test/resources/embeddable.map.xml
+++ b/cayenne-server/src/test/resources/embeddable.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.embeddable"/>
 	<embeddable className="org.apache.cayenne.testdo.embeddable.Embeddable1">
 		<embeddable-attribute name="embedded10" type="java.lang.String" db-attribute-name="EMBEDDED10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/empty.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/empty.map.xml b/cayenne-server/src/test/resources/empty.map.xml
index 89734f3..2ddcdd7 100644
--- a/cayenne-server/src/test/resources/empty.map.xml
+++ b/cayenne-server/src/test/resources/empty.map.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <db-entity name="EMPTY">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<db-entity name="EMPTY">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/enum.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/enum.map.xml b/cayenne-server/src/test/resources/enum.map.xml
index e4a2807..30019c9 100644
--- a/cayenne-server/src/test/resources/enum.map.xml
+++ b/cayenne-server/src/test/resources/enum.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.enum_test"/>
 	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
 	<property name="clientSupported" value="true"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/extended-type.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/extended-type.map.xml b/cayenne-server/src/test/resources/extended-type.map.xml
index 3cfea21..3241fe7 100644
--- a/cayenne-server/src/test/resources/extended-type.map.xml
+++ b/cayenne-server/src/test/resources/extended-type.map.xml
@@ -1,18 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.extended_type"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="EXTENDED_TYPE_TEST">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="200"/>
-    </db-entity>
-    <obj-entity name="ExtendedTypeEntity" className="org.apache.cayenne.testdo.extended_type.ExtendedTypeEntity" dbEntityName="EXTENDED_TYPE_TEST">
-        <obj-attribute name="name" type="org.apache.cayenne.testdo.extended_type.StringET1" db-attribute-path="NAME"/>
-    </obj-entity>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.extended_type"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="EXTENDED_TYPE_TEST">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="200"/>
+	</db-entity>
+	<obj-entity name="ExtendedTypeEntity" className="org.apache.cayenne.testdo.extended_type.ExtendedTypeEntity" dbEntityName="EXTENDED_TYPE_TEST">
+		<obj-attribute name="name" type="org.apache.cayenne.testdo.extended_type.StringET1" db-attribute-path="NAME"/>
+	</obj-entity>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/generated.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/generated.map.xml b/cayenne-server/src/test/resources/generated.map.xml
index c3ddf35..a46b4a9 100644
--- a/cayenne-server/src/test/resources/generated.map.xml
+++ b/cayenne-server/src/test/resources/generated.map.xml
@@ -1,93 +1,91 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.generated"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="GENERATED_COLUMN_COMP_KEY">
-        <db-attribute name="AUTO_PK" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="GENERATED_COLUMN" type="INTEGER" isPrimaryKey="true" isGenerated="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="100"/>
-        <db-attribute name="PROPAGATED_PK" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="GENERATED_COLUMN_COMP_M">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="100"/>
-    </db-entity>
-    <db-entity name="GENERATED_COLUMN_DEP">
-        <db-attribute name="GENERATED_COLUMN_FK" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="100"/>
-    </db-entity>
-    <db-entity name="GENERATED_COLUMN_TEST">
-        <db-attribute name="GENERATED_COLUMN" type="INTEGER" isPrimaryKey="true" isGenerated="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="250"/>
-    </db-entity>
-    <db-entity name="GENERATED_COLUMN_TEST2">
-        <db-attribute name="GENERATED_COLUMN" type="INTEGER" isPrimaryKey="true" isGenerated="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="100"/>
-    </db-entity>
-    <db-entity name="GENERATED_F1">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="GENERATED_F2">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="GENERATED_JOIN">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isGenerated="true" isMandatory="true"/>
-        <db-attribute name="ID1" type="INTEGER"/>
-        <db-attribute name="ID2" type="INTEGER"/>
-    </db-entity>
-    <obj-entity name="GeneratedColumnCompKey" className="org.apache.cayenne.testdo.generated.GeneratedColumnCompKey" dbEntityName="GENERATED_COLUMN_COMP_KEY">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="GeneratedColumnCompMaster" className="org.apache.cayenne.testdo.generated.GeneratedColumnCompMaster" dbEntityName="GENERATED_COLUMN_COMP_M">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="GeneratedColumnDep" className="org.apache.cayenne.testdo.generated.GeneratedColumnDep" dbEntityName="GENERATED_COLUMN_DEP">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="GeneratedColumnTest2" className="org.apache.cayenne.testdo.generated.GeneratedColumnTest2" dbEntityName="GENERATED_COLUMN_TEST2">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="GeneratedColumnTestEntity" className="org.apache.cayenne.testdo.generated.GeneratedColumnTestEntity" dbEntityName="GENERATED_COLUMN_TEST">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="GeneratedF1" className="org.apache.cayenne.testdo.generated.GeneratedF1" clientClassName="test.client.GeneratedF1" dbEntityName="GENERATED_F1" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
-    </obj-entity>
-    <obj-entity name="GeneratedF2" className="org.apache.cayenne.testdo.generated.GeneratedF2" clientClassName="test.client.GeneratedF2" dbEntityName="GENERATED_F2" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
-    </obj-entity>
-    <db-relationship name="toMaster" source="GENERATED_COLUMN_COMP_KEY" target="GENERATED_COLUMN_COMP_M" toMany="false">
-        <db-attribute-pair source="PROPAGATED_PK" target="ID"/>
-    </db-relationship>
-    <db-relationship name="toDetail" source="GENERATED_COLUMN_COMP_M" target="GENERATED_COLUMN_COMP_KEY" toDependentPK="true" toMany="true">
-        <db-attribute-pair source="ID" target="PROPAGATED_PK"/>
-    </db-relationship>
-    <db-relationship name="toMaster" source="GENERATED_COLUMN_DEP" target="GENERATED_COLUMN_TEST" toMany="false">
-        <db-attribute-pair source="GENERATED_COLUMN_FK" target="GENERATED_COLUMN"/>
-    </db-relationship>
-    <db-relationship name="toDep" source="GENERATED_COLUMN_TEST" target="GENERATED_COLUMN_DEP" toDependentPK="true" toMany="false">
-        <db-attribute-pair source="GENERATED_COLUMN" target="GENERATED_COLUMN_FK"/>
-    </db-relationship>
-    <db-relationship name="join" source="GENERATED_F1" target="GENERATED_JOIN" toMany="true">
-        <db-attribute-pair source="ID" target="ID1"/>
-    </db-relationship>
-    <db-relationship name="join" source="GENERATED_F2" target="GENERATED_JOIN" toMany="true">
-        <db-attribute-pair source="ID" target="ID2"/>
-    </db-relationship>
-    <db-relationship name="f1" source="GENERATED_JOIN" target="GENERATED_F1" toMany="false">
-        <db-attribute-pair source="ID1" target="ID"/>
-    </db-relationship>
-    <db-relationship name="f2" source="GENERATED_JOIN" target="GENERATED_F2" toMany="false">
-        <db-attribute-pair source="ID2" target="ID"/>
-    </db-relationship>
-    <obj-relationship name="toMaster" source="GeneratedColumnCompKey" target="GeneratedColumnCompMaster" db-relationship-path="toMaster"/>
-    <obj-relationship name="toDetail" source="GeneratedColumnCompMaster" target="GeneratedColumnCompKey" db-relationship-path="toDetail"/>
-    <obj-relationship name="toMaster" source="GeneratedColumnDep" target="GeneratedColumnTestEntity" db-relationship-path="toMaster"/>
-    <obj-relationship name="toDep" source="GeneratedColumnTestEntity" target="GeneratedColumnDep" db-relationship-path="toDep"/>
-    <obj-relationship name="f2" source="GeneratedF1" target="GeneratedF2" deleteRule="Nullify" db-relationship-path="join.f2"/>
-    <obj-relationship name="f1" source="GeneratedF2" target="GeneratedF1" deleteRule="Nullify" db-relationship-path="join.f1"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.generated"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="GENERATED_COLUMN_COMP_KEY">
+		<db-attribute name="AUTO_PK" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="GENERATED_COLUMN" type="INTEGER" isPrimaryKey="true" isGenerated="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+		<db-attribute name="PROPAGATED_PK" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="GENERATED_COLUMN_COMP_M">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+	</db-entity>
+	<db-entity name="GENERATED_COLUMN_DEP">
+		<db-attribute name="GENERATED_COLUMN_FK" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+	</db-entity>
+	<db-entity name="GENERATED_COLUMN_TEST">
+		<db-attribute name="GENERATED_COLUMN" type="INTEGER" isPrimaryKey="true" isGenerated="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="250"/>
+	</db-entity>
+	<db-entity name="GENERATED_COLUMN_TEST2">
+		<db-attribute name="GENERATED_COLUMN" type="INTEGER" isPrimaryKey="true" isGenerated="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+	</db-entity>
+	<db-entity name="GENERATED_F1">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="GENERATED_F2">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="GENERATED_JOIN">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isGenerated="true" isMandatory="true"/>
+		<db-attribute name="ID1" type="INTEGER"/>
+		<db-attribute name="ID2" type="INTEGER"/>
+	</db-entity>
+	<obj-entity name="GeneratedColumnCompKey" className="org.apache.cayenne.testdo.generated.GeneratedColumnCompKey" dbEntityName="GENERATED_COLUMN_COMP_KEY">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="GeneratedColumnCompMaster" className="org.apache.cayenne.testdo.generated.GeneratedColumnCompMaster" dbEntityName="GENERATED_COLUMN_COMP_M">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="GeneratedColumnDep" className="org.apache.cayenne.testdo.generated.GeneratedColumnDep" dbEntityName="GENERATED_COLUMN_DEP">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="GeneratedColumnTest2" className="org.apache.cayenne.testdo.generated.GeneratedColumnTest2" dbEntityName="GENERATED_COLUMN_TEST2">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="GeneratedColumnTestEntity" className="org.apache.cayenne.testdo.generated.GeneratedColumnTestEntity" dbEntityName="GENERATED_COLUMN_TEST">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="GeneratedF1" className="org.apache.cayenne.testdo.generated.GeneratedF1" clientClassName="test.client.GeneratedF1" dbEntityName="GENERATED_F1" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject"/>
+	<obj-entity name="GeneratedF2" className="org.apache.cayenne.testdo.generated.GeneratedF2" clientClassName="test.client.GeneratedF2" dbEntityName="GENERATED_F2" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject"/>
+	<db-relationship name="toMaster" source="GENERATED_COLUMN_COMP_KEY" target="GENERATED_COLUMN_COMP_M">
+		<db-attribute-pair source="PROPAGATED_PK" target="ID"/>
+	</db-relationship>
+	<db-relationship name="toDetail" source="GENERATED_COLUMN_COMP_M" target="GENERATED_COLUMN_COMP_KEY" toDependentPK="true" toMany="true">
+		<db-attribute-pair source="ID" target="PROPAGATED_PK"/>
+	</db-relationship>
+	<db-relationship name="toMaster" source="GENERATED_COLUMN_DEP" target="GENERATED_COLUMN_TEST">
+		<db-attribute-pair source="GENERATED_COLUMN_FK" target="GENERATED_COLUMN"/>
+	</db-relationship>
+	<db-relationship name="toDep" source="GENERATED_COLUMN_TEST" target="GENERATED_COLUMN_DEP" toDependentPK="true">
+		<db-attribute-pair source="GENERATED_COLUMN" target="GENERATED_COLUMN_FK"/>
+	</db-relationship>
+	<db-relationship name="join" source="GENERATED_F1" target="GENERATED_JOIN" toMany="true">
+		<db-attribute-pair source="ID" target="ID1"/>
+	</db-relationship>
+	<db-relationship name="join" source="GENERATED_F2" target="GENERATED_JOIN" toMany="true">
+		<db-attribute-pair source="ID" target="ID2"/>
+	</db-relationship>
+	<db-relationship name="f1" source="GENERATED_JOIN" target="GENERATED_F1">
+		<db-attribute-pair source="ID1" target="ID"/>
+	</db-relationship>
+	<db-relationship name="f2" source="GENERATED_JOIN" target="GENERATED_F2">
+		<db-attribute-pair source="ID2" target="ID"/>
+	</db-relationship>
+	<obj-relationship name="toMaster" source="GeneratedColumnCompKey" target="GeneratedColumnCompMaster" db-relationship-path="toMaster"/>
+	<obj-relationship name="toDetail" source="GeneratedColumnCompMaster" target="GeneratedColumnCompKey" db-relationship-path="toDetail"/>
+	<obj-relationship name="toMaster" source="GeneratedColumnDep" target="GeneratedColumnTestEntity" db-relationship-path="toMaster"/>
+	<obj-relationship name="toDep" source="GeneratedColumnTestEntity" target="GeneratedColumnDep" db-relationship-path="toDep"/>
+	<obj-relationship name="f2" source="GeneratedF1" target="GeneratedF2" deleteRule="Nullify" db-relationship-path="join.f2"/>
+	<obj-relationship name="f1" source="GeneratedF2" target="GeneratedF1" deleteRule="Nullify" db-relationship-path="join.f1"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/generic.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/generic.map.xml b/cayenne-server/src/test/resources/generic.map.xml
index a95bbcc..eace9e0 100644
--- a/cayenne-server/src/test/resources/generic.map.xml
+++ b/cayenne-server/src/test/resources/generic.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.generic"/>
 	<db-entity name="GENERIC1">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
@@ -22,7 +22,7 @@
 	<db-relationship name="generic2s" source="GENERIC1" target="GENERIC2" toMany="true">
 		<db-attribute-pair source="ID" target="GENERIC1_ID"/>
 	</db-relationship>
-	<db-relationship name="toGeneric1" source="GENERIC2" target="GENERIC1" toMany="false">
+	<db-relationship name="toGeneric1" source="GENERIC2" target="GENERIC1">
 		<db-attribute-pair source="GENERIC1_ID" target="ID"/>
 	</db-relationship>
 	<obj-relationship name="generic2s" source="Generic1" target="Generic2" deleteRule="Cascade" db-relationship-path="generic2s"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/inheritance-single-table1.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/inheritance-single-table1.map.xml b/cayenne-server/src/test/resources/inheritance-single-table1.map.xml
index 144e407..8b453a4 100644
--- a/cayenne-server/src/test/resources/inheritance-single-table1.map.xml
+++ b/cayenne-server/src/test/resources/inheritance-single-table1.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.inheritance_flat"/>
 	<db-entity name="GROUP_MEMBERS">
 		<db-attribute name="group_id" type="BIGINT" isMandatory="true"/>
@@ -47,28 +47,28 @@
 		<obj-attribute name="id" type="java.lang.Long" db-attribute-path="id"/>
 		<obj-attribute name="nickname" type="java.lang.String" db-attribute-path="nickname"/>
 	</obj-entity>
-	<db-relationship name="group" source="GROUP_MEMBERS" target="ROLES" toMany="false">
+	<db-relationship name="group" source="GROUP_MEMBERS" target="ROLES">
 		<db-attribute-pair source="group_id" target="id"/>
 	</db-relationship>
-	<db-relationship name="role" source="GROUP_MEMBERS" target="ROLES" toMany="false">
+	<db-relationship name="role" source="GROUP_MEMBERS" target="ROLES">
 		<db-attribute-pair source="role_id" target="id"/>
 	</db-relationship>
-	<db-relationship name="group" source="GROUP_PROPERTIES" target="ROLES" toMany="false">
+	<db-relationship name="group" source="GROUP_PROPERTIES" target="ROLES">
 		<db-attribute-pair source="id" target="id"/>
 	</db-relationship>
 	<db-relationship name="group_members" source="ROLES" target="GROUP_MEMBERS" toMany="true">
 		<db-attribute-pair source="id" target="group_id"/>
 	</db-relationship>
-	<db-relationship name="group_properties" source="ROLES" target="GROUP_PROPERTIES" toDependentPK="true" toMany="false">
+	<db-relationship name="group_properties" source="ROLES" target="GROUP_PROPERTIES" toDependentPK="true">
 		<db-attribute-pair source="id" target="id"/>
 	</db-relationship>
 	<db-relationship name="role_groups" source="ROLES" target="GROUP_MEMBERS" toMany="true">
 		<db-attribute-pair source="id" target="role_id"/>
 	</db-relationship>
-	<db-relationship name="user_properties" source="ROLES" target="USER_PROPERTIES" toDependentPK="true" toMany="false">
+	<db-relationship name="user_properties" source="ROLES" target="USER_PROPERTIES" toDependentPK="true">
 		<db-attribute-pair source="id" target="id"/>
 	</db-relationship>
-	<db-relationship name="user" source="USER_PROPERTIES" target="ROLES" toMany="false">
+	<db-relationship name="user" source="USER_PROPERTIES" target="ROLES">
 		<db-attribute-pair source="id" target="id"/>
 	</db-relationship>
 	<obj-relationship name="groupMembers" source="Group" target="Role" deleteRule="Nullify" db-relationship-path="group_members.role"/>


[02/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - new XML loader for DataMap - new project version - updated test projects

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/ObjEntityHandlerTest.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/ObjEntityHandlerTest.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/ObjEntityHandlerTest.xml
new file mode 100644
index 0000000..3547aa6
--- /dev/null
+++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/ObjEntityHandlerTest.xml
@@ -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.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<obj-entity name="ArtistCallback" className="org.apache.cayenne.testdo.testmap.ArtistCallback" dbEntityName="ARTIST_CT"
+            abstract="true" superEntityName="Artist" superClassName="super.class" clientClassName="client.class" clientSuperClassName="client.super.class"
+            lock-type="optimistic" readOnly="true" serverOnly="true">
+    <embedded-attribute type="org.apache.cayenne.testdo.embeddable.Embeddable1" name="embeddable1">
+        <embeddable-attribute-override db-attribute-path="test.path" name="test"/>
+    </embedded-attribute>
+    <obj-attribute name="artistName" type="java.lang.String" db-attribute-path="NAME" lock="true"/>
+    <obj-attribute name="dateOfBirth" type="java.util.Date" />
+    <attribute-override name="name" type="int" db-attribute-path="parent.child.name"/>
+
+    <post-add method-name="postAddEntityObjEntity"/>
+    <pre-persist method-name="prePersistEntityObjEntity"/>
+    <post-persist method-name="postPersistEntityObjEntity"/>
+    <pre-update method-name="preUpdateEntityObjEntity"/>
+    <post-update method-name="postUpdateEntityObjEntity"/>
+    <pre-remove method-name="preRemoveEntityObjEntity"/>
+    <post-remove method-name="postRemoveEntityObjEntity"/>
+    <post-load method-name="postLoadEntityObjEntity"/>
+</obj-entity>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/ObjRelationshipHandlerTest.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/ObjRelationshipHandlerTest.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/ObjRelationshipHandlerTest.xml
new file mode 100644
index 0000000..a6255f5
--- /dev/null
+++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/ObjRelationshipHandlerTest.xml
@@ -0,0 +1,20 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~   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.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<obj-relationship name="artistArray" source="ArtGroup" target="Artist" collection-type="java.util.Map" map-key="artistName" deleteRule="Cascade" db-relationship-path="artistGroupArray" lock="true"/>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig1.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig1.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig1.xml
new file mode 100644
index 0000000..0171ef2
--- /dev/null
+++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig1.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain project-version="10">
+	
+</domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig2.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig2.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig2.xml
new file mode 100644
index 0000000..8d841a5
--- /dev/null
+++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig2.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain project-version="10">
+	<map name="testConfigMap2" location="testConfigMap2.map.xml"/>
+</domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig3.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig3.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig3.xml
new file mode 100644
index 0000000..71f687a
--- /dev/null
+++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/cayenne-testConfig3.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain project-version="10">
+	<map name="testConfigMap3_1" location="testConfigMap3_1.map.xml" />
+	<map name="testConfigMap3_2" location="testConfigMap3_2.map.xml" />
+
+	<node name="testConfigNode3" adapter="org.example.test.Adapter"
+		factory="org.example.test.DataSourceFactory" schema-update-strategy="org.example.test.SchemaUpdateStartegy">
+		<map-ref name="testConfigMap3_2" />
+		<data-source>
+			<connectionPool min="1" max="1" />
+			<login />
+		</data-source>
+	</node>
+</domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap2.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap2.map.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap2.map.xml
new file mode 100644
index 0000000..9adb762
--- /dev/null
+++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap2.map.xml
@@ -0,0 +1,26 @@
+<?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/10/modelMap"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	project-version="10">
+
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap3_1.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap3_1.map.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap3_1.map.xml
new file mode 100644
index 0000000..9adb762
--- /dev/null
+++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap3_1.map.xml
@@ -0,0 +1,26 @@
+<?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/10/modelMap"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	project-version="10">
+
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap3_2.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap3_2.map.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap3_2.map.xml
new file mode 100644
index 0000000..9adb762
--- /dev/null
+++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap3_2.map.xml
@@ -0,0 +1,26 @@
+<?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/10/modelMap"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	project-version="10">
+
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap4.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap4.map.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap4.map.xml
new file mode 100644
index 0000000..71c2d15
--- /dev/null
+++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/testConfigMap4.map.xml
@@ -0,0 +1,314 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.testmap"/>
+	<property name="defaultCatalog" value="TEST_CATALOG"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<embeddable className="org.apache.cayenne.testdo.Embeddable">
+		<embeddable-attribute name="test" type="int" db-attribute-name="TEST"/>
+	</embeddable>
+	<procedure name="cayenne_tst_out_proc" returningValue="true">
+		<procedure-parameter name="in_param" type="INTEGER" direction="in"/>
+		<procedure-parameter name="out_param" type="INTEGER" direction="out"/>
+	</procedure>
+	<procedure name="cayenne_tst_select_proc">
+		<procedure-parameter name="aName" type="VARCHAR" length="254" direction="in"/>
+		<procedure-parameter name="paintingPrice" type="INTEGER" direction="in"/>
+	</procedure>
+	<procedure name="cayenne_tst_upd_proc">
+		<procedure-parameter name="paintingPrice" type="INTEGER" direction="in"/>
+	</procedure>
+	<procedure name="cayenne_tst_upd_proc2"/>
+	<db-entity name="ARTGROUP">
+		<db-attribute name="GROUP_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" isMandatory="true" length="100"/>
+		<db-attribute name="PARENT_GROUP_ID" type="INTEGER"/>
+		<qualifier><![CDATA[name = "test"]]></qualifier>
+	</db-entity>
+	<db-entity name="ARTIST">
+		<db-attribute name="ARTIST_ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="ARTIST_NAME" type="CHAR" isMandatory="true" length="254"/>
+		<db-attribute name="DATE_OF_BIRTH" type="DATE"/>
+	</db-entity>
+	<db-entity name="ARTIST_CT">
+		<db-attribute name="ARTIST_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="ARTIST_NAME" type="CHAR" isMandatory="true" length="254"/>
+		<db-attribute name="DATE_OF_BIRTH" type="DATE"/>
+	</db-entity>
+	<db-entity name="ARTIST_EXHIBIT">
+		<db-attribute name="ARTIST_ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="EXHIBIT_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="ARTIST_GROUP">
+		<db-attribute name="ARTIST_ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="GROUP_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="EXHIBIT">
+		<db-attribute name="CLOSING_DATE" type="TIMESTAMP" isMandatory="true"/>
+		<db-attribute name="EXHIBIT_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="GALLERY_ID" type="INTEGER" isMandatory="true"/>
+		<db-attribute name="OPENING_DATE" type="TIMESTAMP" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="GALLERY">
+		<db-attribute name="GALLERY_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="GALLERY_NAME" type="VARCHAR" isMandatory="true" length="100"/>
+		<db-key-generator>
+			<db-generator-type>ORACLE</db-generator-type>
+			<db-generator-name>gallery_seq</db-generator-name>
+			<db-key-cache-size>20</db-key-cache-size>
+		</db-key-generator>
+	</db-entity>
+	<db-entity name="GENERATED_COLUMN">
+		<db-attribute name="GENERATED_COLUMN" type="INTEGER" isPrimaryKey="true" isGenerated="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="250"/>
+	</db-entity>
+	<db-entity name="NULL_TEST">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isGenerated="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+	</db-entity>
+	<db-entity name="PAINTING">
+		<db-attribute name="ARTIST_ID" type="BIGINT"/>
+		<db-attribute name="ESTIMATED_PRICE" type="DECIMAL" length="10" scale="2"/>
+		<db-attribute name="GALLERY_ID" type="INTEGER"/>
+		<db-attribute name="PAINTING_DESCRIPTION" type="VARCHAR" length="255"/>
+		<db-attribute name="PAINTING_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="PAINTING_TITLE" type="VARCHAR" isMandatory="true" length="255"/>
+	</db-entity>
+	<db-entity name="PAINTING1">
+		<db-attribute name="ARTIST_ID" type="BIGINT"/>
+		<db-attribute name="ESTIMATED_PRICE" type="DECIMAL" length="10" scale="2"/>
+		<db-attribute name="GALLERY_ID" type="INTEGER"/>
+		<db-attribute name="PAINTING_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="PAINTING_TITLE" type="VARCHAR" isMandatory="true" length="255"/>
+	</db-entity>
+	<db-entity name="PAINTING_INFO">
+		<db-attribute name="IMAGE_BLOB" type="LONGVARBINARY"/>
+		<db-attribute name="PAINTING_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="TEXT_REVIEW" type="LONGVARCHAR"/>
+	</db-entity>
+	<obj-entity name="ArtGroup" className="org.apache.cayenne.testdo.testmap.ArtGroup" dbEntityName="ARTGROUP">
+		<embedded-attribute name="test" type="org.apache.cayenne.testdo.Embeddable">
+			<embeddable-attribute-override name="test" db-attribute-path="NAME"/>
+		</embedded-attribute>
+	</obj-entity>
+	<obj-entity name="Artist" className="org.apache.cayenne.testdo.testmap.Artist" dbEntityName="ARTIST">
+		<obj-attribute name="artistName" type="java.lang.String" db-attribute-path="ARTIST_NAME"/>
+		<obj-attribute name="dateOfBirth" type="java.util.Date" db-attribute-path="DATE_OF_BIRTH"/>
+	</obj-entity>
+	<obj-entity name="ArtistCallback" className="org.apache.cayenne.testdo.testmap.ArtistCallback" lock-type="optimistic" dbEntityName="ARTIST_CT">
+		<obj-attribute name="artistName" type="java.lang.String"/>
+		<obj-attribute name="dateOfBirth" type="java.util.Date"/>
+		<post-add method-name="prePersistEntityObjEntity"/>
+		<post-persist method-name="postPersistEntityObjEntity"/>
+		<pre-update method-name="preUpdateEntityObjEntity"/>
+		<post-update method-name="postUpdateEntityObjEntity"/>
+		<pre-remove method-name="preRemoveEntityObjEntity"/>
+		<post-remove method-name="postRemoveEntityObjEntity"/>
+		<post-load method-name="postLoadEntityObjEntity"/>
+	</obj-entity>
+	<obj-entity name="ArtistExhibit" className="org.apache.cayenne.testdo.testmap.ArtistExhibit" dbEntityName="ARTIST_EXHIBIT"/>
+	<obj-entity name="CompoundPainting" className="org.apache.cayenne.testdo.testmap.CompoundPainting" dbEntityName="PAINTING">
+		<obj-attribute name="artistName" type="java.lang.String" db-attribute-path="toArtist.ARTIST_NAME"/>
+		<obj-attribute name="estimatedPrice" type="java.math.BigDecimal" db-attribute-path="ESTIMATED_PRICE"/>
+		<obj-attribute name="galleryName" type="java.lang.String" db-attribute-path="toGallery.GALLERY_NAME"/>
+		<obj-attribute name="paintingTitle" type="java.lang.String" db-attribute-path="PAINTING_TITLE"/>
+		<obj-attribute name="textReview" type="java.lang.String" db-attribute-path="toPaintingInfo.TEXT_REVIEW"/>
+	</obj-entity>
+	<obj-entity name="CompoundPaintingLongNames" className="org.apache.cayenne.testdo.testmap.CompoundPaintingLongNames" clientClassName="test.client.CompoundPaintingLongNames" dbEntityName="PAINTING" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
+		<obj-attribute name="artistLongName" type="java.lang.String" db-attribute-path="toArtist.ARTIST_NAME"/>
+		<obj-attribute name="estimatedPrice" type="java.math.BigDecimal" db-attribute-path="ESTIMATED_PRICE"/>
+		<obj-attribute name="galleryLongName" type="java.lang.String" db-attribute-path="toGallery.GALLERY_NAME"/>
+		<obj-attribute name="paintingDescription" type="java.lang.String" db-attribute-path="PAINTING_DESCRIPTION"/>
+		<obj-attribute name="paintingTitle" type="java.lang.String" db-attribute-path="PAINTING_TITLE"/>
+		<obj-attribute name="textLongReview" type="java.lang.String" db-attribute-path="toPaintingInfo.TEXT_REVIEW"/>
+	</obj-entity>
+	<obj-entity name="Exhibit" className="org.apache.cayenne.testdo.testmap.Exhibit" dbEntityName="EXHIBIT">
+		<obj-attribute name="closingDate" type="java.util.Date" db-attribute-path="CLOSING_DATE"/>
+		<obj-attribute name="openingDate" type="java.util.Date" db-attribute-path="OPENING_DATE"/>
+	</obj-entity>
+	<obj-entity name="Gallery" className="org.apache.cayenne.testdo.testmap.Gallery" dbEntityName="GALLERY">
+		<qualifier><![CDATA[galleryName = "test"]]></qualifier>
+		<obj-attribute name="galleryName" type="java.lang.String" db-attribute-path="GALLERY_NAME"/>
+	</obj-entity>
+	<obj-entity name="MeaningfulGeneratedColumnTestEntity" className="org.apache.cayenne.testdo.testmap.MeaningfulGeneratedColumnTestEntity" dbEntityName="GENERATED_COLUMN">
+		<obj-attribute name="generatedColumn" type="java.lang.Integer" db-attribute-path="GENERATED_COLUMN" />
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="NullTestEntity" className="org.apache.cayenne.testdo.testmap.NullTestEntity" dbEntityName="NULL_TEST">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="Painting" className="org.apache.cayenne.testdo.testmap.Painting" dbEntityName="PAINTING" superClassName="org.apache.cayenne.testdo.testmap.ArtDataObject">
+		<obj-attribute name="estimatedPrice" type="java.math.BigDecimal" db-attribute-path="ESTIMATED_PRICE"/>
+		<obj-attribute name="paintingDescription" type="java.lang.String" db-attribute-path="PAINTING_DESCRIPTION"/>
+		<obj-attribute name="paintingTitle" type="java.lang.String" db-attribute-path="PAINTING_TITLE"/>
+	</obj-entity>
+	<obj-entity name="Painting1" className="org.apache.cayenne.testdo.testmap.Painting1" dbEntityName="PAINTING1">
+		<obj-attribute name="estimatedPrice" type="java.math.BigDecimal" db-attribute-path="ESTIMATED_PRICE"/>
+		<obj-attribute name="paintingTitle" type="java.lang.String" db-attribute-path="PAINTING_TITLE"/>
+	</obj-entity>
+	<obj-entity name="PaintingInfo" className="org.apache.cayenne.testdo.testmap.PaintingInfo" dbEntityName="PAINTING_INFO">
+		<obj-attribute name="imageBlob" type="byte[]" db-attribute-path="IMAGE_BLOB"/>
+		<obj-attribute name="textReview" type="java.lang.String" db-attribute-path="TEXT_REVIEW"/>
+	</obj-entity>
+	<obj-entity name="ROArtist" className="org.apache.cayenne.testdo.testmap.ROArtist" readOnly="true" dbEntityName="ARTIST">
+		<obj-attribute name="artistName" type="java.lang.String" db-attribute-path="ARTIST_NAME"/>
+		<obj-attribute name="dateOfBirth" type="java.sql.Date" db-attribute-path="DATE_OF_BIRTH"/>
+	</obj-entity>
+	<obj-entity name="ROPainting" className="org.apache.cayenne.testdo.testmap.ROPainting" readOnly="true" dbEntityName="PAINTING">
+		<obj-attribute name="estimatedPrice" type="java.math.BigDecimal" db-attribute-path="ESTIMATED_PRICE"/>
+		<obj-attribute name="paintingTitle" type="java.lang.String" db-attribute-path="PAINTING_TITLE"/>
+	</obj-entity>
+	<obj-entity name="RWCompoundPainting" className="org.apache.cayenne.testdo.testmap.RWCompoundPainting" dbEntityName="PAINTING">
+		<obj-attribute name="estimatedPrice" type="java.math.BigDecimal" db-attribute-path="ESTIMATED_PRICE"/>
+		<obj-attribute name="paintingTitle" type="java.lang.String" db-attribute-path="PAINTING_TITLE"/>
+		<obj-attribute name="textReview" type="java.lang.String" db-attribute-path="toPaintingInfo.TEXT_REVIEW"/>
+	</obj-entity>
+	<obj-entity name="SubPainting" superEntityName="Painting" abstract="true" serverOnly="true" className="org.apache.cayenne.testdo.testmap.SubPainting" lock-type="optimistic">
+		<attribute-override name="paintingTitle" db-attribute-path="PAINTING_TITLE"/>
+	</obj-entity>
+	<db-relationship name="artistGroupArray" source="ARTGROUP" target="ARTIST_GROUP" toMany="true">
+		<db-attribute-pair source="GROUP_ID" target="GROUP_ID"/>
+	</db-relationship>
+	<db-relationship name="toChildGroups" source="ARTGROUP" target="ARTGROUP" toMany="true">
+		<db-attribute-pair source="GROUP_ID" target="PARENT_GROUP_ID"/>
+	</db-relationship>
+	<db-relationship name="toParentGroup" source="ARTGROUP" target="ARTGROUP">
+		<db-attribute-pair source="PARENT_GROUP_ID" target="GROUP_ID"/>
+	</db-relationship>
+	<db-relationship name="artistExhibitArray" source="ARTIST" target="ARTIST_EXHIBIT" toDependentPK="true" toMany="true">
+		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
+	</db-relationship>
+	<db-relationship name="artistGroupArray" source="ARTIST" target="ARTIST_GROUP" toMany="true">
+		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
+	</db-relationship>
+	<db-relationship name="paintingArray" source="ARTIST" target="PAINTING" toMany="true">
+		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
+	</db-relationship>
+	<db-relationship name="toArtist" source="ARTIST_EXHIBIT" target="ARTIST">
+		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
+	</db-relationship>
+	<db-relationship name="toExhibit" source="ARTIST_EXHIBIT" target="EXHIBIT">
+		<db-attribute-pair source="EXHIBIT_ID" target="EXHIBIT_ID"/>
+	</db-relationship>
+	<db-relationship name="toArtist" source="ARTIST_GROUP" target="ARTIST">
+		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
+	</db-relationship>
+	<db-relationship name="toGroup" source="ARTIST_GROUP" target="ARTGROUP">
+		<db-attribute-pair source="GROUP_ID" target="GROUP_ID"/>
+	</db-relationship>
+	<db-relationship name="artistExhibitArray" source="EXHIBIT" target="ARTIST_EXHIBIT" toDependentPK="true" toMany="true">
+		<db-attribute-pair source="EXHIBIT_ID" target="EXHIBIT_ID"/>
+	</db-relationship>
+	<db-relationship name="toGallery" source="EXHIBIT" target="GALLERY">
+		<db-attribute-pair source="GALLERY_ID" target="GALLERY_ID"/>
+	</db-relationship>
+	<db-relationship name="exhibitArray" source="GALLERY" target="EXHIBIT" toMany="true">
+		<db-attribute-pair source="GALLERY_ID" target="GALLERY_ID"/>
+	</db-relationship>
+	<db-relationship name="paintingArray" source="GALLERY" target="PAINTING" toMany="true">
+		<db-attribute-pair source="GALLERY_ID" target="GALLERY_ID"/>
+	</db-relationship>
+	<db-relationship name="toArtist" source="PAINTING" target="ARTIST">
+		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
+	</db-relationship>
+	<db-relationship name="toGallery" source="PAINTING" target="GALLERY">
+		<db-attribute-pair source="GALLERY_ID" target="GALLERY_ID"/>
+	</db-relationship>
+	<db-relationship name="toPaintingInfo" source="PAINTING" target="PAINTING_INFO" toDependentPK="true">
+		<db-attribute-pair source="PAINTING_ID" target="PAINTING_ID"/>
+	</db-relationship>
+	<db-relationship name="toArtist" source="PAINTING1" target="ARTIST">
+		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
+	</db-relationship>
+	<db-relationship name="painting" source="PAINTING_INFO" target="PAINTING">
+		<db-attribute-pair source="PAINTING_ID" target="PAINTING_ID"/>
+	</db-relationship>
+	<obj-relationship name="artistArray" source="ArtGroup" target="Artist" collection-type="java.util.Map" lock="true" deleteRule="Cascade" db-relationship-path="artistGroupArray.toArtist">
+		<info:property xmlns:info="http://cayenne.apache.org/schema/10/info" name="comment" value="artistGroupArray.toArtist"/>
+	</obj-relationship>
+	<obj-relationship name="childGroupsArray" source="ArtGroup" target="ArtGroup" deleteRule="Nullify" db-relationship-path="toChildGroups"/>
+	<obj-relationship name="toParentGroup" source="ArtGroup" target="ArtGroup" deleteRule="Nullify" db-relationship-path="toParentGroup"/>
+	<obj-relationship name="artistExhibitArray" source="Artist" target="ArtistExhibit" deleteRule="Cascade" db-relationship-path="artistExhibitArray"/>
+	<obj-relationship name="groupArray" source="Artist" target="ArtGroup" deleteRule="Cascade" db-relationship-path="artistGroupArray.toGroup"/>
+	<obj-relationship name="paintingArray" source="Artist" target="Painting" deleteRule="Cascade" db-relationship-path="paintingArray"/>
+	<obj-relationship name="toArtist" source="ArtistExhibit" target="Artist" deleteRule="Nullify" db-relationship-path="toArtist"/>
+	<obj-relationship name="toExhibit" source="ArtistExhibit" target="Exhibit" deleteRule="Nullify" db-relationship-path="toExhibit"/>
+	<obj-relationship name="toArtist" source="CompoundPainting" target="Artist" deleteRule="Nullify" db-relationship-path="toArtist"/>
+	<obj-relationship name="toGallery" source="CompoundPainting" target="Gallery" deleteRule="Nullify" db-relationship-path="toGallery"/>
+	<obj-relationship name="toPaintingInfo" source="CompoundPainting" target="PaintingInfo" deleteRule="Cascade" db-relationship-path="toPaintingInfo"/>
+	<obj-relationship name="toArtist" source="CompoundPaintingLongNames" target="Artist" deleteRule="Nullify" db-relationship-path="toArtist"/>
+	<obj-relationship name="toArtist1" source="CompoundPaintingLongNames" target="ROArtist" deleteRule="Nullify" db-relationship-path="toArtist"/>
+	<obj-relationship name="toGallery" source="CompoundPaintingLongNames" target="Gallery" deleteRule="Nullify" db-relationship-path="toGallery"/>
+	<obj-relationship name="toPaintingInfo" source="CompoundPaintingLongNames" target="PaintingInfo" deleteRule="Nullify" db-relationship-path="toPaintingInfo"/>
+	<obj-relationship name="artistExhibitArray" source="Exhibit" target="ArtistExhibit" deleteRule="Cascade" db-relationship-path="artistExhibitArray"/>
+	<obj-relationship name="toGallery" source="Exhibit" target="Gallery" deleteRule="Nullify" db-relationship-path="toGallery"/>
+	<obj-relationship name="exhibitArray" source="Gallery" target="Exhibit" deleteRule="Cascade" db-relationship-path="exhibitArray"/>
+	<obj-relationship name="paintingArray" source="Gallery" target="Painting" deleteRule="Deny" db-relationship-path="paintingArray"/>
+	<obj-relationship name="toArtist" source="Painting" target="Artist" deleteRule="Nullify" db-relationship-path="toArtist"/>
+	<obj-relationship name="toGallery" source="Painting" target="Gallery" deleteRule="Nullify" db-relationship-path="toGallery"/>
+	<obj-relationship name="toPaintingInfo" source="Painting" target="PaintingInfo" deleteRule="Cascade" db-relationship-path="toPaintingInfo"/>
+	<obj-relationship name="toArtist" source="Painting1" target="Artist" deleteRule="Nullify" db-relationship-path="toArtist"/>
+	<obj-relationship name="painting" source="PaintingInfo" target="Painting" deleteRule="Nullify" db-relationship-path="painting"/>
+	<obj-relationship name="paintingArray" source="ROArtist" target="Painting" deleteRule="Deny" db-relationship-path="paintingArray"/>
+	<obj-relationship name="toArtist" source="ROPainting" target="Artist" deleteRule="Nullify" db-relationship-path="toArtist"/>
+	<query name="EjbqlQueryTest" type="EJBQLQuery">
+		<property name="cayenne.GenericSelectQuery.cacheStrategy" value="SHARED_CACHE"/>
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
+		<ejbql><![CDATA[select a from Artist a]]></ejbql>
+	</query>
+	<query name="NonSelectingQuery" type="SQLTemplate" root="data-map" root-name="testConfigMap4">
+		<property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
+		<sql><![CDATA[INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ESTIMATED_PRICE)
+VALUES (512, 'No Painting Like This', 12.5)]]></sql>
+		<sql adapter-class="org.apache.cayenne.dba.db2.DB2Adapter"><![CDATA[INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ESTIMATED_PRICE) VALUES (512, 'No Painting Like This', 12.5)]]></sql>
+	</query>
+	<query name="ObjectQuery" type="SelectQuery" root="obj-entity" root-name="Painting">
+		<qualifier><![CDATA[toArtist = $artist]]></qualifier>
+		<ordering><![CDATA[paintingTitle]]></ordering>
+	</query>
+	<query name="ParameterizedNonSelectingQuery" type="SQLTemplate" root="data-map" root-name="testConfigMap4">
+		<sql><![CDATA[INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ESTIMATED_PRICE)
+VALUES (#bind($id), #bind($title), #bind($price))]]></sql>
+		<sql adapter-class="org.apache.cayenne.dba.db2.DB2Adapter"><![CDATA[INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ESTIMATED_PRICE) values (#bind($id), #bind($title), #bind($price))]]></sql>
+	</query>
+	<query name="ParameterizedQueryWithLocalCache" type="SelectQuery" root="obj-entity" root-name="Artist">
+		<property name="cayenne.GenericSelectQuery.cacheStrategy" value="LOCAL_CACHE"/>
+		<qualifier><![CDATA[artistName like $name]]></qualifier>
+	</query>
+	<query name="ParameterizedQueryWithSharedCache" type="SelectQuery" root="obj-entity" root-name="Artist">
+		<property name="cayenne.GenericSelectQuery.cacheStrategy" value="SHARED_CACHE"/>
+		<qualifier><![CDATA[artistName like $name]]></qualifier>
+	</query>
+	<query name="ProcedureQuery" type="ProcedureQuery" root="procedure" root-name="cayenne_tst_select_proc" result-entity="Artist"/>
+	<query name="QueryWithLocalCache" type="SelectQuery" root="obj-entity" root-name="Artist">
+		<property name="cayenne.GenericSelectQuery.cacheStrategy" value="LOCAL_CACHE"/>
+	</query>
+	<query name="QueryWithOrdering" type="SelectQuery" root="obj-entity" root-name="Artist">
+		<ordering descending="true" ignore-case="true"><![CDATA[artistName]]></ordering>
+		<ordering><![CDATA[dateOfBirth]]></ordering>
+	</query>
+	<query name="QueryWithPrefetch" type="SelectQuery" root="obj-entity" root-name="Gallery">
+		<prefetch>paintingArray</prefetch>
+	</query>
+	<query name="QueryWithQualifier" type="SelectQuery" root="obj-entity" root-name="Artist">
+		<qualifier><![CDATA[artistName = $param1]]></qualifier>
+	</query>
+	<query name="QueryWithSharedCache" type="SelectQuery" root="obj-entity" root-name="Artist">
+		<property name="cayenne.GenericSelectQuery.cacheStrategy" value="SHARED_CACHE"/>
+	</query>
+	<query name="SelectTestLower" type="SQLTemplate" root="data-map" root-name="testConfigMap4">
+		<property name="cayenne.SQLTemplate.columnNameCapitalization" value="LOWER"/>
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
+		<sql><![CDATA[select * from ARTIST]]></sql>
+	</query>
+	<query name="SelectTestUpper" type="SQLTemplate" root="data-map" root-name="testConfigMap4">
+		<property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
+		<sql><![CDATA[select * from ARTIST]]></sql>
+	</query>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/people.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/people.map.xml b/cayenne-server/src/test/resources/people.map.xml
index c62eeed..c3b7d97 100644
--- a/cayenne-server/src/test/resources/people.map.xml
+++ b/cayenne-server/src/test/resources/people.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.inheritance_people"/>
 	<db-entity name="ADDRESS">
 		<db-attribute name="ADDRESS_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
@@ -61,7 +61,7 @@
 	<obj-entity name="PersonNotes" className="org.apache.cayenne.testdo.inheritance_people.PersonNotes" dbEntityName="PERSON_NOTES">
 		<obj-attribute name="notes" type="java.lang.String" db-attribute-path="NOTES"/>
 	</obj-entity>
-	<db-relationship name="toPerson" source="ADDRESS" target="PERSON" toMany="false">
+	<db-relationship name="toPerson" source="ADDRESS" target="PERSON">
 		<db-attribute-pair source="PERSON_ID" target="PERSON_ID"/>
 	</db-relationship>
 	<db-relationship name="representatives" source="CLIENT_COMPANY" target="PERSON" toMany="true">
@@ -70,7 +70,7 @@
 	<db-relationship name="employees" source="DEPARTMENT" target="PERSON" toMany="true">
 		<db-attribute-pair source="DEPARTMENT_ID" target="DEPARTMENT_ID"/>
 	</db-relationship>
-	<db-relationship name="toManager" source="DEPARTMENT" target="PERSON" toMany="false">
+	<db-relationship name="toManager" source="DEPARTMENT" target="PERSON">
 		<db-attribute-pair source="MANAGER_ID" target="PERSON_ID"/>
 	</db-relationship>
 	<db-relationship name="employeeAddresses" source="PERSON" target="ADDRESS" toMany="true">
@@ -82,13 +82,13 @@
 	<db-relationship name="notes" source="PERSON" target="PERSON_NOTES" toMany="true">
 		<db-attribute-pair source="PERSON_ID" target="PERSON_ID"/>
 	</db-relationship>
-	<db-relationship name="toClientCompany" source="PERSON" target="CLIENT_COMPANY" toMany="false">
+	<db-relationship name="toClientCompany" source="PERSON" target="CLIENT_COMPANY">
 		<db-attribute-pair source="CLIENT_COMPANY_ID" target="CLIENT_COMPANY_ID"/>
 	</db-relationship>
-	<db-relationship name="toDepartment" source="PERSON" target="DEPARTMENT" toMany="false">
+	<db-relationship name="toDepartment" source="PERSON" target="DEPARTMENT">
 		<db-attribute-pair source="DEPARTMENT_ID" target="DEPARTMENT_ID"/>
 	</db-relationship>
-	<db-relationship name="person" source="PERSON_NOTES" target="PERSON" toMany="false">
+	<db-relationship name="person" source="PERSON_NOTES" target="PERSON">
 		<db-attribute-pair source="PERSON_ID" target="PERSON_ID"/>
 	</db-relationship>
 	<obj-relationship name="notes" source="AbstractPerson" target="PersonNotes" deleteRule="Nullify" db-relationship-path="notes"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/primitive.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/primitive.map.xml b/cayenne-server/src/test/resources/primitive.map.xml
index d5e83dc..8173637 100644
--- a/cayenne-server/src/test/resources/primitive.map.xml
+++ b/cayenne-server/src/test/resources/primitive.map.xml
@@ -1,20 +1,20 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.primitive"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="PRIMITIVES_TEST">
-        <db-attribute name="BOOLEAN_COLUMN" type="BOOLEAN"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="INT_COLUMN" type="INTEGER"/>
-    </db-entity>
-    <obj-entity name="PrimitivesTestEntity" className="org.apache.cayenne.testdo.primitive.PrimitivesTestEntity" dbEntityName="PRIMITIVES_TEST">
-        <obj-attribute name="booleanColumn" type="boolean" db-attribute-path="BOOLEAN_COLUMN"/>
-        <obj-attribute name="intColumn" type="int" db-attribute-path="INT_COLUMN"/>
-    </obj-entity>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.primitive"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="PRIMITIVES_TEST">
+		<db-attribute name="BOOLEAN_COLUMN" type="BOOLEAN"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="INT_COLUMN" type="INTEGER"/>
+	</db-entity>
+	<obj-entity name="PrimitivesTestEntity" className="org.apache.cayenne.testdo.primitive.PrimitivesTestEntity" dbEntityName="PRIMITIVES_TEST">
+		<obj-attribute name="booleanColumn" type="boolean" db-attribute-path="BOOLEAN_COLUMN"/>
+		<obj-attribute name="intColumn" type="int" db-attribute-path="INT_COLUMN"/>
+	</obj-entity>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/qualified.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/qualified.map.xml b/cayenne-server/src/test/resources/qualified.map.xml
index 0a30f4a..fb854cd 100644
--- a/cayenne-server/src/test/resources/qualified.map.xml
+++ b/cayenne-server/src/test/resources/qualified.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.qualified"/>
 	<property name="quoteSqlIdentifiers" value="true"/>
 	<db-entity name="TEST_QUALIFIED1">
@@ -29,7 +29,7 @@
 	<db-relationship name="qualified2s" source="TEST_QUALIFIED1" target="TEST_QUALIFIED2" toMany="true">
 		<db-attribute-pair source="ID" target="QUALIFIED1_ID"/>
 	</db-relationship>
-	<db-relationship name="qualified1" source="TEST_QUALIFIED2" target="TEST_QUALIFIED1" toMany="false">
+	<db-relationship name="qualified1" source="TEST_QUALIFIED2" target="TEST_QUALIFIED1">
 		<db-attribute-pair source="QUALIFIED1_ID" target="ID"/>
 	</db-relationship>
 	<obj-relationship name="qualified2s" source="Qualified1" target="Qualified2" db-relationship-path="qualified2s"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/quoted-identifiers.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/quoted-identifiers.map.xml b/cayenne-server/src/test/resources/quoted-identifiers.map.xml
index 16d6713..13e638b 100644
--- a/cayenne-server/src/test/resources/quoted-identifiers.map.xml
+++ b/cayenne-server/src/test/resources/quoted-identifiers.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.quotemap"/>
 	<property name="quoteSqlIdentifiers" value="true"/>
 	<db-entity name="QUOTED_ADDRESS">
@@ -30,10 +30,10 @@
 		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
 		<obj-attribute name="salary" type="java.lang.Integer" db-attribute-path="salary"/>
 	</obj-entity>
-	<db-relationship name="personRel" source="QUOTED_ADDRESS" target="quote Person" toMany="false">
+	<db-relationship name="personRel" source="QUOTED_ADDRESS" target="quote Person">
 		<db-attribute-pair source="ADDRESS ID" target="address_id"/>
 	</db-relationship>
-	<db-relationship name="addressRel" source="quote Person" target="QUOTED_ADDRESS" toMany="false">
+	<db-relationship name="addressRel" source="quote Person" target="QUOTED_ADDRESS">
 		<db-attribute-pair source="address_id" target="ADDRESS ID"/>
 	</db-relationship>
 	<obj-relationship name="person_Rel" source="QuoteAdress" target="Quote_Person" deleteRule="Nullify" db-relationship-path="personRel"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/reflexive.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/reflexive.map.xml b/cayenne-server/src/test/resources/reflexive.map.xml
index fc8ed64..043f31d 100644
--- a/cayenne-server/src/test/resources/reflexive.map.xml
+++ b/cayenne-server/src/test/resources/reflexive.map.xml
@@ -1,25 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.reflexive"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="org.apache.cayenne.testdo.reflexive"/>
-    <db-entity name="REFLEXIVE">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" isMandatory="true" length="200"/>
-        <db-attribute name="PARENT_ID" type="INTEGER"/>
-    </db-entity>
-    <obj-entity name="Reflexive" className="org.apache.cayenne.testdo.reflexive.Reflexive" clientClassName="org.apache.cayenne.testdo.reflexive.ClientReflexive" dbEntityName="REFLEXIVE">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <db-relationship name="children" source="REFLEXIVE" target="REFLEXIVE" toMany="true">
-        <db-attribute-pair source="ID" target="PARENT_ID"/>
-    </db-relationship>
-    <db-relationship name="toParent" source="REFLEXIVE" target="REFLEXIVE" toMany="false">
-        <db-attribute-pair source="PARENT_ID" target="ID"/>
-    </db-relationship>
-    <obj-relationship name="children" source="Reflexive" target="Reflexive" db-relationship-path="children"/>
-    <obj-relationship name="toParent" source="Reflexive" target="Reflexive" db-relationship-path="toParent"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.reflexive"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="org.apache.cayenne.testdo.reflexive"/>
+	<db-entity name="REFLEXIVE">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" isMandatory="true" length="200"/>
+		<db-attribute name="PARENT_ID" type="INTEGER"/>
+	</db-entity>
+	<obj-entity name="Reflexive" className="org.apache.cayenne.testdo.reflexive.Reflexive" clientClassName="org.apache.cayenne.testdo.reflexive.ClientReflexive" dbEntityName="REFLEXIVE">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<db-relationship name="children" source="REFLEXIVE" target="REFLEXIVE" toMany="true">
+		<db-attribute-pair source="ID" target="PARENT_ID"/>
+	</db-relationship>
+	<db-relationship name="toParent" source="REFLEXIVE" target="REFLEXIVE">
+		<db-attribute-pair source="PARENT_ID" target="ID"/>
+	</db-relationship>
+	<obj-relationship name="children" source="Reflexive" target="Reflexive" db-relationship-path="children"/>
+	<obj-relationship name="toParent" source="Reflexive" target="Reflexive" db-relationship-path="toParent"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/relationships-activity.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/relationships-activity.map.xml b/cayenne-server/src/test/resources/relationships-activity.map.xml
index 59e72f3..d8c283d 100644
--- a/cayenne-server/src/test/resources/relationships-activity.map.xml
+++ b/cayenne-server/src/test/resources/relationships-activity.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_activity"/>
 	<db-entity name="X_ACTIVITY">
 		<db-attribute name="ACTIVITY_ID" type="VARCHAR" isPrimaryKey="true" isMandatory="true" length="50"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/relationships-child-master.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/relationships-child-master.map.xml b/cayenne-server/src/test/resources/relationships-child-master.map.xml
index a803e72..530ec52 100644
--- a/cayenne-server/src/test/resources/relationships-child-master.map.xml
+++ b/cayenne-server/src/test/resources/relationships-child-master.map.xml
@@ -1,29 +1,27 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_child_master"/>
-    <db-entity name="CHILD">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="MASTER_ID" type="INTEGER"/>
-    </db-entity>
-    <db-entity name="MASTER">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="100"/>
-    </db-entity>
-    <obj-entity name="Child" className="org.apache.cayenne.testdo.relationships_child_master.Child" dbEntityName="CHILD">
-    </obj-entity>
-    <obj-entity name="Master" className="org.apache.cayenne.testdo.relationships_child_master.Master" dbEntityName="MASTER">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <db-relationship name="master" source="CHILD" target="MASTER" toMany="false">
-        <db-attribute-pair source="MASTER_ID" target="ID"/>
-    </db-relationship>
-    <db-relationship name="children" source="MASTER" target="CHILD" toMany="true">
-        <db-attribute-pair source="ID" target="MASTER_ID"/>
-    </db-relationship>
-    <obj-relationship name="master" source="Child" target="Master" deleteRule="Nullify" db-relationship-path="master"/>
-    <obj-relationship name="children" source="Master" target="Child" deleteRule="Deny" db-relationship-path="children"/>
-
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_child_master"/>
+	<db-entity name="CHILD">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="MASTER_ID" type="INTEGER"/>
+	</db-entity>
+	<db-entity name="MASTER">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+	</db-entity>
+	<obj-entity name="Child" className="org.apache.cayenne.testdo.relationships_child_master.Child" dbEntityName="CHILD"/>
+	<obj-entity name="Master" className="org.apache.cayenne.testdo.relationships_child_master.Master" dbEntityName="MASTER">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<db-relationship name="master" source="CHILD" target="MASTER">
+		<db-attribute-pair source="MASTER_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="children" source="MASTER" target="CHILD" toMany="true">
+		<db-attribute-pair source="ID" target="MASTER_ID"/>
+	</db-relationship>
+	<obj-relationship name="master" source="Child" target="Master" deleteRule="Nullify" db-relationship-path="master"/>
+	<obj-relationship name="children" source="Master" target="Child" deleteRule="Deny" db-relationship-path="children"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/relationships-clob.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/relationships-clob.map.xml b/cayenne-server/src/test/resources/relationships-clob.map.xml
index 550b1a5..bdafd09 100644
--- a/cayenne-server/src/test/resources/relationships-clob.map.xml
+++ b/cayenne-server/src/test/resources/relationships-clob.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_clob"/>
 	<db-entity name="CLOB_DETAIL">
 		<db-attribute name="CLOB_DETAIL_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
@@ -21,7 +21,7 @@
 		<obj-attribute name="clobColumn" type="java.lang.String" db-attribute-path="CLOB_COLUMN"/>
 		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
 	</obj-entity>
-	<db-relationship name="master" source="CLOB_DETAIL" target="CLOB_MASTER" toMany="false">
+	<db-relationship name="master" source="CLOB_DETAIL" target="CLOB_MASTER">
 		<db-attribute-pair source="CLOB_MASTER_ID" target="CLOB_MASTER_ID"/>
 	</db-relationship>
 	<db-relationship name="details" source="CLOB_MASTER" target="CLOB_DETAIL" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/relationships-collection-to-many.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/relationships-collection-to-many.map.xml b/cayenne-server/src/test/resources/relationships-collection-to-many.map.xml
index 29a96cb..6876cea 100644
--- a/cayenne-server/src/test/resources/relationships-collection-to-many.map.xml
+++ b/cayenne-server/src/test/resources/relationships-collection-to-many.map.xml
@@ -1,26 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_collection_to_many"/>
-    <db-entity name="COLLECTION_TO_MANY">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="COLLECTION_TO_MANY_TARGET">
-        <db-attribute name="COLLECTION_TO_MANY_ID" type="INTEGER"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <obj-entity name="CollectionToMany" className="org.apache.cayenne.testdo.relationships_collection_to_many.CollectionToMany" dbEntityName="COLLECTION_TO_MANY">
-    </obj-entity>
-    <obj-entity name="CollectionToManyTarget" className="org.apache.cayenne.testdo.relationships_collection_to_many.CollectionToManyTarget" dbEntityName="COLLECTION_TO_MANY_TARGET">
-    </obj-entity>
-    <db-relationship name="targets" source="COLLECTION_TO_MANY" target="COLLECTION_TO_MANY_TARGET" toMany="true">
-        <db-attribute-pair source="ID" target="COLLECTION_TO_MANY_ID"/>
-    </db-relationship>
-    <db-relationship name="collectionToMany" source="COLLECTION_TO_MANY_TARGET" target="COLLECTION_TO_MANY" toMany="false">
-        <db-attribute-pair source="COLLECTION_TO_MANY_ID" target="ID"/>
-    </db-relationship>
-    <obj-relationship name="targets" source="CollectionToMany" target="CollectionToManyTarget" collection-type="java.util.Collection" db-relationship-path="targets"/>
-    <obj-relationship name="collectionToMany" source="CollectionToManyTarget" target="CollectionToMany" db-relationship-path="collectionToMany"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_collection_to_many"/>
+	<db-entity name="COLLECTION_TO_MANY">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="COLLECTION_TO_MANY_TARGET">
+		<db-attribute name="COLLECTION_TO_MANY_ID" type="INTEGER"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<obj-entity name="CollectionToMany" className="org.apache.cayenne.testdo.relationships_collection_to_many.CollectionToMany" dbEntityName="COLLECTION_TO_MANY"/>
+	<obj-entity name="CollectionToManyTarget" className="org.apache.cayenne.testdo.relationships_collection_to_many.CollectionToManyTarget" dbEntityName="COLLECTION_TO_MANY_TARGET"/>
+	<db-relationship name="targets" source="COLLECTION_TO_MANY" target="COLLECTION_TO_MANY_TARGET" toMany="true">
+		<db-attribute-pair source="ID" target="COLLECTION_TO_MANY_ID"/>
+	</db-relationship>
+	<db-relationship name="collectionToMany" source="COLLECTION_TO_MANY_TARGET" target="COLLECTION_TO_MANY">
+		<db-attribute-pair source="COLLECTION_TO_MANY_ID" target="ID"/>
+	</db-relationship>
+	<obj-relationship name="targets" source="CollectionToMany" target="CollectionToManyTarget" collection-type="java.util.Collection" db-relationship-path="targets"/>
+	<obj-relationship name="collectionToMany" source="CollectionToManyTarget" target="CollectionToMany" db-relationship-path="collectionToMany"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/relationships-delete-rules.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/relationships-delete-rules.map.xml b/cayenne-server/src/test/resources/relationships-delete-rules.map.xml
index b875d45..5a7cd1a 100644
--- a/cayenne-server/src/test/resources/relationships-delete-rules.map.xml
+++ b/cayenne-server/src/test/resources/relationships-delete-rules.map.xml
@@ -1,71 +1,66 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_delete_rules"/>
-    <db-entity name="DELETE_RULE_FLATA">
-        <db-attribute name="FLATA_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="DELETE_RULE_FLATB">
-        <db-attribute name="FLATB_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="DELETE_RULE_JOIN">
-        <db-attribute name="FLATA_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="FLATB_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="DELETE_RULE_TEST1">
-        <db-attribute name="DEL_RULE_TEST1_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="TEST2_ID" type="INTEGER" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="DELETE_RULE_TEST2">
-        <db-attribute name="DEL_RULE_TEST2_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="DELETE_RULE_TEST3">
-        <db-attribute name="DELETE_RULE_TEST_3_FK" type="INTEGER"/>
-        <db-attribute name="DELETE_RULE_TEST_3_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <obj-entity name="DeleteRuleFlatA" className="org.apache.cayenne.testdo.relationships_delete_rules.DeleteRuleFlatA" dbEntityName="DELETE_RULE_FLATA">
-    </obj-entity>
-    <obj-entity name="DeleteRuleFlatB" className="org.apache.cayenne.testdo.relationships_delete_rules.DeleteRuleFlatB" dbEntityName="DELETE_RULE_FLATB">
-    </obj-entity>
-    <obj-entity name="DeleteRuleTest1" className="org.apache.cayenne.testdo.relationships_delete_rules.DeleteRuleTest1" dbEntityName="DELETE_RULE_TEST1">
-    </obj-entity>
-    <obj-entity name="DeleteRuleTest2" className="org.apache.cayenne.testdo.relationships_delete_rules.DeleteRuleTest2" dbEntityName="DELETE_RULE_TEST2">
-    </obj-entity>
-    <obj-entity name="DeleteRuleTest3" className="org.apache.cayenne.testdo.relationships_delete_rules.DeleteRuleTest3" dbEntityName="DELETE_RULE_TEST3">
-    </obj-entity>
-    <db-relationship name="joins" source="DELETE_RULE_FLATA" target="DELETE_RULE_JOIN" toDependentPK="true" toMany="true">
-        <db-attribute-pair source="FLATA_ID" target="FLATA_ID"/>
-    </db-relationship>
-    <db-relationship name="joins" source="DELETE_RULE_FLATB" target="DELETE_RULE_JOIN" toDependentPK="true" toMany="true">
-        <db-attribute-pair source="FLATB_ID" target="FLATB_ID"/>
-    </db-relationship>
-    <db-relationship name="toFlatA" source="DELETE_RULE_JOIN" target="DELETE_RULE_FLATA" toMany="false">
-        <db-attribute-pair source="FLATA_ID" target="FLATA_ID"/>
-    </db-relationship>
-    <db-relationship name="toFlatB" source="DELETE_RULE_JOIN" target="DELETE_RULE_FLATB" toMany="false">
-        <db-attribute-pair source="FLATB_ID" target="FLATB_ID"/>
-    </db-relationship>
-    <db-relationship name="deleteRuleTest3Array" source="DELETE_RULE_TEST1" target="DELETE_RULE_TEST3" toMany="true">
-        <db-attribute-pair source="DEL_RULE_TEST1_ID" target="DELETE_RULE_TEST_3_FK"/>
-    </db-relationship>
-    <db-relationship name="test2" source="DELETE_RULE_TEST1" target="DELETE_RULE_TEST2" toMany="false">
-        <db-attribute-pair source="TEST2_ID" target="DEL_RULE_TEST2_ID"/>
-    </db-relationship>
-    <db-relationship name="deleteRuleTest3Array" source="DELETE_RULE_TEST2" target="DELETE_RULE_TEST3" toMany="true">
-        <db-attribute-pair source="DEL_RULE_TEST2_ID" target="DELETE_RULE_TEST_3_FK"/>
-    </db-relationship>
-    <db-relationship name="test1Array" source="DELETE_RULE_TEST2" target="DELETE_RULE_TEST1" toMany="true">
-        <db-attribute-pair source="DEL_RULE_TEST2_ID" target="TEST2_ID"/>
-    </db-relationship>
-    <db-relationship name="toDeleteRuleTest2" source="DELETE_RULE_TEST3" target="DELETE_RULE_TEST2" toMany="false">
-        <db-attribute-pair source="DELETE_RULE_TEST_3_FK" target="DEL_RULE_TEST2_ID"/>
-    </db-relationship>
-    <obj-relationship name="flatB" source="DeleteRuleFlatA" target="DeleteRuleFlatB" db-relationship-path="joins.toFlatB"/>
-    <obj-relationship name="untitledRel" source="DeleteRuleFlatB" target="DeleteRuleFlatA" db-relationship-path="joins.toFlatA"/>
-    <obj-relationship name="test2" source="DeleteRuleTest1" target="DeleteRuleTest2" deleteRule="Deny" db-relationship-path="test2"/>
-    <obj-relationship name="deleteRuleTest3Array" source="DeleteRuleTest2" target="DeleteRuleTest3" db-relationship-path="deleteRuleTest3Array"/>
-    <obj-relationship name="test1Array" source="DeleteRuleTest2" target="DeleteRuleTest1" deleteRule="Nullify" db-relationship-path="test1Array"/>
-    <obj-relationship name="toDeleteRuleTest2" source="DeleteRuleTest3" target="DeleteRuleTest2" db-relationship-path="toDeleteRuleTest2"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_delete_rules"/>
+	<db-entity name="DELETE_RULE_FLATA">
+		<db-attribute name="FLATA_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="DELETE_RULE_FLATB">
+		<db-attribute name="FLATB_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="DELETE_RULE_JOIN">
+		<db-attribute name="FLATA_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="FLATB_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="DELETE_RULE_TEST1">
+		<db-attribute name="DEL_RULE_TEST1_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="TEST2_ID" type="INTEGER" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="DELETE_RULE_TEST2">
+		<db-attribute name="DEL_RULE_TEST2_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="DELETE_RULE_TEST3">
+		<db-attribute name="DELETE_RULE_TEST_3_FK" type="INTEGER"/>
+		<db-attribute name="DELETE_RULE_TEST_3_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<obj-entity name="DeleteRuleFlatA" className="org.apache.cayenne.testdo.relationships_delete_rules.DeleteRuleFlatA" dbEntityName="DELETE_RULE_FLATA"/>
+	<obj-entity name="DeleteRuleFlatB" className="org.apache.cayenne.testdo.relationships_delete_rules.DeleteRuleFlatB" dbEntityName="DELETE_RULE_FLATB"/>
+	<obj-entity name="DeleteRuleTest1" className="org.apache.cayenne.testdo.relationships_delete_rules.DeleteRuleTest1" dbEntityName="DELETE_RULE_TEST1"/>
+	<obj-entity name="DeleteRuleTest2" className="org.apache.cayenne.testdo.relationships_delete_rules.DeleteRuleTest2" dbEntityName="DELETE_RULE_TEST2"/>
+	<obj-entity name="DeleteRuleTest3" className="org.apache.cayenne.testdo.relationships_delete_rules.DeleteRuleTest3" dbEntityName="DELETE_RULE_TEST3"/>
+	<db-relationship name="joins" source="DELETE_RULE_FLATA" target="DELETE_RULE_JOIN" toDependentPK="true" toMany="true">
+		<db-attribute-pair source="FLATA_ID" target="FLATA_ID"/>
+	</db-relationship>
+	<db-relationship name="joins" source="DELETE_RULE_FLATB" target="DELETE_RULE_JOIN" toDependentPK="true" toMany="true">
+		<db-attribute-pair source="FLATB_ID" target="FLATB_ID"/>
+	</db-relationship>
+	<db-relationship name="toFlatA" source="DELETE_RULE_JOIN" target="DELETE_RULE_FLATA">
+		<db-attribute-pair source="FLATA_ID" target="FLATA_ID"/>
+	</db-relationship>
+	<db-relationship name="toFlatB" source="DELETE_RULE_JOIN" target="DELETE_RULE_FLATB">
+		<db-attribute-pair source="FLATB_ID" target="FLATB_ID"/>
+	</db-relationship>
+	<db-relationship name="deleteRuleTest3Array" source="DELETE_RULE_TEST1" target="DELETE_RULE_TEST3" toMany="true">
+		<db-attribute-pair source="DEL_RULE_TEST1_ID" target="DELETE_RULE_TEST_3_FK"/>
+	</db-relationship>
+	<db-relationship name="test2" source="DELETE_RULE_TEST1" target="DELETE_RULE_TEST2">
+		<db-attribute-pair source="TEST2_ID" target="DEL_RULE_TEST2_ID"/>
+	</db-relationship>
+	<db-relationship name="deleteRuleTest3Array" source="DELETE_RULE_TEST2" target="DELETE_RULE_TEST3" toMany="true">
+		<db-attribute-pair source="DEL_RULE_TEST2_ID" target="DELETE_RULE_TEST_3_FK"/>
+	</db-relationship>
+	<db-relationship name="test1Array" source="DELETE_RULE_TEST2" target="DELETE_RULE_TEST1" toMany="true">
+		<db-attribute-pair source="DEL_RULE_TEST2_ID" target="TEST2_ID"/>
+	</db-relationship>
+	<db-relationship name="toDeleteRuleTest2" source="DELETE_RULE_TEST3" target="DELETE_RULE_TEST2">
+		<db-attribute-pair source="DELETE_RULE_TEST_3_FK" target="DEL_RULE_TEST2_ID"/>
+	</db-relationship>
+	<obj-relationship name="flatB" source="DeleteRuleFlatA" target="DeleteRuleFlatB" db-relationship-path="joins.toFlatB"/>
+	<obj-relationship name="untitledRel" source="DeleteRuleFlatB" target="DeleteRuleFlatA" db-relationship-path="joins.toFlatA"/>
+	<obj-relationship name="test2" source="DeleteRuleTest1" target="DeleteRuleTest2" deleteRule="Deny" db-relationship-path="test2"/>
+	<obj-relationship name="deleteRuleTest3Array" source="DeleteRuleTest2" target="DeleteRuleTest3" db-relationship-path="deleteRuleTest3Array"/>
+	<obj-relationship name="test1Array" source="DeleteRuleTest2" target="DeleteRuleTest1" deleteRule="Nullify" db-relationship-path="test1Array"/>
+	<obj-relationship name="toDeleteRuleTest2" source="DeleteRuleTest3" target="DeleteRuleTest2" db-relationship-path="toDeleteRuleTest2"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/relationships-flattened.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/relationships-flattened.map.xml b/cayenne-server/src/test/resources/relationships-flattened.map.xml
index d5a0ee5..b62e3f3 100644
--- a/cayenne-server/src/test/resources/relationships-flattened.map.xml
+++ b/cayenne-server/src/test/resources/relationships-flattened.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_flattened"/>
 	<db-entity name="COMPLEX_JOIN">
 		<db-attribute name="EXTRA_COLUMN" type="VARCHAR" length="50"/>
@@ -45,8 +45,7 @@
 		<db-attribute name="FT5_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="NAME" type="VARCHAR" isMandatory="true" length="100"/>
 	</db-entity>
-	<obj-entity name="FlattenedCircular" className="org.apache.cayenne.testdo.relationships_flattened.FlattenedCircular" dbEntityName="FLATTENED_CIRCULAR">
-	</obj-entity>
+	<obj-entity name="FlattenedCircular" className="org.apache.cayenne.testdo.relationships_flattened.FlattenedCircular" dbEntityName="FLATTENED_CIRCULAR"/>
 	<obj-entity name="FlattenedTest1" className="org.apache.cayenne.testdo.relationships_flattened.FlattenedTest1" dbEntityName="FLATTENED_TEST_1">
 		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
 	</obj-entity>
@@ -62,16 +61,16 @@
 	<obj-entity name="FlattenedTest5" className="org.apache.cayenne.testdo.relationships_flattened.FlattenedTest5" dbEntityName="FLATTENED_TEST_5">
 		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
 	</obj-entity>
-	<db-relationship name="toFT1" source="COMPLEX_JOIN" target="FLATTENED_TEST_1" toMany="false">
+	<db-relationship name="toFT1" source="COMPLEX_JOIN" target="FLATTENED_TEST_1">
 		<db-attribute-pair source="FT1_FK" target="FT1_ID"/>
 	</db-relationship>
-	<db-relationship name="toFT3" source="COMPLEX_JOIN" target="FLATTENED_TEST_3" toMany="false">
+	<db-relationship name="toFT3" source="COMPLEX_JOIN" target="FLATTENED_TEST_3">
 		<db-attribute-pair source="FT3_FK" target="FT3_ID"/>
 	</db-relationship>
-	<db-relationship name="toFT1" source="COMPLEX_JOIN2" target="FLATTENED_TEST_1" toMany="false">
+	<db-relationship name="toFT1" source="COMPLEX_JOIN2" target="FLATTENED_TEST_1">
 		<db-attribute-pair source="FT1_FK" target="FT1_ID"/>
 	</db-relationship>
-	<db-relationship name="toFT5" source="COMPLEX_JOIN2" target="FLATTENED_TEST_5" toMany="false">
+	<db-relationship name="toFT5" source="COMPLEX_JOIN2" target="FLATTENED_TEST_5">
 		<db-attribute-pair source="FT5_FK" target="FT5_ID"/>
 	</db-relationship>
 	<db-relationship name="side1s" source="FLATTENED_CIRCULAR" target="FLATTENED_CIRCULAR_JOIN" toDependentPK="true" toMany="true">
@@ -80,10 +79,10 @@
 	<db-relationship name="side2s" source="FLATTENED_CIRCULAR" target="FLATTENED_CIRCULAR_JOIN" toDependentPK="true" toMany="true">
 		<db-attribute-pair source="ID" target="SIDE1_ID"/>
 	</db-relationship>
-	<db-relationship name="side1" source="FLATTENED_CIRCULAR_JOIN" target="FLATTENED_CIRCULAR" toMany="false">
+	<db-relationship name="side1" source="FLATTENED_CIRCULAR_JOIN" target="FLATTENED_CIRCULAR">
 		<db-attribute-pair source="SIDE1_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="side2" source="FLATTENED_CIRCULAR_JOIN" target="FLATTENED_CIRCULAR" toMany="false">
+	<db-relationship name="side2" source="FLATTENED_CIRCULAR_JOIN" target="FLATTENED_CIRCULAR">
 		<db-attribute-pair source="SIDE2_ID" target="ID"/>
 	</db-relationship>
 	<db-relationship name="complexJoins" source="FLATTENED_TEST_1" target="COMPLEX_JOIN" toMany="true">
@@ -98,7 +97,7 @@
 	<db-relationship name="ft3Array" source="FLATTENED_TEST_2" target="FLATTENED_TEST_3" toMany="true">
 		<db-attribute-pair source="FT2_ID" target="FT2_ID"/>
 	</db-relationship>
-	<db-relationship name="toFT1" source="FLATTENED_TEST_2" target="FLATTENED_TEST_1" toMany="false">
+	<db-relationship name="toFT1" source="FLATTENED_TEST_2" target="FLATTENED_TEST_1">
 		<db-attribute-pair source="FT1_ID" target="FT1_ID"/>
 	</db-relationship>
 	<db-relationship name="complexJoins" source="FLATTENED_TEST_3" target="COMPLEX_JOIN" toMany="true">
@@ -107,13 +106,13 @@
 	<db-relationship name="ft4Array" source="FLATTENED_TEST_3" target="FLATTENED_TEST_4" toMany="true">
 		<db-attribute-pair source="FT3_ID" target="FT3_ID"/>
 	</db-relationship>
-	<db-relationship name="toFT2" source="FLATTENED_TEST_3" target="FLATTENED_TEST_2" toMany="false">
+	<db-relationship name="toFT2" source="FLATTENED_TEST_3" target="FLATTENED_TEST_2">
 		<db-attribute-pair source="FT2_ID" target="FT2_ID"/>
 	</db-relationship>
-	<db-relationship name="toFT3" source="FLATTENED_TEST_4" target="FLATTENED_TEST_3" toMany="false">
+	<db-relationship name="toFT3" source="FLATTENED_TEST_4" target="FLATTENED_TEST_3">
 		<db-attribute-pair source="FT3_ID" target="FT3_ID"/>
 	</db-relationship>
-	<db-relationship name="complexJoin2" source="FLATTENED_TEST_5" target="COMPLEX_JOIN2" toMany="false">
+	<db-relationship name="complexJoin2" source="FLATTENED_TEST_5" target="COMPLEX_JOIN2">
 		<db-attribute-pair source="FT5_ID" target="FT5_FK"/>
 	</db-relationship>
 	<obj-relationship name="side1s" source="FlattenedCircular" target="FlattenedCircular" db-relationship-path="side1s.side1"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/relationships-set-to-many.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/relationships-set-to-many.map.xml b/cayenne-server/src/test/resources/relationships-set-to-many.map.xml
index 882d8d4..fedc4b6 100644
--- a/cayenne-server/src/test/resources/relationships-set-to-many.map.xml
+++ b/cayenne-server/src/test/resources/relationships-set-to-many.map.xml
@@ -1,26 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_set_to_many"/>
-    <db-entity name="SET_TO_MANY">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="SET_TO_MANY_TARGET">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="SET_TO_MANY_ID" type="INTEGER"/>
-    </db-entity>
-    <obj-entity name="SetToMany" className="org.apache.cayenne.testdo.relationships_set_to_many.SetToMany" dbEntityName="SET_TO_MANY">
-    </obj-entity>
-    <obj-entity name="SetToManyTarget" className="org.apache.cayenne.testdo.relationships_set_to_many.SetToManyTarget" dbEntityName="SET_TO_MANY_TARGET">
-    </obj-entity>
-    <db-relationship name="targets" source="SET_TO_MANY" target="SET_TO_MANY_TARGET" toMany="true">
-        <db-attribute-pair source="ID" target="SET_TO_MANY_ID"/>
-    </db-relationship>
-    <db-relationship name="setToMany" source="SET_TO_MANY_TARGET" target="SET_TO_MANY" toMany="false">
-        <db-attribute-pair source="SET_TO_MANY_ID" target="ID"/>
-    </db-relationship>
-    <obj-relationship name="targets" source="SetToMany" target="SetToManyTarget" collection-type="java.util.Set" db-relationship-path="targets"/>
-    <obj-relationship name="setToMany" source="SetToManyTarget" target="SetToMany" db-relationship-path="setToMany"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_set_to_many"/>
+	<db-entity name="SET_TO_MANY">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="SET_TO_MANY_TARGET">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="SET_TO_MANY_ID" type="INTEGER"/>
+	</db-entity>
+	<obj-entity name="SetToMany" className="org.apache.cayenne.testdo.relationships_set_to_many.SetToMany" dbEntityName="SET_TO_MANY"/>
+	<obj-entity name="SetToManyTarget" className="org.apache.cayenne.testdo.relationships_set_to_many.SetToManyTarget" dbEntityName="SET_TO_MANY_TARGET"/>
+	<db-relationship name="targets" source="SET_TO_MANY" target="SET_TO_MANY_TARGET" toMany="true">
+		<db-attribute-pair source="ID" target="SET_TO_MANY_ID"/>
+	</db-relationship>
+	<db-relationship name="setToMany" source="SET_TO_MANY_TARGET" target="SET_TO_MANY">
+		<db-attribute-pair source="SET_TO_MANY_ID" target="ID"/>
+	</db-relationship>
+	<obj-relationship name="targets" source="SetToMany" target="SetToManyTarget" collection-type="java.util.Set" db-relationship-path="targets"/>
+	<obj-relationship name="setToMany" source="SetToManyTarget" target="SetToMany" db-relationship-path="setToMany"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/relationships-to-many-fk.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/relationships-to-many-fk.map.xml b/cayenne-server/src/test/resources/relationships-to-many-fk.map.xml
index 1c8257a..69c6496 100644
--- a/cayenne-server/src/test/resources/relationships-to-many-fk.map.xml
+++ b/cayenne-server/src/test/resources/relationships-to-many-fk.map.xml
@@ -1,48 +1,48 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_to_many_fk"/>
-    <db-entity name="TO_MANY_FKDEP">
-        <db-attribute name="DEP_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="200"/>
-        <db-attribute name="OTHER_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="TO_MANY_FKROOT">
-        <db-attribute name="FK_ID" type="INTEGER"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="100"/>
-    </db-entity>
-    <db-entity name="TO_MANY_ROOT2">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="100"/>
-    </db-entity>
-    <obj-entity name="ToManyFkDep" className="org.apache.cayenne.testdo.relationships_to_many_fk.ToManyFkDep" dbEntityName="TO_MANY_FKDEP">
-        <obj-attribute name="depId" type="java.lang.Integer" db-attribute-path="DEP_ID"/>
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="ToManyFkRoot" className="org.apache.cayenne.testdo.relationships_to_many_fk.ToManyFkRoot" dbEntityName="TO_MANY_FKROOT">
-        <obj-attribute name="depId" type="java.lang.Integer" db-attribute-path="FK_ID"/>
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="ToManyRoot2" className="org.apache.cayenne.testdo.relationships_to_many_fk.ToManyRoot2" dbEntityName="TO_MANY_ROOT2">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <db-relationship name="root" source="TO_MANY_FKDEP" target="TO_MANY_FKROOT" toMany="false">
-        <db-attribute-pair source="DEP_ID" target="FK_ID"/>
-    </db-relationship>
-    <db-relationship name="root2" source="TO_MANY_FKDEP" target="TO_MANY_ROOT2" toMany="false">
-        <db-attribute-pair source="OTHER_ID" target="ID"/>
-    </db-relationship>
-    <db-relationship name="deps" source="TO_MANY_FKROOT" target="TO_MANY_FKDEP" toMany="true">
-        <db-attribute-pair source="FK_ID" target="DEP_ID"/>
-    </db-relationship>
-    <db-relationship name="deps" source="TO_MANY_ROOT2" target="TO_MANY_FKDEP" toDependentPK="true" toMany="true">
-        <db-attribute-pair source="ID" target="OTHER_ID"/>
-    </db-relationship>
-    <obj-relationship name="root" source="ToManyFkDep" target="ToManyFkRoot" db-relationship-path="root"/>
-    <obj-relationship name="root2" source="ToManyFkDep" target="ToManyRoot2" db-relationship-path="root2"/>
-    <obj-relationship name="deps" source="ToManyFkRoot" target="ToManyFkDep" db-relationship-path="deps"/>
-    <obj-relationship name="deps" source="ToManyRoot2" target="ToManyFkDep" db-relationship-path="deps"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.relationships_to_many_fk"/>
+	<db-entity name="TO_MANY_FKDEP">
+		<db-attribute name="DEP_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="200"/>
+		<db-attribute name="OTHER_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="TO_MANY_FKROOT">
+		<db-attribute name="FK_ID" type="INTEGER"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+	</db-entity>
+	<db-entity name="TO_MANY_ROOT2">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+	</db-entity>
+	<obj-entity name="ToManyFkDep" className="org.apache.cayenne.testdo.relationships_to_many_fk.ToManyFkDep" dbEntityName="TO_MANY_FKDEP">
+		<obj-attribute name="depId" type="java.lang.Integer" db-attribute-path="DEP_ID"/>
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="ToManyFkRoot" className="org.apache.cayenne.testdo.relationships_to_many_fk.ToManyFkRoot" dbEntityName="TO_MANY_FKROOT">
+		<obj-attribute name="depId" type="java.lang.Integer" db-attribute-path="FK_ID"/>
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="ToManyRoot2" className="org.apache.cayenne.testdo.relationships_to_many_fk.ToManyRoot2" dbEntityName="TO_MANY_ROOT2">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<db-relationship name="root" source="TO_MANY_FKDEP" target="TO_MANY_FKROOT">
+		<db-attribute-pair source="DEP_ID" target="FK_ID"/>
+	</db-relationship>
+	<db-relationship name="root2" source="TO_MANY_FKDEP" target="TO_MANY_ROOT2">
+		<db-attribute-pair source="OTHER_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="deps" source="TO_MANY_FKROOT" target="TO_MANY_FKDEP" toMany="true">
+		<db-attribute-pair source="FK_ID" target="DEP_ID"/>
+	</db-relationship>
+	<db-relationship name="deps" source="TO_MANY_ROOT2" target="TO_MANY_FKDEP" toDependentPK="true" toMany="true">
+		<db-attribute-pair source="ID" target="OTHER_ID"/>
+	</db-relationship>
+	<obj-relationship name="root" source="ToManyFkDep" target="ToManyFkRoot" db-relationship-path="root"/>
+	<obj-relationship name="root2" source="ToManyFkDep" target="ToManyRoot2" db-relationship-path="root2"/>
+	<obj-relationship name="deps" source="ToManyFkRoot" target="ToManyFkDep" db-relationship-path="deps"/>
+	<obj-relationship name="deps" source="ToManyRoot2" target="ToManyFkDep" db-relationship-path="deps"/>
 </data-map>

[03/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - new XML loader for DataMap - new project version - updated test projects

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/inheritance-vertical.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/inheritance-vertical.map.xml b/cayenne-server/src/test/resources/inheritance-vertical.map.xml
index 5183951..a437439 100644
--- a/cayenne-server/src/test/resources/inheritance-vertical.map.xml
+++ b/cayenne-server/src/test/resources/inheritance-vertical.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.inheritance_vertical"/>
 	<db-entity name="IV1_ROOT">
 		<db-attribute name="DISCRIMINATOR" type="VARCHAR" length="10"/>
@@ -96,8 +96,7 @@
 	<obj-entity name="Iv2Sub1" superEntityName="Iv2Root" className="org.apache.cayenne.testdo.inheritance_vertical.Iv2Sub1">
 		<qualifier><![CDATA[discriminator = "Iv2Sub1"]]></qualifier>
 	</obj-entity>
-	<obj-entity name="Iv2X" className="org.apache.cayenne.testdo.inheritance_vertical.Iv2X" dbEntityName="IV2_X">
-	</obj-entity>
+	<obj-entity name="Iv2X" className="org.apache.cayenne.testdo.inheritance_vertical.Iv2X" dbEntityName="IV2_X"/>
 	<obj-entity name="IvAbstract" abstract="true" className="org.apache.cayenne.testdo.inheritance_vertical.IvAbstract" dbEntityName="IV_ABSTRACT">
 		<obj-attribute name="type" type="java.lang.String" db-attribute-path="TYPE"/>
 	</obj-entity>
@@ -150,19 +149,19 @@
 		<qualifier><![CDATA[discriminator = "IvSub3"]]></qualifier>
 		<pre-persist method-name="onPrePersist"/>
 	</obj-entity>
-	<db-relationship name="sub1" source="IV1_ROOT" target="IV1_SUB1" toDependentPK="true" toMany="false">
+	<db-relationship name="sub1" source="IV1_ROOT" target="IV1_SUB1" toDependentPK="true">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="root" source="IV1_SUB1" target="IV1_ROOT" toMany="false">
+	<db-relationship name="root" source="IV1_SUB1" target="IV1_ROOT">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="sub1" source="IV2_ROOT" target="IV2_SUB1" toDependentPK="true" toMany="false">
+	<db-relationship name="sub1" source="IV2_ROOT" target="IV2_SUB1" toDependentPK="true">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="root" source="IV2_SUB1" target="IV2_ROOT" toMany="false">
+	<db-relationship name="root" source="IV2_SUB1" target="IV2_ROOT">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="x" source="IV2_SUB1" target="IV2_X" toMany="false">
+	<db-relationship name="x" source="IV2_SUB1" target="IV2_X">
 		<db-attribute-pair source="X_ID" target="ID"/>
 	</db-relationship>
 	<db-relationship name="sub1" source="IV2_X" target="IV2_SUB1" toMany="true">
@@ -171,34 +170,34 @@
 	<db-relationship name="children" source="IV_ABSTRACT" target="IV_ABSTRACT" toMany="true">
 		<db-attribute-pair source="ID" target="PARENT_ID"/>
 	</db-relationship>
-	<db-relationship name="concrete" source="IV_ABSTRACT" target="IV_CONCRETE" toDependentPK="true" toMany="false">
+	<db-relationship name="concrete" source="IV_ABSTRACT" target="IV_CONCRETE" toDependentPK="true">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="parent" source="IV_ABSTRACT" target="IV_ABSTRACT" toMany="false">
+	<db-relationship name="parent" source="IV_ABSTRACT" target="IV_ABSTRACT">
 		<db-attribute-pair source="PARENT_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="impl" source="IV_BASE" target="IV_IMPL" toDependentPK="true" toMany="false">
-		<db-attribute-pair source="ID" target="ID"/>
-	</db-relationship>
-	<db-relationship name="impl" source="IV_BASE_WITH_LOCK" target="IV_IMPL_WITH_LOCK" toDependentPK="true" toMany="false">
+	<db-relationship name="impl" source="IV_BASE" target="IV_IMPL" toDependentPK="true">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="abstract" source="IV_CONCRETE" target="IV_ABSTRACT" toMany="false">
+	<db-relationship name="impl" source="IV_BASE_WITH_LOCK" target="IV_IMPL_WITH_LOCK" toDependentPK="true">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="base" source="IV_IMPL" target="IV_BASE" toMany="false">
+	<db-relationship name="abstract" source="IV_CONCRETE" target="IV_ABSTRACT">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="base" source="IV_IMPL_WITH_LOCK" target="IV_BASE_WITH_LOCK" toMany="false">
+	<db-relationship name="base" source="IV_IMPL" target="IV_BASE">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="other1" source="IV_IMPL" target="IV_OTHER" toMany="false">
+	<db-relationship name="other1" source="IV_IMPL" target="IV_OTHER">
 		<db-attribute-pair source="OTHER1_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="other2" source="IV_IMPL" target="IV_OTHER" toMany="false">
+	<db-relationship name="other2" source="IV_IMPL" target="IV_OTHER">
 		<db-attribute-pair source="OTHER2_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="other1" source="IV_IMPL_WITH_LOCK" target="IV_OTHER" toMany="false">
+	<db-relationship name="base" source="IV_IMPL_WITH_LOCK" target="IV_BASE_WITH_LOCK">
+		<db-attribute-pair source="ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="other1" source="IV_IMPL_WITH_LOCK" target="IV_OTHER">
 		<db-attribute-pair source="OTHER1_ID" target="ID"/>
 	</db-relationship>
 	<db-relationship name="impls" source="IV_OTHER" target="IV_IMPL" toMany="true">
@@ -210,28 +209,28 @@
 	<db-relationship name="ivSub3s" source="IV_ROOT" target="IV_SUB3" toMany="true">
 		<db-attribute-pair source="ID" target="IV_ROOT_ID"/>
 	</db-relationship>
-	<db-relationship name="sub1" source="IV_ROOT" target="IV_SUB1" toDependentPK="true" toMany="false">
+	<db-relationship name="sub1" source="IV_ROOT" target="IV_SUB1" toDependentPK="true">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="sub2" source="IV_ROOT" target="IV_SUB2" toDependentPK="true" toMany="false">
+	<db-relationship name="sub2" source="IV_ROOT" target="IV_SUB2" toDependentPK="true">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="sub3" source="IV_ROOT" target="IV_SUB3" toDependentPK="true" toMany="false">
+	<db-relationship name="sub3" source="IV_ROOT" target="IV_SUB3" toDependentPK="true">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="master" source="IV_SUB1" target="IV_ROOT" toMany="false">
+	<db-relationship name="master" source="IV_SUB1" target="IV_ROOT">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="sub1Sub1" source="IV_SUB1" target="IV_SUB1_SUB1" toDependentPK="true" toMany="false">
+	<db-relationship name="sub1Sub1" source="IV_SUB1" target="IV_SUB1_SUB1" toDependentPK="true">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="master" source="IV_SUB1_SUB1" target="IV_SUB1" toMany="false">
+	<db-relationship name="master" source="IV_SUB1_SUB1" target="IV_SUB1">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="master" source="IV_SUB2" target="IV_ROOT" toMany="false">
+	<db-relationship name="master" source="IV_SUB2" target="IV_ROOT">
 		<db-attribute-pair source="ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="ivRoot1" source="IV_SUB3" target="IV_ROOT" toMany="false">
+	<db-relationship name="ivRoot1" source="IV_SUB3" target="IV_ROOT">
 		<db-attribute-pair source="IV_ROOT_ID" target="ID"/>
 	</db-relationship>
 	<obj-relationship name="x" source="Iv2Sub1" target="Iv2X" deleteRule="Nullify" db-relationship-path="sub1.x"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/inheritance.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/inheritance.map.xml b/cayenne-server/src/test/resources/inheritance.map.xml
index df054be..ea96c45 100644
--- a/cayenne-server/src/test/resources/inheritance.map.xml
+++ b/cayenne-server/src/test/resources/inheritance.map.xml
@@ -1,46 +1,44 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.inheritance"/>
-    <db-entity name="BASE_ENTITY">
-        <db-attribute name="BASE_ENTITY_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="DIRECT_TO_SUB_ENTITY_ID" type="INTEGER"/>
-        <db-attribute name="ENTITY_TYPE" type="VARCHAR" length="255"/>
-        <db-attribute name="RELATED_ENTITY_ID" type="INTEGER" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="DIRECT_TO_SUB_ENTITY">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="RELATED_ENTITY">
-        <db-attribute name="RELATED_ENTITY_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <obj-entity name="BaseEntity" className="org.apache.cayenne.testdo.inheritance.BaseEntity" dbEntityName="BASE_ENTITY">
-        <obj-attribute name="entityType" type="java.lang.String" db-attribute-path="ENTITY_TYPE"/>
-    </obj-entity>
-    <obj-entity name="DirectToSubEntity" className="org.apache.cayenne.testdo.inheritance.DirectToSubEntity" dbEntityName="DIRECT_TO_SUB_ENTITY">
-    </obj-entity>
-    <obj-entity name="RelatedEntity" className="org.apache.cayenne.testdo.inheritance.RelatedEntity" dbEntityName="RELATED_ENTITY">
-    </obj-entity>
-    <obj-entity name="SubEntity" superEntityName="BaseEntity" className="org.apache.cayenne.testdo.inheritance.SubEntity">
-        <qualifier><![CDATA[entityType = "sub"]]></qualifier>
-    </obj-entity>
-    <db-relationship name="directToSubEntities" source="BASE_ENTITY" target="DIRECT_TO_SUB_ENTITY" toMany="false">
-        <db-attribute-pair source="DIRECT_TO_SUB_ENTITY_ID" target="ID"/>
-    </db-relationship>
-    <db-relationship name="relatedEntities" source="BASE_ENTITY" target="RELATED_ENTITY" toMany="false">
-        <db-attribute-pair source="RELATED_ENTITY_ID" target="RELATED_ENTITY_ID"/>
-    </db-relationship>
-    <db-relationship name="subEntity" source="DIRECT_TO_SUB_ENTITY" target="BASE_ENTITY" toMany="true">
-        <db-attribute-pair source="ID" target="DIRECT_TO_SUB_ENTITY_ID"/>
-    </db-relationship>
-    <db-relationship name="entities" source="RELATED_ENTITY" target="BASE_ENTITY" toMany="true">
-        <db-attribute-pair source="RELATED_ENTITY_ID" target="RELATED_ENTITY_ID"/>
-    </db-relationship>
-    <obj-relationship name="toDirectToSubEntity" source="BaseEntity" target="DirectToSubEntity" deleteRule="Nullify" db-relationship-path="directToSubEntities"/>
-    <obj-relationship name="toRelatedEntity" source="BaseEntity" target="RelatedEntity" deleteRule="Nullify" db-relationship-path="relatedEntities"/>
-    <obj-relationship name="subEntities" source="DirectToSubEntity" target="SubEntity" db-relationship-path="subEntity"/>
-    <obj-relationship name="baseEntities" source="RelatedEntity" target="BaseEntity" db-relationship-path="entities"/>
-    <obj-relationship name="subEntities" source="RelatedEntity" target="SubEntity" db-relationship-path="entities"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.inheritance"/>
+	<db-entity name="BASE_ENTITY">
+		<db-attribute name="BASE_ENTITY_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="DIRECT_TO_SUB_ENTITY_ID" type="INTEGER"/>
+		<db-attribute name="ENTITY_TYPE" type="VARCHAR" length="255"/>
+		<db-attribute name="RELATED_ENTITY_ID" type="INTEGER" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="DIRECT_TO_SUB_ENTITY">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="RELATED_ENTITY">
+		<db-attribute name="RELATED_ENTITY_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<obj-entity name="BaseEntity" className="org.apache.cayenne.testdo.inheritance.BaseEntity" dbEntityName="BASE_ENTITY">
+		<obj-attribute name="entityType" type="java.lang.String" db-attribute-path="ENTITY_TYPE"/>
+	</obj-entity>
+	<obj-entity name="DirectToSubEntity" className="org.apache.cayenne.testdo.inheritance.DirectToSubEntity" dbEntityName="DIRECT_TO_SUB_ENTITY"/>
+	<obj-entity name="RelatedEntity" className="org.apache.cayenne.testdo.inheritance.RelatedEntity" dbEntityName="RELATED_ENTITY"/>
+	<obj-entity name="SubEntity" superEntityName="BaseEntity" className="org.apache.cayenne.testdo.inheritance.SubEntity">
+		<qualifier><![CDATA[entityType = "sub"]]></qualifier>
+	</obj-entity>
+	<db-relationship name="directToSubEntities" source="BASE_ENTITY" target="DIRECT_TO_SUB_ENTITY">
+		<db-attribute-pair source="DIRECT_TO_SUB_ENTITY_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="relatedEntities" source="BASE_ENTITY" target="RELATED_ENTITY">
+		<db-attribute-pair source="RELATED_ENTITY_ID" target="RELATED_ENTITY_ID"/>
+	</db-relationship>
+	<db-relationship name="subEntity" source="DIRECT_TO_SUB_ENTITY" target="BASE_ENTITY" toMany="true">
+		<db-attribute-pair source="ID" target="DIRECT_TO_SUB_ENTITY_ID"/>
+	</db-relationship>
+	<db-relationship name="entities" source="RELATED_ENTITY" target="BASE_ENTITY" toMany="true">
+		<db-attribute-pair source="RELATED_ENTITY_ID" target="RELATED_ENTITY_ID"/>
+	</db-relationship>
+	<obj-relationship name="toDirectToSubEntity" source="BaseEntity" target="DirectToSubEntity" deleteRule="Nullify" db-relationship-path="directToSubEntities"/>
+	<obj-relationship name="toRelatedEntity" source="BaseEntity" target="RelatedEntity" deleteRule="Nullify" db-relationship-path="relatedEntities"/>
+	<obj-relationship name="subEntities" source="DirectToSubEntity" target="SubEntity" db-relationship-path="subEntity"/>
+	<obj-relationship name="baseEntities" source="RelatedEntity" target="BaseEntity" db-relationship-path="entities"/>
+	<obj-relationship name="subEntities" source="RelatedEntity" target="SubEntity" db-relationship-path="entities"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/lifecycle-callbacks-order.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/lifecycle-callbacks-order.map.xml b/cayenne-server/src/test/resources/lifecycle-callbacks-order.map.xml
index 1afdc32..3d6efd9 100644
--- a/cayenne-server/src/test/resources/lifecycle-callbacks-order.map.xml
+++ b/cayenne-server/src/test/resources/lifecycle-callbacks-order.map.xml
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.lifecycle_callbacks_order"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="org.apache.cayenne.testdo.lifecycle_callbacks_order"/>
-    <db-entity name="LIFECYCLE">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="100"/>
-    </db-entity>
-    <obj-entity name="Lifecycle" className="org.apache.cayenne.testdo.lifecycle_callbacks_order.Lifecycle" dbEntityName="LIFECYCLE">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.lifecycle_callbacks_order"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="org.apache.cayenne.testdo.lifecycle_callbacks_order"/>
+	<db-entity name="LIFECYCLE">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+	</db-entity>
+	<obj-entity name="Lifecycle" className="org.apache.cayenne.testdo.lifecycle_callbacks_order.Lifecycle" dbEntityName="LIFECYCLE">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/lifecycles.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/lifecycles.map.xml b/cayenne-server/src/test/resources/lifecycles.map.xml
index 098b4c5..31a741b 100644
--- a/cayenne-server/src/test/resources/lifecycles.map.xml
+++ b/cayenne-server/src/test/resources/lifecycles.map.xml
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.lifecycles"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="org.apache.cayenne.testdo.lifecycles"/>
-    <db-entity name="LIFECYCLES">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" isMandatory="true" length="100"/>
-    </db-entity>
-    <obj-entity name="Lifecycles" className="org.apache.cayenne.testdo.lifecycles.Lifecycles" clientClassName="org.apache.cayenne.testdo.lifecycles.ClientLifecycles" dbEntityName="LIFECYCLES">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.lifecycles"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="org.apache.cayenne.testdo.lifecycles"/>
+	<db-entity name="LIFECYCLES">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" isMandatory="true" length="100"/>
+	</db-entity>
+	<obj-entity name="Lifecycles" className="org.apache.cayenne.testdo.lifecycles.Lifecycles" clientClassName="org.apache.cayenne.testdo.lifecycles.ClientLifecycles" dbEntityName="LIFECYCLES">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/lob.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/lob.map.xml b/cayenne-server/src/test/resources/lob.map.xml
index e797df7..df846e1 100644
--- a/cayenne-server/src/test/resources/lob.map.xml
+++ b/cayenne-server/src/test/resources/lob.map.xml
@@ -1,53 +1,53 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.lob"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="BLOB_TEST">
-        <db-attribute name="BLOB_COL" type="BLOB"/>
-        <db-attribute name="BLOB_TEST_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="CLOB_TEST">
-        <db-attribute name="CLOB_COL" type="CLOB"/>
-        <db-attribute name="CLOB_TEST_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="NCLOB_TEST">
-        <db-attribute name="NCLOB_COL" type="NCLOB"/>
-        <db-attribute name="NCLOB_TEST_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="CLOB_TEST_RELATION">
-        <db-attribute name="CVALUE" type="INTEGER"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="ID_CLOB" type="INTEGER" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="TEST">
-        <db-attribute name="TEST_ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="TEST_NAME" type="CHAR" isMandatory="true" length="254"/>
-    </db-entity>
-    <obj-entity name="BlobTestEntity" className="org.apache.cayenne.testdo.lob.BlobTestEntity" dbEntityName="BLOB_TEST">
-        <obj-attribute name="blobCol" type="byte[]" db-attribute-path="BLOB_COL"/>
-    </obj-entity>
-    <obj-entity name="ClobTestEntity" className="org.apache.cayenne.testdo.lob.ClobTestEntity" dbEntityName="CLOB_TEST">
-        <obj-attribute name="clobCol" type="java.lang.String" db-attribute-path="CLOB_COL"/>
-    </obj-entity>
-    <obj-entity name="NClobTestEntity" className="org.apache.cayenne.testdo.lob.NClobTestEntity" dbEntityName="NCLOB_TEST">
-        <obj-attribute name="nclobCol" type="java.lang.String" db-attribute-path="NCLOB_COL"/>
-    </obj-entity>
-    <obj-entity name="ClobTestRelation" className="org.apache.cayenne.testdo.lob.ClobTestRelation" dbEntityName="CLOB_TEST_RELATION">
-        <obj-attribute name="id" type="java.lang.Integer" db-attribute-path="ID"/>
-        <obj-attribute name="value" type="java.lang.Integer" db-attribute-path="CVALUE"/>
-    </obj-entity>
-    <db-relationship name="clob" source="CLOB_TEST" target="CLOB_TEST_RELATION" toMany="true">
-        <db-attribute-pair source="CLOB_TEST_ID" target="ID_CLOB"/>
-    </db-relationship>
-    <db-relationship name="CLOB_REL" source="CLOB_TEST_RELATION" target="CLOB_TEST" toMany="false">
-        <db-attribute-pair source="ID_CLOB" target="CLOB_TEST_ID"/>
-    </db-relationship>
-    <obj-relationship name="clobValue" source="ClobTestEntity" target="ClobTestRelation" db-relationship-path="clob"/>
-    <obj-relationship name="clobId" source="ClobTestRelation" target="ClobTestEntity" db-relationship-path="CLOB_REL"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.lob"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="BLOB_TEST">
+		<db-attribute name="BLOB_COL" type="BLOB"/>
+		<db-attribute name="BLOB_TEST_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="CLOB_TEST">
+		<db-attribute name="CLOB_COL" type="CLOB"/>
+		<db-attribute name="CLOB_TEST_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="CLOB_TEST_RELATION">
+		<db-attribute name="CVALUE" type="INTEGER"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="ID_CLOB" type="INTEGER" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="NCLOB_TEST">
+		<db-attribute name="NCLOB_COL" type="NCLOB"/>
+		<db-attribute name="NCLOB_TEST_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="TEST">
+		<db-attribute name="TEST_ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="TEST_NAME" type="CHAR" isMandatory="true" length="254"/>
+	</db-entity>
+	<obj-entity name="BlobTestEntity" className="org.apache.cayenne.testdo.lob.BlobTestEntity" dbEntityName="BLOB_TEST">
+		<obj-attribute name="blobCol" type="byte[]" db-attribute-path="BLOB_COL"/>
+	</obj-entity>
+	<obj-entity name="ClobTestEntity" className="org.apache.cayenne.testdo.lob.ClobTestEntity" dbEntityName="CLOB_TEST">
+		<obj-attribute name="clobCol" type="java.lang.String" db-attribute-path="CLOB_COL"/>
+	</obj-entity>
+	<obj-entity name="ClobTestRelation" className="org.apache.cayenne.testdo.lob.ClobTestRelation" dbEntityName="CLOB_TEST_RELATION">
+		<obj-attribute name="id" type="java.lang.Integer" db-attribute-path="ID"/>
+		<obj-attribute name="value" type="java.lang.Integer" db-attribute-path="CVALUE"/>
+	</obj-entity>
+	<obj-entity name="NClobTestEntity" className="org.apache.cayenne.testdo.lob.NClobTestEntity" dbEntityName="NCLOB_TEST">
+		<obj-attribute name="nclobCol" type="java.lang.String" db-attribute-path="NCLOB_COL"/>
+	</obj-entity>
+	<db-relationship name="clob" source="CLOB_TEST" target="CLOB_TEST_RELATION" toMany="true">
+		<db-attribute-pair source="CLOB_TEST_ID" target="ID_CLOB"/>
+	</db-relationship>
+	<db-relationship name="CLOB_REL" source="CLOB_TEST_RELATION" target="CLOB_TEST">
+		<db-attribute-pair source="ID_CLOB" target="CLOB_TEST_ID"/>
+	</db-relationship>
+	<obj-relationship name="clobValue" source="ClobTestEntity" target="ClobTestRelation" db-relationship-path="clob"/>
+	<obj-relationship name="clobId" source="ClobTestRelation" target="ClobTestEntity" db-relationship-path="CLOB_REL"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/locking.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/locking.map.xml b/cayenne-server/src/test/resources/locking.map.xml
index 9092352..54df6d1 100644
--- a/cayenne-server/src/test/resources/locking.map.xml
+++ b/cayenne-server/src/test/resources/locking.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.locking"/>
 	<db-entity name="LOCKING_HELPER">
 		<db-attribute name="LOCKING_HELPER_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
@@ -29,13 +29,13 @@
 		<obj-attribute name="description" type="java.lang.String" db-attribute-path="DESCRIPTION"/>
 		<obj-attribute name="name" type="java.lang.String" lock="true" db-attribute-path="NAME"/>
 	</obj-entity>
-	<db-relationship name="toRelLockingTest" source="LOCKING_HELPER" target="REL_LOCKING_TEST" toMany="false">
+	<db-relationship name="toRelLockingTest" source="LOCKING_HELPER" target="REL_LOCKING_TEST">
 		<db-attribute-pair source="REL_LOCKING_TEST_ID" target="REL_LOCKING_TEST_ID"/>
 	</db-relationship>
 	<db-relationship name="lockingHelpers" source="REL_LOCKING_TEST" target="LOCKING_HELPER" toMany="true">
 		<db-attribute-pair source="REL_LOCKING_TEST_ID" target="REL_LOCKING_TEST_ID"/>
 	</db-relationship>
-	<db-relationship name="toSimpleLockingTest" source="REL_LOCKING_TEST" target="SIMPLE_LOCKING_TEST" toMany="false">
+	<db-relationship name="toSimpleLockingTest" source="REL_LOCKING_TEST" target="SIMPLE_LOCKING_TEST">
 		<db-attribute-pair source="SIMPLE_LOCKING_TEST_ID" target="LOCKING_TEST_ID"/>
 	</db-relationship>
 	<db-relationship name="relaLockingTests" source="SIMPLE_LOCKING_TEST" target="REL_LOCKING_TEST" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/map-db1.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/map-db1.map.xml b/cayenne-server/src/test/resources/map-db1.map.xml
index 7d1ef52..c5f332e 100644
--- a/cayenne-server/src/test/resources/map-db1.map.xml
+++ b/cayenne-server/src/test/resources/map-db1.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.db1"/>
 	<db-entity name="CROSSDB_M1E1">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/map-db2.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/map-db2.map.xml b/cayenne-server/src/test/resources/map-db2.map.xml
index ebe3163..fd3750c 100644
--- a/cayenne-server/src/test/resources/map-db2.map.xml
+++ b/cayenne-server/src/test/resources/map-db2.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.db2"/>
 	<db-entity name="CROSSDB_M2E1">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
@@ -23,10 +23,10 @@
 	<db-relationship name="listOfM2E2" source="CROSSDB_M2E1" target="CROSSDB_M2E2" toMany="true">
 		<db-attribute-pair source="ID" target="M2E1_ID"/>
 	</db-relationship>
-	<db-relationship name="toM1E1" source="CROSSDB_M2E2" target="CROSSDB_M1E1" toMany="false">
+	<db-relationship name="toM1E1" source="CROSSDB_M2E2" target="CROSSDB_M1E1">
 		<db-attribute-pair source="M1E1_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="toM2E1" source="CROSSDB_M2E2" target="CROSSDB_M2E1" toMany="false">
+	<db-relationship name="toM2E1" source="CROSSDB_M2E2" target="CROSSDB_M2E1">
 		<db-attribute-pair source="M2E1_ID" target="ID"/>
 	</db-relationship>
 	<obj-relationship name="listOfM2E2" source="CrossdbM2E1" target="CrossdbM2E2" db-relationship-path="listOfM2E2"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/map-to-many.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/map-to-many.map.xml b/cayenne-server/src/test/resources/map-to-many.map.xml
index 99dce4d..7852632 100644
--- a/cayenne-server/src/test/resources/map-to-many.map.xml
+++ b/cayenne-server/src/test/resources/map-to-many.map.xml
@@ -1,57 +1,46 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.map_to_many"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="org.apache.cayenne.testdo.map_to_many"/>
-
-    <db-entity name="ID_MAP_TO_MANY">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="ID_MAP_TO_MANY_TARGET">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="MAP_TO_MANY_ID" type="INTEGER"/>
-    </db-entity>
-
-    <db-entity name="MAP_TO_MANY">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="MAP_TO_MANY_TARGET">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="MAP_TO_MANY_ID" type="INTEGER"/>
-        <db-attribute name="NAME" type="VARCHAR" isMandatory="true" length="100"/>
-    </db-entity>
-
-    <obj-entity name="IdMapToMany" className="org.apache.cayenne.testdo.map_to_many.IdMapToMany" clientClassName="org.apache.cayenne.testdo.map_to_many.ClientIdMapToMany" dbEntityName="ID_MAP_TO_MANY">
-    </obj-entity>
-    <obj-entity name="IdMapToManyTarget" className="org.apache.cayenne.testdo.map_to_many.IdMapToManyTarget" clientClassName="org.apache.cayenne.testdo.map_to_many.ClientIdMapToManyTarget" dbEntityName="ID_MAP_TO_MANY_TARGET">
-    </obj-entity>
-
-    <obj-entity name="MapToMany" className="org.apache.cayenne.testdo.map_to_many.MapToMany" dbEntityName="MAP_TO_MANY">
-    </obj-entity>
-    <obj-entity name="MapToManyTarget" className="org.apache.cayenne.testdo.map_to_many.MapToManyTarget" dbEntityName="MAP_TO_MANY_TARGET">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-
-    <db-relationship name="targets" source="ID_MAP_TO_MANY" target="ID_MAP_TO_MANY_TARGET" toMany="true">
-        <db-attribute-pair source="ID" target="MAP_TO_MANY_ID"/>
-    </db-relationship>
-    <db-relationship name="mapToMany" source="ID_MAP_TO_MANY_TARGET" target="ID_MAP_TO_MANY" toMany="false">
-        <db-attribute-pair source="MAP_TO_MANY_ID" target="ID"/>
-    </db-relationship>
-
-    <db-relationship name="targets" source="MAP_TO_MANY" target="MAP_TO_MANY_TARGET" toMany="true">
-        <db-attribute-pair source="ID" target="MAP_TO_MANY_ID"/>
-    </db-relationship>
-    <db-relationship name="mapToMany" source="MAP_TO_MANY_TARGET" target="MAP_TO_MANY" toMany="false">
-        <db-attribute-pair source="MAP_TO_MANY_ID" target="ID"/>
-    </db-relationship>
-
-    <obj-relationship name="targets" source="IdMapToMany" target="IdMapToManyTarget" collection-type="java.util.Map" db-relationship-path="targets"/>
-    <obj-relationship name="mapToMany" source="IdMapToManyTarget" target="IdMapToMany" db-relationship-path="mapToMany"/>
-
-    <obj-relationship name="targets" source="MapToMany" target="MapToManyTarget" collection-type="java.util.Map" map-key="name" db-relationship-path="targets"/>
-    <obj-relationship name="mapToMany" source="MapToManyTarget" target="MapToMany" db-relationship-path="mapToMany"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.map_to_many"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="org.apache.cayenne.testdo.map_to_many"/>
+	<db-entity name="ID_MAP_TO_MANY">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="ID_MAP_TO_MANY_TARGET">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="MAP_TO_MANY_ID" type="INTEGER"/>
+	</db-entity>
+	<db-entity name="MAP_TO_MANY">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="MAP_TO_MANY_TARGET">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="MAP_TO_MANY_ID" type="INTEGER"/>
+		<db-attribute name="NAME" type="VARCHAR" isMandatory="true" length="100"/>
+	</db-entity>
+	<obj-entity name="IdMapToMany" className="org.apache.cayenne.testdo.map_to_many.IdMapToMany" clientClassName="org.apache.cayenne.testdo.map_to_many.ClientIdMapToMany" dbEntityName="ID_MAP_TO_MANY"/>
+	<obj-entity name="IdMapToManyTarget" className="org.apache.cayenne.testdo.map_to_many.IdMapToManyTarget" clientClassName="org.apache.cayenne.testdo.map_to_many.ClientIdMapToManyTarget" dbEntityName="ID_MAP_TO_MANY_TARGET"/>
+	<obj-entity name="MapToMany" className="org.apache.cayenne.testdo.map_to_many.MapToMany" dbEntityName="MAP_TO_MANY"/>
+	<obj-entity name="MapToManyTarget" className="org.apache.cayenne.testdo.map_to_many.MapToManyTarget" dbEntityName="MAP_TO_MANY_TARGET">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<db-relationship name="targets" source="ID_MAP_TO_MANY" target="ID_MAP_TO_MANY_TARGET" toMany="true">
+		<db-attribute-pair source="ID" target="MAP_TO_MANY_ID"/>
+	</db-relationship>
+	<db-relationship name="mapToMany" source="ID_MAP_TO_MANY_TARGET" target="ID_MAP_TO_MANY">
+		<db-attribute-pair source="MAP_TO_MANY_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="targets" source="MAP_TO_MANY" target="MAP_TO_MANY_TARGET" toMany="true">
+		<db-attribute-pair source="ID" target="MAP_TO_MANY_ID"/>
+	</db-relationship>
+	<db-relationship name="mapToMany" source="MAP_TO_MANY_TARGET" target="MAP_TO_MANY">
+		<db-attribute-pair source="MAP_TO_MANY_ID" target="ID"/>
+	</db-relationship>
+	<obj-relationship name="targets" source="IdMapToMany" target="IdMapToManyTarget" collection-type="java.util.Map" db-relationship-path="targets"/>
+	<obj-relationship name="mapToMany" source="IdMapToManyTarget" target="IdMapToMany" db-relationship-path="mapToMany"/>
+	<obj-relationship name="targets" source="MapToMany" target="MapToManyTarget" collection-type="java.util.Map" map-key="name" db-relationship-path="targets"/>
+	<obj-relationship name="mapToMany" source="MapToManyTarget" target="MapToMany" db-relationship-path="mapToMany"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/meaningful-pk.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/meaningful-pk.map.xml b/cayenne-server/src/test/resources/meaningful-pk.map.xml
index ca41207..15e3462 100644
--- a/cayenne-server/src/test/resources/meaningful-pk.map.xml
+++ b/cayenne-server/src/test/resources/meaningful-pk.map.xml
@@ -1,39 +1,39 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.meaningful_pk"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="org.apache.cayenne.testdo.meaningful_pk"/>
-    <db-entity name="MEANINGFUL_PK">
-        <db-attribute name="PK" type="VARCHAR" isPrimaryKey="true" isMandatory="true" length="100"/>
-    </db-entity>
-    <db-entity name="MEANINGFUL_PK_DEP">
-        <db-attribute name="DESCR" type="VARCHAR" length="50"/>
-        <db-attribute name="MASTER_PK" type="INTEGER"/>
-        <db-attribute name="PK_ATTRIBUTE" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="MEANINGFUL_PK_TEST1">
-        <db-attribute name="DESCR" type="VARCHAR" length="50"/>
-        <db-attribute name="PK_ATTRIBUTE" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <obj-entity name="MeaningfulPk" className="org.apache.cayenne.testdo.meaningful_pk.MeaningfulPk" clientClassName="org.apache.cayenne.testdo.meaningful_pk.ClientMeaningfulPk" dbEntityName="MEANINGFUL_PK">
-        <obj-attribute name="pk" type="java.lang.String" db-attribute-path="PK"/>
-    </obj-entity>
-    <obj-entity name="MeaningfulPKDep" className="org.apache.cayenne.testdo.meaningful_pk.MeaningfulPKDep" dbEntityName="MEANINGFUL_PK_DEP">
-        <obj-attribute name="descr" type="java.lang.String" db-attribute-path="DESCR"/>
-    </obj-entity>
-    <obj-entity name="MeaningfulPKTest1" className="org.apache.cayenne.testdo.meaningful_pk.MeaningfulPKTest1" dbEntityName="MEANINGFUL_PK_TEST1">
-        <obj-attribute name="descr" type="java.lang.String" db-attribute-path="DESCR"/>
-        <obj-attribute name="pkAttribute" type="java.lang.Integer" db-attribute-path="PK_ATTRIBUTE"/>
-    </obj-entity>
-    <db-relationship name="toMeaningfulPK" source="MEANINGFUL_PK_DEP" target="MEANINGFUL_PK_TEST1" toMany="false">
-        <db-attribute-pair source="MASTER_PK" target="PK_ATTRIBUTE"/>
-    </db-relationship>
-    <db-relationship name="meaningfulPKDepArray" source="MEANINGFUL_PK_TEST1" target="MEANINGFUL_PK_DEP" toMany="true">
-        <db-attribute-pair source="PK_ATTRIBUTE" target="MASTER_PK"/>
-    </db-relationship>
-    <obj-relationship name="toMeaningfulPK" source="MeaningfulPKDep" target="MeaningfulPKTest1" db-relationship-path="toMeaningfulPK"/>
-    <obj-relationship name="meaningfulPKDepArray" source="MeaningfulPKTest1" target="MeaningfulPKDep" db-relationship-path="meaningfulPKDepArray"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.meaningful_pk"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="org.apache.cayenne.testdo.meaningful_pk"/>
+	<db-entity name="MEANINGFUL_PK">
+		<db-attribute name="PK" type="VARCHAR" isPrimaryKey="true" isMandatory="true" length="100"/>
+	</db-entity>
+	<db-entity name="MEANINGFUL_PK_DEP">
+		<db-attribute name="DESCR" type="VARCHAR" length="50"/>
+		<db-attribute name="MASTER_PK" type="INTEGER"/>
+		<db-attribute name="PK_ATTRIBUTE" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="MEANINGFUL_PK_TEST1">
+		<db-attribute name="DESCR" type="VARCHAR" length="50"/>
+		<db-attribute name="PK_ATTRIBUTE" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<obj-entity name="MeaningfulPKDep" className="org.apache.cayenne.testdo.meaningful_pk.MeaningfulPKDep" dbEntityName="MEANINGFUL_PK_DEP">
+		<obj-attribute name="descr" type="java.lang.String" db-attribute-path="DESCR"/>
+	</obj-entity>
+	<obj-entity name="MeaningfulPKTest1" className="org.apache.cayenne.testdo.meaningful_pk.MeaningfulPKTest1" dbEntityName="MEANINGFUL_PK_TEST1">
+		<obj-attribute name="descr" type="java.lang.String" db-attribute-path="DESCR"/>
+		<obj-attribute name="pkAttribute" type="java.lang.Integer" db-attribute-path="PK_ATTRIBUTE"/>
+	</obj-entity>
+	<obj-entity name="MeaningfulPk" className="org.apache.cayenne.testdo.meaningful_pk.MeaningfulPk" clientClassName="org.apache.cayenne.testdo.meaningful_pk.ClientMeaningfulPk" dbEntityName="MEANINGFUL_PK">
+		<obj-attribute name="pk" type="java.lang.String" db-attribute-path="PK"/>
+	</obj-entity>
+	<db-relationship name="toMeaningfulPK" source="MEANINGFUL_PK_DEP" target="MEANINGFUL_PK_TEST1">
+		<db-attribute-pair source="MASTER_PK" target="PK_ATTRIBUTE"/>
+	</db-relationship>
+	<db-relationship name="meaningfulPKDepArray" source="MEANINGFUL_PK_TEST1" target="MEANINGFUL_PK_DEP" toMany="true">
+		<db-attribute-pair source="PK_ATTRIBUTE" target="MASTER_PK"/>
+	</db-relationship>
+	<obj-relationship name="toMeaningfulPK" source="MeaningfulPKDep" target="MeaningfulPKTest1" db-relationship-path="toMeaningfulPK"/>
+	<obj-relationship name="meaningfulPKDepArray" source="MeaningfulPKTest1" target="MeaningfulPKDep" db-relationship-path="meaningfulPKDepArray"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/misc-types.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/misc-types.map.xml b/cayenne-server/src/test/resources/misc-types.map.xml
index 616ab44..59ed67c 100644
--- a/cayenne-server/src/test/resources/misc-types.map.xml
+++ b/cayenne-server/src/test/resources/misc-types.map.xml
@@ -1,38 +1,38 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.misc_types"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="ARRAYS_ENTITY">
-        <db-attribute name="BYTE_ARRAY" type="VARBINARY" length="200"/>
-        <db-attribute name="BYTE_WRAPPER_ARRAY" type="VARBINARY" length="200"/>
-        <db-attribute name="CHAR_ARRAY" type="VARCHAR" length="200"/>
-        <db-attribute name="CHAR_WRAPPER_ARRAY" type="VARCHAR" length="200"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="CHARACTER_ENTITY">
-        <db-attribute name="CHARACTER_FIELD" type="CHAR" length="1"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="SERIALIZABLE_ENTITY">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="SERIALIZABLE_FIELD" type="BLOB"/>
-    </db-entity>
-    <obj-entity name="ArraysEntity" className="org.apache.cayenne.testdo.misc_types.ArraysEntity" dbEntityName="ARRAYS_ENTITY">
-        <obj-attribute name="byteArray" type="byte[]" db-attribute-path="BYTE_ARRAY"/>
-        <obj-attribute name="byteWrapperArray" type="java.lang.Byte[]" db-attribute-path="BYTE_WRAPPER_ARRAY"/>
-        <obj-attribute name="charArray" type="char[]" db-attribute-path="CHAR_ARRAY"/>
-        <obj-attribute name="charWrapperArray" type="java.lang.Character[]" db-attribute-path="CHAR_WRAPPER_ARRAY"/>
-    </obj-entity>
-    <obj-entity name="CharacterEntity" className="org.apache.cayenne.testdo.misc_types.CharacterEntity" dbEntityName="CHARACTER_ENTITY">
-        <obj-attribute name="characterField" type="java.lang.Character" db-attribute-path="CHARACTER_FIELD"/>
-    </obj-entity>
-    <obj-entity name="SerializableEntity" className="org.apache.cayenne.testdo.misc_types.SerializableEntity" dbEntityName="SERIALIZABLE_ENTITY">
-        <obj-attribute name="serializableField" type="org.apache.cayenne.MockSerializable" db-attribute-path="SERIALIZABLE_FIELD"/>
-    </obj-entity>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.misc_types"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="ARRAYS_ENTITY">
+		<db-attribute name="BYTE_ARRAY" type="VARBINARY" length="200"/>
+		<db-attribute name="BYTE_WRAPPER_ARRAY" type="VARBINARY" length="200"/>
+		<db-attribute name="CHAR_ARRAY" type="VARCHAR" length="200"/>
+		<db-attribute name="CHAR_WRAPPER_ARRAY" type="VARCHAR" length="200"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="CHARACTER_ENTITY">
+		<db-attribute name="CHARACTER_FIELD" type="CHAR" length="1"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="SERIALIZABLE_ENTITY">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="SERIALIZABLE_FIELD" type="BLOB"/>
+	</db-entity>
+	<obj-entity name="ArraysEntity" className="org.apache.cayenne.testdo.misc_types.ArraysEntity" dbEntityName="ARRAYS_ENTITY">
+		<obj-attribute name="byteArray" type="byte[]" db-attribute-path="BYTE_ARRAY"/>
+		<obj-attribute name="byteWrapperArray" type="java.lang.Byte[]" db-attribute-path="BYTE_WRAPPER_ARRAY"/>
+		<obj-attribute name="charArray" type="char[]" db-attribute-path="CHAR_ARRAY"/>
+		<obj-attribute name="charWrapperArray" type="java.lang.Character[]" db-attribute-path="CHAR_WRAPPER_ARRAY"/>
+	</obj-entity>
+	<obj-entity name="CharacterEntity" className="org.apache.cayenne.testdo.misc_types.CharacterEntity" dbEntityName="CHARACTER_ENTITY">
+		<obj-attribute name="characterField" type="java.lang.Character" db-attribute-path="CHARACTER_FIELD"/>
+	</obj-entity>
+	<obj-entity name="SerializableEntity" className="org.apache.cayenne.testdo.misc_types.SerializableEntity" dbEntityName="SERIALIZABLE_ENTITY">
+		<obj-attribute name="serializableField" type="org.apache.cayenne.MockSerializable" db-attribute-path="SERIALIZABLE_FIELD"/>
+	</obj-entity>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/mixed-persistence-strategy.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/mixed-persistence-strategy.map.xml b/cayenne-server/src/test/resources/mixed-persistence-strategy.map.xml
index d800e13..e8aa9f5 100644
--- a/cayenne-server/src/test/resources/mixed-persistence-strategy.map.xml
+++ b/cayenne-server/src/test/resources/mixed-persistence-strategy.map.xml
@@ -1,36 +1,36 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.mixed_persistence_strategy"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="MIXED_PERSISTENCE_STRATEGY">
-        <db-attribute name="DESCRIPTION" type="VARCHAR" length="200"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="200"/>
-    </db-entity>
-    <db-entity name="MIXED_PERSISTENCE_STRATEGY2">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="MASTER_ID" type="INTEGER"/>
-        <db-attribute name="NAME" type="VARCHAR" length="200"/>
-    </db-entity>
-    <obj-entity name="MixedPersistenceStrategy" className="org.apache.cayenne.testdo.mixed_persistence_strategy.MixedPersistenceStrategy" dbEntityName="MIXED_PERSISTENCE_STRATEGY">
-        <obj-attribute name="description" type="java.lang.String" db-attribute-path="DESCRIPTION"/>
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="MixedPersistenceStrategy2" className="org.apache.cayenne.testdo.mixed_persistence_strategy.MixedPersistenceStrategy2" dbEntityName="MIXED_PERSISTENCE_STRATEGY2">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <db-relationship name="details" source="MIXED_PERSISTENCE_STRATEGY" target="MIXED_PERSISTENCE_STRATEGY2" toMany="true">
-        <db-attribute-pair source="ID" target="MASTER_ID"/>
-    </db-relationship>
-    <db-relationship name="master" source="MIXED_PERSISTENCE_STRATEGY2" target="MIXED_PERSISTENCE_STRATEGY" toMany="false">
-        <db-attribute-pair source="MASTER_ID" target="ID"/>
-    </db-relationship>
-    <obj-relationship name="details" source="MixedPersistenceStrategy" target="MixedPersistenceStrategy2" db-relationship-path="details"/>
-    <obj-relationship name="master" source="MixedPersistenceStrategy2" target="MixedPersistenceStrategy" db-relationship-path="master"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.mixed_persistence_strategy"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="MIXED_PERSISTENCE_STRATEGY">
+		<db-attribute name="DESCRIPTION" type="VARCHAR" length="200"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="200"/>
+	</db-entity>
+	<db-entity name="MIXED_PERSISTENCE_STRATEGY2">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="MASTER_ID" type="INTEGER"/>
+		<db-attribute name="NAME" type="VARCHAR" length="200"/>
+	</db-entity>
+	<obj-entity name="MixedPersistenceStrategy" className="org.apache.cayenne.testdo.mixed_persistence_strategy.MixedPersistenceStrategy" dbEntityName="MIXED_PERSISTENCE_STRATEGY">
+		<obj-attribute name="description" type="java.lang.String" db-attribute-path="DESCRIPTION"/>
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="MixedPersistenceStrategy2" className="org.apache.cayenne.testdo.mixed_persistence_strategy.MixedPersistenceStrategy2" dbEntityName="MIXED_PERSISTENCE_STRATEGY2">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<db-relationship name="details" source="MIXED_PERSISTENCE_STRATEGY" target="MIXED_PERSISTENCE_STRATEGY2" toMany="true">
+		<db-attribute-pair source="ID" target="MASTER_ID"/>
+	</db-relationship>
+	<db-relationship name="master" source="MIXED_PERSISTENCE_STRATEGY2" target="MIXED_PERSISTENCE_STRATEGY">
+		<db-attribute-pair source="MASTER_ID" target="ID"/>
+	</db-relationship>
+	<obj-relationship name="details" source="MixedPersistenceStrategy" target="MixedPersistenceStrategy2" db-relationship-path="details"/>
+	<obj-relationship name="master" source="MixedPersistenceStrategy2" target="MixedPersistenceStrategy" db-relationship-path="master"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/multi-tier.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/multi-tier.map.xml b/cayenne-server/src/test/resources/multi-tier.map.xml
index 016fc58..a63f0a3 100644
--- a/cayenne-server/src/test/resources/multi-tier.map.xml
+++ b/cayenne-server/src/test/resources/multi-tier.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.mt"/>
 	<property name="clientSupported" value="true"/>
 	<property name="defaultClientPackage" value="org.apache.cayenne.testdo.mt"/>
@@ -54,23 +54,21 @@
 		<obj-attribute name="charColumn" type="java.lang.String" db-attribute-path="CHAR_COLUMN"/>
 		<obj-attribute name="intColumn" type="java.lang.Integer" db-attribute-path="INT_COLUMN"/>
 	</obj-entity>
-	<obj-entity name="MtTable4" className="org.apache.cayenne.testdo.mt.MtTable4" clientClassName="org.apache.cayenne.testdo.mt.ClientMtTable4" dbEntityName="MT_TABLE4">
-	</obj-entity>
-	<obj-entity name="MtTable5" className="org.apache.cayenne.testdo.mt.MtTable5" clientClassName="org.apache.cayenne.testdo.mt.ClientMtTable5" dbEntityName="MT_TABLE5">
-	</obj-entity>
-	<db-relationship name="toTable4" source="MT_JOIN45" target="MT_TABLE4" toMany="false">
+	<obj-entity name="MtTable4" className="org.apache.cayenne.testdo.mt.MtTable4" clientClassName="org.apache.cayenne.testdo.mt.ClientMtTable4" dbEntityName="MT_TABLE4"/>
+	<obj-entity name="MtTable5" className="org.apache.cayenne.testdo.mt.MtTable5" clientClassName="org.apache.cayenne.testdo.mt.ClientMtTable5" dbEntityName="MT_TABLE5"/>
+	<db-relationship name="toTable4" source="MT_JOIN45" target="MT_TABLE4">
 		<db-attribute-pair source="TABLE4_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="toTable5" source="MT_JOIN45" target="MT_TABLE5" toMany="false">
+	<db-relationship name="toTable5" source="MT_JOIN45" target="MT_TABLE5">
 		<db-attribute-pair source="TABLE5_ID" target="ID"/>
 	</db-relationship>
 	<db-relationship name="table2Array" source="MT_TABLE1" target="MT_TABLE2" toMany="true">
 		<db-attribute-pair source="TABLE1_ID" target="TABLE1_ID"/>
 	</db-relationship>
-	<db-relationship name="table1" source="MT_TABLE2" target="MT_TABLE1" toMany="false">
+	<db-relationship name="table1" source="MT_TABLE2" target="MT_TABLE1">
 		<db-attribute-pair source="TABLE1_ID" target="TABLE1_ID"/>
 	</db-relationship>
-	<db-relationship name="table3" source="MT_TABLE2" target="MT_TABLE3" toMany="false">
+	<db-relationship name="table3" source="MT_TABLE2" target="MT_TABLE3">
 		<db-attribute-pair source="TABLE3_ID" target="TABLE3_ID"/>
 	</db-relationship>
 	<db-relationship name="table2Array" source="MT_TABLE3" target="MT_TABLE2" toMany="true">
@@ -88,8 +86,7 @@
 	<obj-relationship name="table2Array" source="MtTable3" target="MtTable2" deleteRule="Deny" db-relationship-path="table2Array"/>
 	<obj-relationship name="table5s" source="MtTable4" target="MtTable5" db-relationship-path="joins.toTable5"/>
 	<obj-relationship name="table4s" source="MtTable5" target="MtTable4" db-relationship-path="joins.toTable4"/>
-	<query name="AllMtTable1" type="SelectQuery" root="obj-entity" root-name="MtTable1">
-	</query>
+	<query name="AllMtTable1" type="SelectQuery" root="obj-entity" root-name="MtTable1"/>
 	<query name="MtQueryWithLocalCache" type="SelectQuery" root="obj-entity" root-name="MtTable1">
 		<property name="cayenne.GenericSelectQuery.cacheStrategy" value="LOCAL_CACHE"/>
 	</query>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/no-pk.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/no-pk.map.xml b/cayenne-server/src/test/resources/no-pk.map.xml
index 37f913a..27fe104 100644
--- a/cayenne-server/src/test/resources/no-pk.map.xml
+++ b/cayenne-server/src/test/resources/no-pk.map.xml
@@ -1,17 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.no_pk"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="NO_PK_TEST">
-        <db-attribute name="ATTRIBUTE1" type="INTEGER"/>
-    </db-entity>
-    <obj-entity name="NoPkTestEntity" className="org.apache.cayenne.testdo.no_pk.NoPkTestEntity" dbEntityName="NO_PK_TEST">
-        <obj-attribute name="attribute1" type="java.lang.Integer" db-attribute-path="ATTRIBUTE1"/>
-    </obj-entity>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.no_pk"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="NO_PK_TEST">
+		<db-attribute name="ATTRIBUTE1" type="INTEGER"/>
+	</db-entity>
+	<obj-entity name="NoPkTestEntity" className="org.apache.cayenne.testdo.no_pk.NoPkTestEntity" dbEntityName="NO_PK_TEST">
+		<obj-attribute name="attribute1" type="java.lang.Integer" db-attribute-path="ATTRIBUTE1"/>
+	</obj-entity>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/numeric-types.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/numeric-types.map.xml b/cayenne-server/src/test/resources/numeric-types.map.xml
index 179add2..65d4000 100644
--- a/cayenne-server/src/test/resources/numeric-types.map.xml
+++ b/cayenne-server/src/test/resources/numeric-types.map.xml
@@ -1,79 +1,79 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.numeric_types"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="BIGDECIMAL_ENTITY">
-        <db-attribute name="BIGDECIMAL_FIELD" type="NUMERIC" length="12" scale="2"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="BIGINTEGER_ENTITY">
-        <db-attribute name="BIG_INTEGER_FIELD" type="BIGINT"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="BIT_TEST">
-        <db-attribute name="BIT_COLUMN" type="BIT" isMandatory="true"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="BOOLEAN_TEST">
-        <db-attribute name="BOOLEAN_COLUMN" type="BOOLEAN" isMandatory="true"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="DECIMAL_PK_TST">
-        <db-attribute name="DECIMAL_PK" type="DECIMAL" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="100"/>
-    </db-entity>
-    <db-entity name="FLOAT_TEST">
-        <db-attribute name="FLOAT_COL" type="FLOAT"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <db-entity name="LONG_ENTITY">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="LONG_FIELD" type="BIGINT"/>
-    </db-entity>
-    <db-entity name="SMALLINT_TEST">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="SMALLINT_COL" type="SMALLINT"/>
-    </db-entity>
-    <db-entity name="TINYINT_TEST">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="TINYINT_COL" type="TINYINT"/>
-    </db-entity>
-    <obj-entity name="BigDecimalEntity" className="org.apache.cayenne.testdo.numeric_types.BigDecimalEntity" dbEntityName="BIGDECIMAL_ENTITY">
-        <obj-attribute name="bigDecimalField" type="java.math.BigDecimal" db-attribute-path="BIGDECIMAL_FIELD"/>
-    </obj-entity>
-    <obj-entity name="BigIntegerEntity" className="org.apache.cayenne.testdo.numeric_types.BigIntegerEntity" dbEntityName="BIGINTEGER_ENTITY">
-        <obj-attribute name="bigIntegerField" type="java.math.BigInteger" db-attribute-path="BIG_INTEGER_FIELD"/>
-    </obj-entity>
-    <obj-entity name="BitNumberTestEntity" className="org.apache.cayenne.testdo.numeric_types.BitNumberTestEntity" dbEntityName="BIT_TEST">
-        <obj-attribute name="bitColumn" type="java.lang.Integer" db-attribute-path="BIT_COLUMN"/>
-    </obj-entity>
-    <obj-entity name="BitTestEntity" className="org.apache.cayenne.testdo.numeric_types.BitTestEntity" dbEntityName="BIT_TEST">
-        <obj-attribute name="bitColumn" type="java.lang.Boolean" db-attribute-path="BIT_COLUMN"/>
-    </obj-entity>
-    <obj-entity name="BooleanTestEntity" className="org.apache.cayenne.testdo.numeric_types.BooleanTestEntity" dbEntityName="BOOLEAN_TEST">
-        <obj-attribute name="booleanColumn" type="java.lang.Boolean" db-attribute-path="BOOLEAN_COLUMN"/>
-    </obj-entity>
-    <obj-entity name="DecimalPKTest1" className="org.apache.cayenne.testdo.numeric_types.DecimalPKTest1" dbEntityName="DECIMAL_PK_TST">
-        <obj-attribute name="decimalPK" type="java.lang.Double" db-attribute-path="DECIMAL_PK"/>
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="DecimalPKTestEntity" className="org.apache.cayenne.testdo.numeric_types.DecimalPKTestEntity" dbEntityName="DECIMAL_PK_TST">
-        <obj-attribute name="decimalPK" type="java.math.BigDecimal" db-attribute-path="DECIMAL_PK"/>
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="LongEntity" className="org.apache.cayenne.testdo.numeric_types.LongEntity" dbEntityName="LONG_ENTITY">
-        <obj-attribute name="longField" type="java.lang.Long" db-attribute-path="LONG_FIELD"/>
-    </obj-entity>
-    <obj-entity name="SmallintTestEntity" className="org.apache.cayenne.testdo.numeric_types.SmallintTestEntity" dbEntityName="SMALLINT_TEST">
-        <obj-attribute name="smallintCol" type="java.lang.Short" db-attribute-path="SMALLINT_COL"/>
-    </obj-entity>
-    <obj-entity name="TinyintTestEntity" className="org.apache.cayenne.testdo.numeric_types.TinyintTestEntity" dbEntityName="TINYINT_TEST">
-        <obj-attribute name="tinyintCol" type="java.lang.Byte" db-attribute-path="TINYINT_COL"/>
-    </obj-entity>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.numeric_types"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="BIGDECIMAL_ENTITY">
+		<db-attribute name="BIGDECIMAL_FIELD" type="NUMERIC" length="12" scale="2"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="BIGINTEGER_ENTITY">
+		<db-attribute name="BIG_INTEGER_FIELD" type="BIGINT"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="BIT_TEST">
+		<db-attribute name="BIT_COLUMN" type="BIT" isMandatory="true"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="BOOLEAN_TEST">
+		<db-attribute name="BOOLEAN_COLUMN" type="BOOLEAN" isMandatory="true"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="DECIMAL_PK_TST">
+		<db-attribute name="DECIMAL_PK" type="DECIMAL" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+	</db-entity>
+	<db-entity name="FLOAT_TEST">
+		<db-attribute name="FLOAT_COL" type="FLOAT"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="LONG_ENTITY">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="LONG_FIELD" type="BIGINT"/>
+	</db-entity>
+	<db-entity name="SMALLINT_TEST">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="SMALLINT_COL" type="SMALLINT"/>
+	</db-entity>
+	<db-entity name="TINYINT_TEST">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="TINYINT_COL" type="TINYINT"/>
+	</db-entity>
+	<obj-entity name="BigDecimalEntity" className="org.apache.cayenne.testdo.numeric_types.BigDecimalEntity" dbEntityName="BIGDECIMAL_ENTITY">
+		<obj-attribute name="bigDecimalField" type="java.math.BigDecimal" db-attribute-path="BIGDECIMAL_FIELD"/>
+	</obj-entity>
+	<obj-entity name="BigIntegerEntity" className="org.apache.cayenne.testdo.numeric_types.BigIntegerEntity" dbEntityName="BIGINTEGER_ENTITY">
+		<obj-attribute name="bigIntegerField" type="java.math.BigInteger" db-attribute-path="BIG_INTEGER_FIELD"/>
+	</obj-entity>
+	<obj-entity name="BitNumberTestEntity" className="org.apache.cayenne.testdo.numeric_types.BitNumberTestEntity" dbEntityName="BIT_TEST">
+		<obj-attribute name="bitColumn" type="java.lang.Integer" db-attribute-path="BIT_COLUMN"/>
+	</obj-entity>
+	<obj-entity name="BitTestEntity" className="org.apache.cayenne.testdo.numeric_types.BitTestEntity" dbEntityName="BIT_TEST">
+		<obj-attribute name="bitColumn" type="java.lang.Boolean" db-attribute-path="BIT_COLUMN"/>
+	</obj-entity>
+	<obj-entity name="BooleanTestEntity" className="org.apache.cayenne.testdo.numeric_types.BooleanTestEntity" dbEntityName="BOOLEAN_TEST">
+		<obj-attribute name="booleanColumn" type="java.lang.Boolean" db-attribute-path="BOOLEAN_COLUMN"/>
+	</obj-entity>
+	<obj-entity name="DecimalPKTest1" className="org.apache.cayenne.testdo.numeric_types.DecimalPKTest1" dbEntityName="DECIMAL_PK_TST">
+		<obj-attribute name="decimalPK" type="java.lang.Double" db-attribute-path="DECIMAL_PK"/>
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="DecimalPKTestEntity" className="org.apache.cayenne.testdo.numeric_types.DecimalPKTestEntity" dbEntityName="DECIMAL_PK_TST">
+		<obj-attribute name="decimalPK" type="java.math.BigDecimal" db-attribute-path="DECIMAL_PK"/>
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="LongEntity" className="org.apache.cayenne.testdo.numeric_types.LongEntity" dbEntityName="LONG_ENTITY">
+		<obj-attribute name="longField" type="java.lang.Long" db-attribute-path="LONG_FIELD"/>
+	</obj-entity>
+	<obj-entity name="SmallintTestEntity" className="org.apache.cayenne.testdo.numeric_types.SmallintTestEntity" dbEntityName="SMALLINT_TEST">
+		<obj-attribute name="smallintCol" type="java.lang.Short" db-attribute-path="SMALLINT_COL"/>
+	</obj-entity>
+	<obj-entity name="TinyintTestEntity" className="org.apache.cayenne.testdo.numeric_types.TinyintTestEntity" dbEntityName="TINYINT_TEST">
+		<obj-attribute name="tinyintCol" type="java.lang.Byte" db-attribute-path="TINYINT_COL"/>
+	</obj-entity>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/oneway-rels.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/oneway-rels.map.xml b/cayenne-server/src/test/resources/oneway-rels.map.xml
index 9ce6d58..4d33b2c 100644
--- a/cayenne-server/src/test/resources/oneway-rels.map.xml
+++ b/cayenne-server/src/test/resources/oneway-rels.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.oneway"/>
 	<db-entity name="oneway_table1">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
@@ -18,16 +18,13 @@
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="TABLE3_ID" type="INTEGER"/>
 	</db-entity>
-	<obj-entity name="OnewayTable1" className="org.apache.cayenne.testdo.oneway.OnewayTable1" dbEntityName="oneway_table1">
-	</obj-entity>
+	<obj-entity name="OnewayTable1" className="org.apache.cayenne.testdo.oneway.OnewayTable1" dbEntityName="oneway_table1"/>
 	<obj-entity name="OnewayTable2" className="org.apache.cayenne.testdo.oneway.OnewayTable2" dbEntityName="oneway_table2">
 		<obj-attribute name="id" type="java.lang.Integer" db-attribute-path="ID"/>
 	</obj-entity>
-	<obj-entity name="OnewayTable3" className="org.apache.cayenne.testdo.oneway.OnewayTable3" dbEntityName="oneway_table3">
-	</obj-entity>
-	<obj-entity name="OnewayTable4" className="org.apache.cayenne.testdo.oneway.OnewayTable4" dbEntityName="oneway_table4">
-	</obj-entity>
-	<db-relationship name="toOneOneWayDb" source="oneway_table2" target="oneway_table1" toMany="false">
+	<obj-entity name="OnewayTable3" className="org.apache.cayenne.testdo.oneway.OnewayTable3" dbEntityName="oneway_table3"/>
+	<obj-entity name="OnewayTable4" className="org.apache.cayenne.testdo.oneway.OnewayTable4" dbEntityName="oneway_table4"/>
+	<db-relationship name="toOneOneWayDb" source="oneway_table2" target="oneway_table1">
 		<db-attribute-pair source="TABLE1_ID" target="ID"/>
 	</db-relationship>
 	<db-relationship name="toManyOneWayDb" source="oneway_table3" target="oneway_table4" toMany="true">

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

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

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/cayenne-testConfig3.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/cayenne-testConfig3.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/cayenne-testConfig3.xml
deleted file mode 100644
index 1a2e3e5..0000000
--- a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/cayenne-testConfig3.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<domain project-version="6">
-	<map name="testConfigMap3_1" location="testConfigMap3_1.map.xml" />
-	<map name="testConfigMap3_2" location="testConfigMap3_2.map.xml" />
-
-	<node name="testConfigNode3" adapter="org.example.test.Adapter"
-		factory="org.example.test.DataSourceFactory" schema-update-strategy="org.example.test.SchemaUpdateStartegy">
-		<map-ref name="testConfigMap3_2" />
-		<data-source>
-			<connectionPool min="1" max="1" />
-			<login />
-		</data-source>
-	</node>
-</domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/testConfigMap2.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/testConfigMap2.map.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/testConfigMap2.map.xml
deleted file mode 100644
index 6b79eb5..0000000
--- a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/testConfigMap2.map.xml
+++ /dev/null
@@ -1,7 +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">
-
-</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/testConfigMap3_1.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/testConfigMap3_1.map.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/testConfigMap3_1.map.xml
deleted file mode 100644
index 6b79eb5..0000000
--- a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/testConfigMap3_1.map.xml
+++ /dev/null
@@ -1,7 +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">
-
-</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/testConfigMap3_2.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/testConfigMap3_2.map.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/testConfigMap3_2.map.xml
deleted file mode 100644
index 6b79eb5..0000000
--- a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/testConfigMap3_2.map.xml
+++ /dev/null
@@ -1,7 +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">
-
-</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/DbEntityHandlerTest.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/DbEntityHandlerTest.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/DbEntityHandlerTest.xml
new file mode 100644
index 0000000..f941c79
--- /dev/null
+++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/DbEntityHandlerTest.xml
@@ -0,0 +1,25 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~   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.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<db-entity name="ARTGROUP" catalog="catalog" schema="schema">
+    <db-attribute name="GROUP_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" isGenerated="true"/>
+    <db-attribute name="NAME" type="VARCHAR" isMandatory="true" length="100"/>
+    <db-attribute name="PARENT_GROUP_ID" type="BIT" scale="10"/>
+    <qualifier><![CDATA[name = "test"]]></qualifier>
+</db-entity>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/DbKeyGeneratorHandlerTest.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/DbKeyGeneratorHandlerTest.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/DbKeyGeneratorHandlerTest.xml
new file mode 100644
index 0000000..dc0291a
--- /dev/null
+++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/DbKeyGeneratorHandlerTest.xml
@@ -0,0 +1,24 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~   Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you under the Apache License, Version 2.0 (the
+  ~  "License"); you may not use this file except in compliance
+  ~  with the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing,
+  ~  software distributed under the License is distributed on an
+  ~  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~  KIND, either express or implied.  See the License for the
+  ~  specific language governing permissions and limitations
+  ~  under the License.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<db-key-generator>
+    <db-generator-type>ORACLE</db-generator-type>
+    <db-generator-name>gallery_seq</db-generator-name>
+    <db-key-cache-size>20</db-key-cache-size>
+</db-key-generator>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/DbRelationshipHandlerTest.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/DbRelationshipHandlerTest.xml b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/DbRelationshipHandlerTest.xml
new file mode 100644
index 0000000..dfaed06
--- /dev/null
+++ b/cayenne-server/src/test/resources/org/apache/cayenne/configuration/xml/DbRelationshipHandlerTest.xml
@@ -0,0 +1,22 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~   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.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<db-relationship name="artistPaintings" source="ARTIST" target="PAINTING" toDependentPK="true" toMany="true">
+    <db-attribute-pair source="ID" target="ARTIST_ID"/>
+</db-relationship>


[06/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - new XML loader for DataMap - new project version - updated test projects

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptor.java
index fe18894..335f109 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptor.java
@@ -42,6 +42,31 @@ public class QueryDescriptor implements Serializable, ConfigurationNode, XMLSeri
     public static final String PROCEDURE_QUERY = "ProcedureQuery";
 
     /**
+     * @since 4.1
+     */
+    public static final String OBJ_ENTITY_ROOT = "obj-entity";
+
+    /**
+     * @since 4.1
+     */
+    public static final String DB_ENTITY_ROOT = "db-entity";
+
+    /**
+     * @since 4.1
+     */
+    public static final String PROCEDURE_ROOT = "procedure";
+
+    /**
+     * @since 4.1
+     */
+    public static final String DATA_MAP_ROOT = "data-map";
+
+    /**
+     * @since 4.1
+     */
+    public static final String JAVA_CLASS_ROOT = "java-class";
+
+    /**
      * Creates new SelectQuery query descriptor.
      */
     public static SelectQueryDescriptor selectQueryDescriptor() {
@@ -189,47 +214,36 @@ public class QueryDescriptor implements Serializable, ConfigurationNode, XMLSeri
     }
 
     @Override
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<query name=\"");
-        encoder.print(getName());
-        encoder.print("\" type=\"");
-        encoder.print(type);
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("query").attribute("name", getName()).attribute("type", type);
 
         String rootString = null;
         String rootType = null;
 
         if (root instanceof String) {
-            rootType = MapLoader.OBJ_ENTITY_ROOT;
+            rootType = OBJ_ENTITY_ROOT;
             rootString = root.toString();
         } else if (root instanceof ObjEntity) {
-            rootType = MapLoader.OBJ_ENTITY_ROOT;
+            rootType = OBJ_ENTITY_ROOT;
             rootString = ((ObjEntity) root).getName();
         } else if (root instanceof DbEntity) {
-            rootType = MapLoader.DB_ENTITY_ROOT;
+            rootType = DB_ENTITY_ROOT;
             rootString = ((DbEntity) root).getName();
         } else if (root instanceof Procedure) {
-            rootType = MapLoader.PROCEDURE_ROOT;
+            rootType = PROCEDURE_ROOT;
             rootString = ((Procedure) root).getName();
         } else if (root instanceof Class<?>) {
-            rootType = MapLoader.JAVA_CLASS_ROOT;
+            rootType = JAVA_CLASS_ROOT;
             rootString = ((Class<?>) root).getName();
         }
 
         if (rootType != null) {
-            encoder.print("\" root=\"");
-            encoder.print(rootType);
-            encoder.print("\" root-name=\"");
-            encoder.print(rootString);
+            encoder.attribute("root", rootType).attribute("root-name", rootString);
         }
-
-        encoder.println("\">");
-
-        encoder.indent(1);
-
         encodeProperties(encoder);
 
-        encoder.indent(-1);
-        encoder.println("</query>");
+        delegate.visitQuery(this);
+        encoder.end();
     }
 
     void encodeProperties(XMLEncoder encoder) {
@@ -238,7 +252,7 @@ public class QueryDescriptor implements Serializable, ConfigurationNode, XMLSeri
             if(value == null || value.isEmpty()) {
                 continue;
             }
-            encoder.printProperty(property.getKey(), value);
+            encoder.property(property.getKey(), value);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java
index 10038cc..cd5235f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java
@@ -88,7 +88,7 @@ public class QueryDescriptorLoader {
         return descriptor;
     }
 
-    void setName(String name) {
+    public void setName(String name) {
         this.name = name;
     }
 
@@ -98,7 +98,7 @@ public class QueryDescriptorLoader {
      * and can't be changed without complete upgrade system rewrite
      * @param factory old style query factory class
      */
-    void setLegacyFactory(String factory) {
+    public void setLegacyFactory(String factory) {
         switch (factory) {
             case "org.apache.cayenne.map.SelectQueryBuilder":
                 queryType = QueryDescriptor.SELECT_QUERY;
@@ -117,7 +117,7 @@ public class QueryDescriptorLoader {
         }
     }
 
-    void setQueryType(String queryType) {
+    public void setQueryType(String queryType) {
         this.queryType = queryType;
     }
 
@@ -132,20 +132,20 @@ public class QueryDescriptorLoader {
         Object root = null;
 
         if (rootType == null
-                || MapLoader.DATA_MAP_ROOT.equals(rootType)
+                || QueryDescriptor.DATA_MAP_ROOT.equals(rootType)
                 || rootName == null) {
             root = dataMap;
         }
-        else if (MapLoader.OBJ_ENTITY_ROOT.equals(rootType)) {
+        else if (QueryDescriptor.OBJ_ENTITY_ROOT.equals(rootType)) {
             root = dataMap.getObjEntity(rootName);
         }
-        else if (MapLoader.DB_ENTITY_ROOT.equals(rootType)) {
+        else if (QueryDescriptor.DB_ENTITY_ROOT.equals(rootType)) {
             root = dataMap.getDbEntity(rootName);
         }
-        else if (MapLoader.PROCEDURE_ROOT.equals(rootType)) {
+        else if (QueryDescriptor.PROCEDURE_ROOT.equals(rootType)) {
             root = dataMap.getProcedure(rootName);
         }
-        else if (MapLoader.JAVA_CLASS_ROOT.equals(rootType)) {
+        else if (QueryDescriptor.JAVA_CLASS_ROOT.equals(rootType)) {
             // setting root to ObjEntity, since creating a Class requires
             // the knowledge of the ClassLoader
             root = dataMap.getObjEntityForJavaClass(rootName);
@@ -154,20 +154,20 @@ public class QueryDescriptorLoader {
         return (root != null) ? root : dataMap;
     }
 
-    void setResultEntity(String resultEntity) {
+    public void setResultEntity(String resultEntity) {
         this.resultEntity = resultEntity;
     }
 
     /**
      * Sets the information pertaining to the root of the query.
      */
-    void setRoot(DataMap dataMap, String rootType, String rootName) {
+    public void setRoot(DataMap dataMap, String rootType, String rootName) {
         this.dataMap = dataMap;
         this.rootType = rootType;
         this.rootName = rootName;
     }
 
-    void setEjbql(String ejbql) {
+    public void setEjbql(String ejbql) {
         this.ejbql = ejbql;
     }
 
@@ -175,7 +175,7 @@ public class QueryDescriptorLoader {
      * Adds raw sql. If adapterClass parameter is not null, sets the SQL string to be
      * adapter-specific. Otherwise it is used as a default SQL string.
      */
-    void addSql(String sql, String adapterClass) {
+    public void addSql(String sql, String adapterClass) {
         if (adapterClass == null) {
             this.sql = sql;
         }
@@ -188,7 +188,7 @@ public class QueryDescriptorLoader {
         }
     }
 
-    void setQualifier(String qualifier) {
+    public void setQualifier(String qualifier) {
         if (qualifier == null || qualifier.trim().length() == 0) {
             this.qualifier = null;
         }
@@ -197,7 +197,7 @@ public class QueryDescriptorLoader {
         }
     }
 
-    void addProperty(String name, String value) {
+    public void addProperty(String name, String value) {
         if (properties == null) {
             properties = new HashMap<>();
         }
@@ -205,7 +205,7 @@ public class QueryDescriptorLoader {
         properties.put(name, value);
     }
 
-    void addOrdering(String path, String descending, String ignoreCase) {
+    public void addOrdering(String path, String descending, String ignoreCase) {
         if (orderings == null) {
             orderings = new ArrayList<>();
         }
@@ -232,7 +232,7 @@ public class QueryDescriptorLoader {
         orderings.add(new Ordering(path, order));
     }
 
-    void addPrefetch(String path) {
+    public void addPrefetch(String path) {
         if (path == null || (path != null && path.trim().length() == 0)) {
             // throw??
             return;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
index f9b1ff0..e9c14f7 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.map;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.query.SQLTemplate;
 import org.apache.cayenne.util.XMLEncoder;
 
@@ -97,78 +98,64 @@ public class SQLTemplateDescriptor extends QueryDescriptor {
     }
 
     @Override
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<query name=\"");
-        encoder.print(getName());
-        encoder.print("\" type=\"");
-        encoder.print(type);
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("query")
+                .attribute("name", getName())
+                .attribute("type", type);
 
         String rootString = null;
         String rootType = null;
 
         if (root instanceof String) {
-            rootType = MapLoader.OBJ_ENTITY_ROOT;
+            rootType = QueryDescriptor.OBJ_ENTITY_ROOT;
             rootString = root.toString();
         } else if (root instanceof ObjEntity) {
-            rootType = MapLoader.OBJ_ENTITY_ROOT;
+            rootType = QueryDescriptor.OBJ_ENTITY_ROOT;
             rootString = ((ObjEntity) root).getName();
         } else if (root instanceof DbEntity) {
-            rootType = MapLoader.DB_ENTITY_ROOT;
+            rootType = QueryDescriptor.DB_ENTITY_ROOT;
             rootString = ((DbEntity) root).getName();
         } else if (root instanceof Procedure) {
-            rootType = MapLoader.PROCEDURE_ROOT;
+            rootType = QueryDescriptor.PROCEDURE_ROOT;
             rootString = ((Procedure) root).getName();
         } else if (root instanceof Class<?>) {
-            rootType = MapLoader.JAVA_CLASS_ROOT;
+            rootType = QueryDescriptor.JAVA_CLASS_ROOT;
             rootString = ((Class<?>) root).getName();
         } else if (root instanceof DataMap) {
-            rootType = MapLoader.DATA_MAP_ROOT;
+            rootType = QueryDescriptor.DATA_MAP_ROOT;
             rootString = ((DataMap) root).getName();
         }
 
         if (rootType != null) {
-            encoder.print("\" root=\"");
-            encoder.print(rootType);
-            encoder.print("\" root-name=\"");
-            encoder.print(rootString);
+            encoder.attribute("root", rootType).attribute("root-name", rootString);
         }
 
-        encoder.println("\">");
-
-        encoder.indent(1);
-
         // print properties
         encodeProperties(encoder);
-
         // encode default SQL
         if (sql != null) {
-            encoder.print("<sql><![CDATA[");
-            encoder.print(sql);
-            encoder.println("]]></sql>");
+            encoder.start("sql").cdata(sql, true).end();
         }
 
         // encode adapter SQL
         if (adapterSql != null && !adapterSql.isEmpty()) {
-
             // sorting entries by adapter name
-            TreeSet<String> keys = new TreeSet<String>(adapterSql.keySet());
+            TreeSet<String> keys = new TreeSet<>(adapterSql.keySet());
             for (String key : keys) {
                 String value = adapterSql.get(key);
-
                 if (key != null && value != null) {
                     String sql = value.trim();
                     if (sql.length() > 0) {
-                        encoder.print("<sql adapter-class=\"");
-                        encoder.print(key);
-                        encoder.print("\"><![CDATA[");
-                        encoder.print(sql);
-                        encoder.println("]]></sql>");
+                        encoder.start("sql")
+                                .attribute("adapter-class", key)
+                                .cdata(sql, true)
+                                .end();
                     }
                 }
             }
         }
 
-        encoder.indent(-1);
-        encoder.println("</query>");
+        delegate.visitQuery(this);
+        encoder.end();
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/SelectQueryDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/SelectQueryDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/map/SelectQueryDescriptor.java
index e844b3e..7a677fb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/SelectQueryDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/SelectQueryDescriptor.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.map;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.query.Ordering;
 import org.apache.cayenne.query.PrefetchTreeNode;
@@ -26,7 +27,6 @@ import org.apache.cayenne.util.XMLEncoder;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
 /**
  * @since 4.0
@@ -153,59 +153,45 @@ public class SelectQueryDescriptor extends QueryDescriptor {
     }
 
     @Override
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<query name=\"");
-        encoder.print(getName());
-        encoder.print("\" type=\"");
-        encoder.print(type);
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("query")
+                .attribute("name", getName())
+                .attribute("type", type);
 
         String rootString = null;
         String rootType = null;
 
         if (root instanceof String) {
-            rootType = MapLoader.OBJ_ENTITY_ROOT;
+            rootType = QueryDescriptor.OBJ_ENTITY_ROOT;
             rootString = root.toString();
         } else if (root instanceof ObjEntity) {
-            rootType = MapLoader.OBJ_ENTITY_ROOT;
+            rootType = QueryDescriptor.OBJ_ENTITY_ROOT;
             rootString = ((ObjEntity) root).getName();
         } else if (root instanceof DbEntity) {
-            rootType = MapLoader.DB_ENTITY_ROOT;
+            rootType = QueryDescriptor.DB_ENTITY_ROOT;
             rootString = ((DbEntity) root).getName();
         } else if (root instanceof Procedure) {
-            rootType = MapLoader.PROCEDURE_ROOT;
+            rootType = QueryDescriptor.PROCEDURE_ROOT;
             rootString = ((Procedure) root).getName();
         } else if (root instanceof Class<?>) {
-            rootType = MapLoader.JAVA_CLASS_ROOT;
+            rootType = QueryDescriptor.JAVA_CLASS_ROOT;
             rootString = ((Class<?>) root).getName();
         }
 
         if (rootType != null) {
-            encoder.print("\" root=\"");
-            encoder.print(rootType);
-            encoder.print("\" root-name=\"");
-            encoder.print(rootString);
+            encoder.attribute("root", rootType).attribute("root-name", rootString);
         }
 
-        encoder.println("\">");
-
-        encoder.indent(1);
-
         // print properties
         encodeProperties(encoder);
 
         // encode qualifier
         if (qualifier != null) {
-            encoder.print("<qualifier>");
-            qualifier.encodeAsXML(encoder);
-            encoder.println("</qualifier>");
+            encoder.start("qualifier").nested(qualifier, delegate).end();
         }
 
         // encode orderings
-        if (orderings != null && !orderings.isEmpty()) {
-            for (Ordering ordering : orderings) {
-                ordering.encodeAsXML(encoder);
-            }
-        }
+        encoder.nested(orderings, delegate);
 
         PrefetchTreeNode prefetchTree = new PrefetchTreeNode();
 
@@ -215,9 +201,9 @@ public class SelectQueryDescriptor extends QueryDescriptor {
             node.setPhantom(false);
         }
 
-        prefetchTree.encodeAsXML(encoder);
+        encoder.nested(prefetchTree, delegate);
 
-        encoder.indent(-1);
-        encoder.println("</query>");
+        delegate.visitQuery(this);
+        encoder.end();
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java b/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java
index bc13719..a450b3b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import java.util.StringTokenizer;
 
 import org.apache.cayenne.Persistent;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.EntityResolver;
@@ -41,7 +42,7 @@ import org.apache.cayenne.util.XMLSerializable;
  * 
  * @since 1.1
  */
-class BaseQueryMetadata implements QueryMetadata, XMLSerializable, Serializable {
+class BaseQueryMetadata implements QueryMetadata, Serializable {
 
 	private static final long serialVersionUID = 5129792493303459115L;
 
@@ -195,41 +196,6 @@ class BaseQueryMetadata implements QueryMetadata, XMLSerializable, Serializable
 		}
 	}
 
-	public void encodeAsXML(XMLEncoder encoder) {
-
-		if (fetchingDataRows != QueryMetadata.FETCHING_DATA_ROWS_DEFAULT) {
-			encoder.printProperty(QueryMetadata.FETCHING_DATA_ROWS_PROPERTY, fetchingDataRows);
-		}
-
-		if (fetchOffset != QueryMetadata.FETCH_OFFSET_DEFAULT) {
-			encoder.printProperty(QueryMetadata.FETCH_OFFSET_PROPERTY, fetchOffset);
-		}
-
-		if (fetchLimit != QueryMetadata.FETCH_LIMIT_DEFAULT) {
-			encoder.printProperty(QueryMetadata.FETCH_LIMIT_PROPERTY, fetchLimit);
-		}
-
-		if (pageSize != QueryMetadata.PAGE_SIZE_DEFAULT) {
-			encoder.printProperty(QueryMetadata.PAGE_SIZE_PROPERTY, pageSize);
-		}
-
-		if (cacheStrategy != null && QueryCacheStrategy.getDefaultStrategy() != cacheStrategy) {
-			encoder.printProperty(QueryMetadata.CACHE_STRATEGY_PROPERTY, cacheStrategy.name());
-		}
-
-		if (statementFetchSize != QueryMetadata.STATEMENT_FETCH_SIZE_DEFAULT) {
-			encoder.printProperty(QueryMetadata.STATEMENT_FETCH_SIZE_PROPERTY, statementFetchSize);
-		}
-
-		if (prefetchTree != null) {
-			prefetchTree.encodeAsXML(encoder);
-		}
-
-		if (cacheGroup != null) {
-			encoder.printProperty(QueryMetadata.CACHE_GROUPS_PROPERTY, cacheGroup);
-		}
-	}
-
 	/**
 	 * @since 1.2
 	 */

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/EJBQLQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/EJBQLQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/query/EJBQLQuery.java
index 18732c7..7103562 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/EJBQLQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/EJBQLQuery.java
@@ -19,6 +19,7 @@
 package org.apache.cayenne.query;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.ejbql.EJBQLCompiledExpression;
 import org.apache.cayenne.ejbql.EJBQLException;
 import org.apache.cayenne.ejbql.EJBQLParserFactory;
@@ -36,7 +37,7 @@ import java.util.Map;
  * 
  * @since 3.0
  */
-public class EJBQLQuery extends CacheableQuery implements XMLSerializable {
+public class EJBQLQuery extends CacheableQuery {
 
     @Deprecated
     protected String name;
@@ -224,28 +225,6 @@ public class EJBQLQuery extends CacheableQuery implements XMLSerializable {
         metadata.setFetchOffset(fetchOffset);
     }
 
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<query name=\"");
-        encoder.print(getName());
-        encoder.print("\" factory=\"");
-        encoder.print("org.apache.cayenne.map.EjbqlBuilder");
-
-        encoder.println("\">");
-
-        encoder.indent(1);
-
-        metadata.encodeAsXML(encoder);
-
-        if (ejbqlStatement != null) {
-            encoder.print("<ejbql><![CDATA[");
-            encoder.print(ejbqlStatement);
-            encoder.println("]]></ejbql>");
-        }
-
-        encoder.indent(-1);
-        encoder.println("</query>");
-    }
-
     public void setEjbqlStatement(String text) {
         this.ejbqlStatement = text;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java b/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java
index 3625df6..38d6a2e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java
@@ -19,6 +19,8 @@
 
 package org.apache.cayenne.query;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.configuration.EmptyConfigurationNodeVisitor;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionException;
 import org.apache.cayenne.exp.parser.ASTDbPath;
@@ -431,22 +433,12 @@ public class Ordering implements Comparator<Object>, Serializable, XMLSerializab
 	 * @since 1.1
 	 */
 	@Override
-	public void encodeAsXML(XMLEncoder encoder) {
-		encoder.print("<ordering");
-
-		if (isDescending()) {
-			encoder.print(" descending=\"true\"");
-		}
-
-		if (isCaseInsensitive()) {
-			encoder.print(" ignore-case=\"true\"");
-		}
-
-		encoder.print(">");
-		if (getSortSpec() != null) {
-			getSortSpec().encodeAsXML(encoder);
-		}
-		encoder.println("</ordering>");
+	public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+		encoder.start("ordering")
+				.attribute("descending", isDescending())
+				.attribute("ignore-case", isCaseInsensitive())
+				.nested(getSortSpec(), delegate)
+				.end();
 	}
 
 	@Override
@@ -454,7 +446,7 @@ public class Ordering implements Comparator<Object>, Serializable, XMLSerializab
 		StringWriter buffer = new StringWriter();
 		PrintWriter pw = new PrintWriter(buffer);
 		XMLEncoder encoder = new XMLEncoder(pw);
-		encodeAsXML(encoder);
+		encodeAsXML(encoder, new EmptyConfigurationNodeVisitor());
 		pw.close();
 		buffer.flush();
 		return buffer.toString();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java b/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java
index a1d0fb6..2f72e4e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne.query;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
@@ -96,7 +97,8 @@ public class PrefetchTreeNode implements Serializable, XMLSerializable {
 		this.semantics = UNDEFINED_SEMANTICS;
 	}
 
-	public void encodeAsXML(XMLEncoder encoder) {
+	@Override
+	public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
 		traverse(new XMLEncoderOperation(encoder));
 	}
 
@@ -218,7 +220,7 @@ public class PrefetchTreeNode implements Serializable, XMLSerializable {
 	 */
 	public void traverse(PrefetchProcessor processor) {
 
-		boolean result = false;
+		boolean result;
 
 		if (isPhantom()) {
 			result = processor.startPhantomPrefetch(this);
@@ -500,31 +502,33 @@ public class PrefetchTreeNode implements Serializable, XMLSerializable {
 		}
 
 		public boolean startDisjointPrefetch(PrefetchTreeNode node) {
-			encoder.print("<prefetch type=\"disjoint\">");
-			encoder.print(node.getPath());
-			encoder.println("</prefetch>");
+			encoder.start("prefetch")
+					.attribute("type", "disjoint")
+					.cdata(node.getPath(), true)
+					.end();
 			return true;
 		}
 
 		public boolean startDisjointByIdPrefetch(PrefetchTreeNode node) {
-			encoder.print("<prefetch type=\"disjointById\">");
-			encoder.print(node.getPath());
-			encoder.println("</prefetch>");
+			encoder.start("prefetch")
+					.attribute("type", "disjointById")
+					.cdata(node.getPath(), true)
+					.end();
 			return true;
 		}
 
 		public boolean startJointPrefetch(PrefetchTreeNode node) {
-			encoder.print("<prefetch type=\"joint\">");
-			encoder.print(node.getPath());
-			encoder.println("</prefetch>");
+			encoder.start("prefetch")
+					.attribute("type", "joint")
+					.cdata(node.getPath(), true)
+					.end();
 			return true;
 		}
 
 		public boolean startUnknownPrefetch(PrefetchTreeNode node) {
-			encoder.print("<prefetch>");
-			encoder.print(node.getPath());
-			encoder.println("</prefetch>");
-
+			encoder.start("prefetch")
+					.cdata(node.getPath(), true)
+					.end();
 			return true;
 		}
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/ProcedureQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/ProcedureQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/query/ProcedureQuery.java
index 12ac3c7..462bd8d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/ProcedureQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/ProcedureQuery.java
@@ -20,9 +20,10 @@
 package org.apache.cayenne.query;
 
 import org.apache.cayenne.access.jdbc.ColumnDescriptor;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.QueryDescriptor;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
 
@@ -54,7 +55,7 @@ import java.util.Map;
  * {@link org.apache.cayenne.access.DataContext#performGenericQuery(Query)}.
  * </p>
  */
-public class ProcedureQuery extends AbstractQuery implements ParameterizedQuery, XMLSerializable {
+public class ProcedureQuery extends AbstractQuery implements ParameterizedQuery {
 
     public static final String COLUMN_NAME_CAPITALIZATION_PROPERTY = "cayenne.ProcedureQuery.columnNameCapitalization";
 
@@ -226,53 +227,6 @@ public class ProcedureQuery extends AbstractQuery implements ParameterizedQuery,
     }
 
     /**
-     * Prints itself as XML to the provided PrintWriter.
-     * 
-     * @since 1.1
-     */
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<query name=\"");
-        encoder.print(getName());
-        encoder.print("\" factory=\"");
-        encoder.print("org.apache.cayenne.map.ProcedureQueryBuilder");
-
-        encoder.print("\" root=\"");
-        encoder.print(MapLoader.PROCEDURE_ROOT);
-
-        String rootString = null;
-
-        if (root instanceof String) {
-            rootString = root.toString();
-        }
-        else if (root instanceof Procedure) {
-            rootString = ((Procedure) root).getName();
-        }
-
-        if (rootString != null) {
-            encoder.print("\" root-name=\"");
-            encoder.print(rootString);
-        }
-
-        if (resultEntityName != null) {
-            encoder.print("\" result-entity=\"");
-            encoder.print(resultEntityName);
-        }
-
-        encoder.println("\">");
-        encoder.indent(1);
-
-        metaData.encodeAsXML(encoder);
-        if (getColumnNamesCapitalization() != CapsStrategy.DEFAULT) {
-            encoder.printProperty(
-                    COLUMN_NAME_CAPITALIZATION_PROPERTY,
-                    getColumnNamesCapitalization().name());
-        }
-
-        encoder.indent(-1);
-        encoder.println("</query>");
-    }
-
-    /**
      * Creates and returns a new ProcedureQuery built using this query as a prototype and
      * substituting template parameters with the values from the map.
      * 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
index 1fe3be2..554bb8b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
@@ -20,12 +20,13 @@
 package org.apache.cayenne.query;
 
 import org.apache.cayenne.access.QueryEngine;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.QueryDescriptor;
 import org.apache.cayenne.map.SQLResult;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
@@ -69,7 +70,7 @@ import java.util.TreeSet;
  * 
  * @since 1.1
  */
-public class SQLTemplate extends AbstractQuery implements ParameterizedQuery, XMLSerializable {
+public class SQLTemplate extends AbstractQuery implements ParameterizedQuery {
 
 	private static final long serialVersionUID = -3073521388289663641L;
 
@@ -198,92 +199,6 @@ public class SQLTemplate extends AbstractQuery implements ParameterizedQuery, XM
 	}
 
 	/**
-	 * Prints itself as XML to the provided PrintWriter.
-	 * 
-	 * @since 1.1
-	 */
-	@Override
-	public void encodeAsXML(XMLEncoder encoder) {
-		encoder.print("<query name=\"");
-		encoder.print(getName());
-		encoder.print("\" factory=\"");
-		encoder.print("org.apache.cayenne.map.SQLTemplateBuilder");
-
-		String rootString = null;
-		String rootType = null;
-
-		if (root instanceof String) {
-			rootType = MapLoader.OBJ_ENTITY_ROOT;
-			rootString = root.toString();
-		} else if (root instanceof ObjEntity) {
-			rootType = MapLoader.OBJ_ENTITY_ROOT;
-			rootString = ((ObjEntity) root).getName();
-		} else if (root instanceof DbEntity) {
-			rootType = MapLoader.DB_ENTITY_ROOT;
-			rootString = ((DbEntity) root).getName();
-		} else if (root instanceof Procedure) {
-			rootType = MapLoader.PROCEDURE_ROOT;
-			rootString = ((Procedure) root).getName();
-		} else if (root instanceof Class<?>) {
-			rootType = MapLoader.JAVA_CLASS_ROOT;
-			rootString = ((Class<?>) root).getName();
-		} else if (root instanceof DataMap) {
-			rootType = MapLoader.DATA_MAP_ROOT;
-			rootString = ((DataMap) root).getName();
-		}
-
-		if (rootType != null) {
-			encoder.print("\" root=\"");
-			encoder.print(rootType);
-			encoder.print("\" root-name=\"");
-			encoder.print(rootString);
-		}
-
-		encoder.println("\">");
-
-		encoder.indent(1);
-
-		metaData.encodeAsXML(encoder);
-
-		if (getColumnNamesCapitalization() != CapsStrategy.DEFAULT) {
-			encoder.printProperty(COLUMN_NAME_CAPITALIZATION_PROPERTY, getColumnNamesCapitalization().name());
-		}
-
-		// encode default SQL
-		if (defaultTemplate != null) {
-			encoder.print("<sql><![CDATA[");
-			encoder.print(defaultTemplate);
-			encoder.println("]]></sql>");
-		}
-
-		// encode adapter SQL
-		if (templates != null && !templates.isEmpty()) {
-
-			// sorting entries by adapter name
-			TreeSet<String> keys = new TreeSet<String>(templates.keySet());
-			for (String key : keys) {
-				String value = templates.get(key);
-
-				if (key != null && value != null) {
-					String sql = value.trim();
-					if (sql.length() > 0) {
-						encoder.print("<sql adapter-class=\"");
-						encoder.print(key);
-						encoder.print("\"><![CDATA[");
-						encoder.print(sql);
-						encoder.println("]]></sql>");
-					}
-				}
-			}
-		}
-
-		// TODO: support parameter encoding
-
-		encoder.indent(-1);
-		encoder.println("</query>");
-	}
-
-	/**
 	 * Initializes query parameters using a set of properties.
 	 * 
 	 * @since 1.1

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
index ff9660e..b2d5bd1 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
@@ -24,14 +24,15 @@ import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.ResultBatchIterator;
 import org.apache.cayenne.ResultIterator;
 import org.apache.cayenne.ResultIteratorCallback;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.exp.Property;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.QueryDescriptor;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
 
@@ -48,7 +49,7 @@ import java.util.Map;
  * other parameters that serve as runtime hints to Cayenne on how to optimize
  * the fetch and result processing.
  */
-public class SelectQuery<T> extends AbstractQuery implements ParameterizedQuery, XMLSerializable, Select<T> {
+public class SelectQuery<T> extends AbstractQuery implements ParameterizedQuery, Select<T> {
 
 	private static final long serialVersionUID = 5486418811888197559L;
 
@@ -434,73 +435,6 @@ public class SelectQuery<T> extends AbstractQuery implements ParameterizedQuery,
 	}
 
 	/**
-	 * Prints itself as XML to the provided PrintWriter.
-	 * 
-	 * @since 1.1
-	 */
-	public void encodeAsXML(XMLEncoder encoder) {
-		encoder.print("<query name=\"");
-		encoder.print(getName());
-		encoder.print("\" factory=\"");
-		encoder.print("org.apache.cayenne.map.SelectQueryBuilder");
-
-		String rootString = null;
-		String rootType = null;
-
-		if (root instanceof String) {
-			rootType = MapLoader.OBJ_ENTITY_ROOT;
-			rootString = root.toString();
-		} else if (root instanceof ObjEntity) {
-			rootType = MapLoader.OBJ_ENTITY_ROOT;
-			rootString = ((ObjEntity) root).getName();
-		} else if (root instanceof DbEntity) {
-			rootType = MapLoader.DB_ENTITY_ROOT;
-			rootString = ((DbEntity) root).getName();
-		} else if (root instanceof Procedure) {
-			rootType = MapLoader.PROCEDURE_ROOT;
-			rootString = ((Procedure) root).getName();
-		} else if (root instanceof Class<?>) {
-			rootType = MapLoader.JAVA_CLASS_ROOT;
-			rootString = ((Class<?>) root).getName();
-		}
-
-		if (rootType != null) {
-			encoder.print("\" root=\"");
-			encoder.print(rootType);
-			encoder.print("\" root-name=\"");
-			encoder.print(rootString);
-		}
-
-		encoder.println("\">");
-
-		encoder.indent(1);
-
-		// print properties
-		if (distinct != DISTINCT_DEFAULT) {
-			encoder.printProperty(DISTINCT_PROPERTY, distinct);
-		}
-
-		metaData.encodeAsXML(encoder);
-
-		// encode qualifier
-		if (qualifier != null) {
-			encoder.print("<qualifier>");
-			qualifier.encodeAsXML(encoder);
-			encoder.println("</qualifier>");
-		}
-
-		// encode orderings
-		if (orderings != null && !orderings.isEmpty()) {
-			for (Ordering ordering : orderings) {
-				ordering.encodeAsXML(encoder);
-			}
-		}
-
-		encoder.indent(-1);
-		encoder.println("</query>");
-	}
-
-	/**
 	 * A shortcut for {@link #queryWithParameters(Map, boolean)}that prunes
 	 * parts of qualifier that have no parameter value set.
 	 */

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
index 429efdb..db596bb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
@@ -35,26 +35,14 @@ import java.util.Map;
  */
 class LifecycleCallbackEventHandler {
 
-    private EntityResolver resolver;
     private Map<String, Collection<AbstractCallback>> listeners;
     private Collection<AbstractCallback> defaultListeners;
 
     LifecycleCallbackEventHandler(EntityResolver resolver) {
-        this.resolver = resolver;
         this.listeners = new HashMap<>();
         this.defaultListeners = new ArrayList<>();
     }
 
-    private boolean excludingDefaultListeners(String entityName) {
-        ObjEntity entity = resolver.getObjEntity(entityName);
-        return entity != null && entity.isExcludingDefaultListeners();
-    }
-
-    private boolean excludingSuperclassListeners(String entityName) {
-        ObjEntity entity = resolver.getObjEntity(entityName);
-        return entity != null && entity.isExcludingSuperclassListeners();
-    }
-
     boolean isEmpty() {
         return listeners.isEmpty() && defaultListeners.isEmpty();
     }
@@ -140,8 +128,7 @@ class LifecycleCallbackEventHandler {
     void performCallbacks(Persistent object) {
 
         // default listeners are invoked first
-        if (!defaultListeners.isEmpty()
-                && !excludingDefaultListeners(object.getObjectId().getEntityName())) {
+        if (!defaultListeners.isEmpty()) {
             for (AbstractCallback listener : defaultListeners) {
                 listener.performCallback(object);
             }
@@ -171,9 +158,7 @@ class LifecycleCallbackEventHandler {
         }
 
         // recursively perform super callbacks first
-        if (!excludingSuperclassListeners(object.getObjectId().getEntityName())) {
-            performCallbacks(object, callbackEntityClass.getSuperclass());
-        }
+        performCallbacks(object, callbackEntityClass.getSuperclass());
 
         // perform callbacks on provided class
         String key = callbackEntityClass.getName();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java
index d869d4c..7314488 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java
@@ -127,11 +127,6 @@ class IncrementalSelectQuery<T> extends SelectQuery<T> {
 	}
 
 	@Override
-	public void encodeAsXML(XMLEncoder encoder) {
-		query.encodeAsXML(encoder);
-	}
-
-	@Override
 	public boolean equals(Object obj) {
 		return query.equals(obj);
 	}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/util/XMLEncoder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/util/XMLEncoder.java b/cayenne-server/src/main/java/org/apache/cayenne/util/XMLEncoder.java
index 7551d99..039ca4d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/util/XMLEncoder.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/util/XMLEncoder.java
@@ -21,12 +21,26 @@ package org.apache.cayenne.util;
 
 import java.io.PrintWriter;
 import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedList;
 import java.util.Map;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+
 /**
+ * <p>
  * A helper class to encode objects to XML.
- * 
+ * </p>
+ * Usage: <pre>{@code
+ *      XMLEncoder encoder = new XMLEncoder(writer);
+ *      encoder
+ *          .start("tag").attribute("name", "tag_name_attribute")
+ *          .start("nested_tag").attribute("name", "nested_tag_name).cdata("tag text element").end()
+ *          .end();
+ * }</pre>
+ *
  * @since 1.1
+ * @since 4.1 API is greatly reworked to be more usable
  */
 public class XMLEncoder {
 
@@ -37,6 +51,12 @@ public class XMLEncoder {
     protected boolean indentLine;
     protected int indentTimes;
 
+    protected boolean tagOpened;
+    protected boolean cdata;
+    protected int currentTagLevel;
+    protected int lastTagLevel;
+    protected Deque<String> openTags = new LinkedList<>();
+
     public XMLEncoder(PrintWriter out) {
         this(out, null, null);
     }
@@ -54,163 +74,275 @@ public class XMLEncoder {
         this.projectVersion = projectVersion;
     }
 
-    public PrintWriter getPrintWriter() {
-        return out;
-    }
-
-    public void indent(int i) {
+    public XMLEncoder indent(int i) {
         indentTimes += i;
         if (indentTimes < 0) {
             indentTimes = 0;
         }
+        return this;
+    }
+
+    public XMLEncoder print(String text) {
+        printIndent();
+        out.print(text);
+        return this;
+    }
+
+    public XMLEncoder println(String text) {
+        printIndent();
+        out.println(text);
+        indentLine = true;
+        return this;
     }
 
     /**
-     * Utility method that prints all map values, assuming they are XMLSerializable
-     * objects.
+     * @since 3.1
      */
-    public void print(Map<?, ? extends XMLSerializable> map) {
-        for (XMLSerializable value : map.values()) {
-            value.encodeAsXML(this);
+    public XMLEncoder println() {
+        out.println();
+        indentLine = true;
+        return this;
+    }
+
+    private XMLEncoder printIndent() {
+        if (indentLine) {
+            indentLine = false;
+
+            if (indentTimes > 0 && indent != null) {
+                for (int i = 0; i < indentTimes; i++) {
+                    out.print(indent);
+                }
+            }
         }
+        return this;
     }
 
     /**
-     * Utility method that prints all map values, assuming they are XMLSerializable
-     * objects.
+     * @since 4.1
+     * @param tag to start
+     * @return this
      */
-    public void print(Collection<? extends XMLSerializable> c) {
-        for (XMLSerializable value : c) {
-            value.encodeAsXML(this);
+    public XMLEncoder start(String tag) {
+        if(tagOpened) {
+            println(">").indent(1);
         }
+        printIndent().print("<").print(tag);
+
+        lastTagLevel = ++currentTagLevel;
+        tagOpened = true;
+        openTags.push(tag);
+        return this;
     }
 
     /**
-     * Inserts an optional project version attribute in the output. If the project version
-     * is not initialized for encoder, will do nothing.
-     * 
-     * @since 3.1
+     * This method will track presence of nested tags and print closure accordingly
+     *
+     * @since 4.1
+     * @return this
      */
-    public void printProjectVersion() {
-        printAttribute("project-version", projectVersion);
+    public XMLEncoder end() {
+        tagOpened = false;
+        if(lastTagLevel == currentTagLevel-- && !cdata) {
+            openTags.pop();
+            println("/>");
+        } else {
+            if(!cdata) {
+                indent(-1).printIndent();
+            }
+            cdata = false;
+            print("</").print(openTags.pop()).println(">");
+        }
+        return this;
     }
 
     /**
-     * Prints an XML attribute. The value is trimmed (so leading and following spaces are
-     * lost) and then encoded to be a proper XML attribute value. E.g. "&amp;" becomes
-     * "&amp;amp;", etc.
-     * 
-     * @since 3.1
+     * @since 4.1
+     * @param name of the attribute
+     * @param value of the attribute
+     * @return this
      */
-    public void printAttribute(String name, String value) {
-        printAttribute(name, value, false);
+    public XMLEncoder attribute(String name, String value) {
+        return attribute(name, value, false);
     }
 
     /**
-     * @since 3.1
+     * @since 4.1
+     * @param name of the attribute
+     * @param value of the attribute
+     * @param newLine should this attribute be printed on new line
+     * @return this
      */
-    public void printlnAttribute(String name, String value) {
-        printAttribute(name, value, true);
-    }
-
-    private void printAttribute(String name, String value, boolean lineBreak) {
-        if (value == null) {
-            return;
+    public XMLEncoder attribute(String name, String value, boolean newLine) {
+        if(Util.isEmptyString(value)) {
+            return this;
         }
 
-        value = value.trim();
-        if (value.length() == 0) {
-            return;
+        if(newLine) {
+            indent(1).println().printIndent();
         }
-
-        value = Util.encodeXmlAttribute(value);
-
-        printIndent();
-        out.print(' ');
-        out.print(name);
-        out.print("=\"");
-        out.print(value);
-        out.print("\"");
-        if (lineBreak) {
-            println();
+        print(" ").print(name).print("=\"").print(Util.encodeXmlAttribute(value)).print("\"");
+        if(newLine) {
+            indent(-1);
         }
+        return this;
     }
 
     /**
-     * Prints a common XML element - property with name and value.
+     * @since 4.1
+     * @param name of the attribute
+     * @param value of the attribute
+     * @return this
      */
-    public void printProperty(String name, String value) {
-        printIndent();
-        out.print("<property");
-        printAttribute("name", name);
-        printAttribute("value", value);
-        out.println("/>");
-        indentLine = true;
+    public XMLEncoder attribute(String name, boolean value) {
+        if(!value) {
+            return this;
+        }
+        return attribute(name, "true");
     }
 
     /**
-     * Prints a common XML element - property with name and value.
+     * @since 4.1
+     * @param name of the attribute
+     * @param value of the attribute
+     * @return this
      */
-    public void printProperty(String name, boolean b) {
-        printProperty(name, String.valueOf(b));
+    public XMLEncoder attribute(String name, int value) {
+        if(value == 0) {
+            return this;
+        }
+        return attribute(name, String.valueOf(value));
     }
 
     /**
-     * Prints a common XML element - property with name and value.
+     * @since 4.1
+     * @param data char data
+     * @return this
      */
-    public void printProperty(String name, int i) {
-        printProperty(name, String.valueOf(i));
+    public XMLEncoder cdata(String data) {
+        return cdata(data, false);
     }
 
-    public void print(String text) {
-        printIndent();
-        out.print(text);
+    /**
+     * @since 4.1
+     * @param data char data
+     * @param escape does this data need to be enclosed into &lt;![CDATA[ ... ]]&gt;
+     * @return this
+     */
+    public XMLEncoder cdata(String data, boolean escape) {
+        if(tagOpened) {
+            print(">");
+        }
+        cdata = true;
+        if(escape) {
+            print("<![CDATA[");
+        }
+        print(data);
+        if(escape) {
+            print("]]>");
+        }
+        return this;
     }
 
-    public void print(char c) {
-        printIndent();
-        out.print(c);
+    /**
+     * @since 4.1
+     * @param object nested object to serialize
+     * @param delegate visitor
+     * @return this
+     */
+    public XMLEncoder nested(XMLSerializable object, ConfigurationNodeVisitor delegate) {
+        if(object == null) {
+            return this;
+        }
+        object.encodeAsXML(this, delegate);
+        return this;
     }
 
-    public void print(boolean b) {
-        printIndent();
-        out.print(b);
+    /**
+     * @since 4.1
+     * @param collection of nested objects
+     * @param delegate visitor
+     * @return this
+     */
+    public XMLEncoder nested(Collection<? extends XMLSerializable> collection, ConfigurationNodeVisitor delegate) {
+        if(collection == null) {
+            return this;
+        }
+        for (XMLSerializable value : collection) {
+            value.encodeAsXML(this, delegate);
+        }
+        return this;
     }
 
-    public void print(int i) {
-        printIndent();
-        out.print(i);
+    /**
+     * @since 4.1
+     * @param map of nested objects
+     * @param delegate visitor
+     * @return this
+     */
+    public XMLEncoder nested(Map<?, ? extends XMLSerializable> map, ConfigurationNodeVisitor delegate) {
+        if(map == null) {
+            return this;
+        }
+        for (XMLSerializable value : map.values()) {
+            value.encodeAsXML(this, delegate);
+        }
+        return this;
     }
 
-    public void println(String text) {
-        printIndent();
-        out.println(text);
+    /**
+     * Prints a common XML element - property with name and value.
+     * @since 4.1
+     */
+    public XMLEncoder property(String name, String value) {
+        if(Util.isEmptyString(value)) {
+            return this;
+        }
+        start("property").attribute("name", name).attribute("value", value).end();
         indentLine = true;
+        return this;
     }
 
     /**
-     * @since 3.1
+     * Prints a common XML element - property with name and value.
+     * @since 4.1
      */
-    public void println() {
-        out.println();
-        indentLine = true;
+    public XMLEncoder property(String name, boolean b) {
+        if(!b) {
+            return this;
+        }
+        return property(name, "true");
     }
 
-    public void println(char c) {
-        printIndent();
-        out.println(c);
-        indentLine = true;
+    /**
+     * Prints a common XML element - property with name and value.
+     * @since 4.1
+     */
+    public XMLEncoder property(String name, int i) {
+        if(i == 0) {
+            return this;
+        }
+        return property(name, String.valueOf(i));
     }
 
-    private void printIndent() {
-        if (indentLine) {
-            indentLine = false;
-
-            if (indentTimes > 0 && indent != null) {
-                for (int i = 0; i < indentTimes; i++) {
-                    out.print(indent);
-                }
-            }
+    /**
+     * Prints common XML element - tag with name and text value (&lt;tag>value&lt;/tag>)
+     * If value is empty, nothing will be printed.
+     * @since 4.1
+     */
+    public XMLEncoder simpleTag(String tag, String value) {
+        if (!Util.isEmptyString(value)) {
+            start(tag).cdata(value).end();
         }
+        return this;
+    }
+
+    /**
+     * Inserts an optional project version attribute in the output. If the project version
+     * is not initialized for encoder, will do nothing.
+     *
+     * @since 4.1
+     */
+    public XMLEncoder projectVersion() {
+        return attribute("project-version", projectVersion, true);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/util/XMLSerializable.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/util/XMLSerializable.java b/cayenne-server/src/main/java/org/apache/cayenne/util/XMLSerializable.java
index 3c6cba0..2646785 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/util/XMLSerializable.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/util/XMLSerializable.java
@@ -19,6 +19,8 @@
 
 package org.apache.cayenne.util;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+
 /**
  * Interface for Cayenne objects that can be saved to XML.
  * 
@@ -30,5 +32,5 @@ public interface XMLSerializable {
      * 
      * @since 1.1
      */
-    public void encodeAsXML(XMLEncoder encoder);
+    void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate);
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/dbimport.xsd
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/dbimport.xsd b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/dbimport.xsd
new file mode 100644
index 0000000..a100799
--- /dev/null
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/dbimport.xsd
@@ -0,0 +1,106 @@
+<?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.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<xs:schema targetNamespace="http://cayenne.apache.org/schema/10/dbimport"
+           xmlns:dbi="http://cayenne.apache.org/schema/10/dbimport"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="10">
+
+    <xs:element name="config">
+        <xs:complexType>
+            <xs:complexContent>
+                <xs:extension base="dbi:container">
+                    <xs:sequence>
+                        <xs:element name="catalog" minOccurs="0" maxOccurs="unbounded" type="dbi:catalog"/>
+                        <xs:element name="schema" minOccurs="0" maxOccurs="unbounded" type="dbi:schema"/>
+                        <xs:element name="tableType" minOccurs="0" maxOccurs="unbounded" type="dbi:db-type"/>
+
+                        <xs:element name="defaultPackage" minOccurs="0" type="xs:string"/>
+                        <xs:element name="forceDataMapCatalog" minOccurs="0" type="xs:boolean"/>
+                        <xs:element name="forceDataMapSchema" minOccurs="0" type="xs:boolean"/>
+                        <xs:element name="meaningfulPkTables" minOccurs="0" type="xs:string"/>
+                        <xs:element name="namingStrategy" minOccurs="0" type="xs:string"/>
+                        <xs:element name="skipPrimaryKeyLoading" minOccurs="0" type="xs:boolean"/>
+                        <xs:element name="skipRelationshipsLoading" minOccurs="0" type="xs:boolean"/>
+                        <xs:element name="stripFromTableNames" minOccurs="0" type="xs:string"/>
+                        <xs:element name="useJava7Types" minOccurs="0" type="xs:boolean"/>
+                        <xs:element name="usePrimitives" minOccurs="0" type="xs:boolean"/>
+
+                        <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+                    </xs:sequence>
+                </xs:extension>
+            </xs:complexContent>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:simpleType name="db-type">
+        <xs:restriction base="xs:string">
+            <xs:pattern value="[0-9a-zA-Z$_.]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="includeTable" mixed="true">
+        <xs:sequence>
+            <xs:element name="name" minOccurs="0" type="dbi:db-type"/>
+            <xs:element name="includeColumn" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="excludeColumn" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+
+            <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="container" abstract="true">
+        <xs:sequence>
+            <xs:element name="includeTable" type="dbi:includeTable" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="excludeTable" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="includeColumn" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="excludeColumn" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="includeProcedure" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="excludeProcedure" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+
+            <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="schema">
+        <xs:complexContent>
+            <xs:extension base="dbi:container">
+                <xs:sequence>
+                    <xs:element name="name" type="dbi:db-type"/>
+
+                    <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+                </xs:sequence>
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+    <xs:complexType name="catalog">
+        <xs:complexContent>
+            <xs:extension base="dbi:container">
+                <xs:sequence>
+                    <xs:element name="name" type="dbi:db-type"/>
+                    <xs:element name="schema" type="dbi:schema" minOccurs="0" maxOccurs="unbounded"/>
+
+                    <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+                </xs:sequence>
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+</xs:schema>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/domain.xsd
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/domain.xsd b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/domain.xsd
new file mode 100644
index 0000000..40809d5
--- /dev/null
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/domain.xsd
@@ -0,0 +1,130 @@
+<?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.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<xs:schema targetNamespace="http://cayenne.apache.org/schema/10/domain"
+           elementFormDefault="qualified" version="10"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           xmlns:cay="http://cayenne.apache.org/schema/10/domain">
+
+    <xs:element name="domain">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:property"/>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:map"/>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:node"/>
+                <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+            </xs:sequence>
+            <xs:attribute name="project-version" use="required" type="xs:string"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="property">
+        <xs:annotation>
+            <xs:documentation>A generic property used by other elements.</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:attribute name="name" use="required" type="xs:string"/>
+            <xs:attribute name="value" use="required" type="xs:string"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="map">
+        <xs:annotation>
+            <xs:documentation>Link to an external file with data map.</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:attribute name="name" use="required" type="xs:string"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="node">
+        <xs:annotation>
+            <xs:documentation>Data node description.</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:map-ref"/>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:data-source"/>
+                <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+            </xs:sequence>
+            <xs:attribute name="name" use="required" type="xs:string"/>
+            <xs:attribute name="factory" use="required" type="xs:string"/>
+            <xs:attribute name="adapter" type="xs:string"/>
+            <xs:attribute name="schema-update-strategy" type="xs:string"/>
+            <xs:attribute name="parameters" type="xs:string"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="map-ref">
+        <xs:annotation>
+            <xs:documentation>A reference to a map.</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:attribute name="name" use="required" type="xs:string"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="data-source">
+        <xs:annotation>
+            <xs:documentation>Data source configuration.</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element minOccurs="0" maxOccurs="1" ref="cay:driver"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="cay:url"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="cay:connectionPool"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="cay:login"/>
+                <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="driver">
+        <xs:complexType>
+            <xs:attribute name="value" type="xs:string"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="url">
+        <xs:complexType>
+            <xs:attribute name="value" type="xs:string"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="connectionPool">
+        <xs:complexType>
+            <xs:attribute name="min" use="required" type="xs:int"/>
+            <xs:attribute name="max" use="required" type="xs:int"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="login">
+        <xs:complexType>
+            <xs:attribute name="userName" type="xs:string"/>
+            <xs:attribute name="password" type="xs:string"/>
+            <xs:attribute name="passwordLocation" type="xs:string"/>
+            <xs:attribute name="passwordSource" type="xs:string"/>
+            <xs:attribute name="encoderClass" type="xs:string"/>
+            <xs:attribute name="encoderKey" type="xs:string"/>
+            <xs:attribute name="encoderSalt" type="xs:string"/>
+        </xs:complexType>
+    </xs:element>
+
+</xs:schema>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/info.xsd
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/info.xsd b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/info.xsd
new file mode 100644
index 0000000..480b24d
--- /dev/null
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/info.xsd
@@ -0,0 +1,29 @@
+<?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.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<xs:schema targetNamespace="http://cayenne.apache.org/schema/10/info"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="10">
+    <xs:element name="property">
+        <xs:complexType>
+            <xs:attribute name="name" use="required" type="xs:string"/>
+            <xs:attribute name="value" type="xs:string"/>
+        </xs:complexType>
+    </xs:element>
+</xs:schema>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/modelMap.xsd
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/modelMap.xsd b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/modelMap.xsd
new file mode 100644
index 0000000..7f36483
--- /dev/null
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/modelMap.xsd
@@ -0,0 +1,356 @@
+<?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.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<!--
+	Cayenne entity map schema 
+	Defines format of Cayenne DataMap XML files (*.map.xml).  DataMap files contain
+	the metadata needed for Cayenne object-relational features. Multiple DataMaps
+	are usually combined in one shared namespace, so the elements of the DataMap
+	may reference objects from other DataMaps.
+--> 
+<xs:schema targetNamespace="http://cayenne.apache.org/schema/10/modelMap"
+	xmlns:cay="http://cayenne.apache.org/schema/10/modelMap"
+	xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="10">
+	<xs:element name="data-map">
+		<xs:complexType>
+			<xs:sequence>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:property"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:embeddable"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:procedure"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:db-entity"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:obj-entity"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:db-relationship"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:obj-relationship"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:query"/>
+				<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+			</xs:sequence>
+			<xs:attribute name="project-version" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="db-entity">
+		<xs:complexType>
+			<xs:sequence>
+				<xs:element maxOccurs="unbounded" ref="cay:db-attribute"/>
+				<xs:element minOccurs="0" ref="cay:db-key-generator"/>
+				
+				<!-- Qualifier for DB Entity -->
+				<xs:element minOccurs="0" ref="cay:qualifier"/>
+
+				<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+			</xs:sequence>
+			<xs:attribute name="name" use="required" type="xs:string"/>
+			<xs:attribute name="schema" type="xs:string"/>
+			<xs:attribute name="catalog" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="db-attribute">
+		<xs:annotation>
+			<xs:documentation>A database column.</xs:documentation>
+		</xs:annotation>
+		<xs:complexType>
+			<xs:sequence>
+				<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+			</xs:sequence>
+			<xs:attribute name="isMandatory" type="xs:boolean"/>
+			<xs:attribute name="isPrimaryKey" type="xs:boolean">
+				<xs:annotation>
+					<xs:documentation>If true, the value of attribute is unique and used as a primary key identifier.</xs:documentation>
+				</xs:annotation>
+			</xs:attribute>
+			<xs:attribute name="isGenerated" type="xs:boolean"/>
+			<xs:attribute name="length" type="xs:integer"/>
+			<xs:attribute name="name" use="required" type="xs:string"/>
+			<xs:attribute name="scale" type="xs:integer"/>
+			<xs:attribute name="type" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:element name="obj-entity">
+		<xs:annotation>
+			<xs:documentation>A persistent Java class managed by Cayenne.</xs:documentation>
+		</xs:annotation>
+		<xs:complexType>
+			<xs:sequence>
+				<xs:element minOccurs="0" ref="cay:qualifier"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:embedded-attribute"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:obj-attribute"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:attribute-override"/>
+				
+				<!--  Callbacks -->
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:post-add"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:pre-persist"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:post-persist"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:pre-update"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:post-update"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:pre-remove"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:post-remove"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:post-load"/>
+
+				<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+			</xs:sequence>
+			<xs:attribute name="className" type="xs:string"/>
+			<xs:attribute name="abstract" type="xs:boolean"/>
+			<xs:attribute name="readOnly" type="xs:boolean"/>
+			<xs:attribute name="clientClassName" type="xs:string"/>
+			<xs:attribute name="clientSuperClassName" type="xs:string"/>
+			<xs:attribute name="dbEntityName" type="xs:string"/>
+			<xs:attribute name="lock-type" type="xs:string"/>
+			<xs:attribute name="name" use="required" type="xs:string"/>
+			<xs:attribute name="superClassName" type="xs:string"/>
+			<xs:attribute name="superEntityName" type="xs:string"/>
+			<xs:attribute name="serverOnly" type="xs:boolean"/>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:element name="qualifier" type="xs:string"/>
+
+	<xs:element name="obj-attribute">
+		<xs:complexType>
+			<xs:sequence>
+				<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+			</xs:sequence>
+			<xs:attribute name="db-attribute-path" type="xs:string"/>
+			<xs:attribute name="lock" type="xs:boolean"/>
+			<xs:attribute name="name" use="required" type="xs:string"/>
+			<xs:attribute name="type" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:element name="attribute-override">
+		<xs:complexType>
+			<xs:attribute name="db-attribute-path" type="xs:string"/>
+			<xs:attribute name="lock" type="xs:boolean"/>
+			<xs:attribute name="name" type="xs:string"/>
+			<xs:attribute name="type" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:element name="db-relationship">
+		<xs:complexType>
+			<xs:sequence>
+				<xs:element minOccurs="1" maxOccurs="unbounded" ref="cay:db-attribute-pair"/>
+				<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+			</xs:sequence>
+			<xs:attribute name="name" use="required" type="xs:string"/>
+			<xs:attribute name="source" use="required" type="xs:string"/>
+			<xs:attribute name="target" use="required" type="xs:string"/>
+			<xs:attribute name="toDependentPK" type="xs:boolean"/>
+			<xs:attribute name="toMany" type="xs:boolean"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="db-attribute-pair">
+		<xs:complexType>
+			<xs:attribute name="source" use="required" type="xs:string"/>
+			<xs:attribute name="target" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="obj-relationship">
+		<xs:complexType>
+			<xs:sequence>
+				<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+			</xs:sequence>
+			<xs:attribute name="db-relationship-path" use="required" type="xs:string"/>
+			<xs:attribute name="deleteRule" type="xs:string"/>
+			<xs:attribute name="lock" type="xs:boolean"/>
+			<xs:attribute name="name" use="required" type="xs:string"/>
+			<xs:attribute name="source" use="required" type="xs:string"/>
+			<xs:attribute name="target" use="required" type="xs:string"/>
+			<xs:attribute name="collection-type" type="xs:string"/>
+			<xs:attribute name="map-key" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:element name="query">
+		<xs:complexType>
+			<xs:sequence>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:property"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:sql"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:ejbql"/>
+				<xs:element name="qualifier" minOccurs="0" maxOccurs="unbounded" type="xs:string"/>
+				<xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:ordering"/>
+				<xs:element name="prefetch" minOccurs="0" maxOccurs="unbounded" type="xs:string"/>
+				<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+			</xs:sequence>
+			<xs:attribute name="type" use="required" type="xs:string"/>
+			<xs:attribute name="name" use="required" type="xs:string"/>
+			<xs:attribute name="root" type="xs:string"/>
+			<xs:attribute name="root-name" type="xs:string"/>
+			<xs:attribute name="result-entity" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:element name="ordering">
+		<xs:complexType>
+			<xs:simpleContent>
+				<xs:extension base="xs:string">
+					<xs:attribute name="descending" type="xs:boolean"/>
+					<xs:attribute name="ignore-case" type="xs:boolean"/>
+				</xs:extension>
+			</xs:simpleContent>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:element name="sql">
+		<xs:annotation>
+			<xs:documentation>Defines arbitrary SQL statement. Note that SQL statement can be customized for different SQL dialects per DbAdapter class. If no adapter-specific statement is found, the one with no adapter label is used by default.</xs:documentation>
+		</xs:annotation>
+		<xs:complexType>
+			<xs:simpleContent>
+				<xs:extension base="xs:string">
+					<xs:attribute name="adapter-class" type="xs:string"/>
+				</xs:extension>
+			</xs:simpleContent>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:element name="ejbql" type="xs:string"/>
+
+	<xs:element name="property">
+		<xs:annotation>
+			<xs:documentation>A generic property used by other elements.</xs:documentation>
+		</xs:annotation>
+		<xs:complexType>
+			<xs:attribute name="name" use="required" type="xs:string"/>
+			<xs:attribute name="value" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="embeddable">
+		<xs:complexType>
+			<xs:sequence>
+				<xs:element name="embeddable-attribute" minOccurs="0" maxOccurs="unbounded">
+					<xs:complexType>
+						<xs:attribute name="name" use="required" type="xs:string"/>
+						<xs:attribute name="type" use="required" type="xs:string"/>
+						<xs:attribute name="db-attribute-name" use="required" type="xs:string"/>
+					</xs:complexType>
+				</xs:element>
+				<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+			</xs:sequence>
+			<xs:attribute name="className" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:element name="embedded-attribute">
+		<xs:complexType>
+			<xs:sequence>
+				<xs:element minOccurs="0" maxOccurs="unbounded"
+					ref="cay:embeddable-attribute-override"/>
+			</xs:sequence>
+			<xs:attribute name="type" use="required" type="xs:string"/>
+			<xs:attribute name="name" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:element name="embeddable-attribute-override">
+		<xs:complexType>
+			<xs:attribute name="db-attribute-path" use="required" type="xs:string"/>
+			<xs:attribute name="name" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:element name="procedure">
+		<xs:complexType>
+			<xs:sequence>
+				<xs:element minOccurs="0" maxOccurs="unbounded" name="procedure-parameter">
+					<xs:complexType>
+						<xs:attribute name="name" use="required" type="xs:string"/>
+						<xs:attribute name="type" use="required" type="xs:string"/>
+						<xs:attribute name="length" type="xs:integer"/>
+						<xs:attribute name="direction" use="required" type="xs:string"/>
+					</xs:complexType>
+				</xs:element>
+				<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+			</xs:sequence>
+			<xs:attribute name="name" use="required" type="xs:string"/>
+			<xs:attribute name="schema" type="xs:string"/>
+			<xs:attribute name="catalog" type="xs:string"/>
+			<xs:attribute name="returningValue" type="xs:boolean"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="pre-update">
+		<xs:complexType>
+			<xs:attribute name="method-name" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="post-persist">
+		<xs:complexType>
+			<xs:attribute name="method-name" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="post-update">
+		<xs:complexType>
+			<xs:attribute name="method-name" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="post-add">
+		<xs:complexType>
+			<xs:attribute name="method-name" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="pre-persist">
+		<xs:complexType>
+			<xs:attribute name="method-name" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="post-remove">
+		<xs:complexType>
+			<xs:attribute name="method-name" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="post-load">
+		<xs:complexType>
+			<xs:attribute name="method-name" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+	<xs:element name="pre-remove">
+		<xs:complexType>
+			<xs:attribute name="method-name" use="required" type="xs:string"/>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:element name="db-key-generator">
+		<xs:annotation>
+			<xs:documentation>Used to install the Automatic Sequence/Key Generation facility for db-entity. This feature is intended for use with simple (non-compound) integral primary keys.</xs:documentation>
+		</xs:annotation>
+		<xs:complexType>
+			<xs:sequence>
+				<xs:element name="db-generator-type" type="xs:string">
+					<xs:annotation>
+						<xs:documentation>Specifies the Key Generation Method that will be employed
+      'ORACLE'               - use Oracle's SEQUENCE
+      'NAMED_SEQUENCE_TABLE' - use USER designated SEQUENCE TABLE. User specifies the name of a DBMS Table with the schema (sequence INT) which will be used to hold sequence values (not supported yet)</xs:documentation>
+					</xs:annotation>
+				</xs:element>
+				<xs:element minOccurs="0" name="db-generator-name" type="xs:string">
+					<xs:annotation>
+						<xs:documentation>For db-generator-type ORACLE this is the name of the ORACLE SEQUENCE to use. The SEQUENCE is assumed to already exist in the Database.
+If this is db-generator-type NAMED_SEQUENCE_TABLE Key Generation, this specifies the name of the SEQUENCE TABLE to use. The NAMED_SEQUENCE_TABLE is assumed to already exist in the database.</xs:documentation>
+					</xs:annotation>
+				</xs:element>
+				<xs:element minOccurs="0" name="db-key-cache-size" type="xs:integer">
+					<xs:annotation>
+						<xs:documentation>Size of key cache. For db-generator-type ORACLE , this value MUST match the Oracle SEQUENCE  INCREMENT value.  If there is a mismatch between this value and the Oracle SEQUENCE INCREMENT value, then there will likely be duplicate key problems.
+For db-generator-type NAMED_SEQUENCE_TABLE , this tells how many keys the Container will fetch in a single DBMS call.</xs:documentation>
+					</xs:annotation>
+				</xs:element>
+			</xs:sequence>
+		</xs:complexType>
+	</xs:element>
+</xs:schema>

[13/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - updated test projects version in all modules

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDbAttributeChange.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDbAttributeChange.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDbAttributeChange.map.xml-result
index c53bde2..c3153b2 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDbAttributeChange.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDbAttributeChange.map.xml-result
@@ -18,10 +18,10 @@
   ~  specific language governing permissions and limitations
   ~  under the License.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
 
     <db-entity name="CHILD" schema="SCHEMA_01">
         <db-attribute name="COL3" type="DECIMAL" length="5" scale="1"/>
@@ -51,7 +51,7 @@
         <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>
-    <db-relationship name="parent" source="CHILD" target="parent" toMany="false">
+    <db-relationship name="parent" source="CHILD" target="parent">
         <db-attribute-pair source="parent_id" target="ID"/>
     </db-relationship>
     <db-relationship name="children" source="parent" target="CHILD" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDefaultPackage.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDefaultPackage.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDefaultPackage.map.xml-result
index f581dc4..fa0709c 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDefaultPackage.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDefaultPackage.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultPackage" value="com.example.test"/>
     <property name="defaultSchema" value="SCHEMA_01"/>
     <db-entity name="CHILD" schema="SCHEMA_01">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.map.xml-result
index d5d7849..7c00c4d 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFilteringWithSchema.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
     <db-entity name="CHILD" schema="SCHEMA_01">
         <db-attribute name="COL3" type="DECIMAL" length="10" scale="2"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFkAttributeRename.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFkAttributeRename.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFkAttributeRename.map.xml
index 948e121..3201832 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFkAttributeRename.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFkAttributeRename.map.xml
@@ -17,10 +17,10 @@
   ~  specific language governing permissions and limitations
   ~  under the License.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
 
     <db-entity name="CHILD" schema="SCHEMA_01">
         <db-attribute name="id" type="INTEGER" length="10"/>
@@ -33,7 +33,7 @@
     </obj-entity>
     <obj-entity name="Parent" className="Parent" dbEntityName="PARENT">
     </obj-entity>
-    <db-relationship name="parent" source="CHILD" target="PARENT" toMany="false">
+    <db-relationship name="parent" source="CHILD" target="PARENT">
         <db-attribute-pair source="parent_id" target="id"/>
     </db-relationship>
     <db-relationship name="children" source="PARENT" target="CHILD" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFkAttributeRename.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFkAttributeRename.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFkAttributeRename.map.xml-result
index d10b90d..1dc92c1 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFkAttributeRename.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFkAttributeRename.map.xml-result
@@ -18,10 +18,10 @@
   ~  specific language governing permissions and limitations
   ~  under the License.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
 
     <db-entity name="CHILD" schema="SCHEMA_01">
         <db-attribute name="PAR" type="INTEGER" length="10"/>
@@ -34,7 +34,7 @@
     </obj-entity>
     <obj-entity name="Parent" className="Parent" dbEntityName="PARENT">
     </obj-entity>
-    <db-relationship name="parent" source="CHILD" target="PARENT" toMany="false">
+    <db-relationship name="parent" source="CHILD" target="PARENT">
         <db-attribute-pair source="PAR" target="id"/>
     </db-relationship>
     <db-relationship name="children" source="PARENT" target="CHILD" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFlattensManyToManyWithRecursiveLink.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFlattensManyToManyWithRecursiveLink.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFlattensManyToManyWithRecursiveLink.map.xml-result
index 8263273..6dbb77a 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFlattensManyToManyWithRecursiveLink.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testFlattensManyToManyWithRecursiveLink.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultPackage" value="org.not.my.home"/>
     <db-entity name="A" schema="APP">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
@@ -37,10 +37,10 @@
     <db-relationship name="aAArray1" source="A" target="A_A" toDependentPK="true" toMany="true">
         <db-attribute-pair source="ID" target="A2_ID"/>
     </db-relationship>
-    <db-relationship name="toA" source="A_A" target="A" toMany="false">
+    <db-relationship name="toA" source="A_A" target="A">
         <db-attribute-pair source="A1_ID" target="ID"/>
     </db-relationship>
-    <db-relationship name="toA1" source="A_A" target="A" toMany="false">
+    <db-relationship name="toA1" source="A_A" target="A">
         <db-attribute-pair source="A2_ID" target="ID"/>
     </db-relationship>
     <obj-relationship name="aArray" source="A" target="A" db-relationship-path="aAArray.toA1"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testForceDataMapSchema.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testForceDataMapSchema.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testForceDataMapSchema.map.xml
index 1d9dea0..71b53ce 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testForceDataMapSchema.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testForceDataMapSchema.map.xml
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultPackage" value="com.example.test"/>
     <property name="defaultCatalog" value="XCATALOG"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testForceDataMapSchema.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testForceDataMapSchema.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testForceDataMapSchema.map.xml-result
index 4a6e490..bb43f01 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testForceDataMapSchema.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testForceDataMapSchema.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultPackage" value="com.example.test"/>
     <property name="defaultCatalog" value="XCATALOG"/>
     <db-entity name="CHILD" catalog="XCATALOG">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableAndColumn.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableAndColumn.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableAndColumn.map.xml
index 2317476..dd1477f 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableAndColumn.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableAndColumn.map.xml
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<db-entity name="testImportAddTableAndColumn" schema="APP">
 		<db-attribute name="COL1" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
 		<db-attribute name="COL2" type="CHAR" length="25"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableAndColumn.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableAndColumn.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableAndColumn.map.xml-result
index 42a8e15..46cedfb 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableAndColumn.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableAndColumn.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <db-entity name="CHILD" schema="APP">
         <db-attribute name="COL3" type="DECIMAL" length="10" scale="2"/>
         <db-attribute name="COL4" type="VARCHAR" length="25"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewDataMap.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewDataMap.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewDataMap.map.xml-result
index 923f87b..86d75cb 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewDataMap.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewDataMap.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<db-entity name="TEST_TABLE" schema="APP">
 		<db-attribute name="COL1" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
 		<db-attribute name="COL2" type="CHAR" length="25"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationship.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationship.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationship.map.xml
index 73043b1..5879a4f 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationship.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationship.map.xml
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
     <db-entity name="TABLE1" schema="SCHEMA_01">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationship.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationship.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationship.map.xml-result
index 5daeef7..23e2f6f 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationship.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationship.map.xml-result
@@ -17,10 +17,10 @@
   ~  specific language governing permissions and limitations
   ~  under the License.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	 <property name="defaultSchema" value="SCHEMA_01"/>
 	 <db-entity name="TABLE1" schema="SCHEMA_01">
     		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
@@ -40,7 +40,7 @@
      <db-relationship name="table2s" source="TABLE1" target="TABLE2" toMany="true">
         <db-attribute-pair source="ID" target="TABLE1_ID"/>
      </db-relationship>
-     <db-relationship name="table1" source="TABLE2" target="TABLE1" toMany="false">
+     <db-relationship name="table1" source="TABLE2" target="TABLE1">
         <db-attribute-pair source="TABLE1_ID" target="ID"/>
      </db-relationship>
      <obj-relationship name="table2s" source="Table1" target="Table2" deleteRule="Deny" db-relationship-path="table2s"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges.map.xml
index a22e016..3d96df4 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges.map.xml
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.   
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<db-entity name="testImportWithoutChanges" schema="APP">
 		<db-attribute name="COL1" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
 		<db-attribute name="COL2" type="CHAR" length="25"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges.map.xml-result
index 25c85af..305db18 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportWithoutChanges.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<db-entity name="testImportWithoutChanges" schema="APP">
 		<db-attribute name="COL1" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
 		<db-attribute name="COL2" type="CHAR" length="25"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance.map.xml
index b849751..83dbec4 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance.map.xml
@@ -17,10 +17,10 @@
   ~  specific language governing permissions and limitations
   ~  under the License.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
 
     <db-entity name="CHILD" schema="SCHEMA_01">
         <db-attribute name="id" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance.map.xml-result
index 7e54338..a2a3361 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testInheritance.map.xml-result
@@ -17,10 +17,10 @@
   ~  specific language governing permissions and limitations
   ~  under the License.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
 
     <db-entity name="CHILD" schema="SCHEMA_01">
         <db-attribute name="id" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
@@ -37,7 +37,7 @@
     </obj-entity>
     <obj-entity name="ParentSub" superEntityName="Parent" className="ParentSub">
     </obj-entity>
-    <db-relationship name="parent" source="CHILD" target="PARENT" toMany="false">
+    <db-relationship name="parent" source="CHILD" target="PARENT">
         <db-attribute-pair source="parent_id" target="id"/>
     </db-relationship>
     <db-relationship name="children" source="PARENT" target="CHILD" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava7Types.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava7Types.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava7Types.map.xml
index 08ac7f7..19b7c6a 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava7Types.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava7Types.map.xml
@@ -17,10 +17,10 @@
   ~  specific language governing permissions and limitations
   ~  under the License.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
 </data-map>
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava7Types.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava7Types.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava7Types.map.xml-result
index 480c302..f157727 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava7Types.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava7Types.map.xml-result
@@ -18,10 +18,10 @@
   ~  specific language governing permissions and limitations
   ~  under the License.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
 
     <db-entity name="CHILD" schema="SCHEMA_01">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava8Types.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava8Types.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava8Types.map.xml
index 08ac7f7..19b7c6a 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava8Types.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava8Types.map.xml
@@ -17,10 +17,10 @@
   ~  specific language governing permissions and limitations
   ~  under the License.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
 </data-map>
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava8Types.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava8Types.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava8Types.map.xml-result
index 687ac07..c1ce16c 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava8Types.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testJava8Types.map.xml-result
@@ -18,10 +18,10 @@
   ~  specific language governing permissions and limitations
   ~  under the License.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
 
     <db-entity name="CHILD" schema="SCHEMA_01">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
index 203c001..beb1352 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
 	<db-entity name="PICK_SCHEDULE" schema="APP">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
 		<db-attribute name="OWNER_ID" type="INTEGER" length="10"/>
@@ -39,16 +39,16 @@
 	</obj-entity>
 	<obj-entity name="PlayerInfo" className="PlayerInfo" dbEntityName="PLAYER_INFO">
 	</obj-entity>
-	<db-relationship name="selectedPlayer" source="PICK_SCHEDULE" target="PLAYER" toMany="false">
+	<db-relationship name="selectedPlayer" source="PICK_SCHEDULE" target="PLAYER">
 		<db-attribute-pair source="SELECTED_PLAYER_ID" target="ID"/>
 	</db-relationship>
 	<db-relationship name="pickSchedules" source="PLAYER" target="PICK_SCHEDULE" toMany="true">
 		<db-attribute-pair source="ID" target="SELECTED_PLAYER_ID"/>
 	</db-relationship>
-	<db-relationship name="playerInfo" source="PLAYER" target="PLAYER_INFO" toDependentPK="true" toMany="false">
+	<db-relationship name="playerInfo" source="PLAYER" target="PLAYER_INFO" toDependentPK="true">
 		<db-attribute-pair source="ID" target="PLAYER_ID"/>
 	</db-relationship>
-	<db-relationship name="player" source="PLAYER_INFO" target="PLAYER" toMany="false">
+	<db-relationship name="player" source="PLAYER_INFO" target="PLAYER">
 		<db-attribute-pair source="PLAYER_ID" target="ID"/>
 	</db-relationship>
 	<obj-relationship name="selectedPlayer" source="PickSchedule" target="Player" deleteRule="Nullify" db-relationship-path="selectedPlayer"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveCustomObjMappings.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveCustomObjMappings.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveCustomObjMappings.map.xml
index 909c5f9..dabdce4 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveCustomObjMappings.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveCustomObjMappings.map.xml
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
     <db-entity name="PARENT" schema="SCHEMA_01">
         <db-attribute name="COL2" type="CHAR" length="25"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveCustomObjMappings.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveCustomObjMappings.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveCustomObjMappings.map.xml-result
index d874808..388d2e7 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveCustomObjMappings.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveCustomObjMappings.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
     <db-entity name="PARENT" schema="SCHEMA_01">
         <db-attribute name="COL2" type="CHAR" length="25"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveRelationships.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveRelationships.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveRelationships.map.xml
index 5d3c059..96ee6c4 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveRelationships.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveRelationships.map.xml
@@ -17,10 +17,10 @@
   specific language governing permissions and limitations
   under the License.
   -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
     <db-entity name="CHILD" schema="APP">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
         <db-attribute name="PARENT_ID" type="INTEGER" length="10"/>
@@ -33,10 +33,10 @@
     </obj-entity>
     <obj-entity name="Parent" className="Parent" dbEntityName="PARENT">
     </obj-entity>
-    <db-relationship name="toParent" source="CHILD" target="PARENT" toMany="false">
+    <db-relationship name="toParent" source="CHILD" target="PARENT">
         <db-attribute-pair source="PARENT_ID" target="ID"/>
     </db-relationship>
-    <db-relationship name="toParent" source="PARENT" target="CHILD" toMany="false">
+    <db-relationship name="toParent" source="PARENT" target="CHILD">
         <db-attribute-pair source="ID" target="PARENT_ID"/>
     </db-relationship>
     <obj-relationship name="toParent" source="Child" target="Parent" deleteRule="Nullify" db-relationship-path="toParent"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveRelationships.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveRelationships.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveRelationships.map.xml-result
index 818c17f..02176b8 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveRelationships.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testPreserveRelationships.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <db-entity name="CHILD" schema="APP">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
     </db-entity>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.map.xml-result
index 24f69a4..11e6642 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSchemasAndTableExclude.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
     <db-entity name="PARENT" schema="SCHEMA_01">
         <db-attribute name="COL2" type="CHAR" length="25"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipPrimaryKeyLoading.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipPrimaryKeyLoading.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipPrimaryKeyLoading.map.xml
index 1f08680..2786c7f 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipPrimaryKeyLoading.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipPrimaryKeyLoading.map.xml
@@ -17,10 +17,10 @@
   specific language governing permissions and limitations
   under the License.
   -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
     <property name="defaultPackage" value="com.my.home"/>
     <db-entity name="A" schema="APP">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipPrimaryKeyLoading.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipPrimaryKeyLoading.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipPrimaryKeyLoading.map.xml-result
index 4da960f..672be4d 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipPrimaryKeyLoading.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipPrimaryKeyLoading.map.xml-result
@@ -17,10 +17,10 @@
   specific language governing permissions and limitations
   under the License.
   -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
     <property name="defaultPackage" value="com.my.home"/>
     <db-entity name="A" schema="APP">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipRelationshipsLoading.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipRelationshipsLoading.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipRelationshipsLoading.map.xml
index a245765..2b3b19e 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipRelationshipsLoading.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipRelationshipsLoading.map.xml
@@ -17,10 +17,10 @@
   specific language governing permissions and limitations
   under the License.
   -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
     <property name="defaultPackage" value="com.my.home"/>
     <db-entity name="A" schema="APP">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
@@ -41,10 +41,10 @@
     <db-relationship name="aBArray" source="A" target="A_B" toMany="true">
         <db-attribute-pair source="ID" target="A_ID"/>
     </db-relationship>
-    <db-relationship name="toA" source="A_B" target="A" toMany="false">
+    <db-relationship name="toA" source="A_B" target="A">
         <db-attribute-pair source="A_ID" target="ID"/>
     </db-relationship>
-    <db-relationship name="toB" source="A_B" target="B" toMany="false">
+    <db-relationship name="toB" source="A_B" target="B">
         <db-attribute-pair source="B_ID" target="ID"/>
     </db-relationship>
     <db-relationship name="aBArray" source="B" target="A_B" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipRelationshipsLoading.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipRelationshipsLoading.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipRelationshipsLoading.map.xml-result
index a245765..2b3b19e 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipRelationshipsLoading.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testSkipRelationshipsLoading.map.xml-result
@@ -17,10 +17,10 @@
   specific language governing permissions and limitations
   under the License.
   -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
     <property name="defaultPackage" value="com.my.home"/>
     <db-entity name="A" schema="APP">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
@@ -41,10 +41,10 @@
     <db-relationship name="aBArray" source="A" target="A_B" toMany="true">
         <db-attribute-pair source="ID" target="A_ID"/>
     </db-relationship>
-    <db-relationship name="toA" source="A_B" target="A" toMany="false">
+    <db-relationship name="toA" source="A_B" target="A">
         <db-attribute-pair source="A_ID" target="ID"/>
     </db-relationship>
-    <db-relationship name="toB" source="A_B" target="B" toMany="false">
+    <db-relationship name="toB" source="A_B" target="B">
         <db-attribute-pair source="B_ID" target="ID"/>
     </db-relationship>
     <db-relationship name="aBArray" source="B" target="A_B" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testTableTypes.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testTableTypes.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testTableTypes.map.xml-result
index cdc9ddd..fc393be 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testTableTypes.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testTableTypes.map.xml-result
@@ -17,10 +17,10 @@
     specific language governing permissions and limitations
     under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <db-entity name="PERSON" schema="APP">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
     </db-entity>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testUnFlattensManyToMany.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testUnFlattensManyToMany.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testUnFlattensManyToMany.map.xml
index 689a94a..59b6045 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testUnFlattensManyToMany.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testUnFlattensManyToMany.map.xml
@@ -17,10 +17,10 @@
   specific language governing permissions and limitations
   under the License.
   -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
     <property name="defaultPackage" value="com.my.home"/>
     <db-entity name="A" schema="APP">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
@@ -41,10 +41,10 @@
     <db-relationship name="aBs" source="A" target="A_B" toDependentPK="true" toMany="true">
         <db-attribute-pair source="ID" target="A_ID"/>
     </db-relationship>
-    <db-relationship name="toA" source="A_B" target="A" toMany="false">
+    <db-relationship name="toA" source="A_B" target="A">
         <db-attribute-pair source="A_ID" target="ID"/>
     </db-relationship>
-    <db-relationship name="toB" source="A_B" target="B" toMany="false">
+    <db-relationship name="toB" source="A_B" target="B">
         <db-attribute-pair source="B_ID" target="ID"/>
     </db-relationship>
     <db-relationship name="aBs" source="B" target="A_B" toDependentPK="true" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testUnFlattensManyToMany.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testUnFlattensManyToMany.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testUnFlattensManyToMany.map.xml-result
index 46d6a84..8fb75bf 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testUnFlattensManyToMany.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testUnFlattensManyToMany.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultPackage" value="org.not.my.home"/>
     <db-entity name="A" schema="APP">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
@@ -60,10 +60,10 @@
     <db-relationship name="aBs" source="A" target="A_B" toDependentPK="true" toMany="true">
         <db-attribute-pair source="ID" target="A_ID"/>
     </db-relationship>
-    <db-relationship name="toA" source="A_B" target="A" toMany="false">
+    <db-relationship name="toA" source="A_B" target="A">
         <db-attribute-pair source="A_ID" target="ID"/>
     </db-relationship>
-    <db-relationship name="toB" source="A_B" target="B" toMany="false">
+    <db-relationship name="toB" source="A_B" target="B">
         <db-attribute-pair source="B_ID" target="ID"/>
     </db-relationship>
     <db-relationship name="aBs" source="B" target="A_B" toDependentPK="true" toMany="true">
@@ -72,10 +72,10 @@
     <db-relationship name="xIes" source="X" target="X_Y" toDependentPK="true" toMany="true">
         <db-attribute-pair source="ID" target="X_ID"/>
     </db-relationship>
-    <db-relationship name="x" source="X_Y" target="X" toMany="false">
+    <db-relationship name="x" source="X_Y" target="X">
         <db-attribute-pair source="X_ID" target="ID"/>
     </db-relationship>
-    <db-relationship name="y" source="X_Y" target="Y" toMany="false">
+    <db-relationship name="y" source="X_Y" target="Y">
         <db-attribute-pair source="Y_ID" target="ID"/>
     </db-relationship>
     <db-relationship name="xIes" source="Y" target="X_Y" toDependentPK="true" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testViewsExclude.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testViewsExclude.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testViewsExclude.map.xml-result
index f3e21bf..de41dbc 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testViewsExclude.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testViewsExclude.map.xml-result
@@ -17,10 +17,10 @@
     specific language governing permissions and limitations
     under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <db-entity name="GIRL" schema="APP">
         <db-attribute name="ID" type="INTEGER" isMandatory="true" length="10"/>
     </db-entity>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/cayenne-testDomain.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/cayenne-testDomain.xml b/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/cayenne-testDomain.xml
index 3f63c14..2acb92b 100644
--- a/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/cayenne-testDomain.xml
+++ b/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/cayenne-testDomain.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="6">
+<domain project-version="10">
 	<map name="testDomainMap"/>
     <map name="testAdditionalMap"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/testAdditionalMap.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/testAdditionalMap.map.xml b/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/testAdditionalMap.map.xml
index f9a80fb..ca2a724 100644
--- a/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/testAdditionalMap.map.xml
+++ b/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/testAdditionalMap.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/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">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultPackage" value="pack"/>
     <db-entity name="TestRelEntity">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/testDomainMap.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/testDomainMap.map.xml b/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/testDomainMap.map.xml
index d0ff3f5..2abab83 100644
--- a/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/testDomainMap.map.xml
+++ b/maven-plugins/maven-cayenne-plugin/src/test/resources/cgen/testDomainMap.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/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">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="pack"/>
 	<embeddable className="pack.Embeddable">
 		<embeddable-attribute name="embAttr" type="java.lang.String" db-attribute-name="EMB_ATTR"/>


[16/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - Cleanup and fix - Update Modeler

Posted by nt...@apache.org.
CAY-2335: New XML loading/saving mechanics with support of plugable handlers
  - Cleanup and fix
  - Update Modeler


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

Branch: refs/heads/master
Commit: d608777a919f3807267c16dc3db0f70fcd24328b
Parents: 70ca356
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Jul 25 15:00:13 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Jul 25 15:00:13 2017 +0300

----------------------------------------------------------------------
 .../cayenne/gen/ClassGenerationAction.java      |  2 +-
 .../gen/ClientClassGenerationAction.java        | 10 +-
 .../reverse/configuration/ToolsModule.java      |  3 +
 .../dbsync/reverse/dbimport/DbImportModule.java | 15 ++-
 .../reverse/dbimport/DefaultDbImportAction.java | 12 +--
 .../dbimport/DefaultDbImportActionTest.java     | 29 +++---
 .../dbimport/ManyToManyCandidateEntityTest.java | 10 +-
 .../apache/cayenne/project/ProjectModule.java   |  4 +-
 .../project/extension/ProjectExtension.java     |  3 +-
 .../project/upgrade/v7/ProjectUpgrader_V7.java  | 42 ---------
 .../project/upgrade/v9/ProjectUpgrader_V9.java  | 44 ---------
 .../org/apache/cayenne/modeler/Application.java |  8 ++
 .../modeler/ProjectFileChangeTracker.java       |  5 +-
 .../cayenne/modeler/action/CopyAction.java      |  3 +-
 .../modeler/action/ImportDataMapAction.java     | 13 +--
 .../modeler/action/OpenProjectAction.java       | 96 ++++++++++----------
 .../dialog/codegen/CustomModeController.java    |  4 +-
 .../dialog/codegen/GeneratorController.java     |  4 +-
 .../dialog/codegen/StandardModeController.java  |  4 +-
 .../dialog/db/load/ModelerDbImportAction.java   |  4 +-
 .../modeler/editor/ObjCallbackMethod.java       |  3 +-
 .../cayenne/modeler/graph/BaseGraphBuilder.java |  4 +-
 .../cayenne/modeler/graph/GraphBuilder.java     | 16 ++--
 .../apache/cayenne/modeler/graph/GraphMap.java  |  6 +-
 .../modeler/init/CayenneModelerModule.java      |  6 ++
 .../modeler/util/CayenneTransferable.java       | 14 +--
 26 files changed, 159 insertions(+), 205 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
----------------------------------------------------------------------
diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
index 8d08c52..e86bcba 100644
--- a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
+++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
@@ -522,7 +522,7 @@ public class ClassGenerationAction {
 	 *
 	 * @since 4.0 throws exception
 	 */
-	public void addEntities(Collection<ObjEntity> entities) throws CayenneException {
+	public void addEntities(Collection<ObjEntity> entities) throws CayenneRuntimeException {
 		if (artifactsGenerationMode == ArtifactsGenerationMode.ENTITY
 				|| artifactsGenerationMode == ArtifactsGenerationMode.ALL) {
 			if (entities != null) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java
----------------------------------------------------------------------
diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java
index bca02a2..c944f40 100644
--- a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java
+++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.gen;
 
 import java.util.Collection;
 
-import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.QueryDescriptor;
 
@@ -70,16 +70,12 @@ public class ClientClassGenerationAction extends ClassGenerationAction {
     }
 
     /**
-     *
-     * @param entities
-     * @throws CayenneException
-     *
      * @since 4.0 throws exception
      */
     @Override
-    public void addEntities(Collection<ObjEntity> entities) throws CayenneException {
+    public void addEntities(Collection<ObjEntity> entities) throws CayenneRuntimeException {
         if (!dataMap.isClientSupported()) {
-            throw new CayenneException("Can't create client classes. Check client supported option on DataMap configuration.");
+            throw new CayenneRuntimeException("Can't create client classes. Check client supported option on DataMap configuration.");
         }
         if (entities != null) {
             for (ObjEntity entity : entities) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
index dc057dc..bd6ae66 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -58,6 +58,7 @@ import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
 import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
 import org.apache.cayenne.log.Slf4jJdbcEventLogger;
 import org.apache.cayenne.log.JdbcEventLogger;
+import org.apache.cayenne.project.ProjectModule;
 import org.apache.cayenne.project.extension.ExtensionAwareHandlerFactory;
 import org.apache.cayenne.resource.ClassLoaderResourceLocator;
 import org.apache.cayenne.resource.ResourceLocator;
@@ -116,6 +117,8 @@ public class ToolsModule implements Module {
         binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
         binder.bind(HandlerFactory.class).to(ExtensionAwareHandlerFactory.class);
         binder.bind(DataChannelMetaData.class).to(DefaultDataChannelMetaData.class);
+
+        ProjectModule.contributeExtensions(binder);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java
index f709886..7cb227c 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java
@@ -20,12 +20,19 @@
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
 import org.apache.cayenne.configuration.ConfigurationNameMapper;
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultDataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
+import org.apache.cayenne.configuration.xml.HandlerFactory;
+import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.Module;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.project.FileProjectSaver;
+import org.apache.cayenne.project.ProjectModule;
 import org.apache.cayenne.project.ProjectSaver;
+import org.apache.cayenne.project.extension.ExtensionAwareHandlerFactory;
 
 /**
  * A DI module that bootstraps {@link DbImportAction}.
@@ -40,7 +47,11 @@ public class DbImportModule implements Module {
         binder.bind(DbImportAction.class).to(DefaultDbImportAction.class);
         binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
         binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-        binder.bind(MapLoader.class).to(MapLoader.class);
+        binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
+        binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
+        binder.bind(DataChannelMetaData.class).to(DefaultDataChannelMetaData.class);
+        binder.bind(HandlerFactory.class).to(ExtensionAwareHandlerFactory.class);
+        ProjectModule.contributeExtensions(binder);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
index 3ada4bd..c31aaab 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
@@ -19,6 +19,7 @@
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
 import org.apache.cayenne.configuration.ConfigurationTree;
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
 import org.apache.cayenne.configuration.server.DbAdapterFactory;
@@ -41,7 +42,6 @@ import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
 import org.apache.cayenne.map.Procedure;
@@ -52,7 +52,6 @@ import org.apache.cayenne.validation.SimpleValidationFailure;
 import org.apache.cayenne.validation.ValidationFailure;
 import org.apache.cayenne.validation.ValidationResult;
 import org.slf4j.Logger;
-import org.xml.sax.InputSource;
 
 import javax.sql.DataSource;
 import java.io.File;
@@ -76,14 +75,14 @@ public class DefaultDbImportAction implements DbImportAction {
     private final Logger logger;
     private final DataSourceFactory dataSourceFactory;
     private final DbAdapterFactory adapterFactory;
-    private final MapLoader mapLoader;
+    private final DataMapLoader mapLoader;
     private final MergerTokenFactoryProvider mergerTokenFactoryProvider;
 
     public DefaultDbImportAction(@Inject Logger logger,
                                  @Inject ProjectSaver projectSaver,
                                  @Inject DataSourceFactory dataSourceFactory,
                                  @Inject DbAdapterFactory adapterFactory,
-                                 @Inject MapLoader mapLoader,
+                                 @Inject DataMapLoader mapLoader,
                                  @Inject MergerTokenFactoryProvider mergerTokenFactoryProvider) {
         this.logger = logger;
         this.projectSaver = projectSaver;
@@ -240,9 +239,10 @@ public class DefaultDbImportAction implements DbImportAction {
 
         File file = configuration.getTargetDataMap();
         if (file != null && file.exists() && file.canRead()) {
-            DataMap dataMap = mapLoader.loadDataMap(new InputSource(file.getCanonicalPath()));
+            URLResource configurationResource = new URLResource(file.toURI().toURL());
+            DataMap dataMap = mapLoader.load(configurationResource);
             dataMap.setNamespace(new EntityResolver(Collections.singleton(dataMap)));
-            dataMap.setConfigurationSource(new URLResource(file.toURI().toURL()));
+            dataMap.setConfigurationSource(configurationResource);
 
             return dataMap;
         }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
index 9224519..df8f8b1 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
@@ -19,9 +19,11 @@
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
 import org.apache.cayenne.configuration.server.DbAdapterFactory;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dbsync.DbSyncModule;
 import org.apache.cayenne.dbsync.filter.NamePatternMatcher;
@@ -45,21 +47,22 @@ import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.project.FileProjectSaver;
 import org.apache.cayenne.project.Project;
+import org.apache.cayenne.project.extension.ProjectExtension;
+import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.resource.URLResource;
 import org.apache.cayenne.util.Util;
 import org.slf4j.Logger;
 import org.junit.Before;
 import org.junit.Test;
-import org.xml.sax.InputSource;
 
 import javax.sql.DataSource;
 import java.io.File;
 import java.net.URL;
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -129,7 +132,7 @@ public class DefaultDbImportActionTest {
         };
 
         final boolean[] haveWeTriedToSave = {false};
-        DefaultDbImportAction action = buildDbImportAction(new FileProjectSaver() {
+        DefaultDbImportAction action = buildDbImportAction(new FileProjectSaver(Collections.<ProjectExtension>emptyList()) {
             @Override
             public void save(Project project) {
                 haveWeTriedToSave[0] = true;
@@ -175,7 +178,7 @@ public class DefaultDbImportActionTest {
 
         final boolean[] haveWeTriedToSave = {false};
         DefaultDbImportAction action = buildDbImportAction(
-            new FileProjectSaver() {
+            new FileProjectSaver(Collections.<ProjectExtension>emptyList()) {
                 @Override
                 public void save(Project project) {
                     haveWeTriedToSave[0] = true;
@@ -192,9 +195,9 @@ public class DefaultDbImportActionTest {
                 }
             },
 
-            new MapLoader() {
+            new DataMapLoader() {
                 @Override
-                public synchronized DataMap loadDataMap(InputSource src) throws CayenneRuntimeException {
+                public DataMap load(Resource configurationResource) throws CayenneRuntimeException {
                     return new DataMapBuilder().with(
                             dbEntity("ARTGROUP").attributes(
                                     dbAttr("GROUP_ID").typeInt().primaryKey(),
@@ -236,8 +239,8 @@ public class DefaultDbImportActionTest {
         FileProjectSaver projectSaver = mock(FileProjectSaver.class);
         doNothing().when(projectSaver).save(any(Project.class));
 
-        MapLoader mapLoader = mock(MapLoader.class);
-        when(mapLoader.loadDataMap(any(InputSource.class))).thenReturn(new DataMapBuilder().with(
+        DataMapLoader mapLoader = mock(DataMapLoader.class);
+        when(mapLoader.load(any(Resource.class))).thenReturn(new DataMapBuilder().with(
                 dbEntity("ARTGROUP").attributes(
                         dbAttr("NAME").typeVarchar(100).mandatory()
                 )).build());
@@ -248,7 +251,7 @@ public class DefaultDbImportActionTest {
 
         // no changes - we still
         verify(projectSaver, never()).save(any(Project.class));
-        verify(mapLoader, times(1)).loadDataMap(any(InputSource.class));
+        verify(mapLoader, times(1)).load(any(Resource.class));
     }
 
     @Test
@@ -261,8 +264,8 @@ public class DefaultDbImportActionTest {
         FileProjectSaver projectSaver = mock(FileProjectSaver.class);
         doNothing().when(projectSaver).save(any(Project.class));
 
-        MapLoader mapLoader = mock(MapLoader.class);
-        when(mapLoader.loadDataMap(any(InputSource.class))).thenReturn(null);
+        DataMapLoader mapLoader = mock(DataMapLoader.class);
+        when(mapLoader.load(any(Resource.class))).thenReturn(null);
 
         DefaultDbImportAction action = buildDbImportAction(projectSaver, mapLoader, dbLoader);
 
@@ -274,10 +277,10 @@ public class DefaultDbImportActionTest {
         }
 
         verify(projectSaver, never()).save(any(Project.class));
-        verify(mapLoader, never()).loadDataMap(any(InputSource.class));
+        verify(mapLoader, never()).load(any(Resource.class));
     }
 
-    private DefaultDbImportAction buildDbImportAction(FileProjectSaver projectSaver, MapLoader mapLoader, final DbLoader dbLoader)
+    private DefaultDbImportAction buildDbImportAction(FileProjectSaver projectSaver, DataMapLoader mapLoader, final DbLoader dbLoader)
             throws Exception {
 
         Logger log = mock(Logger.class);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java
index ca255ff..3d064e5 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java
@@ -24,8 +24,12 @@ 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.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
+import org.apache.cayenne.configuration.xml.HandlerFactory;
+import org.apache.cayenne.configuration.xml.NoopDataChannelMetaData;
+import org.apache.cayenne.configuration.xml.XMLDataChannelDescriptorLoader;
+import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
 import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
 import org.apache.cayenne.dbsync.naming.NoStemStemmer;
 import org.apache.cayenne.di.AdhocObjectFactory;
@@ -63,6 +67,8 @@ public class ManyToManyCandidateEntityTest {
                 binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
                 binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
                 binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
+                binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
+                binder.bind(DataChannelMetaData.class).to(NoopDataChannelMetaData.class);
             }
         };
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java
index 8f5d011..614d4ed 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java
@@ -43,7 +43,7 @@ public class ProjectModule implements Module {
     /**
      * @since 4.1
      */
-    public static ListBuilder<ProjectExtension> contributeExtension(Binder binder) {
+    public static ListBuilder<ProjectExtension> contributeExtensions(Binder binder) {
         return binder.bindList(ProjectExtension.class);
     }
 
@@ -68,6 +68,6 @@ public class ProjectModule implements Module {
                 .add(UpgradeHandler_V9.class)
                 .add(UpgradeHandler_V10.class);
 
-        contributeExtension(binder);
+        contributeExtensions(binder);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java
index 1bfa33e..cf0a182 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java
@@ -27,11 +27,10 @@ package org.apache.cayenne.project.extension;
  *     ClientRuntime so they can safely store big chunks of data.
  * </p>
  * <p>
- *     Extensions can be contributed by {@link org.apache.cayenne.project.ProjectModule#contributeExtension(org.apache.cayenne.di.Binder)}.
+ *     Extensions can be contributed by {@link org.apache.cayenne.project.ProjectModule#contributeExtensions(org.apache.cayenne.di.Binder)}.
  *     {@link org.apache.cayenne.project.ProjectModule} currently used by Modeler and cli tools, e.g. cdbimport and cgen.
  * </p>
  *
- * @see org.apache.cayenne.project.extension.info.InfoExtension as reference implementation
  * @since 4.1
  */
 public interface ProjectExtension {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v7/ProjectUpgrader_V7.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v7/ProjectUpgrader_V7.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v7/ProjectUpgrader_V7.java
deleted file mode 100644
index c107fce..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v7/ProjectUpgrader_V7.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.project.upgrade.v7;
-
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.project.upgrade.ProjectUpgrader;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
-import org.apache.cayenne.resource.Resource;
-
-/**
- * A ProjectUpgrader that handles project upgrades from version 3.0.0.1 and 6
- * to version 7
- */
-public class ProjectUpgrader_V7 implements ProjectUpgrader {
-
-    @Inject
-    protected Injector injector;
-
-    public UpgradeHandler getUpgradeHandler(Resource projectSource) {
-        UpgradeHandler_V7 handler = new UpgradeHandler_V7(projectSource);
-        injector.injectMembers(handler);
-        return handler;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v9/ProjectUpgrader_V9.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v9/ProjectUpgrader_V9.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v9/ProjectUpgrader_V9.java
deleted file mode 100644
index 2f585b2..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v9/ProjectUpgrader_V9.java
+++ /dev/null
@@ -1,44 +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.project.upgrade.v9;
-
-
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.project.upgrade.ProjectUpgrader;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
-import org.apache.cayenne.resource.Resource;
-
-/**
- * A ProjectUpgrader that handles project upgrades from version 4.0.M4 and 8
- * to version 9.
- */
-public class ProjectUpgrader_V9 implements ProjectUpgrader {
-
-    @Inject
-    protected Injector injector;
-
-    @Override
-    public UpgradeHandler getUpgradeHandler(Resource projectSource) {
-        UpgradeHandler_V9 handler = new UpgradeHandler_V9(projectSource);
-        injector.injectMembers(handler);
-        return handler;
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
index 10dd3aa..3625df2 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
@@ -20,6 +20,7 @@
 package org.apache.cayenne.modeler;
 
 import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.modeler.action.ActionManager;
@@ -80,6 +81,9 @@ public class Application {
     @Inject
     protected Injector injector;
 
+    @Inject
+    protected DataChannelMetaData metaData;
+
     private String newProjectTemporaryName;
 
     public static Application getInstance() {
@@ -280,6 +284,10 @@ public class Application {
         }
     }
 
+    public DataChannelMetaData getMetaData() {
+        return metaData;
+    }
+
     protected void initPreferences() {
         this.cayenneProjectPreferences = new CayenneProjectPreferences();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectFileChangeTracker.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectFileChangeTracker.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectFileChangeTracker.java
index 99866d2..b5b61a6 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectFileChangeTracker.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectFileChangeTracker.java
@@ -84,7 +84,10 @@ public class ProjectFileChangeTracker extends Thread {
             Iterator<DataMap> it = ((DataChannelDescriptor) project.getRootNode()).getDataMaps().iterator();
             while (it.hasNext()) {
                 DataMap dm = it.next();
-                addFile(dm.getConfigurationSource().getURL().getPath());
+                if(dm.getConfigurationSource() != null) {
+                    // if DataMap is in separate file, monitor it
+                    addFile(dm.getConfigurationSource().getURL().getPath());
+                }
             }
 
         }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CopyAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CopyAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CopyAction.java
index b813ed8..8c9499d 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CopyAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CopyAction.java
@@ -26,6 +26,7 @@ import java.awt.event.KeyEvent;
 import javax.swing.KeyStroke;
 
 import org.apache.cayenne.configuration.ConfigurationNode;
+import org.apache.cayenne.configuration.EmptyConfigurationNodeVisitor;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
@@ -111,7 +112,7 @@ public class CopyAction extends CayenneAction {
      * Prints an object in XML format to an output stream
      */
     protected void print(XMLEncoder encoder, XMLSerializable object) {
-        object.encodeAsXML(encoder);
+        object.encodeAsXML(encoder, new EmptyConfigurationNodeVisitor());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDataMapAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDataMapAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDataMapAction.java
index de8d57d..1e80798 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDataMapAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDataMapAction.java
@@ -22,23 +22,22 @@ package org.apache.cayenne.modeler.action;
 import org.apache.cayenne.configuration.ConfigurationNameMapper;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.pref.FSPath;
 import org.apache.cayenne.modeler.util.CayenneAction;
 import org.apache.cayenne.modeler.util.FileFilters;
 import org.apache.cayenne.resource.Resource;
+import org.apache.cayenne.resource.URLResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.xml.sax.InputSource;
 
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.io.File;
-import java.io.InputStream;
 import java.net.URL;
 
 /**
@@ -76,12 +75,8 @@ public class ImportDataMapAction extends CayenneAction {
 
         try {
             URL url = dataMapFile.toURI().toURL();
-
-            try (InputStream in = url.openStream();) {
-                InputSource inSrc = new InputSource(in);
-                inSrc.setSystemId(dataMapFile.getAbsolutePath());
-                newMap = new MapLoader().loadDataMap(inSrc);
-            }
+            DataMapLoader loader = application.getInjector().getInstance(DataMapLoader.class);
+            newMap = loader.load(new URLResource(url));
 
             ConfigurationNode root = getProjectController().getProject().getRootNode();
             newMap.setName(NameBuilder

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java
index e7fcb56..c8465d6 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java
@@ -24,6 +24,9 @@ import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 import java.io.File;
 import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 import javax.swing.JOptionPane;
 import javax.swing.KeyStroke;
@@ -33,10 +36,8 @@ import org.apache.cayenne.modeler.CayenneModelerController;
 import org.apache.cayenne.modeler.dialog.ErrorDebugDialog;
 import org.apache.cayenne.project.Project;
 import org.apache.cayenne.project.ProjectLoader;
-import org.apache.cayenne.project.upgrade.ProjectUpgrader;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
 import org.apache.cayenne.project.upgrade.UpgradeMetaData;
-import org.apache.cayenne.project.upgrade.UpgradeType;
+import org.apache.cayenne.project.upgrade.UpgradeService;
 import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.resource.URLResource;
 import org.apache.cayenne.swing.control.FileMenuItem;
@@ -47,6 +48,19 @@ public class OpenProjectAction extends ProjectAction {
 
     private static Logger logObj = LoggerFactory.getLogger(OpenProjectAction.class);
 
+    private static final Map<String, String> PROJECT_TO_MODELER_VERSION;
+    static {
+        // Correspondence between project version and latest Modeler version that can upgrade it.
+        // Modeler v4.1 can handle versions from 3.1 and 4.0 (including intermediate versions) modeler.
+        Map<String, String> map = new HashMap<>();
+        map.put("1.0",      "v3.0");
+        map.put("1.1",      "v3.0");
+        map.put("1.2",      "v3.0");
+        map.put("2.0",      "v3.0");
+        map.put("3.0.0.1",  "v3.1");
+        PROJECT_TO_MODELER_VERSION = Collections.unmodifiableMap(map);
+    }
+
     private ProjectOpener fileChooser;
 
     public static String getActionName() {
@@ -113,7 +127,7 @@ public class OpenProjectAction extends ProjectAction {
                         Application.getFrame(),
                         "Can't open project - file \"" + file.getPath() + "\" does not exist",
                         "Can't Open Project",
-                        JOptionPane.OK_OPTION);
+                        JOptionPane.ERROR_MESSAGE);
                 return;
             }
 
@@ -123,55 +137,39 @@ public class OpenProjectAction extends ProjectAction {
             URL url = file.toURI().toURL();
             Resource rootSource = new URLResource(url);
 
-            ProjectUpgrader upgrader = getApplication().getInjector().getInstance(ProjectUpgrader.class);
-            UpgradeHandler handler = upgrader.getUpgradeHandler(rootSource);
-            UpgradeMetaData md = handler.getUpgradeMetaData();
-
-            if (UpgradeType.DOWNGRADE_NEEDED == md.getUpgradeType()) {
-                JOptionPane
-                        .showMessageDialog(
-                                Application.getFrame(),
-                                "Can't open project - it was created using a newer version of the Modeler",
-                                "Can't Open Project",
-                                JOptionPane.OK_OPTION);
-                closeProject(false);
-            } else if (UpgradeType.INTERMEDIATE_UPGRADE_NEEDED == md.getUpgradeType()) {
-                JOptionPane
-                        .showMessageDialog(Application.getFrame(),
-                        // TODO: andrus 05/02/2010 - this message shows intermediate
-                                // version of the project XML, not the Modeler code
-                                // version that
-                                // can be used for upgrade
-                                "Can't upgrade project. Open the project in the Modeler v."
-                                        + md.getIntermediateUpgradeVersion()
-                                        + " to do an intermediate upgrade before you can upgrade to v."
-                                        + md.getSupportedVersion(),
-                                "Can't Upgrade Project",
-                                JOptionPane.OK_OPTION);
-                closeProject(false);
-            } else if (UpgradeType.UPGRADE_NEEDED == md.getUpgradeType()) {
-                if (processUpgrades()) {
-                    // perform upgrade
-                    logObj.info("Will upgrade project " + url.getPath());
-                    Resource upgraded = handler.performUpgrade();
-                    if (upgraded != null) {
-                        Project project = openProjectResourse(upgraded, controller);
-
-                        getProjectController().getFileChangeTracker().pauseWatching();
-                        getProjectController().getFileChangeTracker().reconfigure();
-
-                        // need to update project file name if it has changed
-                        if (!file.getAbsolutePath().equals(project.getConfigurationResource().getURL().getPath())) {
-                            File projectFile = new File(project.getConfigurationResource().getURL().toURI());
-                            controller.changePathInLastProjListAction(file, projectFile);
-                        }
+            UpgradeService upgradeService = getApplication().getInjector().getInstance(UpgradeService.class);
+            UpgradeMetaData metaData = upgradeService.getUpgradeType(rootSource);
+            switch (metaData.getUpgradeType()) {
+                case INTERMEDIATE_UPGRADE_NEEDED:
+                    String modelerVersion = PROJECT_TO_MODELER_VERSION.get(metaData.getProjectVersion());
+                    if(modelerVersion == null) {
+                        modelerVersion = "";
+                    }
+                    JOptionPane.showMessageDialog(Application.getFrame(),
+                                    "Open the project in the older Modeler " + modelerVersion
+                                            + " to do an intermediate upgrade\nbefore you can upgrade to latest version.",
+                                    "Can't Upgrade Project", JOptionPane.ERROR_MESSAGE);
+                    closeProject(false);
+                    return;
+
+                case DOWNGRADE_NEEDED:
+                    JOptionPane.showMessageDialog(Application.getFrame(),
+                                    "Can't open project - it was created using a newer version of the Modeler",
+                                    "Can't Open Project", JOptionPane.ERROR_MESSAGE);
+                    closeProject(false);
+                    return;
+
+                case UPGRADE_NEEDED:
+                    if (processUpgrades()) {
+                        rootSource = upgradeService.upgradeProject(rootSource);
                     } else {
                         closeProject(false);
+                        return;
                     }
-                }
-            } else {
-                openProjectResourse(rootSource, controller);
+                    break;
             }
+
+            openProjectResourse(rootSource, controller);
         } catch (Exception ex) {
             logObj.warn("Error loading project file.", ex);
             ErrorDebugDialog.guiWarning(ex, "Error loading project");

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java
index 0250f9c..8d66407 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java
@@ -244,6 +244,8 @@ public class CustomModeController extends GeneratorController {
 
 	@Override
 	protected ClassGenerationAction newGenerator() {
-		return new ClassGenerationAction();
+		ClassGenerationAction action = new ClassGenerationAction();
+		getApplication().getInjector().injectMembers(action);
+		return action;
 	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java
index 6d3452b..962601d 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java
@@ -19,7 +19,7 @@
 
 package org.apache.cayenne.modeler.dialog.codegen;
 
-import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.gen.ArtifactsGenerationMode;
 import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.map.DataMap;
@@ -203,7 +203,7 @@ public abstract class GeneratorController extends CayenneController {
                 }
 
                 generators.add(generator);
-            } catch (CayenneException exception) {
+            } catch (CayenneRuntimeException exception) {
                 JOptionPane.showMessageDialog(this.getView(), exception.getUnlabeledMessage());
                 return null;
             }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/StandardModeController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/StandardModeController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/StandardModeController.java
index e700779..8443956 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/StandardModeController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/StandardModeController.java
@@ -93,7 +93,9 @@ public class StandardModeController extends GeneratorController {
 
     @Override
     protected ClassGenerationAction newGenerator() {
-        return new ClassGenerationAction();
+        ClassGenerationAction action = new ClassGenerationAction();
+        getApplication().getInjector().injectMembers(action);
+        return action;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
index c74df88..5e60bc4 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
@@ -18,12 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.dialog.db.load;
 
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
 import org.apache.cayenne.configuration.server.DbAdapterFactory;
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.project.ProjectSaver;
 import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfiguration;
 import org.apache.cayenne.dbsync.reverse.dbimport.DefaultDbImportAction;
@@ -40,7 +40,7 @@ public class ModelerDbImportAction extends DefaultDbImportAction {
                                  @Inject ProjectSaver projectSaver,
                                  @Inject DataSourceFactory dataSourceFactory,
                                  @Inject DbAdapterFactory adapterFactory,
-                                 @Inject MapLoader mapLoader,
+                                 @Inject DataMapLoader mapLoader,
                                  @Inject MergerTokenFactoryProvider mergerTokenFactoryProvider) {
         super(logger, projectSaver, dataSourceFactory, adapterFactory, mapLoader, mergerTokenFactoryProvider);
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjCallbackMethod.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjCallbackMethod.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjCallbackMethod.java
index 204a975..ddac69d 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjCallbackMethod.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjCallbackMethod.java
@@ -20,6 +20,7 @@ package org.apache.cayenne.modeler.editor;
 
 import java.io.Serializable;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
 
@@ -35,7 +36,7 @@ public class ObjCallbackMethod implements XMLSerializable,
 	}
 
 	@Override
-	public void encodeAsXML(XMLEncoder encoder) {
+	public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
 
         encoder.print("<" + encodeCallbackTypeForXML(callbackType));
         encoder.print(" name=\"" + getName());

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java
index 1b74906..ce89df2 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java
@@ -39,6 +39,7 @@ import javax.swing.JPopupMenu;
 import javax.swing.border.LineBorder;
 import javax.swing.event.UndoableEditEvent;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.event.DataMapEvent;
 import org.apache.cayenne.configuration.event.DataMapListener;
@@ -547,7 +548,8 @@ abstract class BaseGraphBuilder implements GraphBuilder, DataMapListener {
         return rel.getSourceEntity().getName() + "." + rel.getName();
     }
 
-    public void encodeAsXML(XMLEncoder encoder) {
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
         encoder.print("<graph type=\"");
         encoder.print(getType().toString());
         encoder.print("\" scale=\"");

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphBuilder.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphBuilder.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphBuilder.java
index 9b86e0b..665ed86 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphBuilder.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphBuilder.java
@@ -33,40 +33,40 @@ import org.jgraph.graph.DefaultGraphCell;
  * Interface for building graphs which represent some prespective of a domain
  */
 public interface GraphBuilder extends Serializable, XMLSerializable, UndoableEditListener {
-    public static final double ZOOM_FACTOR = 1.3;
+    double ZOOM_FACTOR = 1.3;
     
     /**
      * Builds graph
      */
-    public void buildGraph(ProjectController mediator, DataChannelDescriptor domain, boolean layout);
+    void buildGraph(ProjectController mediator, DataChannelDescriptor domain, boolean layout);
     
     /**
      * Invoked at destroying of the builder
      */
-    public void destroy();
+    void destroy();
     
     /**
      * Returns built graph for this builder
      */
-    public JGraph getGraph();
+    JGraph getGraph();
     
     /**
      * Returns domain.
      */
-    public DataChannelDescriptor getDataDomain();
+    DataChannelDescriptor getDataDomain();
         
     /**
      * Returns type of the graph
      */
-    public GraphType getType();
+    GraphType getType();
     
     /**
      * Returns selected entity, <code>null</code> if none is selected
      */
-    public Entity getSelectedEntity();
+    Entity getSelectedEntity();
     
     /**
      * Returns cell of an entity
      */
-    public DefaultGraphCell getEntityCell(String entityName);
+    DefaultGraphCell getEntityCell(String entityName);
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphMap.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphMap.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphMap.java
index c0da6b1..3ed6d65 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphMap.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphMap.java
@@ -21,6 +21,7 @@ package org.apache.cayenne.modeler.graph;
 import java.util.HashMap;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
@@ -67,7 +68,8 @@ public class GraphMap extends HashMap<GraphType, GraphBuilder> implements XMLSer
         this.selectedType = selectedType;
     }
 
-    public void encodeAsXML(XMLEncoder encoder) {
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
         encoder.print("<graphs");
 //        if (selectedType != null) {
 //            encoder.print(" selected=\"" + selectedType + "\"");
@@ -76,7 +78,7 @@ public class GraphMap extends HashMap<GraphType, GraphBuilder> implements XMLSer
         encoder.indent(1);
         
         for (GraphBuilder builder : values()) {
-            builder.encodeAsXML(encoder);
+            builder.encodeAsXML(encoder, delegate);
         }
         
         encoder.indent(-1);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java
index a0e8a39..30f0f99 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java
@@ -18,6 +18,9 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.init;
 
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultDataChannelMetaData;
+import org.apache.cayenne.configuration.xml.HandlerFactory;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.Module;
 import org.apache.cayenne.modeler.Application;
@@ -27,6 +30,7 @@ import org.apache.cayenne.modeler.init.platform.GenericPlatformInitializer;
 import org.apache.cayenne.modeler.init.platform.PlatformInitializer;
 import org.apache.cayenne.modeler.util.DefaultWidgetFactory;
 import org.apache.cayenne.modeler.util.WidgetFactory;
+import org.apache.cayenne.project.extension.ExtensionAwareHandlerFactory;
 
 /**
  * A DI module for bootstrapping CayenneModeler services.
@@ -39,5 +43,7 @@ public class CayenneModelerModule implements Module {
         binder.bind(Application.class).to(Application.class);
         binder.bind(PlatformInitializer.class).to(GenericPlatformInitializer.class);
         binder.bind(WidgetFactory.class).to(DefaultWidgetFactory.class);
+        binder.bind(HandlerFactory.class).to(ExtensionAwareHandlerFactory.class);
+        binder.bind(DataChannelMetaData.class).to(DefaultDataChannelMetaData.class);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CayenneTransferable.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CayenneTransferable.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CayenneTransferable.java
index ae8fc53..2ac94f7 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CayenneTransferable.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CayenneTransferable.java
@@ -27,6 +27,8 @@ import java.io.Serializable;
 import java.io.StringWriter;
 import java.util.List;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.configuration.EmptyConfigurationNodeVisitor;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
 
@@ -59,18 +61,18 @@ public class CayenneTransferable implements Transferable {
         
         if (flavor == CAYENNE_FLAVOR) {
             return data;
-        }
-        else {
+        } else {
             StringWriter out = new StringWriter();
             XMLEncoder encoder = new XMLEncoder(new PrintWriter(out), "\t");
+            ConfigurationNodeVisitor visitor = new EmptyConfigurationNodeVisitor();
+
             encoder.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
             
             if (data instanceof XMLSerializable) {
-                ((XMLSerializable) data).encodeAsXML(encoder);
-            }
-            else if (data instanceof List) {
+                ((XMLSerializable) data).encodeAsXML(encoder, visitor);
+            } else if (data instanceof List) {
                 for (Object o : (List) data) {
-                    ((XMLSerializable) o).encodeAsXML(encoder);
+                    ((XMLSerializable) o).encodeAsXML(encoder, visitor);
                 }
             }
             


[09/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - new XML loader for DataMap - new project version - updated test projects

Posted by nt...@apache.org.
CAY-2335: New XML loading/saving mechanics with support of plugable handlers
  - new XML loader for DataMap
  - new project version
  - updated test projects


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

Branch: refs/heads/master
Commit: c58b6f406e81de4d90abe888b763a1292c77feb8
Parents: 2c9896c
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Jul 25 12:35:50 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Jul 25 12:35:50 2017 +0300

----------------------------------------------------------------------
 .../upgrade/v6/XMLDataMapLoader_V3_0_0_1.java   |   51 -
 .../project/upgrade/v8/ProjectUpgrader_V8.java  |   42 -
 .../configuration/DataChannelDescriptor.java    |   46 +-
 .../configuration/DataNodeDescriptor.java       |   39 +-
 .../EmptyConfigurationNodeVisitor.java          |  108 ++
 .../configuration/SAXNestedTagHandler.java      |  131 --
 .../XMLDataChannelDescriptorLoader.java         |  389 ------
 .../cayenne/configuration/XMLDataMapLoader.java |   57 -
 .../configuration/server/ServerModule.java      |   11 +-
 .../xml/DataChannelChildrenHandler.java         |  133 ++
 .../configuration/xml/DataChannelHandler.java   |   78 ++
 .../configuration/xml/DataChannelMetaData.java  |   64 +
 .../configuration/xml/DataMapHandler.java       |  142 ++
 .../xml/DataMapLoaderListener.java              |   31 +
 .../xml/DataNodeChildrenHandler.java            |   71 +
 .../xml/DataSourceChildrenHandler.java          |  175 +++
 .../configuration/xml/DbEntityHandler.java      |  146 ++
 .../xml/DbKeyGeneratorHandler.java              |  117 ++
 .../xml/DbRelationshipHandler.java              |   97 ++
 .../xml/DefaultDataChannelMetaData.java         |   91 ++
 .../xml/DefaultHandlerFactory.java              |   44 +
 .../xml/EmbeddableAttributeHandler.java         |   69 +
 .../configuration/xml/EmbeddableHandler.java    |   75 ++
 .../configuration/xml/HandlerFactory.java       |   30 +
 .../configuration/xml/LoaderContext.java        |   63 +
 .../xml/NamespaceAwareNestedTagHandler.java     |   97 ++
 .../xml/NoopDataChannelMetaData.java            |   42 +
 .../configuration/xml/ObjEntityHandler.java     |  210 +++
 .../xml/ObjRelationshipHandler.java             |  109 ++
 .../configuration/xml/ProcedureHandler.java     |  114 ++
 .../xml/QueryDescriptorHandler.java             |  191 +++
 .../configuration/xml/RootDataMapHandler.java   |   51 +
 .../configuration/xml/SAXNestedTagHandler.java  |  175 +++
 .../xml/XMLDataChannelDescriptorLoader.java     |  149 +++
 .../configuration/xml/XMLDataMapLoader.java     |  102 ++
 .../org/apache/cayenne/conn/DataSourceInfo.java |   47 +-
 .../java/org/apache/cayenne/exp/Expression.java |   10 +-
 .../java/org/apache/cayenne/map/Attribute.java  |    4 +-
 .../org/apache/cayenne/map/CallbackMap.java     |    6 +-
 .../java/org/apache/cayenne/map/DataMap.java    |  131 +-
 .../org/apache/cayenne/map/DbAttribute.java     |   32 +-
 .../java/org/apache/cayenne/map/DbEntity.java   |   33 +-
 .../java/org/apache/cayenne/map/DbJoin.java     |   24 +-
 .../org/apache/cayenne/map/DbKeyGenerator.java  |   29 +-
 .../org/apache/cayenne/map/DbRelationship.java  |   28 +-
 .../cayenne/map/EJBQLQueryDescriptor.java       |   19 +-
 .../java/org/apache/cayenne/map/Embeddable.java |   20 +-
 .../apache/cayenne/map/EmbeddableAttribute.java |   26 +-
 .../apache/cayenne/map/EmbeddedAttribute.java   |   33 +-
 .../org/apache/cayenne/map/EntityListener.java  |    4 +-
 .../java/org/apache/cayenne/map/MapLoader.java  | 1261 ------------------
 .../org/apache/cayenne/map/ObjAttribute.java    |   32 +-
 .../java/org/apache/cayenne/map/ObjEntity.java  |   86 +-
 .../org/apache/cayenne/map/ObjRelationship.java |   49 +-
 .../java/org/apache/cayenne/map/Procedure.java  |   39 +-
 .../apache/cayenne/map/ProcedureParameter.java  |   47 +-
 .../cayenne/map/ProcedureQueryDescriptor.java   |   36 +-
 .../org/apache/cayenne/map/QueryDescriptor.java |   58 +-
 .../cayenne/map/QueryDescriptorLoader.java      |   32 +-
 .../cayenne/map/SQLTemplateDescriptor.java      |   53 +-
 .../cayenne/map/SelectQueryDescriptor.java      |   46 +-
 .../apache/cayenne/query/BaseQueryMetadata.java |   38 +-
 .../org/apache/cayenne/query/EJBQLQuery.java    |   25 +-
 .../java/org/apache/cayenne/query/Ordering.java |   26 +-
 .../apache/cayenne/query/PrefetchTreeNode.java  |   34 +-
 .../apache/cayenne/query/ProcedureQuery.java    |   52 +-
 .../org/apache/cayenne/query/SQLTemplate.java   |   91 +-
 .../org/apache/cayenne/query/SelectQuery.java   |   72 +-
 .../reflect/LifecycleCallbackEventHandler.java  |   19 +-
 .../cayenne/remote/IncrementalSelectQuery.java  |    5 -
 .../org/apache/cayenne/util/XMLEncoder.java     |  326 +++--
 .../apache/cayenne/util/XMLSerializable.java    |    4 +-
 .../org/apache/cayenne/schema/10/dbimport.xsd   |  106 ++
 .../org/apache/cayenne/schema/10/domain.xsd     |  130 ++
 .../org/apache/cayenne/schema/10/info.xsd       |   29 +
 .../org/apache/cayenne/schema/10/modelMap.xsd   |  356 +++++
 .../XMLDataChannelDescriptorLoaderTest.java     |  165 ---
 .../configuration/xml/BaseHandlerTest.java      |   76 ++
 .../configuration/xml/DbEntityHandlerTest.java  |   82 ++
 .../xml/DbKeyGeneratorHandlerTest.java          |   51 +
 .../xml/DbRelationshipHandlerTest.java          |   58 +
 .../configuration/xml/ObjEntityHandlerTest.java |   86 ++
 .../xml/ObjRelationshipHandlerTest.java         |   61 +
 .../xml/XMLDataChannelDescriptorLoaderTest.java |  171 +++
 .../configuration/xml/XMLDataMapLoaderTest.java |  158 +++
 .../org/apache/cayenne/map/DataMapTest.java     |   41 +-
 .../apache/cayenne/map/MapLoaderLoadTest.java   |  175 ---
 .../org/apache/cayenne/map/MockAttribute.java   |    4 +-
 .../java/org/apache/cayenne/map/MockEntity.java |    4 +-
 .../apache/cayenne/map/MockRelationship.java    |    4 +-
 .../apache/cayenne/map/ObjRelationshipIT.java   |    6 +-
 .../cayenne/map/QueryDescriptorLoaderTest.java  |    6 +-
 .../org/apache/cayenne/query/EJBQLQueryIT.java  |   30 +-
 .../cayenne/unit/di/server/DBCleaner.java       |    2 +-
 .../cayenne/unit/di/server/SchemaBuilder.java   |   16 +-
 .../unit/di/server/ServerCaseModule.java        |    8 +-
 .../src/test/resources/array-type.map.xml       |   32 +-
 .../src/test/resources/binary-pk.map.xml        |   64 +-
 .../src/test/resources/cay-2032.map.xml         |   13 +-
 .../test/resources/cay743/cayenne-domain.xml    |    2 +-
 .../src/test/resources/cay743/map1.map.xml      |    6 +-
 .../src/test/resources/cay743/map2.map.xml      |    6 +-
 .../src/test/resources/cayenne-array-type.xml   |    5 +-
 .../src/test/resources/cayenne-binary-pk.xml    |    5 +-
 .../src/test/resources/cayenne-cay-2032.xml     |    3 +-
 .../src/test/resources/cayenne-compound.xml     |    5 +-
 .../src/test/resources/cayenne-date-time.xml    |    5 +-
 .../src/test/resources/cayenne-delete-rules.xml |    5 +-
 .../src/test/resources/cayenne-embeddable.xml   |    5 +-
 .../src/test/resources/cayenne-empty.xml        |    5 +-
 .../src/test/resources/cayenne-enum.xml         |    3 +-
 .../test/resources/cayenne-extended-type.xml    |    5 +-
 .../src/test/resources/cayenne-generated.xml    |    5 +-
 .../src/test/resources/cayenne-generic.xml      |    5 +-
 .../cayenne-inheritance-single-table1.xml       |    3 +-
 .../resources/cayenne-inheritance-vertical.xml  |    3 +-
 .../src/test/resources/cayenne-inheritance.xml  |    5 +-
 .../cayenne-lifecycle-callbacks-order.xml       |    5 +-
 .../src/test/resources/cayenne-lifecycles.xml   |    5 +-
 .../src/test/resources/cayenne-lob.xml          |    5 +-
 .../src/test/resources/cayenne-locking.xml      |    3 +-
 .../src/test/resources/cayenne-map-to-many.xml  |    5 +-
 .../test/resources/cayenne-meaningful-pk.xml    |    5 +-
 .../src/test/resources/cayenne-misc-types.xml   |    5 +-
 .../cayenne-mixed-persistence-strategy.xml      |    5 +-
 .../src/test/resources/cayenne-multi-tier.xml   |    3 +-
 .../src/test/resources/cayenne-multinode.xml    |    3 +-
 .../src/test/resources/cayenne-no-pk.xml        |    5 +-
 .../test/resources/cayenne-numeric-types.xml    |    5 +-
 .../src/test/resources/cayenne-oneway-rels.xml  |    3 +-
 ...nne.configuration.rop.server.test-config.xml |    4 +-
 .../src/test/resources/cayenne-people.xml       |    3 +-
 .../src/test/resources/cayenne-primitive.xml    |    5 +-
 .../src/test/resources/cayenne-qualified.xml    |    3 +-
 .../resources/cayenne-quoted-identifiers.xml    |    3 +-
 .../src/test/resources/cayenne-reflexive.xml    |    5 +-
 .../cayenne-relationships-activity.xml          |    3 +-
 .../cayenne-relationships-child-master.xml      |    5 +-
 .../resources/cayenne-relationships-clob.xml    |    3 +-
 ...cayenne-relationships-collection-to-many.xml |    5 +-
 .../cayenne-relationships-delete-rules.xml      |    5 +-
 .../cayenne-relationships-flattened.xml         |    3 +-
 .../cayenne-relationships-set-to-many.xml       |    5 +-
 .../cayenne-relationships-to-many-fk.xml        |    5 +-
 .../cayenne-relationships-to-one-fk.xml         |    5 +-
 .../test/resources/cayenne-relationships.xml    |    3 +-
 .../src/test/resources/cayenne-return-types.xml |    5 +-
 .../src/test/resources/cayenne-soft-delete.xml  |    5 +-
 .../src/test/resources/cayenne-sus.xml          |    3 +-
 .../test/resources/cayenne-table-primitives.xml |    5 +-
 .../src/test/resources/cayenne-testmap.xml      |    2 +-
 .../src/test/resources/cayenne-things.xml       |    5 +-
 .../src/test/resources/cayenne-toone.xml        |    5 +-
 .../cayenne-unsupported-distinct-types.xml      |    3 +-
 .../src/test/resources/cayenne-uuid.xml         |    5 +-
 .../test/resources/cayenne-weighted-sort.xml    |    3 +-
 .../src/test/resources/compound.map.xml         |  124 +-
 .../src/test/resources/custom-name-file.xml     |    2 +-
 .../src/test/resources/date-time.map.xml        |   64 +-
 .../src/test/resources/delete-rules.map.xml     |  124 +-
 .../src/test/resources/embeddable.map.xml       |    6 +-
 cayenne-server/src/test/resources/empty.map.xml |   14 +-
 cayenne-server/src/test/resources/enum.map.xml  |    6 +-
 .../src/test/resources/extended-type.map.xml    |   32 +-
 .../src/test/resources/generated.map.xml        |  180 ++-
 .../src/test/resources/generic.map.xml          |    8 +-
 .../resources/inheritance-single-table1.map.xml |   18 +-
 .../test/resources/inheritance-vertical.map.xml |   59 +-
 .../src/test/resources/inheritance.map.xml      |   86 +-
 .../resources/lifecycle-callbacks-order.map.xml |   28 +-
 .../src/test/resources/lifecycles.map.xml       |   28 +-
 cayenne-server/src/test/resources/lob.map.xml   |  102 +-
 .../src/test/resources/locking.map.xml          |   10 +-
 .../src/test/resources/map-db1.map.xml          |    6 +-
 .../src/test/resources/map-db2.map.xml          |   10 +-
 .../src/test/resources/map-to-many.map.xml      |   99 +-
 .../src/test/resources/meaningful-pk.map.xml    |   74 +-
 .../src/test/resources/misc-types.map.xml       |   72 +-
 .../mixed-persistence-strategy.map.xml          |   68 +-
 .../src/test/resources/multi-tier.map.xml       |   23 +-
 cayenne-server/src/test/resources/no-pk.map.xml |   30 +-
 .../src/test/resources/numeric-types.map.xml    |  154 +--
 .../src/test/resources/oneway-rels.map.xml      |   17 +-
 .../configuration/cayenne-testConfig1.xml       |    4 -
 .../configuration/cayenne-testConfig2.xml       |    4 -
 .../configuration/cayenne-testConfig3.xml       |   14 -
 .../configuration/testConfigMap2.map.xml        |    7 -
 .../configuration/testConfigMap3_1.map.xml      |    7 -
 .../configuration/testConfigMap3_2.map.xml      |    7 -
 .../configuration/xml/DbEntityHandlerTest.xml   |   25 +
 .../xml/DbKeyGeneratorHandlerTest.xml           |   24 +
 .../xml/DbRelationshipHandlerTest.xml           |   22 +
 .../configuration/xml/ObjEntityHandlerTest.xml  |   38 +
 .../xml/ObjRelationshipHandlerTest.xml          |   20 +
 .../configuration/xml/cayenne-testConfig1.xml   |    4 +
 .../configuration/xml/cayenne-testConfig2.xml   |    4 +
 .../configuration/xml/cayenne-testConfig3.xml   |   14 +
 .../configuration/xml/testConfigMap2.map.xml    |   26 +
 .../configuration/xml/testConfigMap3_1.map.xml  |   26 +
 .../configuration/xml/testConfigMap3_2.map.xml  |   26 +
 .../configuration/xml/testConfigMap4.map.xml    |  314 +++++
 .../src/test/resources/people.map.xml           |   16 +-
 .../src/test/resources/primitive.map.xml        |   36 +-
 .../src/test/resources/qualified.map.xml        |    8 +-
 .../test/resources/quoted-identifiers.map.xml   |   10 +-
 .../src/test/resources/reflexive.map.xml        |   46 +-
 .../resources/relationships-activity.map.xml    |    6 +-
 .../relationships-child-master.map.xml          |   52 +-
 .../test/resources/relationships-clob.map.xml   |    8 +-
 .../relationships-collection-to-many.map.xml    |   46 +-
 .../relationships-delete-rules.map.xml          |  133 +-
 .../resources/relationships-flattened.map.xml   |   29 +-
 .../resources/relationships-set-to-many.map.xml |   46 +-
 .../resources/relationships-to-many-fk.map.xml  |   92 +-
 .../resources/relationships-to-one-fk.map.xml   |   46 +-
 .../src/test/resources/relationships.map.xml    |   17 +-
 .../src/test/resources/return-types.map.xml     |  180 +--
 .../src/test/resources/soft-delete.map.xml      |   32 +-
 .../src/test/resources/sus-map.map.xml          |    6 +-
 .../src/test/resources/table-primitives.map.xml |   32 +-
 .../src/test/resources/testmap.map.xml          |   39 +-
 .../src/test/resources/things.map.xml           |  216 +--
 cayenne-server/src/test/resources/toone.map.xml |   48 +-
 .../unsupported-distinct-types.map.xml          |   42 +-
 .../resources/url conversion/cayenne-empty.xml  |    4 +
 .../test/resources/url conversion/empty.map.xml |    9 +
 cayenne-server/src/test/resources/uuid.map.xml  |   44 +-
 .../src/test/resources/weighted-sort.map.xml    |   14 +-
 228 files changed, 6936 insertions(+), 4946 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java
deleted file mode 100644
index 6dc3d52..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java
+++ /dev/null
@@ -1,51 +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.project.upgrade.v6;
-
-import java.io.InputStream;
-import java.net.URL;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.MapLoader;
-import org.apache.cayenne.resource.Resource;
-import org.xml.sax.InputSource;
-
-/**
- * @since 3.1
- */
-class XMLDataMapLoader_V3_0_0_1 {
-
-	public DataMap load(Resource configurationResource) throws CayenneRuntimeException {
-
-		MapLoader mapLoader = new MapLoader();
-		URL url = configurationResource.getURL();
-
-		DataMap map;
-
-		try (InputStream in = url.openStream();) {
-
-			map = mapLoader.loadDataMap(new InputSource(in));
-		} catch (Exception e) {
-			throw new CayenneRuntimeException("Error loading configuration from %s", e, url);
-		}
-
-		return map;
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v8/ProjectUpgrader_V8.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v8/ProjectUpgrader_V8.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v8/ProjectUpgrader_V8.java
deleted file mode 100644
index 461d118..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v8/ProjectUpgrader_V8.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.project.upgrade.v8;
-
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.project.upgrade.ProjectUpgrader;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
-import org.apache.cayenne.resource.Resource;
-
-/**
- * A ProjectUpgrader that handles project upgrades from version 4.0.M3 and 7
- * to version 8.
- */
-public class ProjectUpgrader_V8 implements ProjectUpgrader {
-
-    @Inject
-    protected Injector injector;
-
-    @Override
-    public UpgradeHandler getUpgradeHandler(Resource projectSource) {
-        UpgradeHandler_V8 handler = new UpgradeHandler_V8(projectSource);
-        injector.injectMembers(handler);
-        return handler;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java
index bc3929b..92bd8bb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java
@@ -40,6 +40,11 @@ public class DataChannelDescriptor implements ConfigurationNode, Serializable, X
 
 	private static final long serialVersionUID = 6567527544207035602L;
 
+	/**
+	 * The namespace in which the data map XML file will be created.
+	 */
+	public static final String SCHEMA_XSD = "http://cayenne.apache.org/schema/10/domain";
+
 	protected String name;
 	protected Map<String, String> properties;
 	protected Collection<DataMap> dataMaps;
@@ -53,58 +58,41 @@ public class DataChannelDescriptor implements ConfigurationNode, Serializable, X
 		nodeDescriptors = new ArrayList<>(3);
 	}
 
-	public void encodeAsXML(XMLEncoder encoder) {
+	@Override
+	public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
 
-		encoder.print("<domain");
-		encoder.printProjectVersion();
-		encoder.println(">");
-
-		encoder.indent(1);
-		boolean breakNeeded = false;
+		encoder.start("domain")
+				.attribute("xmlns", SCHEMA_XSD)
+				.attribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance", true)
+				.attribute("xsi:schemaLocation", SCHEMA_XSD + " " + SCHEMA_XSD + ".xsd", true)
+				.projectVersion();
 
 		if (!properties.isEmpty()) {
-			breakNeeded = true;
-
 			List<String> keys = new ArrayList<>(properties.keySet());
 			Collections.sort(keys);
 
 			for (String key : keys) {
-				encoder.printProperty(key, properties.get(key));
+				encoder.property(key, properties.get(key));
 			}
 		}
 
 		if (!dataMaps.isEmpty()) {
-			if (breakNeeded) {
-				encoder.println();
-			} else {
-				breakNeeded = true;
-			}
-
 			List<DataMap> maps = new ArrayList<>(this.dataMaps);
 			Collections.sort(maps);
 
 			for (DataMap dataMap : maps) {
-
-				encoder.print("<map");
-				encoder.printAttribute("name", dataMap.getName().trim());
-				encoder.println("/>");
+				encoder.start("map").attribute("name", dataMap.getName().trim()).end();
 			}
 		}
 
 		if (!nodeDescriptors.isEmpty()) {
-			if (breakNeeded) {
-				encoder.println();
-			} else {
-				breakNeeded = true;
-			}
-
 			List<DataNodeDescriptor> nodes = new ArrayList<>(nodeDescriptors);
 			Collections.sort(nodes);
-			encoder.print(nodes);
+			encoder.nested(nodes, delegate);
 		}
 
-		encoder.indent(-1);
-		encoder.println("</domain>");
+		delegate.visitDataChannelDescriptor(this);
+		encoder.end();
 	}
 
 	public <T> T acceptVisitor(ConfigurationNodeVisitor<T> visitor) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataNodeDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataNodeDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataNodeDescriptor.java
index 7192d0d..6ece619 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataNodeDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DataNodeDescriptor.java
@@ -81,57 +81,50 @@ public class DataNodeDescriptor implements ConfigurationNode, XMLSerializable,
         this.dataChannelDescriptor = dataChannelDescriptor;
     }
 
+    @Override
     public int compareTo(DataNodeDescriptor o) {
         String o1 = getName();
         String o2 = o.getName();
 
         if (o1 == null) {
             return (o2 != null) ? -1 : 0;
-        }
-        else if (o2 == null) {
+        } else if (o2 == null) {
             return 1;
         }
-        else {
-            return o1.compareTo(o2);
-        }
+        return o1.compareTo(o2);
     }
 
+    @Override
     public <T> T acceptVisitor(ConfigurationNodeVisitor<T> visitor) {
         return visitor.visitDataNodeDescriptor(this);
     }
 
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<node");
-        encoder.printlnAttribute("name", name);
-        encoder.indent(1);
-
-        encoder.printlnAttribute("adapter", adapterType);
-        encoder.printlnAttribute("factory", dataSourceFactoryType);
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("node")
+                .attribute("name", name, false)
+                .attribute("adapter", adapterType, true)
+                .attribute("factory", dataSourceFactoryType, true);
         
         if (!XMLPoolingDataSourceFactory.class.getName().equals(dataSourceFactoryType)) {
-            encoder.printlnAttribute("parameters", parameters);
+            encoder.attribute("parameters", parameters);
         }
-        encoder.printlnAttribute("schema-update-strategy", schemaUpdateStrategyType);
-        encoder.println(">");
+        encoder.attribute("schema-update-strategy", schemaUpdateStrategyType, true);
 
         if (!dataMapNames.isEmpty()) {
-
             List<String> names = new ArrayList<>(dataMapNames);
             Collections.sort(names);
-
             for (String mapName : names) {
-                encoder.print("<map-ref");
-                encoder.printAttribute("name", mapName);
-                encoder.println("/>");
+                encoder.start("map-ref").attribute("name", mapName).end();
             }
         }
 
         if (dataSourceDescriptor != null && XMLPoolingDataSourceFactory.class.getName().equals(dataSourceFactoryType)) {
-            dataSourceDescriptor.encodeAsXML(encoder);
+            dataSourceDescriptor.encodeAsXML(encoder, delegate);
         }
 
-        encoder.indent(-1);
-        encoder.println("</node>");
+        delegate.visitDataNodeDescriptor(this);
+        encoder.end();
     }
 
     public String getName() {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/EmptyConfigurationNodeVisitor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/EmptyConfigurationNodeVisitor.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/EmptyConfigurationNodeVisitor.java
new file mode 100644
index 0000000..84289d2
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/EmptyConfigurationNodeVisitor.java
@@ -0,0 +1,108 @@
+/*****************************************************************
+ *   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.configuration;
+
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.Embeddable;
+import org.apache.cayenne.map.EmbeddableAttribute;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.ProcedureParameter;
+import org.apache.cayenne.map.QueryDescriptor;
+
+/**
+ * @since 4.1
+ */
+public class EmptyConfigurationNodeVisitor implements ConfigurationNodeVisitor<Void> {
+    @Override
+    public Void visitDataChannelDescriptor(DataChannelDescriptor channelDescriptor) {
+        return null;
+    }
+
+    @Override
+    public Void visitDataNodeDescriptor(DataNodeDescriptor nodeDescriptor) {
+        return null;
+    }
+
+    @Override
+    public Void visitDataMap(DataMap dataMap) {
+        return null;
+    }
+
+    @Override
+    public Void visitObjEntity(ObjEntity entity) {
+        return null;
+    }
+
+    @Override
+    public Void visitDbEntity(DbEntity entity) {
+        return null;
+    }
+
+    @Override
+    public Void visitEmbeddable(Embeddable embeddable) {
+        return null;
+    }
+
+    @Override
+    public Void visitEmbeddableAttribute(EmbeddableAttribute attribute) {
+        return null;
+    }
+
+    @Override
+    public Void visitObjAttribute(ObjAttribute attribute) {
+        return null;
+    }
+
+    @Override
+    public Void visitDbAttribute(DbAttribute attribute) {
+        return null;
+    }
+
+    @Override
+    public Void visitObjRelationship(ObjRelationship relationship) {
+        return null;
+    }
+
+    @Override
+    public Void visitDbRelationship(DbRelationship relationship) {
+        return null;
+    }
+
+    @Override
+    public Void visitProcedure(Procedure procedure) {
+        return null;
+    }
+
+    @Override
+    public Void visitProcedureParameter(ProcedureParameter parameter) {
+        return null;
+    }
+
+    @Override
+    public Void visitQuery(QueryDescriptor query) {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/SAXNestedTagHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/SAXNestedTagHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/SAXNestedTagHandler.java
deleted file mode 100644
index 3891e83..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/SAXNestedTagHandler.java
+++ /dev/null
@@ -1,131 +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.configuration;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.DefaultHandler;
-
-/**
- * A superclass of nested tag handlers for parsing of XML documents with SAX.
- * 
- * @since 3.1
- */
-public class SAXNestedTagHandler extends DefaultHandler {
-
-    private final static Locator NOOP_LOCATOR = new Locator() {
-
-        public int getColumnNumber() {
-            return -1;
-        }
-
-        public int getLineNumber() {
-            return -1;
-        }
-
-        public String getPublicId() {
-            return "<unknown>";
-        }
-
-        public String getSystemId() {
-            return "<unknown>";
-        }
-    };
-
-    protected XMLReader parser;
-    protected ContentHandler parentHandler;
-    protected Locator locator;
-
-    public SAXNestedTagHandler(XMLReader parser, SAXNestedTagHandler parentHandler) {
-        this.parentHandler = parentHandler;
-        this.parser = parser;
-
-        if (parentHandler != null) {
-            locator = parentHandler.locator;
-        }
-
-        if (locator == null) {
-            locator = NOOP_LOCATOR;
-        }
-    }
-
-    protected String unexpectedTagMessage(String tagFound, String... tagsExpected) {
-
-        List<String> expected = tagsExpected != null
-                ? Arrays.asList(tagsExpected)
-                : Collections.<String> emptyList();
-
-        return String
-                .format(
-                        "tag <%s> is unexpected at [%d,%d]. The following tags are allowed here: %s",
-                        tagFound,
-                        locator.getColumnNumber(),
-                        locator.getLineNumber(),
-                        expected);
-    }
-
-    protected ContentHandler createChildTagHandler(
-            String namespaceURI,
-            String localName,
-            String qName,
-            Attributes attributes) {
-
-        // loose handling of unrecognized tags - just ignore them
-        return new SAXNestedTagHandler(parser, this);
-    }
-
-    protected void stop() {
-        // pop self from the handler stack
-        parser.setContentHandler(parentHandler);
-    }
-
-    @Override
-    public final void startElement(
-            String namespaceURI,
-            String localName,
-            String qName,
-            Attributes attributes) throws SAXException {
-
-        // push child handler to the stack...
-        ContentHandler childHandler = createChildTagHandler(
-                namespaceURI,
-                localName,
-                qName,
-                attributes);
-        parser.setContentHandler(childHandler);
-    }
-
-    @Override
-    public void endElement(String namespaceURI, String localName, String qName)
-            throws SAXException {
-        stop();
-    }
-
-    @Override
-    public void setDocumentLocator(Locator locator) {
-        this.locator = locator;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java
deleted file mode 100644
index ad9341a..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java
+++ /dev/null
@@ -1,389 +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.configuration;
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.conn.DataSourceInfo;
-import org.apache.cayenne.di.AdhocObjectFactory;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.resource.Resource;
-import org.apache.cayenne.util.Util;
-import org.slf4j.LoggerFactory;
-import org.slf4j.Logger;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.XMLReader;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-/**
- * @since 3.1
- */
-public class XMLDataChannelDescriptorLoader implements DataChannelDescriptorLoader {
-
-	private static Logger logger = LoggerFactory.getLogger(XMLDataChannelDescriptorLoader.class);
-
-	static final String DOMAIN_TAG = "domain";
-	static final String MAP_TAG = "map";
-	static final String NODE_TAG = "node";
-	static final String PROPERTY_TAG = "property";
-	static final String MAP_REF_TAG = "map-ref";
-	static final String DATA_SOURCE_TAG = "data-source";
-
-	/**
-	 * @deprecated the caller should use password resolving strategy instead of
-	 *             resolving the password on the spot. For one thing this can be
-	 *             used in the Modeler and no password may be available.
-	 */
-	@Deprecated
-	private static String passwordFromURL(URL url) {
-		InputStream inputStream = null;
-		String password = null;
-
-		try {
-			inputStream = url.openStream();
-			password = passwordFromInputStream(inputStream);
-		} catch (IOException exception) {
-			// Log the error while trying to open the stream. A null
-			// password will be returned as a result.
-			logger.warn(exception.getMessage(), exception);
-		}
-
-		return password;
-	}
-
-	/**
-	 * @deprecated the caller should use password resolving strategy instead of
-	 *             resolving the password on the spot. For one thing this can be
-	 *             used in the Modeler and no password may be available.
-	 */
-	@Deprecated
-	private static String passwordFromInputStream(InputStream inputStream) {
-		String password = null;
-
-		try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));) {
-
-			password = bufferedReader.readLine();
-		} catch (IOException exception) {
-			logger.warn(exception.getMessage(), exception);
-		} finally {
-
-			try {
-				inputStream.close();
-			} catch (IOException exception) {
-			}
-		}
-
-		return password;
-	}
-
-	@Inject
-	protected DataMapLoader dataMapLoader;
-
-	@Inject
-	protected ConfigurationNameMapper nameMapper;
-
-	@Inject
-	protected AdhocObjectFactory objectFactory;
-
-	@Override
-	public ConfigurationTree<DataChannelDescriptor> load(Resource configurationResource) throws ConfigurationException {
-
-		if (configurationResource == null) {
-			throw new NullPointerException("Null configurationResource");
-		}
-
-		URL configurationURL = configurationResource.getURL();
-
-		logger.info("Loading XML configuration resource from " + configurationURL);
-
-		DataChannelDescriptor descriptor = new DataChannelDescriptor();
-		descriptor.setConfigurationSource(configurationResource);
-		descriptor.setName(nameMapper.configurationNodeName(DataChannelDescriptor.class, configurationResource));
-
-		DataChannelHandler rootHandler;
-
-		InputStream in = null;
-
-		try {
-			in = configurationURL.openStream();
-			XMLReader parser = Util.createXmlReader();
-
-			rootHandler = new DataChannelHandler(descriptor, parser);
-			parser.setContentHandler(rootHandler);
-			parser.setErrorHandler(rootHandler);
-			parser.parse(new InputSource(in));
-		} catch (Exception e) {
-			throw new ConfigurationException("Error loading configuration from %s", e, configurationURL);
-		} finally {
-			try {
-				if (in != null) {
-					in.close();
-				}
-			} catch (IOException ioex) {
-				logger.info("failure closing input stream for " + configurationURL + ", ignoring", ioex);
-			}
-		}
-
-		// TODO: andrus 03/10/2010 - actually provide load failures here...
-		return new ConfigurationTree<DataChannelDescriptor>(descriptor, null);
-	}
-
-	final class DataChannelHandler extends SAXNestedTagHandler {
-
-		private DataChannelDescriptor descriptor;
-
-		DataChannelHandler(DataChannelDescriptor dataChannelDescriptor, XMLReader parser) {
-			super(parser, null);
-			this.descriptor = dataChannelDescriptor;
-		}
-
-		@Override
-		protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name,
-				Attributes attributes) {
-
-			if (localName.equals(DOMAIN_TAG)) {
-				return new DataChannelChildrenHandler(parser, this);
-			}
-
-			logger.info(unexpectedTagMessage(localName, DOMAIN_TAG));
-			return super.createChildTagHandler(namespaceURI, localName, name, attributes);
-		}
-	}
-
-	final class DataChannelChildrenHandler extends SAXNestedTagHandler {
-
-		private DataChannelDescriptor descriptor;
-
-		DataChannelChildrenHandler(XMLReader parser, DataChannelHandler parentHandler) {
-			super(parser, parentHandler);
-			this.descriptor = parentHandler.descriptor;
-		}
-
-		@Override
-		protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name,
-				Attributes attributes) {
-
-			if (localName.equals(PROPERTY_TAG)) {
-
-				String key = attributes.getValue("", "name");
-				String value = attributes.getValue("", "value");
-				if (key != null && value != null) {
-					descriptor.getProperties().put(key, value);
-				}
-			} else if (localName.equals(MAP_TAG)) {
-
-				String dataMapName = attributes.getValue("", "name");
-				Resource baseResource = descriptor.getConfigurationSource();
-
-				String dataMapLocation = nameMapper.configurationLocation(DataMap.class, dataMapName);
-
-				Resource dataMapResource = baseResource.getRelativeResource(dataMapLocation);
-
-				logger.info("Loading XML DataMap resource from " + dataMapResource.getURL());
-
-				DataMap dataMap = dataMapLoader.load(dataMapResource);
-				dataMap.setName(dataMapName);
-				dataMap.setLocation(dataMapLocation);
-				dataMap.setConfigurationSource(dataMapResource);
-				dataMap.setDataChannelDescriptor(descriptor);
-
-                descriptor.getDataMaps().add(dataMap);
-            } else if (localName.equals(NODE_TAG)) {
-
-				String nodeName = attributes.getValue("", "name");
-				if (nodeName == null) {
-					throw new ConfigurationException("Error: <node> without 'name'.");
-				}
-
-				DataNodeDescriptor nodeDescriptor = new DataNodeDescriptor();
-				nodeDescriptor.setConfigurationSource(descriptor.getConfigurationSource());
-				descriptor.getNodeDescriptors().add(nodeDescriptor);
-
-				nodeDescriptor.setName(nodeName);
-				nodeDescriptor.setAdapterType(attributes.getValue("", "adapter"));
-
-				String parameters = attributes.getValue("", "parameters");
-				nodeDescriptor.setParameters(parameters);
-
-				String dataSourceFactory = attributes.getValue("", "factory");
-				nodeDescriptor.setDataSourceFactoryType(dataSourceFactory);
-				nodeDescriptor.setSchemaUpdateStrategyType(attributes.getValue("", "schema-update-strategy"));
-				nodeDescriptor.setDataChannelDescriptor(descriptor);
-
-				return new DataNodeChildrenHandler(parser, this, nodeDescriptor);
-			}
-
-			return super.createChildTagHandler(namespaceURI, localName, name, attributes);
-		}
-	}
-
-	final class DataNodeChildrenHandler extends SAXNestedTagHandler {
-
-		private DataNodeDescriptor nodeDescriptor;
-
-		DataNodeChildrenHandler(XMLReader parser, SAXNestedTagHandler parentHandler, DataNodeDescriptor nodeDescriptor) {
-			super(parser, parentHandler);
-			this.nodeDescriptor = nodeDescriptor;
-		}
-
-		@Override
-		protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name,
-				Attributes attributes) {
-
-			if (localName.equals(MAP_REF_TAG)) {
-
-				String mapName = attributes.getValue("", "name");
-				nodeDescriptor.getDataMapNames().add(mapName);
-			} else if (localName.equals(DATA_SOURCE_TAG)) {
-
-				DataSourceInfo dataSourceDescriptor = new DataSourceInfo();
-				nodeDescriptor.setDataSourceDescriptor(dataSourceDescriptor);
-				return new DataSourceChildrenHandler(parser, this, dataSourceDescriptor);
-			}
-
-			return super.createChildTagHandler(namespaceURI, localName, name, attributes);
-		}
-	}
-
-	class DataSourceChildrenHandler extends SAXNestedTagHandler {
-
-		private DataSourceInfo dataSourceDescriptor;
-
-		DataSourceChildrenHandler(XMLReader parser, DataNodeChildrenHandler parentHandler,
-				DataSourceInfo dataSourceDescriptor) {
-			super(parser, parentHandler);
-			this.dataSourceDescriptor = dataSourceDescriptor;
-		}
-
-		@Override
-		protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name,
-				Attributes attributes) {
-
-			if (localName.equals("driver")) {
-				String className = attributes.getValue("", "value");
-				dataSourceDescriptor.setJdbcDriver(className);
-			} else if (localName.equals("login")) {
-
-				logger.info("loading user name and password.");
-
-				String encoderClass = attributes.getValue("encoderClass");
-
-				String encoderKey = attributes.getValue("encoderKey");
-				if (encoderKey == null) {
-					encoderKey = attributes.getValue("encoderSalt");
-				}
-
-				String password = attributes.getValue("password");
-				String passwordLocation = attributes.getValue("passwordLocation");
-				String passwordSource = attributes.getValue("passwordSource");
-				if (passwordSource == null) {
-					passwordSource = DataSourceInfo.PASSWORD_LOCATION_MODEL;
-				}
-
-				String username = attributes.getValue("userName");
-
-				dataSourceDescriptor.setPasswordEncoderClass(encoderClass);
-				dataSourceDescriptor.setPasswordEncoderKey(encoderKey);
-				dataSourceDescriptor.setPasswordLocation(passwordLocation);
-				dataSourceDescriptor.setPasswordSource(passwordSource);
-				dataSourceDescriptor.setUserName(username);
-
-				// Replace {} in passwordSource with encoderSalt -- useful for
-				// EXECUTABLE
-				// & URL options
-				if (encoderKey != null) {
-					passwordSource = passwordSource.replaceAll("\\{\\}", encoderKey);
-				}
-
-				String encoderType = dataSourceDescriptor.getPasswordEncoderClass();
-				PasswordEncoding passwordEncoder = null;
-				if (encoderType != null) {
-					passwordEncoder = objectFactory.newInstance(PasswordEncoding.class, encoderType);
-				}
-
-				if (passwordLocation != null) {
-					if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH)) {
-
-						ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-						URL url = classLoader.getResource(username);
-						if (url != null) {
-							password = passwordFromURL(url);
-						} else {
-							logger.error("Could not find resource in CLASSPATH: " + passwordSource);
-						}
-					} else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_URL)) {
-						try {
-							password = passwordFromURL(new URL(passwordSource));
-						} catch (MalformedURLException exception) {
-							logger.warn(exception.getMessage(), exception);
-						}
-					} else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE)) {
-						if (passwordSource != null) {
-							try {
-								Process process = Runtime.getRuntime().exec(passwordSource);
-								password = passwordFromInputStream(process.getInputStream());
-								process.waitFor();
-							} catch (IOException exception) {
-								logger.warn(exception.getMessage(), exception);
-							} catch (InterruptedException exception) {
-								logger.warn(exception.getMessage(), exception);
-							}
-						}
-					}
-				}
-
-				if (password != null && passwordEncoder != null) {
-					dataSourceDescriptor.setPassword(passwordEncoder.decodePassword(password, encoderKey));
-				}
-			} else if (localName.equals("url")) {
-				dataSourceDescriptor.setDataSourceUrl(attributes.getValue("value"));
-			} else if (localName.equals("connectionPool")) {
-				String min = attributes.getValue("min");
-				if (min != null) {
-					try {
-						dataSourceDescriptor.setMinConnections(Integer.parseInt(min));
-					} catch (NumberFormatException nfex) {
-						logger.info("Non-numeric 'min' attribute", nfex);
-						throw new ConfigurationException("Non-numeric 'min' attribute '%s'", nfex, min);
-					}
-				}
-
-				String max = attributes.getValue("max");
-				if (max != null) {
-					try {
-						dataSourceDescriptor.setMaxConnections(Integer.parseInt(max));
-					} catch (NumberFormatException nfex) {
-						logger.info("Non-numeric 'max' attribute", nfex);
-						throw new ConfigurationException("Non-numeric 'max' attribute '%s'", nfex, max);
-					}
-				}
-			}
-
-			return super.createChildTagHandler(namespaceURI, localName, name, attributes);
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataMapLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataMapLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataMapLoader.java
deleted file mode 100644
index d5cce91..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataMapLoader.java
+++ /dev/null
@@ -1,57 +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.configuration;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.MapLoader;
-import org.apache.cayenne.resource.Resource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.InputSource;
-
-import java.io.InputStream;
-import java.net.URL;
-
-/**
- * @since 3.1
- */
-public class XMLDataMapLoader implements DataMapLoader {
-
-    private static Logger logger = LoggerFactory.getLogger(XMLDataMapLoader.class);
-
-    public DataMap load(Resource configurationResource) throws CayenneRuntimeException {
-
-        // TODO: andrus 11.27.2009 - deprecate MapLoader and implement a loader
-        // here. MapLoader is in the wrong place, exposes ContentHandler methods and
-        // implements if/else contextless matching of tags... should use something like
-        // SAXNestedTagHandler instead.
-        MapLoader mapLoader = new MapLoader();
-        URL url = configurationResource.getURL();
-
-        try (InputStream in = url.openStream()) {
-            return mapLoader.loadDataMap(new InputSource(in));
-        } catch (Exception e) {
-            throw new CayenneRuntimeException(
-                    "Error loading configuration from %s",
-                    e,
-                    url);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
index 962bba9..c86371d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
@@ -71,8 +71,12 @@ import org.apache.cayenne.configuration.DefaultRuntimeProperties;
 import org.apache.cayenne.configuration.ObjectContextFactory;
 import org.apache.cayenne.configuration.ObjectStoreFactory;
 import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader;
-import org.apache.cayenne.configuration.XMLDataMapLoader;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
+import org.apache.cayenne.configuration.xml.HandlerFactory;
+import org.apache.cayenne.configuration.xml.NoopDataChannelMetaData;
+import org.apache.cayenne.configuration.xml.XMLDataChannelDescriptorLoader;
+import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
 import org.apache.cayenne.dba.db2.DB2Sniffer;
 import org.apache.cayenne.dba.derby.DerbySniffer;
 import org.apache.cayenne.dba.firebird.FirebirdSniffer;
@@ -403,5 +407,8 @@ public class ServerModule implements Module {
         binder.bind(RowReaderFactory.class).to(DefaultRowReaderFactory.class);
 
         binder.bind(SQLTemplateProcessor.class).to(VelocitySQLTemplateProcessor.class);
+
+        binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
+        binder.bind(DataChannelMetaData.class).to(NoopDataChannelMetaData.class);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelChildrenHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelChildrenHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelChildrenHandler.java
new file mode 100644
index 0000000..9dc65af
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelChildrenHandler.java
@@ -0,0 +1,133 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.resource.Resource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+
+/**
+ * @since 4.1
+ */
+final class DataChannelChildrenHandler extends SAXNestedTagHandler {
+
+    private static Logger logger = LoggerFactory.getLogger(XMLDataChannelDescriptorLoader.class);
+
+    static final String OLD_MAP_TAG = "map";
+    static final String NODE_TAG = "node";
+    static final String PROPERTY_TAG = "property";
+    static final String DATA_MAP_TAG = "data-map";
+
+
+    private XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader;
+    private DataChannelDescriptor descriptor;
+
+    private DataNodeDescriptor nodeDescriptor;
+
+    DataChannelChildrenHandler(XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader, DataChannelHandler parentHandler) {
+        super(parentHandler);
+        this.xmlDataChannelDescriptorLoader = xmlDataChannelDescriptorLoader;
+        this.descriptor = parentHandler.descriptor;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) {
+        switch (localName) {
+            case PROPERTY_TAG:
+                addProperty(attributes);
+                return true;
+
+            case OLD_MAP_TAG:
+                addMap(attributes);
+                return true;
+
+            case NODE_TAG:
+                addNode(attributes);
+                return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    protected ContentHandler createChildTagHandler(String namespaceURI, String localName,
+                                                   String name, Attributes attributes) {
+        if (NODE_TAG.equals(localName)) {
+            nodeDescriptor = new DataNodeDescriptor();
+            return new DataNodeChildrenHandler(xmlDataChannelDescriptorLoader, this, nodeDescriptor);
+        }
+
+        if (DATA_MAP_TAG.equals(localName)) {
+            return new DataMapHandler(loaderContext);
+        }
+
+        return super.createChildTagHandler(namespaceURI, localName, name, attributes);
+    }
+
+    private void addProperty(Attributes attributes) {
+        String key = attributes.getValue("name");
+        String value = attributes.getValue("value");
+        if (key != null && value != null) {
+            descriptor.getProperties().put(key, value);
+        }
+    }
+
+    private void addMap(Attributes attributes) {
+        String dataMapName = attributes.getValue("name");
+        Resource baseResource = descriptor.getConfigurationSource();
+
+        String dataMapLocation = xmlDataChannelDescriptorLoader.nameMapper.configurationLocation(DataMap.class, dataMapName);
+
+        Resource dataMapResource = baseResource.getRelativeResource(dataMapLocation);
+
+        logger.info("Loading XML DataMap resource from " + dataMapResource.getURL());
+
+        DataMap dataMap = xmlDataChannelDescriptorLoader.dataMapLoader.load(dataMapResource);
+        dataMap.setName(dataMapName);
+        dataMap.setLocation(dataMapLocation);
+        dataMap.setConfigurationSource(dataMapResource);
+        dataMap.setDataChannelDescriptor(descriptor);
+
+        descriptor.getDataMaps().add(dataMap);
+    }
+
+    private void addNode(Attributes attributes) {
+        String nodeName = attributes.getValue("name");
+        if (nodeName == null) {
+            throw new ConfigurationException("Error: <node> without 'name'.");
+        }
+
+        nodeDescriptor.setConfigurationSource(descriptor.getConfigurationSource());
+        nodeDescriptor.setName(nodeName);
+        nodeDescriptor.setAdapterType(attributes.getValue("adapter"));
+        nodeDescriptor.setParameters(attributes.getValue("parameters"));
+        nodeDescriptor.setDataSourceFactoryType(attributes.getValue("factory"));
+        nodeDescriptor.setSchemaUpdateStrategyType(attributes.getValue("schema-update-strategy"));
+        nodeDescriptor.setDataChannelDescriptor(descriptor);
+
+        descriptor.getNodeDescriptors().add(nodeDescriptor);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelHandler.java
new file mode 100644
index 0000000..e5e4c71
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelHandler.java
@@ -0,0 +1,78 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.configuration.xml;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.util.LocalizedStringsHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+final class DataChannelHandler extends SAXNestedTagHandler {
+
+    private static Logger logger = LoggerFactory.getLogger(XMLDataChannelDescriptorLoader.class);
+
+    static final String DOMAIN_TAG = "domain";
+
+    private XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader;
+    DataChannelDescriptor descriptor;
+
+    DataChannelHandler(XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader, DataChannelDescriptor dataChannelDescriptor, LoaderContext loaderContext) {
+        super(loaderContext);
+        this.xmlDataChannelDescriptorLoader = xmlDataChannelDescriptorLoader;
+        this.descriptor = dataChannelDescriptor;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+        switch (localName) {
+            case DOMAIN_TAG:
+                validateVersion(attributes);
+                return true;
+        }
+        return super.processElement(namespaceURI, localName, attributes);
+    }
+
+    protected void validateVersion(Attributes attributes) {
+        String version = attributes.getValue("project-version");
+        if(!XMLDataChannelDescriptorLoader.CURRENT_PROJECT_VERSION.equals(version)) {
+            throw new CayenneRuntimeException("Unsupported project version: %s, please upgrade project using Modeler v%s",
+                    version, LocalizedStringsHandler.getString("cayenne.version"));
+        }
+    }
+
+    @Override
+    protected ContentHandler createChildTagHandler(String namespaceURI, String localName,
+                                                   String name, Attributes attributes) {
+
+        if (localName.equals(DOMAIN_TAG)) {
+            return new DataChannelChildrenHandler(xmlDataChannelDescriptorLoader, this);
+        }
+
+        logger.info(unexpectedTagMessage(localName, DOMAIN_TAG));
+        return super.createChildTagHandler(namespaceURI, localName, name, attributes);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelMetaData.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelMetaData.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelMetaData.java
new file mode 100644
index 0000000..3e0cd20
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataChannelMetaData.java
@@ -0,0 +1,64 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.configuration.ConfigurationNode;
+
+/**
+ * <p>
+ * Storage for all kind of meta data that is not required for runtime.
+ * </p>
+ * <p>
+ * Currently used by Modeler and cli tools (e.g. Maven, Ant and Gradle) to store project extra data.
+ * </p>
+ *
+ * <p>
+ * Usage: <pre>
+ *      // attach custom information to data map
+ *      metaData.add(dataMap, myObject);
+ *
+ *      // read data
+ *      MyObject obj = metaData.get(dataMap, MyObject.class);
+ * </pre>
+ * </p>
+ *
+ * @since 4.1
+ */
+public interface DataChannelMetaData {
+
+    /**
+     * Store data for object.
+     *
+     * @param key object for which we want to store data
+     * @param value data to store
+     */
+    void add(ConfigurationNode key, Object value);
+
+    /**
+     *
+     * Get meta data for object
+     *
+     * @param key object for wich we want meta data
+     * @param type meta data type class
+     * @param <T> meta data type
+     * @return value or {@code null} if no data available
+     */
+    <T> T get(ConfigurationNode key, Class<T> type);
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapHandler.java
new file mode 100644
index 0000000..ea508f5
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapHandler.java
@@ -0,0 +1,142 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.cayenne.map.DataMap;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 4.1
+ */
+public class DataMapHandler extends NamespaceAwareNestedTagHandler {
+
+    /* This constants must be in sync with dataMap.xsd schema */
+    private static final String DATA_MAP_TAG         = "data-map";
+    private static final String PROPERTY_TAG         = "property";
+    private static final String DB_ENTITY_TAG        = "db-entity";
+    private static final String OBJ_ENTITY_TAG       = "obj-entity";
+    private static final String DB_RELATIONSHIP_TAG  = "db-relationship";
+    private static final String OBJ_RELATIONSHIP_TAG = "obj-relationship";
+    private static final String EMBEDDABLE_TAG       = "embeddable";
+    private static final String PROCEDURE_TAG        = "procedure";
+    private static final String QUERY_TAG            = "query";
+
+    public static final String TRUE = "true";
+
+    private DataMap dataMap;
+
+    private Map<String, Object> mapProperties;
+
+    public DataMapHandler(NamespaceAwareNestedTagHandler parentHandler) {
+        super(parentHandler);
+    }
+
+    public DataMapHandler(LoaderContext loaderContext) {
+        super(loaderContext);
+        setTargetNamespace(DataMap.SCHEMA_XSD);
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName,
+                                     Attributes attributes) throws SAXException {
+        switch (localName) {
+            case PROPERTY_TAG:
+                addProperty(attributes);
+                return true;
+
+            case DATA_MAP_TAG:
+                this.dataMap = new DataMap();
+                return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    protected ContentHandler createChildTagHandler(String namespaceURI, String localName,
+                                                   String qName, Attributes attributes) {
+
+        if(namespaceURI.equals(targetNamespace)) {
+            switch (localName) {
+                case DB_ENTITY_TAG:
+                    return new DbEntityHandler(this, dataMap);
+
+                case OBJ_ENTITY_TAG:
+                    return new ObjEntityHandler(this, dataMap);
+
+                case DB_RELATIONSHIP_TAG:
+                    return new DbRelationshipHandler(this, dataMap);
+
+                case OBJ_RELATIONSHIP_TAG:
+                    return new ObjRelationshipHandler(this, dataMap);
+
+                case PROCEDURE_TAG:
+                    return new ProcedureHandler(this, dataMap);
+
+                case QUERY_TAG:
+                    return new QueryDescriptorHandler(this, dataMap);
+
+                case EMBEDDABLE_TAG:
+                    return new EmbeddableHandler(this, dataMap);
+            }
+        }
+
+        return super.createChildTagHandler(namespaceURI, localName, qName, attributes);
+    }
+
+    @Override
+    protected void beforeScopeEnd() {
+        dataMap.initWithProperties(mapProperties);
+        loaderContext.dataMapLoaded(dataMap);
+    }
+
+    private void addProperty(Attributes attributes) throws SAXException {
+        String name = attributes.getValue("name");
+        if (null == name) {
+            throw new SAXException("MapLoader::processStartDataMapProperty(), no property name.");
+        }
+
+        String value = attributes.getValue("value");
+        if (null == value) {
+            throw new SAXException("MapLoader::processStartDataMapProperty(), no property value.");
+        }
+
+        // special meaning for <property name="name" .../>
+        if("name".equals(name)) {
+            dataMap.setName(value);
+            return;
+        }
+
+        if (mapProperties == null) {
+            mapProperties = new TreeMap<>();
+        }
+
+        mapProperties.put(name, value);
+    }
+
+    public DataMap getDataMap() {
+        return dataMap;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapLoaderListener.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapLoaderListener.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapLoaderListener.java
new file mode 100644
index 0000000..c9f4ccd
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataMapLoaderListener.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.configuration.xml;
+
+import org.apache.cayenne.map.DataMap;
+
+/**
+ * @since 4.1
+ */
+public interface DataMapLoaderListener {
+
+    void onDataMapLoaded(DataMap dataMap);
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataNodeChildrenHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataNodeChildrenHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataNodeChildrenHandler.java
new file mode 100644
index 0000000..b98bd73
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataNodeChildrenHandler.java
@@ -0,0 +1,71 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.conn.DataSourceInfo;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+
+/**
+ * @since 4.1
+ */
+final class DataNodeChildrenHandler extends SAXNestedTagHandler {
+
+    static final String DATA_SOURCE_TAG = "data-source";
+    static final String MAP_REF_TAG = "map-ref";
+
+    private XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader;
+    private DataNodeDescriptor nodeDescriptor;
+
+    private DataSourceInfo dataSourceDescriptor;
+
+    DataNodeChildrenHandler(XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader, SAXNestedTagHandler parentHandler, DataNodeDescriptor nodeDescriptor) {
+        super(parentHandler);
+        this.xmlDataChannelDescriptorLoader = xmlDataChannelDescriptorLoader;
+        this.nodeDescriptor = nodeDescriptor;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) {
+        switch (localName) {
+            case MAP_REF_TAG:
+                nodeDescriptor.getDataMapNames().add(attributes.getValue("name"));
+                return true;
+
+            case DATA_SOURCE_TAG:
+                nodeDescriptor.setDataSourceDescriptor(dataSourceDescriptor);
+                return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    protected ContentHandler createChildTagHandler(String namespaceURI, String localName,
+                                                   String name, Attributes attributes) {
+        if (DATA_SOURCE_TAG.equals(localName)) {
+            dataSourceDescriptor = new DataSourceInfo();
+            return new DataSourceChildrenHandler(xmlDataChannelDescriptorLoader, this, dataSourceDescriptor);
+        }
+
+        return super.createChildTagHandler(namespaceURI, localName, name, attributes);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataSourceChildrenHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataSourceChildrenHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataSourceChildrenHandler.java
new file mode 100644
index 0000000..b860b1f
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/xml/DataSourceChildrenHandler.java
@@ -0,0 +1,175 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.configuration.PasswordEncoding;
+import org.apache.cayenne.conn.DataSourceInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+
+/**
+ * @since 4.1
+ */
+class DataSourceChildrenHandler extends SAXNestedTagHandler {
+
+    private static Logger logger = LoggerFactory.getLogger(XMLDataChannelDescriptorLoader.class);
+
+    static final String DRIVER_TAG = "driver";
+    static final String LOGIN_TAG = "login";
+    static final String URL_TAG = "url";
+    static final String CONNECTION_POOL_TAG = "connectionPool";
+
+
+    private XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader;
+    private DataSourceInfo dataSourceDescriptor;
+
+    DataSourceChildrenHandler(XMLDataChannelDescriptorLoader xmlDataChannelDescriptorLoader,
+                              DataNodeChildrenHandler parentHandler,
+                              DataSourceInfo dataSourceDescriptor) {
+        super(parentHandler);
+        this.xmlDataChannelDescriptorLoader = xmlDataChannelDescriptorLoader;
+        this.dataSourceDescriptor = dataSourceDescriptor;
+    }
+
+    @Override
+    protected boolean processElement(String namespaceURI, String localName, Attributes attributes) {
+        switch (localName) {
+            case DRIVER_TAG:
+                dataSourceDescriptor.setJdbcDriver(attributes.getValue("value"));
+                return true;
+
+            case LOGIN_TAG:
+                configureCredentials(attributes);
+                return true;
+
+            case URL_TAG:
+                dataSourceDescriptor.setDataSourceUrl(attributes.getValue("value"));
+                return true;
+
+            case CONNECTION_POOL_TAG:
+                configureConnectionPool(attributes);
+                return true;
+        }
+
+        return false;
+    }
+
+    void configureCredentials(Attributes attributes) {
+        logger.info("loading user name and password.");
+
+        String encoderClass = attributes.getValue("encoderClass");
+
+        String encoderKey = attributes.getValue("encoderKey");
+        if (encoderKey == null) {
+            encoderKey = attributes.getValue("encoderSalt");
+        }
+
+        String password = attributes.getValue("password");
+        String passwordLocation = attributes.getValue("passwordLocation");
+        String passwordSource = attributes.getValue("passwordSource");
+        if (passwordSource == null) {
+            passwordSource = DataSourceInfo.PASSWORD_LOCATION_MODEL;
+        }
+
+        String username = attributes.getValue("userName");
+
+        dataSourceDescriptor.setPasswordEncoderClass(encoderClass);
+        dataSourceDescriptor.setPasswordEncoderKey(encoderKey);
+        dataSourceDescriptor.setPasswordLocation(passwordLocation);
+        dataSourceDescriptor.setPasswordSource(passwordSource);
+        dataSourceDescriptor.setUserName(username);
+
+        // Replace {} in passwordSource with encoderSalt -- useful for EXECUTABLE & URL options
+        if (encoderKey != null) {
+            passwordSource = passwordSource.replaceAll("\\{\\}", encoderKey);
+        }
+
+        String encoderType = dataSourceDescriptor.getPasswordEncoderClass();
+        PasswordEncoding passwordEncoder = null;
+        if (encoderType != null) {
+            passwordEncoder = xmlDataChannelDescriptorLoader.objectFactory.newInstance(PasswordEncoding.class, encoderType);
+        }
+
+        if (passwordLocation != null) {
+            switch (passwordLocation) {
+                case DataSourceInfo.PASSWORD_LOCATION_CLASSPATH:
+
+                    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+                    URL url = classLoader.getResource(username);
+                    if (url != null) {
+                        password = XMLDataChannelDescriptorLoader.passwordFromURL(url);
+                    } else {
+                        logger.error("Could not find resource in CLASSPATH: " + passwordSource);
+                    }
+                    break;
+                case DataSourceInfo.PASSWORD_LOCATION_URL:
+                    try {
+                        password = XMLDataChannelDescriptorLoader.passwordFromURL(new URL(passwordSource));
+                    } catch (MalformedURLException exception) {
+                        logger.warn(exception.getMessage(), exception);
+                    }
+                    break;
+                case DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE:
+                    if (passwordSource != null) {
+                        try {
+                            Process process = Runtime.getRuntime().exec(passwordSource);
+                            password = XMLDataChannelDescriptorLoader.passwordFromInputStream(process.getInputStream());
+                            process.waitFor();
+                        } catch (IOException | InterruptedException exception) {
+                            logger.warn(exception.getMessage(), exception);
+                        }
+                    }
+                    break;
+            }
+        }
+
+        if (password != null && passwordEncoder != null) {
+            dataSourceDescriptor.setPassword(passwordEncoder.decodePassword(password, encoderKey));
+        }
+    }
+
+    void configureConnectionPool(Attributes attributes) {
+        String min = attributes.getValue("min");
+        if (min != null) {
+            try {
+                dataSourceDescriptor.setMinConnections(Integer.parseInt(min));
+            } catch (NumberFormatException nfex) {
+                logger.info("Non-numeric 'min' attribute", nfex);
+                throw new ConfigurationException("Non-numeric 'min' attribute '%s'", nfex, min);
+            }
+        }
+
+        String max = attributes.getValue("max");
+        if (max != null) {
+            try {
+                dataSourceDescriptor.setMaxConnections(Integer.parseInt(max));
+            } catch (NumberFormatException nfex) {
+                logger.info("Non-numeric 'max' attribute", nfex);
+                throw new ConfigurationException("Non-numeric 'max' attribute '%s'", nfex, max);
+            }
+        }
+    }
+}

[12/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - ProjectExtension - new upgrade handlers

Posted by nt...@apache.org.
CAY-2335: New XML loading/saving mechanics with support of plugable handlers
  - ProjectExtension
  - new upgrade handlers


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

Branch: refs/heads/master
Commit: 38553b1603b9622a6eae691131a4106591649556
Parents: c58b6f4
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Jul 25 12:39:56 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Jul 25 12:39:56 2017 +0300

----------------------------------------------------------------------
 .../cayenne/project/CompoundSaverDelegate.java  | 183 +++++++
 .../cayenne/project/ConfigurationSaver.java     |  12 +-
 .../cayenne/project/FileProjectSaver.java       |  25 +-
 .../org/apache/cayenne/project/Project.java     |  10 +-
 .../apache/cayenne/project/ProjectModule.java   |  43 +-
 .../cayenne/project/SaveableNodesGetter.java    |  11 +-
 .../project/extension/BaseSaverDelegate.java    | 133 +++++
 .../extension/ExtensionAwareHandlerFactory.java |  69 +++
 .../project/extension/LoaderDelegate.java       |  45 ++
 .../project/extension/ProjectExtension.java     |  49 ++
 .../project/extension/SaverDelegate.java        |  45 ++
 .../project/upgrade/BaseUpgradeHandler.java     | 218 --------
 .../upgrade/DataSourceInfoLoader_3_0_0_1.java   | 228 ---------
 .../project/upgrade/DefaultUpgradeService.java  | 318 ++++++++++++
 .../project/upgrade/ProjectUpgrader.java        |  34 --
 .../cayenne/project/upgrade/UpgradeHandler.java |  57 ---
 .../cayenne/project/upgrade/UpgradeService.java |  33 ++
 .../cayenne/project/upgrade/UpgradeUnit.java    |  54 ++
 .../upgrade/handlers/UpgradeHandler.java        |  58 +++
 .../upgrade/handlers/UpgradeHandler_V10.java    |  68 +++
 .../upgrade/handlers/UpgradeHandler_V7.java     | 109 ++++
 .../upgrade/handlers/UpgradeHandler_V8.java     |  99 ++++
 .../upgrade/handlers/UpgradeHandler_V9.java     |  81 +++
 .../project/upgrade/v6/ProjectUpgrader_V6.java  |  43 --
 .../project/upgrade/v6/UpgradeHandler_V6.java   | 118 -----
 ...XMLDataChannelDescriptorLoader_V3_0_0_1.java | 299 -----------
 .../v6/XMLDataSourceInfoLoader_V3_0_0_1.java    | 300 -----------
 .../project/upgrade/v7/UpgradeHandler_V7.java   | 137 -----
 .../project/upgrade/v8/UpgradeHandler_V8.java   | 174 -------
 .../project/upgrade/v9/UpgradeHandler_V9.java   | 145 ------
 .../project/DataChannelProjectLoaderTest.java   |  19 +-
 .../project/DataChannelProjectSaverTest.java    |  30 +-
 .../cayenne/project/FileProjectSaverTest.java   |   4 +-
 .../upgrade/DefaultUpgradeServiceTest.java      | 163 ++++++
 .../handlers/BaseUpgradeHandlerTest.java        |  71 +++
 .../handlers/UpgradeHandler_V10Test.java        |  66 +++
 .../upgrade/handlers/UpgradeHandler_V7Test.java |  94 ++++
 .../upgrade/handlers/UpgradeHandler_V8Test.java |  97 ++++
 .../upgrade/handlers/UpgradeHandler_V9Test.java |  69 +++
 .../upgrade/v7/ProjectUpgrader_V7Test.java      | 499 -------------------
 .../upgrade/v8/ProjectUpgrader_V8Test.java      | 197 --------
 .../upgrade/v9/ProjectUpgrader_V9Test.java      | 249 ---------
 .../apache/cayenne/project/cayenne-PROJECT1.xml |  14 +-
 .../apache/cayenne/project/cayenne-PROJECT2.xml |  16 +-
 .../cayenne/project/testProjectMap1_1.map.xml   |  10 +-
 .../cayenne/project/testProjectMap1_2.map.xml   |  10 +-
 .../cayenne/project/testProjectMap2_1.map.xml   |  10 +-
 .../cayenne/project/testProjectMap2_2.map.xml   |  10 +-
 .../upgrade/handlers/cayenne-project-v10.xml    |   3 +
 .../upgrade/handlers/cayenne-project-v11.xml    |   3 +
 .../handlers/cayenne-project-v3.2.1.0.xml       |   3 +
 .../upgrade/handlers/cayenne-project-v5.xml     |   3 +
 .../upgrade/handlers/cayenne-project-v6.xml     |  17 +
 .../upgrade/handlers/cayenne-project-v7.xml     |  15 +
 .../upgrade/handlers/cayenne-project-v8.xml     |  15 +
 .../upgrade/handlers/cayenne-project-v9.xml     |  15 +
 .../upgrade/handlers/test-map-v6.map.xml        |  21 +
 .../upgrade/handlers/test-map-v7.map.xml        |  31 ++
 .../upgrade/handlers/test-map-v8.map.xml        |  13 +
 .../upgrade/handlers/test-map-v9.map.xml        |  12 +
 60 files changed, 2194 insertions(+), 2783 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/CompoundSaverDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/CompoundSaverDelegate.java b/cayenne-project/src/main/java/org/apache/cayenne/project/CompoundSaverDelegate.java
new file mode 100644
index 0000000..5ea7a29
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/CompoundSaverDelegate.java
@@ -0,0 +1,183 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project;
+
+import java.util.Collection;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.Embeddable;
+import org.apache.cayenne.map.EmbeddableAttribute;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.ProcedureParameter;
+import org.apache.cayenne.map.QueryDescriptor;
+import org.apache.cayenne.project.extension.SaverDelegate;
+import org.apache.cayenne.util.XMLEncoder;
+
+/**
+ * @since 4.1
+ */
+class CompoundSaverDelegate implements SaverDelegate {
+
+    Collection<SaverDelegate> delegates;
+
+    CompoundSaverDelegate(Collection<SaverDelegate> delegates) {
+        this.delegates = delegates;
+        setParentDelegate(this);
+    }
+
+    @Override
+    public Void visitDataChannelDescriptor(DataChannelDescriptor channelDescriptor) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitDataChannelDescriptor(channelDescriptor);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitDataNodeDescriptor(DataNodeDescriptor nodeDescriptor) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitDataNodeDescriptor(nodeDescriptor);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitDataMap(DataMap dataMap) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitDataMap(dataMap);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitObjEntity(ObjEntity entity) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitObjEntity(entity);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitDbEntity(DbEntity entity) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitDbEntity(entity);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitEmbeddable(Embeddable embeddable) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitEmbeddable(embeddable);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitEmbeddableAttribute(EmbeddableAttribute attribute) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitEmbeddableAttribute(attribute);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitObjAttribute(ObjAttribute attribute) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitObjAttribute(attribute);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitDbAttribute(DbAttribute attribute) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitDbAttribute(attribute);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitObjRelationship(ObjRelationship relationship) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitObjRelationship(relationship);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitDbRelationship(DbRelationship relationship) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitDbRelationship(relationship);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitProcedure(Procedure procedure) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitProcedure(procedure);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitProcedureParameter(ProcedureParameter parameter) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitProcedureParameter(parameter);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitQuery(QueryDescriptor query) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.visitQuery(query);
+        }
+        return null;
+    }
+
+    @Override
+    public void setXMLEncoder(XMLEncoder encoder) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.setXMLEncoder(encoder);
+        }
+    }
+
+    @Override
+    public void setParentDelegate(SaverDelegate parentDelegate) {
+        for(SaverDelegate delegate : delegates) {
+            delegate.setParentDelegate(parentDelegate);
+        }
+    }
+
+    @Override
+    public SaverDelegate getParentDelegate() {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java
index 9ed8a88..1aab516 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java
@@ -19,10 +19,12 @@
 package org.apache.cayenne.project;
 
 import java.io.PrintWriter;
+import java.util.Collection;
 
 import org.apache.cayenne.configuration.BaseConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.project.extension.SaverDelegate;
 import org.apache.cayenne.util.XMLEncoder;
 
 /**
@@ -32,17 +34,20 @@ class ConfigurationSaver extends BaseConfigurationNodeVisitor<Void> {
 
     private PrintWriter printWriter;
     private String version;
+    private SaverDelegate delegate;
 
-    ConfigurationSaver(PrintWriter printWriter, String version) {
+    ConfigurationSaver(PrintWriter printWriter, String version, SaverDelegate delegate) {
         this.printWriter = printWriter;
         this.version = version;
+        this.delegate = delegate;
     }
 
     @Override
     public Void visitDataChannelDescriptor(DataChannelDescriptor node) {
         XMLEncoder encoder = new XMLEncoder(printWriter, "\t", version);
         printXMLHeader(encoder);
-        node.encodeAsXML(encoder);
+        delegate.setXMLEncoder(encoder);
+        node.encodeAsXML(encoder, delegate);
         return null;
     }
 
@@ -50,7 +55,8 @@ class ConfigurationSaver extends BaseConfigurationNodeVisitor<Void> {
     public Void visitDataMap(DataMap node) {
         XMLEncoder encoder = new XMLEncoder(printWriter, "\t", version);
         printXMLHeader(encoder);
-        node.encodeAsXML(encoder);
+        delegate.setXMLEncoder(encoder);
+        node.encodeAsXML(encoder, delegate);
         return null;
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java b/cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java
index c37d763..fe01162 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java
@@ -23,6 +23,8 @@ import org.apache.cayenne.configuration.ConfigurationNameMapper;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.project.extension.ProjectExtension;
+import org.apache.cayenne.project.extension.SaverDelegate;
 import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.resource.URLResource;
 import org.apache.cayenne.util.Util;
@@ -38,6 +40,7 @@ import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 /**
  * A ProjectSaver saving project configuration to the file system.
@@ -53,16 +56,24 @@ public class FileProjectSaver implements ProjectSaver {
 	protected ConfigurationNodeVisitor<Collection<ConfigurationNode>> saveableNodesGetter;
 	protected String fileEncoding;
 
-	public FileProjectSaver() {
+	protected Collection<SaverDelegate> saverDelegates;
+
+	public FileProjectSaver(@Inject List<ProjectExtension> extensions) {
 		resourceGetter = new ConfigurationSourceGetter();
 		saveableNodesGetter = new SaveableNodesGetter();
 
 		// this is not configurable yet... probably doesn't have to be
 		fileEncoding = "UTF-8";
+
+		saverDelegates = new ArrayList<>(extensions.size());
+		for(ProjectExtension extension : extensions) {
+			SaverDelegate delegate = extension.createSaverDelegate();
+			saverDelegates.add(delegate);
+		}
 	}
 
 	public String getSupportedVersion() {
-		return "9";
+		return String.valueOf(Project.VERSION);
 	}
 
 	public void save(Project project) {
@@ -169,7 +180,7 @@ public class FileProjectSaver implements ProjectSaver {
 		for (SaveUnit unit : units) {
 
 			String name = unit.targetFile.getName();
-			if (name == null || name.length() < 3) {
+			if (name.length() < 3) {
 				name = "cayenne-project";
 			}
 
@@ -185,8 +196,8 @@ public class FileProjectSaver implements ProjectSaver {
 				unit.targetTempFile.delete();
 			}
 
-			try (PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(
-					unit.targetTempFile), fileEncoding));) {
+			try (PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(
+					new FileOutputStream(unit.targetTempFile), fileEncoding))) {
 				saveToTempFile(unit, printWriter);
 			} catch (UnsupportedEncodingException e) {
 				throw new CayenneRuntimeException("Unsupported encoding '%s' (%s)", e, fileEncoding, e.getMessage());
@@ -198,7 +209,9 @@ public class FileProjectSaver implements ProjectSaver {
 	}
 
 	void saveToTempFile(SaveUnit unit, PrintWriter printWriter) {
-		unit.node.acceptVisitor(new ConfigurationSaver(printWriter, getSupportedVersion()));
+		unit.node.acceptVisitor(
+				new ConfigurationSaver(printWriter, getSupportedVersion(), new CompoundSaverDelegate(saverDelegates))
+		);
 	}
 
 	void saveCommit(Collection<SaveUnit> units) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/Project.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/Project.java b/cayenne-project/src/main/java/org/apache/cayenne/project/Project.java
index ad0458b..a1ebd70 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/Project.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/Project.java
@@ -36,6 +36,14 @@ import org.apache.cayenne.resource.Resource;
  */
 public class Project {
 
+	/**
+	 * Current version of Cayenne project.
+	 * Used by different parsers and savers of project's XML files.
+	 *
+	 * @since 4.1
+	 */
+	static public final int VERSION = 10;
+
 	protected boolean modified;
 
 	protected ConfigurationTree<?> configurationTree;
@@ -45,7 +53,7 @@ public class Project {
 	public Project(ConfigurationTree<?> configurationTree) {
 		this.configurationTree = configurationTree;
 		this.configurationSourceGetter = new ConfigurationSourceGetter();
-		this.unusedResources = new HashSet<URL>();
+		this.unusedResources = new HashSet<>();
 	}
 
 	public ConfigurationTree<?> getConfigurationTree() {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java
index a1eeb98..8f5d011 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java
@@ -19,26 +19,55 @@
 package org.apache.cayenne.project;
 
 import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.ListBuilder;
 import org.apache.cayenne.di.Module;
-import org.apache.cayenne.project.upgrade.ProjectUpgrader;
-import org.apache.cayenne.project.upgrade.v9.ProjectUpgrader_V9;
+import org.apache.cayenne.project.extension.ProjectExtension;
+import org.apache.cayenne.project.upgrade.DefaultUpgradeService;
+import org.apache.cayenne.project.upgrade.UpgradeService;
+import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler;
+import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V10;
+import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V7;
+import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V8;
+import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V9;
 import org.apache.cayenne.project.validation.DefaultProjectValidator;
 import org.apache.cayenne.project.validation.ProjectValidator;
 
 /**
- * A dependency injection (DI) module contributing configuration related to Cayenne mapping project manipulation to a
- * DI container.
+ * A dependency injection (DI) module contributing configuration related
+ * to Cayenne mapping project manipulation to a DI container.
  *
  * @since 4.0
  */
 public class ProjectModule implements Module {
 
+    /**
+     * @since 4.1
+     */
+    public static ListBuilder<ProjectExtension> contributeExtension(Binder binder) {
+        return binder.bindList(ProjectExtension.class);
+    }
+
+    /**
+     * @since 4.1
+     */
+    public static ListBuilder<UpgradeHandler> contributeUpgradeHandler(Binder binder) {
+        return binder.bindList(UpgradeHandler.class);
+    }
+
     public void configure(Binder binder) {
         binder.bind(ProjectLoader.class).to(DataChannelProjectLoader.class);
         binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
-        binder.bind(ProjectUpgrader.class).to(ProjectUpgrader_V9.class);
         binder.bind(ProjectValidator.class).to(DefaultProjectValidator.class);
-        binder.bind(ConfigurationNodeParentGetter.class).to(
-                DefaultConfigurationNodeParentGetter.class);
+        binder.bind(ConfigurationNodeParentGetter.class).to(DefaultConfigurationNodeParentGetter.class);
+
+        binder.bind(UpgradeService.class).to(DefaultUpgradeService.class);
+        // Note: order is important
+        contributeUpgradeHandler(binder)
+                .add(UpgradeHandler_V7.class)
+                .add(UpgradeHandler_V8.class)
+                .add(UpgradeHandler_V9.class)
+                .add(UpgradeHandler_V10.class);
+
+        contributeExtension(binder);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java b/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java
index ca74cc2..8da76e6 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java
@@ -30,19 +30,14 @@ import java.util.Collections;
 /**
  * @since 3.1
  */
-class SaveableNodesGetter extends
-        BaseConfigurationNodeVisitor<Collection<ConfigurationNode>> {
+class SaveableNodesGetter extends BaseConfigurationNodeVisitor<Collection<ConfigurationNode>> {
 
     @Override
-    public Collection<ConfigurationNode> visitDataChannelDescriptor(
-            DataChannelDescriptor descriptor) {
+    public Collection<ConfigurationNode> visitDataChannelDescriptor(DataChannelDescriptor descriptor) {
 
         Collection<ConfigurationNode> nodes = new ArrayList<>();
         nodes.add(descriptor);
-
-        for (DataMap map : descriptor.getDataMaps()) {
-            nodes.add(map);
-        }
+        nodes.addAll(descriptor.getDataMaps());
 
         return nodes;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/extension/BaseSaverDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/extension/BaseSaverDelegate.java b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/BaseSaverDelegate.java
new file mode 100644
index 0000000..08565b2
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/BaseSaverDelegate.java
@@ -0,0 +1,133 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.extension;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.Embeddable;
+import org.apache.cayenne.map.EmbeddableAttribute;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.ProcedureParameter;
+import org.apache.cayenne.map.QueryDescriptor;
+import org.apache.cayenne.util.XMLEncoder;
+
+/**
+ * Base saver delegate that handles common setters/getters, as well as provides empty stub for all methods.
+ *
+ * @since 4.1
+ */
+public class BaseSaverDelegate implements SaverDelegate {
+
+    protected XMLEncoder encoder;
+
+    protected SaverDelegate parentDelegate;
+
+    @Override
+    public Void visitDataChannelDescriptor(DataChannelDescriptor channelDescriptor) {
+        return null;
+    }
+
+    @Override
+    public Void visitDataNodeDescriptor(DataNodeDescriptor nodeDescriptor) {
+        return null;
+    }
+
+    @Override
+    public Void visitDataMap(DataMap dataMap) {
+        return null;
+    }
+
+    @Override
+    public Void visitObjEntity(ObjEntity entity) {
+        return null;
+    }
+
+    @Override
+    public Void visitDbEntity(DbEntity entity) {
+        return null;
+    }
+
+    @Override
+    public Void visitEmbeddable(Embeddable embeddable) {
+        return null;
+    }
+
+    @Override
+    public Void visitEmbeddableAttribute(EmbeddableAttribute attribute) {
+        return null;
+    }
+
+    @Override
+    public Void visitObjAttribute(ObjAttribute attribute) {
+        return null;
+    }
+
+    @Override
+    public Void visitDbAttribute(DbAttribute attribute) {
+        return null;
+    }
+
+    @Override
+    public Void visitObjRelationship(ObjRelationship relationship) {
+        return null;
+    }
+
+    @Override
+    public Void visitDbRelationship(DbRelationship relationship) {
+        return null;
+    }
+
+    @Override
+    public Void visitProcedure(Procedure procedure) {
+        return null;
+    }
+
+    @Override
+    public Void visitProcedureParameter(ProcedureParameter parameter) {
+        return null;
+    }
+
+    @Override
+    public Void visitQuery(QueryDescriptor query) {
+        return null;
+    }
+
+    @Override
+    public void setXMLEncoder(XMLEncoder encoder) {
+        this.encoder = encoder;
+    }
+
+    @Override
+    public void setParentDelegate(SaverDelegate parentDelegate) {
+        this.parentDelegate = parentDelegate;
+    }
+
+    @Override
+    public SaverDelegate getParentDelegate() {
+        return parentDelegate;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ExtensionAwareHandlerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ExtensionAwareHandlerFactory.java b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ExtensionAwareHandlerFactory.java
new file mode 100644
index 0000000..fc7e35d
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ExtensionAwareHandlerFactory.java
@@ -0,0 +1,69 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.extension;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
+import org.apache.cayenne.configuration.xml.NamespaceAwareNestedTagHandler;
+import org.apache.cayenne.di.Inject;
+
+/**
+ * Project parser handlers factory that will use third-party extensions
+ * to provide handlers for unknown tags.
+ *
+ * @see ProjectExtension
+ * @see DefaultHandlerFactory
+ *
+ * @since 4.1
+ */
+public class ExtensionAwareHandlerFactory extends DefaultHandlerFactory {
+
+    Map<String, LoaderDelegate> loaderDelegates = new ConcurrentHashMap<>();
+
+    public ExtensionAwareHandlerFactory(@Inject List<ProjectExtension> extensions) {
+        for(ProjectExtension extension : extensions) {
+            LoaderDelegate delegate = extension.createLoaderDelegate();
+            LoaderDelegate old = loaderDelegates.put(delegate.getTargetNamespace(), delegate);
+            if(old != null) {
+                throw new CayenneRuntimeException("Found two loader delegates for namespace %s",
+                        delegate.getTargetNamespace());
+            }
+        }
+    }
+
+    @Override
+    public NamespaceAwareNestedTagHandler createHandler(String namespace, String localName,
+                                                        NamespaceAwareNestedTagHandler parent) {
+
+        LoaderDelegate delegate = loaderDelegates.get(namespace);
+        if(delegate != null) {
+            NamespaceAwareNestedTagHandler handler = delegate.createHandler(parent, localName);
+            if(handler != null) {
+                return handler;
+            }
+        }
+
+        return super.createHandler(namespace, localName, parent);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/extension/LoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/extension/LoaderDelegate.java b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/LoaderDelegate.java
new file mode 100644
index 0000000..938e7c0
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/LoaderDelegate.java
@@ -0,0 +1,45 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.extension;
+
+import org.apache.cayenne.configuration.xml.NamespaceAwareNestedTagHandler;
+
+/**
+ * Delegate that handles loading process for extension specific parts of XML document.
+ *
+ * @since 4.1
+ */
+public interface LoaderDelegate {
+
+    /**
+     * @return target namespace that this extension is using
+     */
+    String getTargetNamespace();
+
+    /**
+     * Create handler that will handle parsing process further.
+     *
+     * @param parent parent handler
+     * @param tag current tag that in question
+     * @return new handler that will process tag or null if there is no interest in tag
+     */
+    NamespaceAwareNestedTagHandler createHandler(NamespaceAwareNestedTagHandler parent, String tag);
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java
new file mode 100644
index 0000000..1bfa33e
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java
@@ -0,0 +1,49 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.extension;
+
+/**
+ * <p>DataMap XML file extension mechanics.</p>
+ * <p>
+ *     Can be used to enhance datamap.map.xml files with additional (really random) information.
+ *     By default extensions not used by {@link org.apache.cayenne.configuration.server.ServerRuntime} or
+ *     ClientRuntime so they can safely store big chunks of data.
+ * </p>
+ * <p>
+ *     Extensions can be contributed by {@link org.apache.cayenne.project.ProjectModule#contributeExtension(org.apache.cayenne.di.Binder)}.
+ *     {@link org.apache.cayenne.project.ProjectModule} currently used by Modeler and cli tools, e.g. cdbimport and cgen.
+ * </p>
+ *
+ * @see org.apache.cayenne.project.extension.info.InfoExtension as reference implementation
+ * @since 4.1
+ */
+public interface ProjectExtension {
+
+    /**
+     * @return delegate that handle loading phase of XML processing
+     */
+    LoaderDelegate createLoaderDelegate();
+
+    /**
+     * @return delegate that handle saving phase of XML processing
+     */
+    SaverDelegate createSaverDelegate();
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/extension/SaverDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/extension/SaverDelegate.java b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/SaverDelegate.java
new file mode 100644
index 0000000..4ed5c92
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/SaverDelegate.java
@@ -0,0 +1,45 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.extension;
+
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.util.XMLEncoder;
+
+/**
+ * Delegate that handles saving XML of extension.
+ * {@link BaseSaverDelegate} should be used as a base class for custom delegates.
+ *
+ * @since 4.1
+ */
+public interface SaverDelegate extends ConfigurationNodeVisitor<Void> {
+
+    /**
+     * @param encoder provided by caller
+     */
+    void setXMLEncoder(XMLEncoder encoder);
+
+    /**
+     * @param parentDelegate parent delegate, provided by caller
+     */
+    void setParentDelegate(SaverDelegate parentDelegate);
+
+    SaverDelegate getParentDelegate();
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/BaseUpgradeHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/BaseUpgradeHandler.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/BaseUpgradeHandler.java
deleted file mode 100644
index 89a7b82..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/BaseUpgradeHandler.java
+++ /dev/null
@@ -1,218 +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.project.upgrade;
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.resource.Resource;
-import org.apache.cayenne.util.Util;
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.DefaultHandler;
-
-import java.io.InputStream;
-import java.net.URL;
-
-/**
- * A common superclass of UpgradeHandlers.
- * 
- * @since 3.1
- */
-// there's no guarantee this will survive the further version upgrades, but for
-// now all
-// the code here seems like version-agnostic
-public abstract class BaseUpgradeHandler implements UpgradeHandler {
-
-	static final String UNKNOWN_VERSION = "0";
-	static final String MIN_SUPPORTED_VERSION = "3.0.0.1";
-
-	protected Resource projectSource;
-	protected UpgradeMetaData metaData;
-
-	public BaseUpgradeHandler(Resource projectSource) {
-
-		if (projectSource == null) {
-			throw new NullPointerException("Null project source");
-		}
-
-		this.projectSource = projectSource;
-	}
-
-	/**
-	 * Creates a single common EntityResolver for all project DataMaps, setting
-	 * it as a namespace for all of them. This is needed for resolving cross-map
-	 * relationships.
-	 */
-	protected void attachToNamespace(DataChannelDescriptor channelDescriptor) {
-		EntityResolver entityResolver = new EntityResolver(channelDescriptor.getDataMaps());
-
-		for (DataMap map : entityResolver.getDataMaps()) {
-			map.setNamespace(entityResolver);
-		}
-	}
-
-	@Override
-	public Resource getProjectSource() {
-		return projectSource;
-	}
-
-	@Override
-	public UpgradeMetaData getUpgradeMetaData() {
-		// no attempts at thread-safety... shouldn't be needed for upgrades
-		if (metaData == null) {
-			metaData = loadMetaData();
-		}
-
-		return metaData;
-	}
-
-	@Override
-	public Resource performUpgrade() throws ConfigurationException {
-		UpgradeMetaData metaData = getUpgradeMetaData();
-		switch (metaData.getUpgradeType()) {
-			case DOWNGRADE_NEEDED:
-				throw new ConfigurationException("Downgrade can not be performed");
-			case INTERMEDIATE_UPGRADE_NEEDED:
-				throw new ConfigurationException("Upgrade can not be performed - intermediate version upgrade needed");
-			case UPGRADE_NEEDED:
-				return doPerformUpgrade(metaData);
-			default:
-				return getProjectSource();
-		}
-	}
-
-	/**
-	 * Does the actual project upgrade, assuming the caller already verified
-	 * that the upgrade is possible.
-	 * 
-	 * @param metaData
-	 *            object describing the type of upgrade
-	 */
-	protected abstract Resource doPerformUpgrade(UpgradeMetaData metaData) throws ConfigurationException;
-
-	protected abstract String getToVersion();
-
-	/**
-	 * Creates a metadata object describing the type of upgrade needed.
-	 */
-	protected UpgradeMetaData loadMetaData() {
-		String version = loadProjectVersion();
-
-		UpgradeMetaData metadata = new UpgradeMetaData();
-		metadata.setSupportedVersion(getToVersion());
-		metadata.setProjectVersion(version);
-
-		int c1 = compareVersions(version, MIN_SUPPORTED_VERSION);
-		int c2 = compareVersions(getToVersion(), version);
-
-		if (c1 < 0) {
-			metadata.setIntermediateUpgradeVersion(MIN_SUPPORTED_VERSION);
-			metadata.setUpgradeType(UpgradeType.INTERMEDIATE_UPGRADE_NEEDED);
-		} else if (c2 < 0) {
-			metadata.setUpgradeType(UpgradeType.DOWNGRADE_NEEDED);
-		} else if (c2 == 0) {
-			metadata.setUpgradeType(UpgradeType.UPGRADE_NOT_NEEDED);
-		} else {
-			metadata.setUpgradeType(UpgradeType.UPGRADE_NEEDED);
-		}
-
-		return metadata;
-	}
-
-	/**
-	 * A default method for quick extraction of the project version from an XML
-	 * file.
-	 */
-	protected String loadProjectVersion() {
-
-		RootTagHandler rootHandler = new RootTagHandler();
-		URL url = projectSource.getURL();
-
-		try (InputStream in = url.openStream();) {
-
-			XMLReader parser = Util.createXmlReader();
-
-			parser.setContentHandler(rootHandler);
-			parser.setErrorHandler(rootHandler);
-			parser.parse(new InputSource(in));
-		} catch (SAXException e) {
-			// expected ... handler will terminate as soon as it finds a root
-			// tag.
-		} catch (Exception e) {
-			throw new ConfigurationException("Error reading configuration from %s", e, url);
-		}
-
-		return rootHandler.projectVersion != null ? rootHandler.projectVersion : UNKNOWN_VERSION;
-	}
-
-	/**
-	 * Compares two String versions.
-	 */
-	protected int compareVersions(String v1, String v2) {
-
-		if (v1.equals(v2)) {
-			return 0;
-		}
-
-		double v1Double = decodeVersion(v1);
-		double v2Double = decodeVersion(v2);
-		return v1Double < v2Double ? -1 : 1;
-	}
-
-	protected double decodeVersion(String version) {
-		if (version == null || version.trim().length() == 0) {
-			return 0;
-		}
-
-		// leave the first dot, and treat remaining as a fraction
-		// remove all non digit chars
-		StringBuilder buffer = new StringBuilder(version.length());
-		boolean dotProcessed = false;
-		for (int i = 0; i < version.length(); i++) {
-			char nextChar = version.charAt(i);
-			if (nextChar == '.' && !dotProcessed) {
-				dotProcessed = true;
-				buffer.append('.');
-			} else if (Character.isDigit(nextChar)) {
-				buffer.append(nextChar);
-			}
-		}
-
-		return Double.parseDouble(buffer.toString());
-	}
-
-	class RootTagHandler extends DefaultHandler {
-
-		private String projectVersion;
-
-		@Override
-		public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
-
-			this.projectVersion = attributes.getValue("", "project-version");
-
-			// bail right away - we are not interested in reading this to the
-			// end
-			throw new SAXException("finished");
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DataSourceInfoLoader_3_0_0_1.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DataSourceInfoLoader_3_0_0_1.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DataSourceInfoLoader_3_0_0_1.java
deleted file mode 100644
index dc52a50..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DataSourceInfoLoader_3_0_0_1.java
+++ /dev/null
@@ -1,228 +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.project.upgrade;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.configuration.PasswordEncoding;
-import org.apache.cayenne.configuration.SAXNestedTagHandler;
-import org.apache.cayenne.conn.DataSourceInfo;
-import org.apache.cayenne.resource.Resource;
-import org.apache.cayenne.util.Util;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.XMLReader;
-
-/**
- * A loader of XML for the {@link DataSourceInfo} object. The loader is
- * compatible with project version 3.0.0.1 and earlier.
- * 
- * @since 3.1
- */
-// TODO: andrus 12.13.2009 - unused yet.. will be used in upgrade manager
-class DataSourceInfoLoader_3_0_0_1 {
-
-	public DataSourceInfo load(Resource configurationResource) throws Exception {
-
-		if (configurationResource == null) {
-			throw new NullPointerException("Null configurationResource");
-		}
-
-		DataSourceInfo dataSourceDescriptor = new DataSourceInfo();
-
-		XMLReader parser = Util.createXmlReader();
-
-		DriverHandler handler = new DriverHandler(dataSourceDescriptor, parser);
-		parser.setContentHandler(handler);
-		parser.setErrorHandler(handler);
-		parser.parse(new InputSource(configurationResource.getURL().openStream()));
-
-		return dataSourceDescriptor;
-	}
-
-	private static String passwordFromURL(URL url) {
-		InputStream inputStream = null;
-		String password = null;
-
-		try {
-			inputStream = url.openStream();
-			password = passwordFromInputStream(inputStream);
-		} catch (IOException exception) {
-			// ignore
-		}
-
-		return password;
-	}
-
-	private static String passwordFromInputStream(InputStream inputStream) {
-		String password = null;
-
-		try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));) {
-
-			password = bufferedReader.readLine();
-		} catch (IOException exception) {
-			// ignoring...
-		} finally {
-
-			try {
-				inputStream.close();
-			} catch (IOException exception) {
-			}
-		}
-
-		return password;
-	}
-
-	private class DriverHandler extends SAXNestedTagHandler {
-
-		private DataSourceInfo dataSourceDescriptor;
-
-		DriverHandler(DataSourceInfo dataSourceDescriptor, XMLReader parser) {
-			super(parser, null);
-			this.dataSourceDescriptor = dataSourceDescriptor;
-		}
-
-		@Override
-		protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name,
-				Attributes attributes) {
-
-			if (localName.equals("driver")) {
-				String className = attributes.getValue("", "class");
-				dataSourceDescriptor.setJdbcDriver(className);
-				return new DriverChildrenHandler(parser, this);
-			}
-
-			return super.createChildTagHandler(namespaceURI, localName, name, attributes);
-		}
-	}
-
-	private class DriverChildrenHandler extends SAXNestedTagHandler {
-
-		private DataSourceInfo dataSourceDescriptor;
-
-		DriverChildrenHandler(XMLReader parser, DriverHandler parentHandler) {
-			super(parser, parentHandler);
-			this.dataSourceDescriptor = parentHandler.dataSourceDescriptor;
-		}
-
-		@Override
-		protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name,
-				Attributes attributes) {
-
-			if (localName.equals("login")) {
-
-				String encoderClass = attributes.getValue("encoderClass");
-
-				String encoderKey = attributes.getValue("encoderKey");
-				if (encoderKey == null) {
-					encoderKey = attributes.getValue("encoderSalt");
-				}
-
-				String password = attributes.getValue("password");
-				String passwordLocation = attributes.getValue("passwordLocation");
-				String passwordSource = attributes.getValue("passwordSource");
-				if (passwordSource == null) {
-					passwordSource = DataSourceInfo.PASSWORD_LOCATION_MODEL;
-				}
-
-				String username = attributes.getValue("userName");
-
-				dataSourceDescriptor.setPasswordEncoderClass(encoderClass);
-				dataSourceDescriptor.setPasswordEncoderKey(encoderKey);
-				dataSourceDescriptor.setPasswordLocation(passwordLocation);
-				dataSourceDescriptor.setPasswordSource(passwordSource);
-				dataSourceDescriptor.setUserName(username);
-
-				// Replace {} in passwordSource with encoderSalt -- useful for
-				// EXECUTABLE
-				// & URL options
-				if (encoderKey != null) {
-					passwordSource = passwordSource.replaceAll("\\{\\}", encoderKey);
-				}
-
-				PasswordEncoding passwordEncoder = dataSourceDescriptor.getPasswordEncoder();
-
-				if (passwordLocation != null) {
-					if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH)) {
-
-						ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-						URL url = classLoader.getResource(username);
-						if (url != null) {
-							password = passwordFromURL(url);
-						} else {
-							// ignoring..
-						}
-					} else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_URL)) {
-						try {
-							password = passwordFromURL(new URL(passwordSource));
-						} catch (MalformedURLException exception) {
-							// ignoring...
-						}
-					} else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE)) {
-						if (passwordSource != null) {
-							try {
-								Process process = Runtime.getRuntime().exec(passwordSource);
-								password = passwordFromInputStream(process.getInputStream());
-								process.waitFor();
-							} catch (IOException exception) {
-								// ignoring...
-							} catch (InterruptedException exception) {
-								// ignoring...
-							}
-						}
-					}
-				}
-
-				if (password != null && passwordEncoder != null) {
-					dataSourceDescriptor.setPassword(passwordEncoder.decodePassword(password, encoderKey));
-				}
-			} else if (localName.equals("url")) {
-				dataSourceDescriptor.setDataSourceUrl(attributes.getValue("value"));
-			} else if (localName.equals("connectionPool")) {
-				String min = attributes.getValue("min");
-				if (min != null) {
-					try {
-						dataSourceDescriptor.setMinConnections(Integer.parseInt(min));
-					} catch (NumberFormatException nfex) {
-						throw new ConfigurationException("Non-numeric 'min' attribute '%s'", nfex, min);
-					}
-				}
-
-				String max = attributes.getValue("max");
-				if (max != null) {
-					try {
-						dataSourceDescriptor.setMaxConnections(Integer.parseInt(max));
-					} catch (NumberFormatException nfex) {
-						throw new ConfigurationException("Non-numeric 'max' attribute '%s'", nfex, max);
-					}
-				}
-			}
-
-			return super.createChildTagHandler(namespaceURI, localName, name, attributes);
-		}
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultUpgradeService.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultUpgradeService.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultUpgradeService.java
new file mode 100644
index 0000000..aafb3d2
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultUpgradeService.java
@@ -0,0 +1,318 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.upgrade;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.configuration.ConfigurationTree;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.project.Project;
+import org.apache.cayenne.project.ProjectSaver;
+import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler;
+import org.apache.cayenne.resource.Resource;
+import org.apache.cayenne.util.Util;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ *
+ * Upgrade service sequence is following:
+ * 1. This cycle should be done by Modeler and will result in a full project upgrade
+ *
+ *  - find all project and datamap resources
+ *  - define set of upgrade handlers to process those resources
+ *  - process DOM (project + N data maps)
+ *  - save & load cycle to flush all DOM changes
+ *  - process project model
+ *  - save once again to cleanup and sort final XML
+ *
+ * 2. This cycle can be used by ServerRuntime to optionally support old project versions
+ *
+ *  - find all project and datamap resources
+ *  - define set of upgrade handlers to process those resources
+ *  - process DOM (project + N data maps)
+ *  - directly load model from DOM w/o saving
+ *  - process project model
+ *
+ * @since 4.1
+ */
+public class DefaultUpgradeService implements UpgradeService {
+
+    public static final String UNKNOWN_VERSION = "0";
+    public static final String MIN_SUPPORTED_VERSION = "6";
+
+    TreeMap<String, UpgradeHandler> handlers = new TreeMap<>(VersionComparator.INSTANCE);
+
+    @Inject
+    private ProjectSaver projectSaver;
+
+    @Inject
+    private DataChannelDescriptorLoader loader;
+
+    public DefaultUpgradeService(@Inject List<UpgradeHandler> handlerList) {
+        for(UpgradeHandler handler : handlerList) {
+            handlers.put(handler.getVersion(), handler);
+        }
+    }
+
+    @Override
+    public UpgradeMetaData getUpgradeType(Resource resource) {
+        UpgradeMetaData metaData = new UpgradeMetaData();
+
+        String version = loadProjectVersion(resource);
+        metaData.setProjectVersion(version);
+        metaData.setSupportedVersion(String.valueOf(Project.VERSION));
+
+        int c1 = VersionComparator.INSTANCE.compare(version, MIN_SUPPORTED_VERSION);
+        if (c1 < 0) {
+            metaData.setIntermediateUpgradeVersion(MIN_SUPPORTED_VERSION);
+            metaData.setUpgradeType(UpgradeType.INTERMEDIATE_UPGRADE_NEEDED);
+            return metaData;
+        }
+
+        int c2 = VersionComparator.INSTANCE.compare(String.valueOf(Project.VERSION), version);
+        if (c2 < 0) {
+            metaData.setUpgradeType(UpgradeType.DOWNGRADE_NEEDED);
+        } else if (c2 == 0) {
+            metaData.setUpgradeType(UpgradeType.UPGRADE_NOT_NEEDED);
+        } else {
+            metaData.setUpgradeType(UpgradeType.UPGRADE_NEEDED);
+        }
+        return metaData;
+    }
+
+    List<UpgradeHandler> getHandlersForVersion(String version) {
+        boolean found = MIN_SUPPORTED_VERSION.equals(version);
+        List<UpgradeHandler> handlerList = new ArrayList<>();
+
+        for(Map.Entry<String, UpgradeHandler> entry : handlers.entrySet()) {
+            if(entry.getKey().equals(version)) {
+                found = true;
+                continue;
+            }
+            if(!found) {
+                continue;
+            }
+
+            handlerList.add(entry.getValue());
+        }
+
+        return handlerList;
+    }
+
+    @Override
+    public Resource upgradeProject(Resource resource) {
+        List<UpgradeHandler> handlerList = getHandlersForVersion(loadProjectVersion(resource));
+
+        resource = upgradeDOM(resource, handlerList);
+        upgradeModel(resource, handlerList);
+
+        return resource;
+    }
+
+    Resource upgradeDOM(Resource resource, List<UpgradeHandler> handlerList) {
+        // Load DOM for all resources
+        Document projectDocument = readDocument(resource);
+        UpgradeUnit projectUnit = new UpgradeUnit(resource, projectDocument);
+
+        List<Resource> dataMapResources = getAdditionalDatamapResources(projectUnit);
+        List<UpgradeUnit> upgradeUnits = new ArrayList<>(dataMapResources.size());
+        for (Resource dataMapResource : dataMapResources) {
+            upgradeUnits.add(new UpgradeUnit(dataMapResource, readDocument(dataMapResource)));
+        }
+
+        // Update DOM
+        for(UpgradeHandler handler : handlerList) {
+            handler.processProjectDom(projectUnit);
+            for(UpgradeUnit dataMapUnit : upgradeUnits) {
+                handler.processDataMapDom(dataMapUnit);
+            }
+        }
+
+        // Save modified DOM back to original files
+        saveDocument(projectUnit);
+        for(UpgradeUnit dataMapUnit : upgradeUnits) {
+            saveDocument(dataMapUnit);
+        }
+
+        return projectUnit.getResource();
+    }
+
+    void upgradeModel(Resource resource, List<UpgradeHandler> handlerList) {
+        // Load Model back from the update XML
+        ConfigurationTree<DataChannelDescriptor> configurationTree = loader.load(resource);
+
+        // Update model level if needed
+        for(UpgradeHandler handler : handlerList) {
+            handler.processModel(configurationTree.getRootNode());
+        }
+
+        // Save project once again via project saver, this will normalize XML to minimize final diff
+        Project project = new Project(configurationTree);
+        projectSaver.save(project);
+    }
+
+    List<Resource> getAdditionalDatamapResources(UpgradeUnit upgradeUnit) {
+        List<Resource> resources = new ArrayList<>();
+        try {
+            XPath xpath = XPathFactory.newInstance().newXPath();
+            NodeList nodes = (NodeList) xpath.evaluate("/domain/map/@name", upgradeUnit.getDocument(), XPathConstants.NODESET);
+            for (int i = 0; i < nodes.getLength(); i++) {
+                Node mapNode = nodes.item(i);
+                // in version 3.0.0.1 and earlier map tag had attribute location,
+                // but it was always equal to data map name + ".map.xml"
+                Resource mapResource = upgradeUnit.getResource().getRelativeResource(mapNode.getNodeValue() + ".map.xml");
+                resources.add(mapResource);
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return resources;
+    }
+
+    protected void saveDocument(UpgradeUnit upgradeUnit) {
+        try {
+            Source input = new DOMSource(upgradeUnit.getDocument());
+            Result output = new StreamResult(Util.toFile(upgradeUnit.getResource().getURL()));
+
+            Transformer transformer = TransformerFactory.newInstance().newTransformer();
+            transformer.transform(input, output);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    protected Document readDocument(Resource resource) {
+        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+        documentBuilderFactory.setNamespaceAware(false);
+        try {
+            DocumentBuilder domBuilder = documentBuilderFactory.newDocumentBuilder();
+            try (InputStream inputStream = resource.getURL().openStream()) {
+                return domBuilder.parse(inputStream);
+            } catch (IOException | SAXException e) {
+                throw new ConfigurationException("Error loading configuration from %s", e, resource);
+            }
+        } catch (ParserConfigurationException e) {
+            throw new ConfigurationException(e);
+        }
+    }
+
+    /**
+     * A default method for quick extraction of the project version from an XML
+     * file.
+     */
+    protected String loadProjectVersion(Resource resource) {
+
+        RootTagHandler rootHandler = new RootTagHandler();
+        URL url = resource.getURL();
+        try (InputStream in = url.openStream()) {
+            XMLReader parser = Util.createXmlReader();
+            parser.setContentHandler(rootHandler);
+            parser.setErrorHandler(rootHandler);
+            parser.parse(new InputSource(in));
+        } catch (SAXException e) {
+            // expected... handler will terminate as soon as it finds a root tag.
+        } catch (Exception e) {
+            throw new ConfigurationException("Error reading configuration from %s", e, url);
+        }
+
+        return rootHandler.projectVersion != null ? rootHandler.projectVersion : UNKNOWN_VERSION;
+    }
+
+    protected static double decodeVersion(String version) {
+        if (version == null || version.trim().length() == 0) {
+            return 0;
+        }
+
+        // leave the first dot, and treat remaining as a fraction
+        // remove all non digit chars
+        StringBuilder buffer = new StringBuilder(version.length());
+        boolean dotProcessed = false;
+        for (int i = 0; i < version.length(); i++) {
+            char nextChar = version.charAt(i);
+            if (nextChar == '.' && !dotProcessed) {
+                dotProcessed = true;
+                buffer.append('.');
+            } else if (Character.isDigit(nextChar)) {
+                buffer.append(nextChar);
+            }
+        }
+
+        return Double.parseDouble(buffer.toString());
+    }
+
+    private static class VersionComparator implements Comparator<String> {
+
+        private static final VersionComparator INSTANCE = new VersionComparator();
+
+        @Override
+        public int compare(String o1, String o2) {
+            if (o1.equals(o2)) {
+                return 0;
+            }
+            double v1Double = decodeVersion(o1);
+            double v2Double = decodeVersion(o2);
+            return v1Double < v2Double ? -1 : 1;
+        }
+    }
+
+    class RootTagHandler extends DefaultHandler {
+
+        private String projectVersion;
+
+        @Override
+        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+
+            this.projectVersion = attributes.getValue("", "project-version");
+
+            // bail right away - we are not interested in reading this to the end
+            throw new SAXException("finished");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/ProjectUpgrader.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/ProjectUpgrader.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/ProjectUpgrader.java
deleted file mode 100644
index 8eac85f..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/ProjectUpgrader.java
+++ /dev/null
@@ -1,34 +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.project.upgrade;
-
-import org.apache.cayenne.resource.Resource;
-
-/**
- * Defines API of an upgrade handler for Cayenne projects.
- * 
- * @since 3.1
- */
-public interface ProjectUpgrader {
-
-    /**
-     * Returns an upgrade handler to process upgrades of a given project.
-     */
-    UpgradeHandler getUpgradeHandler(Resource projectSource);
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeHandler.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeHandler.java
deleted file mode 100644
index e307b90..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeHandler.java
+++ /dev/null
@@ -1,57 +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.project.upgrade;
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.resource.Resource;
-
-/**
- * A stateful helper object for analyzing the projects and performing upgrades.
- * 
- * @since 3.1
- */
-public interface UpgradeHandler {
-
-    /**
-     * Returns the original configuration source for the project before the upgrade.
-     */
-    Resource getProjectSource();
-
-    /**
-     * Returns a metadata object containing information about the upgrade to be performed.
-     * Users should call this method before invoking {@link #performUpgrade()}, to make
-     * sure upgrade is needed and possible. Tools (like CayenneModeler) may use this
-     * object to build user-friendly messages asking for user input on the upgrade.
-     */
-    UpgradeMetaData getUpgradeMetaData();
-
-    /**
-     * Performs an in-place project configuration upgrade, throwing a
-     * {@link ConfigurationException} if the upgrade fails. Before doing the upgrade,
-     * check the handler {@link UpgradeMetaData}. Upgrades will succeed only for projects
-     * that have {@link UpgradeType#UPGRADE_NEEDED} or
-     * {@link UpgradeType#UPGRADE_NOT_NEEDED} statuses. In the later case of course,
-     * upgrade will simply be skipped.
-     * 
-     * @return a configuration Resource for the upgraded project. Depending on the upgrade
-     *         type, it may be the same resource as the original configuration, or a
-     *         totally different resource.
-     */
-    Resource performUpgrade() throws ConfigurationException;
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeService.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeService.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeService.java
new file mode 100644
index 0000000..a9cb480
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeService.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.project.upgrade;
+
+import org.apache.cayenne.resource.Resource;
+
+/**
+ * @since 4.1
+ */
+public interface UpgradeService {
+
+    UpgradeMetaData getUpgradeType(Resource resource);
+
+    Resource upgradeProject(Resource resource);
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeUnit.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeUnit.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeUnit.java
new file mode 100644
index 0000000..3fb0b95
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeUnit.java
@@ -0,0 +1,54 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.upgrade;
+
+import org.apache.cayenne.resource.Resource;
+import org.w3c.dom.Document;
+
+/**
+ * @since 4.1
+ */
+public class UpgradeUnit {
+
+    private Resource resource;
+
+    private Document document;
+
+    public UpgradeUnit(Resource resource, Document document) {
+        this.resource = resource;
+        this.document = document;
+    }
+
+    public Document getDocument() {
+        return document;
+    }
+
+    public Resource getResource() {
+        return resource;
+    }
+
+    public void setDocument(Document document) {
+        this.document = document;
+    }
+
+    public void setResource(Resource resource) {
+        this.resource = resource;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler.java
new file mode 100644
index 0000000..535ec8c
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler.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.project.upgrade.handlers;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.project.upgrade.UpgradeUnit;
+
+/**
+ * Interface that upgrade handlers should implement.
+ * Implementation also should be injected into DI stack in right order.
+ *
+ * @since 4.1
+ */
+public interface UpgradeHandler {
+
+    /**
+     * @return target version for this handler
+     */
+    String getVersion();
+
+    /**
+     * Process DOM for the project root file (e.g. cayenne-project.xml)
+     */
+    void processProjectDom(UpgradeUnit upgradeUnit);
+
+    /**
+     * Process DOM for the data map file (e.g. datamap.map.xml)
+     */
+    void processDataMapDom(UpgradeUnit upgradeUnit);
+
+    /**
+     * This method should be avoided as much as possible, as
+     * using this method will make upgrade process not future proof and
+     * will require refactoring if model should change.
+     */
+    void processModel(DataChannelDescriptor dataChannelDescriptor);
+    // should be this really, but no Java 8 yet:
+    //default void processModel(DataChannelDescriptor dataChannelDescriptor) {}
+
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V10.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V10.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V10.java
new file mode 100644
index 0000000..44b55b6
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V10.java
@@ -0,0 +1,68 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.project.upgrade.handlers;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.project.upgrade.UpgradeUnit;
+import org.w3c.dom.Element;
+
+/**
+ * Upgrade handler for the project version "10" introduced by 4.1.M1 release.
+ * Changes highlight:
+ *      - strict schema for domain (e.g. main project document)
+ *      - new schema for data map allowing usage of additional elements (e.g. XML extensions)
+ *
+ * @since 4.1
+ */
+public class UpgradeHandler_V10 implements UpgradeHandler {
+
+    @Override
+    public String getVersion() {
+        return "10";
+    }
+
+    @Override
+    public void processProjectDom(UpgradeUnit upgradeUnit) {
+        Element domain = upgradeUnit.getDocument().getDocumentElement();
+        // introduce xml namespace and schema for domain
+        domain.setAttribute("xmlns","http://cayenne.apache.org/schema/10/domain");
+        domain.setAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+        domain.setAttribute("xsi:schemaLocation", "http://cayenne.apache.org/schema/10/domain " +
+                "http://cayenne.apache.org/schema/10/domain.xsd");
+        // update version
+        domain.setAttribute("project-version", getVersion());
+    }
+
+    @Override
+    public void processDataMapDom(UpgradeUnit upgradeUnit) {
+        Element dataMap = upgradeUnit.getDocument().getDocumentElement();
+        // update schema
+        dataMap.setAttribute("xmlns","http://cayenne.apache.org/schema/10/modelMap");
+        dataMap.setAttribute("xsi:schemaLocation", "http://cayenne.apache.org/schema/10/modelMap " +
+                "http://cayenne.apache.org/schema/10/modelMap.xsd");
+        // update version
+        dataMap.setAttribute("project-version", getVersion());
+    }
+
+    @Override
+    public void processModel(DataChannelDescriptor dataChannelDescriptor) {
+        // noop
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38553b16/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V7.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V7.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V7.java
new file mode 100644
index 0000000..174e660
--- /dev/null
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V7.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.project.upgrade.handlers;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.project.upgrade.UpgradeUnit;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * @since 4.1
+ */
+public class UpgradeHandler_V7 implements UpgradeHandler {
+
+    @Override
+    public String getVersion() {
+        return "7";
+    }
+
+    @Override
+    public void processProjectDom(UpgradeUnit upgradeUnit) {
+        Element domain = upgradeUnit.getDocument().getDocumentElement();
+        domain.setAttribute("project-version", getVersion());
+
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        Node node;
+        try {
+            node = (Node) xpath.evaluate("/domain/property[@name='cayenne.DataDomain.usingExternalTransactions']",
+                    upgradeUnit.getDocument(), XPathConstants.NODE);
+        }catch (Exception ex) {
+            return;
+        }
+
+        if(node != null) {
+            domain.removeChild(node);
+        }
+    }
+
+    @Override
+    public void processDataMapDom(UpgradeUnit upgradeUnit) {
+        Element dataMap = upgradeUnit.getDocument().getDocumentElement();
+        dataMap.setAttribute("xmlns","http://cayenne.apache.org/schema/7/modelMap");
+        dataMap.setAttribute("xsi:schemaLocation", "http://cayenne.apache.org/schema/7/modelMap " +
+                "http://cayenne.apache.org/schema/7/modelMap.xsd");
+        dataMap.setAttribute("project-version", getVersion());
+    }
+
+    @Override
+    public void processModel(DataChannelDescriptor dataChannelDescriptor) {
+        for (DataMap dataMap : dataChannelDescriptor.getDataMaps()) {
+            // if objEntity has super entity, then checks it for duplicated attributes
+            for (ObjEntity objEntity : dataMap.getObjEntities()) {
+                ObjEntity superEntity = objEntity.getSuperEntity();
+                if (superEntity != null) {
+                    removeShadowAttributes(objEntity, superEntity);
+                }
+            }
+        }
+    }
+
+    /**
+     * Remove attributes from objEntity, if superEntity has attributes with same names.
+     */
+    private void removeShadowAttributes(ObjEntity objEntity, ObjEntity superEntity) {
+
+        List<String> delList = new ArrayList<>();
+
+        // if subAttr and superAttr have same names, adds subAttr to delList
+        for (ObjAttribute subAttr : objEntity.getDeclaredAttributes()) {
+            for (ObjAttribute superAttr : superEntity.getAttributes()) {
+                if (subAttr.getName().equals(superAttr.getName())) {
+                    delList.add(subAttr.getName());
+                }
+            }
+        }
+
+        if (!delList.isEmpty()) {
+            for (String i : delList) {
+                objEntity.removeAttribute(i);
+            }
+        }
+    }
+}


[14/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - updated test projects version in all modules

Posted by nt...@apache.org.
CAY-2335: New XML loading/saving mechanics with support of plugable handlers
  - updated test projects version in all modules


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

Branch: refs/heads/master
Commit: aab05f3c0e591f55aeeff3a7eb08cd50ca5a5256
Parents: 38553b1
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Jul 25 12:42:46 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Jul 25 12:42:46 2017 +0300

----------------------------------------------------------------------
 .../src/test/resources/embeddable.map.xml       |  6 +-
 .../tools/build-include-table.map.xml-result    |  6 +-
 .../apache/cayenne/tools/cgen-dependent.map.xml |  6 +-
 .../org/apache/cayenne/tools/cgen.map.xml       |  6 +-
 cayenne-ant/src/test/resources/testmap.map.xml  | 17 +---
 .../src/test/resources/cayenne-lifecycle.xml    |  2 +-
 .../src/test/resources/lifecycle-map.map.xml    |  6 +-
 .../src/test/resources/cayenne-lifecycle.xml    |  7 +-
 .../src/test/resources/lifecycle-map.map.xml    | 47 +++--------
 .../src/test/resources/cayenne-crypto.xml       |  7 +-
 .../src/test/resources/datamap.map.xml          |  6 +-
 .../cayenne-relationship-optimisation.xml       |  2 +-
 .../dbimport/relationship-optimisation.map.xml  |  6 +-
 .../apache/cayenne/tools/test_datamap.map.xml   |  6 +-
 .../src/test/resources/cayenne-java8.xml        |  7 +-
 cayenne-java8/src/test/resources/java8.map.xml  | 14 ++--
 .../src/test/resources/cayenne-joda.xml         |  7 +-
 cayenne-joda/src/test/resources/joda.map.xml    |  6 +-
 .../src/test/resources/cayenne-lifecycle.xml    |  7 +-
 .../src/test/resources/lifecycle-map.map.xml    | 36 ++++----
 .../persistent/auto/_ClientMtTable1.java        | 51 ++++--------
 .../persistent/auto/_ClientMtTable2.java        | 20 ++---
 .../src/test/resources/cayenne-protostuff.xml   |  9 +-
 .../src/test/resources/protostuff.map.xml       |  8 +-
 .../src/test/resources/cayenne-client.xml       |  3 +-
 .../src/test/resources/embeddable.map.xml       |  6 +-
 .../apache/cayenne/tools/cgen-dependent.map.xml |  4 +-
 .../org/apache/cayenne/tools/cgen.map.xml       |  6 +-
 .../src/test/resources/testmap-client.map.xml   | 88 ++++++++------------
 .../src/test/resources/testmap.map.xml          | 17 +---
 .../test/resources/cgen/cayenne-testDomain.xml  |  5 +-
 .../resources/cgen/testAdditionalMap.map.xml    | 34 ++++----
 .../test/resources/cgen/testDomainMap.map.xml   | 10 ++-
 .../dbimport/testComplexChangeOrder.map.xml     |  8 +-
 .../testComplexChangeOrder.map.xml-result       |  8 +-
 .../testCustomObjectLayerSettings.map.xml       |  6 +-
 ...testCustomObjectLayerSettings.map.xml-result |  6 +-
 .../dbimport/testDbAttributeChange.map.xml      |  8 +-
 .../testDbAttributeChange.map.xml-result        |  8 +-
 .../dbimport/testDefaultPackage.map.xml-result  |  6 +-
 .../testFilteringWithSchema.map.xml-result      |  6 +-
 .../dbimport/testFkAttributeRename.map.xml      |  8 +-
 .../testFkAttributeRename.map.xml-result        |  8 +-
 ...nsManyToManyWithRecursiveLink.map.xml-result | 10 +--
 .../dbimport/testForceDataMapSchema.map.xml     |  6 +-
 .../testForceDataMapSchema.map.xml-result       |  6 +-
 .../testImportAddTableAndColumn.map.xml         |  6 +-
 .../testImportAddTableAndColumn.map.xml-result  |  6 +-
 .../testImportNewDataMap.map.xml-result         |  6 +-
 .../dbimport/testImportNewRelationship.map.xml  |  6 +-
 .../testImportNewRelationship.map.xml-result    |  8 +-
 .../dbimport/testImportWithoutChanges.map.xml   |  6 +-
 .../testImportWithoutChanges.map.xml-result     |  6 +-
 .../tools/dbimport/testInheritance.map.xml      |  6 +-
 .../dbimport/testInheritance.map.xml-result     |  8 +-
 .../tools/dbimport/testJava7Types.map.xml       |  6 +-
 .../dbimport/testJava7Types.map.xml-result      |  6 +-
 .../tools/dbimport/testJava8Types.map.xml       |  6 +-
 .../dbimport/testJava8Types.map.xml-result      |  6 +-
 .../tools/dbimport/testOneToOne.map.xml-result  | 12 +--
 .../testPreserveCustomObjMappings.map.xml       |  6 +-
 ...testPreserveCustomObjMappings.map.xml-result |  6 +-
 .../dbimport/testPreserveRelationships.map.xml  | 10 +--
 .../testPreserveRelationships.map.xml-result    |  6 +-
 .../testSchemasAndTableExclude.map.xml-result   |  6 +-
 .../dbimport/testSkipPrimaryKeyLoading.map.xml  |  6 +-
 .../testSkipPrimaryKeyLoading.map.xml-result    |  6 +-
 .../testSkipRelationshipsLoading.map.xml        | 10 +--
 .../testSkipRelationshipsLoading.map.xml-result | 10 +--
 .../dbimport/testTableTypes.map.xml-result      |  6 +-
 .../dbimport/testUnFlattensManyToMany.map.xml   | 10 +--
 .../testUnFlattensManyToMany.map.xml-result     | 14 ++--
 .../dbimport/testViewsExclude.map.xml-result    |  6 +-
 .../test/resources/cgen/cayenne-testDomain.xml  |  2 +-
 .../resources/cgen/testAdditionalMap.map.xml    |  6 +-
 .../test/resources/cgen/testDomainMap.map.xml   |  6 +-
 76 files changed, 338 insertions(+), 434 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-ant/src/test/resources/embeddable.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-ant/src/test/resources/embeddable.map.xml b/cayenne-ant/src/test/resources/embeddable.map.xml
index 0b5c0b8..10c4db6 100644
--- a/cayenne-ant/src/test/resources/embeddable.map.xml
+++ b/cayenne-ant/src/test/resources/embeddable.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/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">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.embeddable"/>
 	<embeddable className="org.apache.cayenne.testdo.embeddable.Embeddable1">
 		<embeddable-attribute name="embedded10" type="java.lang.String" db-attribute-name="EMBEDDED10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-ant/src/test/resources/org/apache/cayenne/tools/build-include-table.map.xml-result
----------------------------------------------------------------------
diff --git a/cayenne-ant/src/test/resources/org/apache/cayenne/tools/build-include-table.map.xml-result b/cayenne-ant/src/test/resources/org/apache/cayenne/tools/build-include-table.map.xml-result
index 050561f..11fb74e 100644
--- a/cayenne-ant/src/test/resources/org/apache/cayenne/tools/build-include-table.map.xml-result
+++ b/cayenne-ant/src/test/resources/org/apache/cayenne/tools/build-include-table.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <db-entity name="PARENT" schema="APP">
         <db-attribute name="COL2" type="CHAR" length="25"/>
         <db-attribute name="COL3" type="DECIMAL" length="10" scale="2"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-ant/src/test/resources/org/apache/cayenne/tools/cgen-dependent.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-ant/src/test/resources/org/apache/cayenne/tools/cgen-dependent.map.xml b/cayenne-ant/src/test/resources/org/apache/cayenne/tools/cgen-dependent.map.xml
index d06be70..40b3dc5a 100644
--- a/cayenne-ant/src/test/resources/org/apache/cayenne/tools/cgen-dependent.map.xml
+++ b/cayenne-ant/src/test/resources/org/apache/cayenne/tools/cgen-dependent.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://cayenne.apache.org/schema/3.0/modelMap ../../main/resources/org/apache/cayenne/schema/3.0/modelMap.xsd"
-	project-version="1.1">
+	xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.cgen2"/>
 	<db-entity name="MYARTGROUP">
 		<db-attribute name="MY_GROUP_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-ant/src/test/resources/org/apache/cayenne/tools/cgen.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-ant/src/test/resources/org/apache/cayenne/tools/cgen.map.xml b/cayenne-ant/src/test/resources/org/apache/cayenne/tools/cgen.map.xml
index 1c378cf..8f6c005 100644
--- a/cayenne-ant/src/test/resources/org/apache/cayenne/tools/cgen.map.xml
+++ b/cayenne-ant/src/test/resources/org/apache/cayenne/tools/cgen.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/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">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 
 	<db-entity name="ARTGROUP">
 		<db-attribute name="GROUP_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-ant/src/test/resources/testmap.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-ant/src/test/resources/testmap.map.xml b/cayenne-ant/src/test/resources/testmap.map.xml
index 60b94a6..e426dda 100644
--- a/cayenne-ant/src/test/resources/testmap.map.xml
+++ b/cayenne-ant/src/test/resources/testmap.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/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">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.testmap"/>
 	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
 	<property name="clientSupported" value="true"/>
@@ -290,18 +290,9 @@
 		<obj-attribute name="artistName" type="java.lang.String" db-attribute-path="ARTIST_NAME"/>
 		<obj-attribute name="dateOfBirth" type="java.util.Date" db-attribute-path="DATE_OF_BIRTH"/>
 	</obj-entity>
-	<obj-entity name="ArtistCallbackTest" className="org.apache.cayenne.testdo.testmap.ArtistCallbackTest" dbEntityName="ARTIST_CT" exclude-superclass-listeners="true" exclude-default-listeners="true">
+	<obj-entity name="ArtistCallbackTest" className="org.apache.cayenne.testdo.testmap.ArtistCallbackTest" dbEntityName="ARTIST_CT">
 		<obj-attribute name="artistName" type="java.lang.String"/>
 		<obj-attribute name="dateOfBirth" type="java.util.Date"/>
-		<entity-listener class="org.apache.cayenne.testdo.testmap.EntityListenerObjEntity">
-			<post-add method-name="prePersistEntityListener"/>
-			<post-persist method-name="postPersistEntityListener"/>
-			<pre-update method-name="preUpdateEntityListener"/>
-			<post-update method-name="postUpdateEntityListener"/>
-			<pre-remove method-name="preRemoveEntityListener"/>
-			<post-remove method-name="postRemoveEntityListener"/>
-			<post-load method-name="postLoadEntityListener"/>
-		</entity-listener>
 		<post-add method-name="prePersistEntityObjEntity"/>
 		<post-persist method-name="postPersistEntityObjEntity"/>
 		<pre-update method-name="preUpdateEntityObjEntity"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-cache-invalidation/src/test/resources/cayenne-lifecycle.xml
----------------------------------------------------------------------
diff --git a/cayenne-cache-invalidation/src/test/resources/cayenne-lifecycle.xml b/cayenne-cache-invalidation/src/test/resources/cayenne-lifecycle.xml
index 5b9a83e..98ab346 100644
--- a/cayenne-cache-invalidation/src/test/resources/cayenne-lifecycle.xml
+++ b/cayenne-cache-invalidation/src/test/resources/cayenne-lifecycle.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain project-version="10">
 	<map name="lifecycle-map"/>
 
 	<node name="lifecycle-db"

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-cache-invalidation/src/test/resources/lifecycle-map.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-cache-invalidation/src/test/resources/lifecycle-map.map.xml b/cayenne-cache-invalidation/src/test/resources/lifecycle-map.map.xml
index 04e767e..5704316 100644
--- a/cayenne-cache-invalidation/src/test/resources/lifecycle-map.map.xml
+++ b/cayenne-cache-invalidation/src/test/resources/lifecycle-map.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.lifecycle.db"/>
 	<db-entity name="E1">
 		<db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-commitlog/src/test/resources/cayenne-lifecycle.xml
----------------------------------------------------------------------
diff --git a/cayenne-commitlog/src/test/resources/cayenne-lifecycle.xml b/cayenne-commitlog/src/test/resources/cayenne-lifecycle.xml
index 5b9a83e..4144737 100644
--- a/cayenne-commitlog/src/test/resources/cayenne-lifecycle.xml
+++ b/cayenne-commitlog/src/test/resources/cayenne-lifecycle.xml
@@ -1,11 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="lifecycle-map"/>
-
 	<node name="lifecycle-db"
 		 factory="org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory"
-		 schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy"
-		>
+		 schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy">
 		<map-ref name="lifecycle-map"/>
 		<data-source>
 			<driver value="org.hsqldb.jdbcDriver"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml b/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml
index 89905e7..db86a62 100644
--- a/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml
+++ b/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml
@@ -1,27 +1,8 @@
 <?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/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.commitlog.db"/>
 	<db-entity name="AUDITABLE1">
 		<db-attribute name="CHAR_PROPERTY1" type="VARCHAR" length="200"/>
@@ -99,14 +80,10 @@
 		<obj-attribute name="charProperty1" type="java.lang.String" db-attribute-path="CHAR_PROPERTY1"/>
 		<obj-attribute name="charProperty2" type="java.lang.String" db-attribute-path="CHAR_PROPERTY2"/>
 	</obj-entity>
-	<obj-entity name="E1" className="org.apache.cayenne.commitlog.db.E1" dbEntityName="E1">
-	</obj-entity>
-	<obj-entity name="E2" className="org.apache.cayenne.commitlog.db.E2" dbEntityName="E2">
-	</obj-entity>
-	<obj-entity name="E3" className="org.apache.cayenne.commitlog.db.E3" dbEntityName="E3">
-	</obj-entity>
-	<obj-entity name="E4" className="org.apache.cayenne.commitlog.db.E4" dbEntityName="E4">
-	</obj-entity>
+	<obj-entity name="E1" className="org.apache.cayenne.commitlog.db.E1" dbEntityName="E1"/>
+	<obj-entity name="E2" className="org.apache.cayenne.commitlog.db.E2" dbEntityName="E2"/>
+	<obj-entity name="E3" className="org.apache.cayenne.commitlog.db.E3" dbEntityName="E3"/>
+	<obj-entity name="E4" className="org.apache.cayenne.commitlog.db.E4" dbEntityName="E4"/>
 	<db-relationship name="children1" source="AUDITABLE1" target="AUDITABLE_CHILD1" toMany="true">
 		<db-attribute-pair source="ID" target="AUDITABLE1_ID"/>
 	</db-relationship>
@@ -116,22 +93,22 @@
 	<db-relationship name="auditable4s" source="AUDITABLE3" target="AUDITABLE4" toMany="true">
 		<db-attribute-pair source="ID" target="AUDITABLE3_ID"/>
 	</db-relationship>
-	<db-relationship name="auditable3" source="AUDITABLE4" target="AUDITABLE3" toMany="false">
+	<db-relationship name="auditable3" source="AUDITABLE4" target="AUDITABLE3">
 		<db-attribute-pair source="AUDITABLE3_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="parent" source="AUDITABLE_CHILD1" target="AUDITABLE1" toMany="false">
+	<db-relationship name="parent" source="AUDITABLE_CHILD1" target="AUDITABLE1">
 		<db-attribute-pair source="AUDITABLE1_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="parent" source="AUDITABLE_CHILD3" target="AUDITABLE2" toMany="false">
+	<db-relationship name="parent" source="AUDITABLE_CHILD3" target="AUDITABLE2">
 		<db-attribute-pair source="AUDITABLE2_ID" target="ID"/>
 	</db-relationship>
 	<db-relationship name="e34s" source="E3" target="E34" toDependentPK="true" toMany="true">
 		<db-attribute-pair source="ID" target="E3_ID"/>
 	</db-relationship>
-	<db-relationship name="e3" source="E34" target="E3" toMany="false">
+	<db-relationship name="e3" source="E34" target="E3">
 		<db-attribute-pair source="E3_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="e4" source="E34" target="E4" toMany="false">
+	<db-relationship name="e4" source="E34" target="E4">
 		<db-attribute-pair source="E4_ID" target="ID"/>
 	</db-relationship>
 	<db-relationship name="e34s" source="E4" target="E34" toDependentPK="true" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-crypto/src/test/resources/cayenne-crypto.xml
----------------------------------------------------------------------
diff --git a/cayenne-crypto/src/test/resources/cayenne-crypto.xml b/cayenne-crypto/src/test/resources/cayenne-crypto.xml
index bd98b69..1680c10 100644
--- a/cayenne-crypto/src/test/resources/cayenne-crypto.xml
+++ b/cayenne-crypto/src/test/resources/cayenne-crypto.xml
@@ -1,11 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="datamap"/>
-
 	<node name="datanode"
 		 factory="org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory"
-		 schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy"
-		>
+		 schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy">
 		<map-ref name="datamap"/>
 		<data-source>
 			<driver value="org.hsqldb.jdbcDriver"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-crypto/src/test/resources/datamap.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-crypto/src/test/resources/datamap.map.xml b/cayenne-crypto/src/test/resources/datamap.map.xml
index df8c422..fd572a8 100644
--- a/cayenne-crypto/src/test/resources/datamap.map.xml
+++ b/cayenne-crypto/src/test/resources/datamap.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.crypto.db"/>
 	<db-entity name="TABLE1">
 		<db-attribute name="CRYPTO_INT" type="BLOB"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/cayenne-relationship-optimisation.xml
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/cayenne-relationship-optimisation.xml b/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/cayenne-relationship-optimisation.xml
index d4fea49..166a67d 100644
--- a/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/cayenne-relationship-optimisation.xml
+++ b/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/cayenne-relationship-optimisation.xml
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="6">
+<domain project-version="10">
 	<map name="relationship-optimisation"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/relationship-optimisation.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/relationship-optimisation.map.xml b/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/relationship-optimisation.map.xml
index e68645f..280ec56 100644
--- a/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/relationship-optimisation.map.xml
+++ b/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/dbimport/relationship-optimisation.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/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">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<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"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/test_datamap.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/test_datamap.map.xml b/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/test_datamap.map.xml
index 507875f..1fc3742 100644
--- a/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/test_datamap.map.xml
+++ b/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/test_datamap.map.xml
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
 
     <property name="defaultPackage" value="org.example.cayenne.persistent"/>
     <property name="defaultClientPackage" value="tmp"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-java8/src/test/resources/cayenne-java8.xml
----------------------------------------------------------------------
diff --git a/cayenne-java8/src/test/resources/cayenne-java8.xml b/cayenne-java8/src/test/resources/cayenne-java8.xml
index 93f67fd..cd4a0c4 100644
--- a/cayenne-java8/src/test/resources/cayenne-java8.xml
+++ b/cayenne-java8/src/test/resources/cayenne-java8.xml
@@ -1,11 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="java8"/>
-
 	<node name="datanode"
 		 factory="org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory"
-		 schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy"
-		>
+		 schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy">
 		<map-ref name="java8"/>
 		<data-source>
 			<driver value="org.hsqldb.jdbcDriver"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-java8/src/test/resources/java8.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-java8/src/test/resources/java8.map.xml b/cayenne-java8/src/test/resources/java8.map.xml
index 734c915..42f6e86 100644
--- a/cayenne-java8/src/test/resources/java8.map.xml
+++ b/cayenne-java8/src/test/resources/java8.map.xml
@@ -1,17 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.java8.db"/>
-	<db-entity name="LOCAL_DATE_TEST">
-		<db-attribute name="Date" type="DATE"/>
-		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-	</db-entity>
 	<db-entity name="LOCAL_DATETIME_TEST">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="Timestamp" type="TIMESTAMP"/>
 	</db-entity>
+	<db-entity name="LOCAL_DATE_TEST">
+		<db-attribute name="Date" type="DATE"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
 	<db-entity name="LOCAL_TIME_TEST">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="Time" type="TIME"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-joda/src/test/resources/cayenne-joda.xml
----------------------------------------------------------------------
diff --git a/cayenne-joda/src/test/resources/cayenne-joda.xml b/cayenne-joda/src/test/resources/cayenne-joda.xml
index 68673f9..7474d44 100644
--- a/cayenne-joda/src/test/resources/cayenne-joda.xml
+++ b/cayenne-joda/src/test/resources/cayenne-joda.xml
@@ -1,11 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="joda"/>
-
 	<node name="datanode"
 		 factory="org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory"
-		 schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy"
-		>
+		 schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy">
 		<map-ref name="joda"/>
 		<data-source>
 			<driver value="org.hsqldb.jdbcDriver"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-joda/src/test/resources/joda.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-joda/src/test/resources/joda.map.xml b/cayenne-joda/src/test/resources/joda.map.xml
index b1021f8..9fd6c9b 100644
--- a/cayenne-joda/src/test/resources/joda.map.xml
+++ b/cayenne-joda/src/test/resources/joda.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.joda.db"/>
 	<db-entity name="DATE_TIME_TEST">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-lifecycle/src/test/resources/cayenne-lifecycle.xml
----------------------------------------------------------------------
diff --git a/cayenne-lifecycle/src/test/resources/cayenne-lifecycle.xml b/cayenne-lifecycle/src/test/resources/cayenne-lifecycle.xml
index 5b9a83e..4144737 100644
--- a/cayenne-lifecycle/src/test/resources/cayenne-lifecycle.xml
+++ b/cayenne-lifecycle/src/test/resources/cayenne-lifecycle.xml
@@ -1,11 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="lifecycle-map"/>
-
 	<node name="lifecycle-db"
 		 factory="org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory"
-		 schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy"
-		>
+		 schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy">
 		<map-ref name="lifecycle-map"/>
 		<data-source>
 			<driver value="org.hsqldb.jdbcDriver"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml b/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml
index 4a95313..d6763ab 100644
--- a/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml
+++ b/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.lifecycle.db"/>
 	<db-entity name="AUDITABLE1">
 		<db-attribute name="CHAR_PROPERTY1" type="VARCHAR" length="200"/>
@@ -84,18 +84,12 @@
 		<obj-attribute name="charProperty2" type="java.lang.String" db-attribute-path="CHAR_PROPERTY2"/>
 		<obj-attribute name="uuid" type="java.lang.String" db-attribute-path="UUID"/>
 	</obj-entity>
-	<obj-entity name="E1" className="org.apache.cayenne.lifecycle.db.E1" dbEntityName="E1">
-	</obj-entity>
-	<obj-entity name="E2" className="org.apache.cayenne.lifecycle.db.E2" dbEntityName="E2">
-	</obj-entity>
-	<obj-entity name="E3" className="org.apache.cayenne.lifecycle.db.E3" dbEntityName="E3">
-	</obj-entity>
-	<obj-entity name="E4" className="org.apache.cayenne.lifecycle.db.E4" dbEntityName="E4">
-	</obj-entity>
-	<obj-entity name="SortDep" className="org.apache.cayenne.lifecycle.db.SortDep" dbEntityName="SORT_DEP">
-	</obj-entity>
-	<obj-entity name="SortRoot" className="org.apache.cayenne.lifecycle.db.SortRoot" dbEntityName="SORT_ROOT">
-	</obj-entity>
+	<obj-entity name="E1" className="org.apache.cayenne.lifecycle.db.E1" dbEntityName="E1"/>
+	<obj-entity name="E2" className="org.apache.cayenne.lifecycle.db.E2" dbEntityName="E2"/>
+	<obj-entity name="E3" className="org.apache.cayenne.lifecycle.db.E3" dbEntityName="E3"/>
+	<obj-entity name="E4" className="org.apache.cayenne.lifecycle.db.E4" dbEntityName="E4"/>
+	<obj-entity name="SortDep" className="org.apache.cayenne.lifecycle.db.SortDep" dbEntityName="SORT_DEP"/>
+	<obj-entity name="SortRoot" className="org.apache.cayenne.lifecycle.db.SortRoot" dbEntityName="SORT_ROOT"/>
 	<obj-entity name="UuidRoot1" className="org.apache.cayenne.lifecycle.db.UuidRoot1" dbEntityName="UUID_ROOT1">
 		<obj-attribute name="uuid" type="java.lang.String" db-attribute-path="UUID"/>
 	</obj-entity>
@@ -108,28 +102,28 @@
 	<db-relationship name="children" source="AUDITABLE2" target="AUDITABLE_CHILD3" toMany="true">
 		<db-attribute-pair source="ID" target="AUDITABLE2_ID"/>
 	</db-relationship>
-	<db-relationship name="parent" source="AUDITABLE_CHILD1" target="AUDITABLE1" toMany="false">
+	<db-relationship name="parent" source="AUDITABLE_CHILD1" target="AUDITABLE1">
 		<db-attribute-pair source="AUDITABLE1_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="parent" source="AUDITABLE_CHILD2" target="AUDITABLE1" toMany="false">
+	<db-relationship name="parent" source="AUDITABLE_CHILD2" target="AUDITABLE1">
 		<db-attribute-pair source="AUDITABLE1_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="parent" source="AUDITABLE_CHILD3" target="AUDITABLE2" toMany="false">
+	<db-relationship name="parent" source="AUDITABLE_CHILD3" target="AUDITABLE2">
 		<db-attribute-pair source="AUDITABLE2_ID" target="ID"/>
 	</db-relationship>
 	<db-relationship name="e34s" source="E3" target="E34" toDependentPK="true" toMany="true">
 		<db-attribute-pair source="ID" target="E3_ID"/>
 	</db-relationship>
-	<db-relationship name="e3" source="E34" target="E3" toMany="false">
+	<db-relationship name="e3" source="E34" target="E3">
 		<db-attribute-pair source="E3_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="e4" source="E34" target="E4" toMany="false">
+	<db-relationship name="e4" source="E34" target="E4">
 		<db-attribute-pair source="E4_ID" target="ID"/>
 	</db-relationship>
 	<db-relationship name="e34s" source="E4" target="E34" toDependentPK="true" toMany="true">
 		<db-attribute-pair source="ID" target="E4_ID"/>
 	</db-relationship>
-	<db-relationship name="root" source="SORT_DEP" target="SORT_ROOT" toMany="false">
+	<db-relationship name="root" source="SORT_DEP" target="SORT_ROOT">
 		<db-attribute-pair source="ROOT_ID" target="ID"/>
 	</db-relationship>
 	<db-relationship name="deps" source="SORT_ROOT" target="SORT_DEP" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/persistent/auto/_ClientMtTable1.java
----------------------------------------------------------------------
diff --git a/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/persistent/auto/_ClientMtTable1.java b/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/persistent/auto/_ClientMtTable1.java
index f471aa6..e7178e0 100644
--- a/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/persistent/auto/_ClientMtTable1.java
+++ b/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/persistent/auto/_ClientMtTable1.java
@@ -41,15 +41,11 @@ public abstract class _ClientMtTable1 extends PersistentObject {
 
         return dateAttribute;
     }
+
     public void setDateAttribute(LocalDate dateAttribute) {
         if(objectContext != null) {
             objectContext.prepareForAccess(this, "dateAttribute", false);
-        }
-
-        Object oldValue = this.dateAttribute;
-        // notify objectContext about simple property change
-        if(objectContext != null) {
-            objectContext.propertyChanged(this, "dateAttribute", oldValue, dateAttribute);
+            objectContext.propertyChanged(this, "dateAttribute", this.dateAttribute, dateAttribute);
         }
         
         this.dateAttribute = dateAttribute;
@@ -62,15 +58,11 @@ public abstract class _ClientMtTable1 extends PersistentObject {
 
         return globalAttribute;
     }
+
     public void setGlobalAttribute(String globalAttribute) {
         if(objectContext != null) {
             objectContext.prepareForAccess(this, "globalAttribute", false);
-        }
-
-        Object oldValue = this.globalAttribute;
-        // notify objectContext about simple property change
-        if(objectContext != null) {
-            objectContext.propertyChanged(this, "globalAttribute", oldValue, globalAttribute);
+            objectContext.propertyChanged(this, "globalAttribute", this.globalAttribute, globalAttribute);
         }
         
         this.globalAttribute = globalAttribute;
@@ -83,15 +75,11 @@ public abstract class _ClientMtTable1 extends PersistentObject {
 
         return oldDateAttribute;
     }
+
     public void setOldDateAttribute(Date oldDateAttribute) {
         if(objectContext != null) {
             objectContext.prepareForAccess(this, "oldDateAttribute", false);
-        }
-
-        Object oldValue = this.oldDateAttribute;
-        // notify objectContext about simple property change
-        if(objectContext != null) {
-            objectContext.propertyChanged(this, "oldDateAttribute", oldValue, oldDateAttribute);
+            objectContext.propertyChanged(this, "oldDateAttribute", this.oldDateAttribute, oldDateAttribute);
         }
         
         this.oldDateAttribute = oldDateAttribute;
@@ -104,15 +92,11 @@ public abstract class _ClientMtTable1 extends PersistentObject {
 
         return serverAttribute;
     }
+
     public void setServerAttribute(String serverAttribute) {
         if(objectContext != null) {
             objectContext.prepareForAccess(this, "serverAttribute", false);
-        }
-
-        Object oldValue = this.serverAttribute;
-        // notify objectContext about simple property change
-        if(objectContext != null) {
-            objectContext.propertyChanged(this, "serverAttribute", oldValue, serverAttribute);
+            objectContext.propertyChanged(this, "serverAttribute", this.serverAttribute, serverAttribute);
         }
         
         this.serverAttribute = serverAttribute;
@@ -125,15 +109,11 @@ public abstract class _ClientMtTable1 extends PersistentObject {
 
         return timeAttribute;
     }
+
     public void setTimeAttribute(LocalTime timeAttribute) {
         if(objectContext != null) {
             objectContext.prepareForAccess(this, "timeAttribute", false);
-        }
-
-        Object oldValue = this.timeAttribute;
-        // notify objectContext about simple property change
-        if(objectContext != null) {
-            objectContext.propertyChanged(this, "timeAttribute", oldValue, timeAttribute);
+            objectContext.propertyChanged(this, "timeAttribute", this.timeAttribute, timeAttribute);
         }
         
         this.timeAttribute = timeAttribute;
@@ -146,15 +126,11 @@ public abstract class _ClientMtTable1 extends PersistentObject {
 
         return timestampAttribute;
     }
+
     public void setTimestampAttribute(LocalDateTime timestampAttribute) {
         if(objectContext != null) {
             objectContext.prepareForAccess(this, "timestampAttribute", false);
-        }
-
-        Object oldValue = this.timestampAttribute;
-        // notify objectContext about simple property change
-        if(objectContext != null) {
-            objectContext.propertyChanged(this, "timestampAttribute", oldValue, timestampAttribute);
+            objectContext.propertyChanged(this, "timestampAttribute", this.timestampAttribute, timestampAttribute);
         }
         
         this.timestampAttribute = timestampAttribute;
@@ -169,6 +145,7 @@ public abstract class _ClientMtTable1 extends PersistentObject {
 
         return table2Array;
     }
+
     public void addToTable2Array(ClientMtTable2 object) {
         if(objectContext != null) {
             objectContext.prepareForAccess(this, "table2Array", true);
@@ -178,6 +155,7 @@ public abstract class _ClientMtTable1 extends PersistentObject {
 
         this.table2Array.add(object);
     }
+
     public void removeFromTable2Array(ClientMtTable2 object) {
         if(objectContext != null) {
             objectContext.prepareForAccess(this, "table2Array", true);
@@ -187,5 +165,4 @@ public abstract class _ClientMtTable1 extends PersistentObject {
 
         this.table2Array.remove(object);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/persistent/auto/_ClientMtTable2.java
----------------------------------------------------------------------
diff --git a/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/persistent/auto/_ClientMtTable2.java b/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/persistent/auto/_ClientMtTable2.java
index 598fcdf..a6c8c37 100644
--- a/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/persistent/auto/_ClientMtTable2.java
+++ b/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/persistent/auto/_ClientMtTable2.java
@@ -14,7 +14,7 @@ import org.apache.cayenne.util.PersistentObjectHolder;
 public abstract class _ClientMtTable2 extends PersistentObject {
 
     public static final Property<String> GLOBAL_ATTRIBUTE = Property.create("globalAttribute", String.class);
-    public static final Property<org.apache.cayenne.rop.protostuff.persistent.MtTable1> TABLE1 = Property.create("table1", org.apache.cayenne.rop.protostuff.persistent.MtTable1.class);
+    public static final Property<ClientMtTable1> TABLE1 = Property.create("table1", ClientMtTable1.class);
 
     protected String globalAttribute;
     protected ValueHolder table1;
@@ -26,15 +26,11 @@ public abstract class _ClientMtTable2 extends PersistentObject {
 
         return globalAttribute;
     }
+
     public void setGlobalAttribute(String globalAttribute) {
         if(objectContext != null) {
             objectContext.prepareForAccess(this, "globalAttribute", false);
-        }
-
-        Object oldValue = this.globalAttribute;
-        // notify objectContext about simple property change
-        if(objectContext != null) {
-            objectContext.propertyChanged(this, "globalAttribute", oldValue, globalAttribute);
+            objectContext.propertyChanged(this, "globalAttribute", this.globalAttribute, globalAttribute);
         }
         
         this.globalAttribute = globalAttribute;
@@ -49,21 +45,15 @@ public abstract class _ClientMtTable2 extends PersistentObject {
 
         return (ClientMtTable1) table1.getValue();
     }
+
     public void setTable1(ClientMtTable1 table1) {
         if(objectContext != null) {
             objectContext.prepareForAccess(this, "table1", true);
+            objectContext.propertyChanged(this, "table1", this.table1.getValueDirectly(), table1);
         } else if (this.table1 == null) {
         	this.table1 = new PersistentObjectHolder(this, "table1");
 		}
-
-        // note how we notify ObjectContext of change BEFORE the object is actually
-        // changed... this is needed to take a valid current snapshot
-        Object oldValue = this.table1.getValueDirectly();
-        if (objectContext != null) {
-        	objectContext.propertyChanged(this, "table1", oldValue, table1);
-        }
         
         this.table1.setValue(table1);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-protostuff/src/test/resources/cayenne-protostuff.xml
----------------------------------------------------------------------
diff --git a/cayenne-protostuff/src/test/resources/cayenne-protostuff.xml b/cayenne-protostuff/src/test/resources/cayenne-protostuff.xml
index 08d85b1..c5fe84e 100644
--- a/cayenne-protostuff/src/test/resources/cayenne-protostuff.xml
+++ b/cayenne-protostuff/src/test/resources/cayenne-protostuff.xml
@@ -1,11 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="protostuff"/>
-
 	<node name="datanode"
-		  factory="org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory"
-		  schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy"
-	>
+		 factory="org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory"
+		 schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy">
 		<map-ref name="protostuff"/>
 		<data-source>
 			<driver value="org.hsqldb.jdbcDriver"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/cayenne-protostuff/src/test/resources/protostuff.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-protostuff/src/test/resources/protostuff.map.xml b/cayenne-protostuff/src/test/resources/protostuff.map.xml
index d3277bf..a421e26 100644
--- a/cayenne-protostuff/src/test/resources/protostuff.map.xml
+++ b/cayenne-protostuff/src/test/resources/protostuff.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.rop.protostuff.persistent"/>
 	<property name="clientSupported" value="true"/>
 	<property name="defaultClientPackage" value="org.apache.cayenne.rop.protostuff.persistent"/>
@@ -34,7 +34,7 @@
 	<db-relationship name="table2Array" source="MT_TABLE1" target="MT_TABLE2" toMany="true">
 		<db-attribute-pair source="TABLE1_ID" target="TABLE1_ID"/>
 	</db-relationship>
-	<db-relationship name="table1" source="MT_TABLE2" target="MT_TABLE1" toMany="false">
+	<db-relationship name="table1" source="MT_TABLE2" target="MT_TABLE1">
 		<db-attribute-pair source="TABLE1_ID" target="TABLE1_ID"/>
 	</db-relationship>
 	<obj-relationship name="table2Array" source="MtTable1" target="MtTable2" deleteRule="Deny" db-relationship-path="table2Array"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/itests/cayenne-tools-itest/src/test/resources/cayenne-client.xml
----------------------------------------------------------------------
diff --git a/itests/cayenne-tools-itest/src/test/resources/cayenne-client.xml b/itests/cayenne-tools-itest/src/test/resources/cayenne-client.xml
index 1e26e2a..355ac28 100644
--- a/itests/cayenne-tools-itest/src/test/resources/cayenne-client.xml
+++ b/itests/cayenne-tools-itest/src/test/resources/cayenne-client.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="6">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="testmap-client"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/itests/cayenne-tools-itest/src/test/resources/embeddable.map.xml
----------------------------------------------------------------------
diff --git a/itests/cayenne-tools-itest/src/test/resources/embeddable.map.xml b/itests/cayenne-tools-itest/src/test/resources/embeddable.map.xml
index 0b5c0b8..10c4db6 100644
--- a/itests/cayenne-tools-itest/src/test/resources/embeddable.map.xml
+++ b/itests/cayenne-tools-itest/src/test/resources/embeddable.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/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">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.embeddable"/>
 	<embeddable className="org.apache.cayenne.testdo.embeddable.Embeddable1">
 		<embeddable-attribute name="embedded10" type="java.lang.String" db-attribute-name="EMBEDDED10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/itests/cayenne-tools-itest/src/test/resources/org/apache/cayenne/tools/cgen-dependent.map.xml
----------------------------------------------------------------------
diff --git a/itests/cayenne-tools-itest/src/test/resources/org/apache/cayenne/tools/cgen-dependent.map.xml b/itests/cayenne-tools-itest/src/test/resources/org/apache/cayenne/tools/cgen-dependent.map.xml
index d06be70..b72f320 100644
--- a/itests/cayenne-tools-itest/src/test/resources/org/apache/cayenne/tools/cgen-dependent.map.xml
+++ b/itests/cayenne-tools-itest/src/test/resources/org/apache/cayenne/tools/cgen-dependent.map.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://cayenne.apache.org/schema/3.0/modelMap ../../main/resources/org/apache/cayenne/schema/3.0/modelMap.xsd"
+	xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
 	project-version="1.1">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.cgen2"/>
 	<db-entity name="MYARTGROUP">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/itests/cayenne-tools-itest/src/test/resources/org/apache/cayenne/tools/cgen.map.xml
----------------------------------------------------------------------
diff --git a/itests/cayenne-tools-itest/src/test/resources/org/apache/cayenne/tools/cgen.map.xml b/itests/cayenne-tools-itest/src/test/resources/org/apache/cayenne/tools/cgen.map.xml
index 1c378cf..56a2d92 100644
--- a/itests/cayenne-tools-itest/src/test/resources/org/apache/cayenne/tools/cgen.map.xml
+++ b/itests/cayenne-tools-itest/src/test/resources/org/apache/cayenne/tools/cgen.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/9/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">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
+	 project-version="9">
 
 	<db-entity name="ARTGROUP">
 		<db-attribute name="GROUP_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/itests/cayenne-tools-itest/src/test/resources/testmap-client.map.xml
----------------------------------------------------------------------
diff --git a/itests/cayenne-tools-itest/src/test/resources/testmap-client.map.xml b/itests/cayenne-tools-itest/src/test/resources/testmap-client.map.xml
index 21fadf7..87145d5 100644
--- a/itests/cayenne-tools-itest/src/test/resources/testmap-client.map.xml
+++ b/itests/cayenne-tools-itest/src/test/resources/testmap-client.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/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">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.testmap"/>
 	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
 	<property name="clientSupported" value="true"/>
@@ -19,8 +19,7 @@
 	<procedure name="cayenne_tst_upd_proc">
 		<procedure-parameter name="paintingPrice" type="INTEGER" direction="in"/>
 	</procedure>
-	<procedure name="cayenne_tst_upd_proc2">
-	</procedure>
+	<procedure name="cayenne_tst_upd_proc2"/>
 	<db-entity name="ARRAYS_ENTITY">
 		<db-attribute name="BYTE_ARRAY" type="VARBINARY" length="200"/>
 		<db-attribute name="BYTE_WRAPPER_ARRAY" type="VARBINARY" length="200"/>
@@ -290,18 +289,9 @@
 		<obj-attribute name="artistName" type="java.lang.String" db-attribute-path="ARTIST_NAME"/>
 		<obj-attribute name="dateOfBirth" type="java.util.Date" db-attribute-path="DATE_OF_BIRTH"/>
 	</obj-entity>
-	<obj-entity name="ArtistCallbackTest" className="org.apache.cayenne.testdo.testmap.ArtistCallbackTest" clientClassName="org.apache.cayenne.testdo.testmap.client.ArtistCallbackTest" dbEntityName="ARTIST_CT" exclude-superclass-listeners="true" exclude-default-listeners="true">
+	<obj-entity name="ArtistCallbackTest" className="org.apache.cayenne.testdo.testmap.ArtistCallbackTest" clientClassName="org.apache.cayenne.testdo.testmap.client.ArtistCallbackTest" dbEntityName="ARTIST_CT">
 		<obj-attribute name="artistName" type="java.lang.String"/>
 		<obj-attribute name="dateOfBirth" type="java.util.Date"/>
-		<entity-listener class="org.apache.cayenne.testdo.testmap.EntityListenerObjEntity">
-			<post-add method-name="prePersistEntityListener"/>
-			<post-persist method-name="postPersistEntityListener"/>
-			<pre-update method-name="preUpdateEntityListener"/>
-			<post-update method-name="postUpdateEntityListener"/>
-			<pre-remove method-name="preRemoveEntityListener"/>
-			<post-remove method-name="postRemoveEntityListener"/>
-			<post-load method-name="postLoadEntityListener"/>
-		</entity-listener>
 		<post-add method-name="prePersistEntityObjEntity"/>
 		<post-persist method-name="postPersistEntityObjEntity"/>
 		<pre-update method-name="preUpdateEntityObjEntity"/>
@@ -310,8 +300,7 @@
 		<post-remove method-name="postRemoveEntityObjEntity"/>
 		<post-load method-name="postLoadEntityObjEntity"/>
 	</obj-entity>
-	<obj-entity name="ArtistExhibit" className="org.apache.cayenne.testdo.testmap.ArtistExhibit" clientClassName="org.apache.cayenne.testdo.testmap.client.ArtistExhibit" dbEntityName="ARTIST_EXHIBIT">
-	</obj-entity>
+	<obj-entity name="ArtistExhibit" className="org.apache.cayenne.testdo.testmap.ArtistExhibit" clientClassName="org.apache.cayenne.testdo.testmap.client.ArtistExhibit" dbEntityName="ARTIST_EXHIBIT"/>
 	<obj-entity name="BigDecimalEntity" className="org.apache.cayenne.testdo.numeric_types.BigDecimalEntity" clientClassName="org.apache.cayenne.testdo.testmap.client.BigDecimalEntity" dbEntityName="BIGDECIMAL_ENTITY">
 		<obj-attribute name="bigDecimalField" type="java.math.BigDecimal" db-attribute-path="BIGDECIMAL_FIELD"/>
 	</obj-entity>
@@ -412,10 +401,8 @@
 	<obj-entity name="GeneratedColumnTestEntity" className="org.apache.cayenne.testdo.generated.GeneratedColumnTestEntity" clientClassName="org.apache.cayenne.testdo.testmap.client.GeneratedColumnTestEntity" dbEntityName="GENERATED_COLUMN_TEST">
 		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
 	</obj-entity>
-	<obj-entity name="GeneratedF1" className="org.apache.cayenne.testdo.generated.GeneratedF1" clientClassName="org.apache.cayenne.testdo.testmap.client.GeneratedF1" dbEntityName="GENERATED_F1" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
-	</obj-entity>
-	<obj-entity name="GeneratedF2" className="org.apache.cayenne.testdo.generated.GeneratedF2" clientClassName="org.apache.cayenne.testdo.testmap.client.GeneratedF2" dbEntityName="GENERATED_F2" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject">
-	</obj-entity>
+	<obj-entity name="GeneratedF1" className="org.apache.cayenne.testdo.generated.GeneratedF1" clientClassName="org.apache.cayenne.testdo.testmap.client.GeneratedF1" dbEntityName="GENERATED_F1" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject"/>
+	<obj-entity name="GeneratedF2" className="org.apache.cayenne.testdo.generated.GeneratedF2" clientClassName="org.apache.cayenne.testdo.testmap.client.GeneratedF2" dbEntityName="GENERATED_F2" superClassName="org.apache.cayenne.CayenneDataObject" clientSuperClassName="org.apache.cayenne.PersistentObject"/>
 	<obj-entity name="LongEntity" className="org.apache.cayenne.testdo.numeric_types.LongEntity" clientClassName="org.apache.cayenne.testdo.testmap.client.LongEntity" dbEntityName="LONG_ENTITY">
 		<obj-attribute name="longField" type="java.lang.Long" db-attribute-path="LONG_FIELD"/>
 	</obj-entity>
@@ -517,7 +504,7 @@
 	<db-relationship name="toChildGroups" source="ARTGROUP" target="ARTGROUP" toMany="true">
 		<db-attribute-pair source="GROUP_ID" target="PARENT_GROUP_ID"/>
 	</db-relationship>
-	<db-relationship name="toParentGroup" source="ARTGROUP" target="ARTGROUP" toMany="false">
+	<db-relationship name="toParentGroup" source="ARTGROUP" target="ARTGROUP">
 		<db-attribute-pair source="PARENT_GROUP_ID" target="GROUP_ID"/>
 	</db-relationship>
 	<db-relationship name="artistExhibitArray" source="ARTIST" target="ARTIST_EXHIBIT" toDependentPK="true" toMany="true">
@@ -529,25 +516,25 @@
 	<db-relationship name="paintingArray" source="ARTIST" target="PAINTING" toMany="true">
 		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
 	</db-relationship>
-	<db-relationship name="toArtist" source="ARTIST_EXHIBIT" target="ARTIST" toMany="false">
+	<db-relationship name="toArtist" source="ARTIST_EXHIBIT" target="ARTIST">
 		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
 	</db-relationship>
-	<db-relationship name="toExhibit" source="ARTIST_EXHIBIT" target="EXHIBIT" toMany="false">
+	<db-relationship name="toExhibit" source="ARTIST_EXHIBIT" target="EXHIBIT">
 		<db-attribute-pair source="EXHIBIT_ID" target="EXHIBIT_ID"/>
 	</db-relationship>
-	<db-relationship name="toArtist" source="ARTIST_GROUP" target="ARTIST" toMany="false">
+	<db-relationship name="toArtist" source="ARTIST_GROUP" target="ARTIST">
 		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
 	</db-relationship>
-	<db-relationship name="toGroup" source="ARTIST_GROUP" target="ARTGROUP" toMany="false">
+	<db-relationship name="toGroup" source="ARTIST_GROUP" target="ARTGROUP">
 		<db-attribute-pair source="GROUP_ID" target="GROUP_ID"/>
 	</db-relationship>
 	<db-relationship name="binaryPKDetails" source="BINARY_PK_TEST1" target="BINARY_PK_TEST2" toMany="true">
 		<db-attribute-pair source="BIN_ID" target="FK_ID"/>
 	</db-relationship>
-	<db-relationship name="toBinaryPKMaster" source="BINARY_PK_TEST2" target="BINARY_PK_TEST1" toMany="false">
+	<db-relationship name="toBinaryPKMaster" source="BINARY_PK_TEST2" target="BINARY_PK_TEST1">
 		<db-attribute-pair source="FK_ID" target="BIN_ID"/>
 	</db-relationship>
-	<db-relationship name="toCharPK" source="CHAR_FK_TEST" target="CHAR_PK_TEST" toMany="false">
+	<db-relationship name="toCharPK" source="CHAR_FK_TEST" target="CHAR_PK_TEST">
 		<db-attribute-pair source="FK_COL" target="PK_COL"/>
 	</db-relationship>
 	<db-relationship name="charFKs" source="CHAR_PK_TEST" target="CHAR_FK_TEST" toMany="true">
@@ -556,10 +543,10 @@
 	<db-relationship name="clob" source="CLOB_TEST" target="CLOB_TEST_RELATION" toMany="true">
 		<db-attribute-pair source="CLOB_TEST_ID" target="ID_CLOB"/>
 	</db-relationship>
-	<db-relationship name="CLOB_REL" source="CLOB_TEST_RELATION" target="CLOB_TEST" toMany="false">
+	<db-relationship name="CLOB_REL" source="CLOB_TEST_RELATION" target="CLOB_TEST">
 		<db-attribute-pair source="ID_CLOB" target="CLOB_TEST_ID"/>
 	</db-relationship>
-	<db-relationship name="toCompoundPk" source="COMPOUND_FK_TEST" target="COMPOUND_PK_TEST" toMany="false">
+	<db-relationship name="toCompoundPk" source="COMPOUND_FK_TEST" target="COMPOUND_PK_TEST">
 		<db-attribute-pair source="F_KEY1" target="KEY1"/>
 		<db-attribute-pair source="F_KEY2" target="KEY2"/>
 	</db-relationship>
@@ -570,7 +557,7 @@
 	<db-relationship name="artistExhibitArray" source="EXHIBIT" target="ARTIST_EXHIBIT" toDependentPK="true" toMany="true">
 		<db-attribute-pair source="EXHIBIT_ID" target="EXHIBIT_ID"/>
 	</db-relationship>
-	<db-relationship name="toGallery" source="EXHIBIT" target="GALLERY" toMany="false">
+	<db-relationship name="toGallery" source="EXHIBIT" target="GALLERY">
 		<db-attribute-pair source="GALLERY_ID" target="GALLERY_ID"/>
 	</db-relationship>
 	<db-relationship name="exhibitArray" source="GALLERY" target="EXHIBIT" toMany="true">
@@ -579,16 +566,16 @@
 	<db-relationship name="paintingArray" source="GALLERY" target="PAINTING" toMany="true">
 		<db-attribute-pair source="GALLERY_ID" target="GALLERY_ID"/>
 	</db-relationship>
-	<db-relationship name="toMaster" source="GENERATED_COLUMN_COMP_KEY" target="GENERATED_COLUMN_COMP_M" toMany="false">
+	<db-relationship name="toMaster" source="GENERATED_COLUMN_COMP_KEY" target="GENERATED_COLUMN_COMP_M">
 		<db-attribute-pair source="PROPAGATED_PK" target="ID"/>
 	</db-relationship>
 	<db-relationship name="toDetail" source="GENERATED_COLUMN_COMP_M" target="GENERATED_COLUMN_COMP_KEY" toDependentPK="true" toMany="true">
 		<db-attribute-pair source="ID" target="PROPAGATED_PK"/>
 	</db-relationship>
-	<db-relationship name="toMaster" source="GENERATED_COLUMN_DEP" target="GENERATED_COLUMN_TEST" toMany="false">
+	<db-relationship name="toMaster" source="GENERATED_COLUMN_DEP" target="GENERATED_COLUMN_TEST">
 		<db-attribute-pair source="GENERATED_COLUMN_FK" target="GENERATED_COLUMN"/>
 	</db-relationship>
-	<db-relationship name="toDep" source="GENERATED_COLUMN_TEST" target="GENERATED_COLUMN_DEP" toDependentPK="true" toMany="false">
+	<db-relationship name="toDep" source="GENERATED_COLUMN_TEST" target="GENERATED_COLUMN_DEP" toDependentPK="true">
 		<db-attribute-pair source="GENERATED_COLUMN" target="GENERATED_COLUMN_FK"/>
 	</db-relationship>
 	<db-relationship name="join" source="GENERATED_F1" target="GENERATED_JOIN" toMany="true">
@@ -597,13 +584,13 @@
 	<db-relationship name="join" source="GENERATED_F2" target="GENERATED_JOIN" toMany="true">
 		<db-attribute-pair source="ID" target="ID2"/>
 	</db-relationship>
-	<db-relationship name="f1" source="GENERATED_JOIN" target="GENERATED_F1" toMany="false">
+	<db-relationship name="f1" source="GENERATED_JOIN" target="GENERATED_F1">
 		<db-attribute-pair source="ID1" target="ID"/>
 	</db-relationship>
-	<db-relationship name="f2" source="GENERATED_JOIN" target="GENERATED_F2" toMany="false">
+	<db-relationship name="f2" source="GENERATED_JOIN" target="GENERATED_F2">
 		<db-attribute-pair source="ID2" target="ID"/>
 	</db-relationship>
-	<db-relationship name="toMeaningfulPK" source="MEANINGFUL_PK_DEP" target="MEANINGFUL_PK_TEST1" toMany="false">
+	<db-relationship name="toMeaningfulPK" source="MEANINGFUL_PK_DEP" target="MEANINGFUL_PK_TEST1">
 		<db-attribute-pair source="MASTER_PK" target="PK_ATTRIBUTE"/>
 	</db-relationship>
 	<db-relationship name="meaningfulPKDepArray" source="MEANINGFUL_PK_TEST1" target="MEANINGFUL_PK_DEP" toMany="true">
@@ -612,22 +599,22 @@
 	<db-relationship name="details" source="MIXED_PERSISTENCE_STRATEGY" target="MIXED_PERSISTENCE_STRATEGY2" toMany="true">
 		<db-attribute-pair source="ID" target="MASTER_ID"/>
 	</db-relationship>
-	<db-relationship name="master" source="MIXED_PERSISTENCE_STRATEGY2" target="MIXED_PERSISTENCE_STRATEGY" toMany="false">
+	<db-relationship name="master" source="MIXED_PERSISTENCE_STRATEGY2" target="MIXED_PERSISTENCE_STRATEGY">
 		<db-attribute-pair source="MASTER_ID" target="ID"/>
 	</db-relationship>
-	<db-relationship name="toArtist" source="PAINTING" target="ARTIST" toMany="false">
+	<db-relationship name="toArtist" source="PAINTING" target="ARTIST">
 		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
 	</db-relationship>
-	<db-relationship name="toGallery" source="PAINTING" target="GALLERY" toMany="false">
+	<db-relationship name="toGallery" source="PAINTING" target="GALLERY">
 		<db-attribute-pair source="GALLERY_ID" target="GALLERY_ID"/>
 	</db-relationship>
-	<db-relationship name="toPaintingInfo" source="PAINTING" target="PAINTING_INFO" toDependentPK="true" toMany="false">
+	<db-relationship name="toPaintingInfo" source="PAINTING" target="PAINTING_INFO" toDependentPK="true">
 		<db-attribute-pair source="PAINTING_ID" target="PAINTING_ID"/>
 	</db-relationship>
-	<db-relationship name="toArtist" source="PAINTING1" target="ARTIST" toMany="false">
+	<db-relationship name="toArtist" source="PAINTING1" target="ARTIST">
 		<db-attribute-pair source="ARTIST_ID" target="ARTIST_ID"/>
 	</db-relationship>
-	<db-relationship name="painting" source="PAINTING_INFO" target="PAINTING" toMany="false">
+	<db-relationship name="painting" source="PAINTING_INFO" target="PAINTING">
 		<db-attribute-pair source="PAINTING_ID" target="PAINTING_ID"/>
 	</db-relationship>
 	<obj-relationship name="artistArray" source="ArtGroup" target="Artist" deleteRule="Nullify" db-relationship-path="artistGroupArray.toArtist"/>
@@ -671,8 +658,8 @@
 	<obj-relationship name="paintingArray" source="ROArtist" target="Painting" deleteRule="Deny" db-relationship-path="paintingArray"/>
 	<obj-relationship name="toArtist" source="ROPainting" target="Artist" deleteRule="Nullify" db-relationship-path="toArtist"/>
 	<query name="EjbqlQueryTest" type="EJBQLQuery">
-		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<property name="cayenne.GenericSelectQuery.cacheStrategy" value="SHARED_CACHE"/>
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<ejbql><![CDATA[select a from Artist a]]></ejbql>
 	</query>
 	<query name="NonSelectingQuery" type="SQLTemplate" root="data-map" root-name="testmap-client">
@@ -698,8 +685,7 @@ VALUES (#bind($id), #bind($title), #bind($price))]]></sql>
 		<property name="cayenne.GenericSelectQuery.cacheStrategy" value="SHARED_CACHE"/>
 		<qualifier><![CDATA[artistName like $name]]></qualifier>
 	</query>
-	<query name="ProcedureQuery" type="ProcedureQuery" root="procedure" root-name="cayenne_tst_select_proc" result-entity="Artist">
-	</query>
+	<query name="ProcedureQuery" type="ProcedureQuery" root="procedure" root-name="cayenne_tst_select_proc" result-entity="Artist"/>
 	<query name="QueryWithLocalCache" type="SelectQuery" root="obj-entity" root-name="Artist">
 		<property name="cayenne.GenericSelectQuery.cacheStrategy" value="LOCAL_CACHE"/>
 	</query>
@@ -717,28 +703,28 @@ VALUES (#bind($id), #bind($title), #bind($price))]]></sql>
 		<property name="cayenne.GenericSelectQuery.cacheStrategy" value="SHARED_CACHE"/>
 	</query>
 	<query name="SelectDateTest" type="SQLTemplate" root="data-map" root-name="testmap-client">
-		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<sql><![CDATA[SELECT * FROM DATE_TEST]]></sql>
 	</query>
 	<query name="SelectReturnTypesMap1" type="SQLTemplate" root="data-map" root-name="testmap-client">
-		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<sql><![CDATA[SELECT * FROM TYPES_MAPPING_TEST1]]></sql>
 	</query>
 	<query name="SelectReturnTypesMap2" type="SQLTemplate" root="data-map" root-name="testmap-client">
-		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<sql><![CDATA[SELECT * FROM TYPES_MAPPING_TEST2]]></sql>
 	</query>
 	<query name="SelectTestLower" type="SQLTemplate" root="data-map" root-name="testmap-client">
-		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<property name="cayenne.SQLTemplate.columnNameCapitalization" value="LOWER"/>
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<sql><![CDATA[select * from ARTIST]]></sql>
 	</query>
 	<query name="SelectTestUpper" type="SQLTemplate" root="data-map" root-name="testmap-client">
-		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<property name="cayenne.SQLTemplate.columnNameCapitalization" value="UPPER"/>
+		<property name="cayenne.GenericSelectQuery.fetchingDataRows" value="true"/>
 		<sql><![CDATA[select * from ARTIST]]></sql>
 	</query>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/itests/cayenne-tools-itest/src/test/resources/testmap.map.xml
----------------------------------------------------------------------
diff --git a/itests/cayenne-tools-itest/src/test/resources/testmap.map.xml b/itests/cayenne-tools-itest/src/test/resources/testmap.map.xml
index 60b94a6..e426dda 100644
--- a/itests/cayenne-tools-itest/src/test/resources/testmap.map.xml
+++ b/itests/cayenne-tools-itest/src/test/resources/testmap.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/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">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.testmap"/>
 	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
 	<property name="clientSupported" value="true"/>
@@ -290,18 +290,9 @@
 		<obj-attribute name="artistName" type="java.lang.String" db-attribute-path="ARTIST_NAME"/>
 		<obj-attribute name="dateOfBirth" type="java.util.Date" db-attribute-path="DATE_OF_BIRTH"/>
 	</obj-entity>
-	<obj-entity name="ArtistCallbackTest" className="org.apache.cayenne.testdo.testmap.ArtistCallbackTest" dbEntityName="ARTIST_CT" exclude-superclass-listeners="true" exclude-default-listeners="true">
+	<obj-entity name="ArtistCallbackTest" className="org.apache.cayenne.testdo.testmap.ArtistCallbackTest" dbEntityName="ARTIST_CT">
 		<obj-attribute name="artistName" type="java.lang.String"/>
 		<obj-attribute name="dateOfBirth" type="java.util.Date"/>
-		<entity-listener class="org.apache.cayenne.testdo.testmap.EntityListenerObjEntity">
-			<post-add method-name="prePersistEntityListener"/>
-			<post-persist method-name="postPersistEntityListener"/>
-			<pre-update method-name="preUpdateEntityListener"/>
-			<post-update method-name="postUpdateEntityListener"/>
-			<pre-remove method-name="preRemoveEntityListener"/>
-			<post-remove method-name="postRemoveEntityListener"/>
-			<post-load method-name="postLoadEntityListener"/>
-		</entity-listener>
 		<post-add method-name="prePersistEntityObjEntity"/>
 		<post-persist method-name="postPersistEntityObjEntity"/>
 		<pre-update method-name="preUpdateEntityObjEntity"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/cayenne-testDomain.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/cayenne-testDomain.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/cayenne-testDomain.xml
index 3f63c14..6a82e48 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/cayenne-testDomain.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/cayenne-testDomain.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="6">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="testAdditionalMap"/>
 	<map name="testDomainMap"/>
-    <map name="testAdditionalMap"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/testAdditionalMap.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/testAdditionalMap.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/testAdditionalMap.map.xml
index f9a80fb..8d3fb13 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/testAdditionalMap.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/testAdditionalMap.map.xml
@@ -1,18 +1,18 @@
 <?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="pack"/>
-    <db-entity name="TestRelEntity">
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-        <db-attribute name="NAME" type="VARCHAR" length="200"/>
-    </db-entity>
-    <obj-entity name="TestRelEntity" className="pack.TestRelEntity" dbEntityName="TestRelEntity">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <db-relationship name="additionalRel" source="TestRelEntity" target="TestEntity" toMany="false">
-        <db-attribute-pair source="ID" target="TestRelEntity_ID"/>
-    </db-relationship>
-    <obj-relationship name="additionalRel" source="TestRelEntity" target="TestEntity" deleteRule="Nullify" db-relationship-path="additionalRel"/>
-</data-map>
\ No newline at end of file
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="pack"/>
+	<db-entity name="TestRelEntity">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="NAME" type="VARCHAR" length="200"/>
+	</db-entity>
+	<obj-entity name="TestRelEntity" className="pack.TestRelEntity" dbEntityName="TestRelEntity">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<db-relationship name="additionalRel" source="TestRelEntity" target="TestEntity">
+		<db-attribute-pair source="ID" target="TestRelEntity_ID"/>
+	</db-relationship>
+	<obj-relationship name="additionalRel" source="TestRelEntity" target="TestEntity" deleteRule="Nullify" db-relationship-path="additionalRel"/>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/testDomainMap.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/testDomainMap.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/testDomainMap.map.xml
index d0ff3f5..f9d7e31 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/testDomainMap.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/cgen/testDomainMap.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/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">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="pack"/>
 	<embeddable className="pack.Embeddable">
 		<embeddable-attribute name="embAttr" type="java.lang.String" db-attribute-name="EMB_ATTR"/>
@@ -25,7 +25,9 @@
 	</obj-entity>
 	<obj-entity name="TestEntity" className="pack.TestEntity" dbEntityName="TestEntity">
 		<embedded-attribute name="embeddedAtr" type="pack.Embeddable"/>
-		<obj-attribute name="testAttr" type="java.lang.String" db-attribute-path="testAttr"/>
+		<obj-attribute name="testAttr" type="java.lang.String" db-attribute-path="testAttr">
+			<info:property xmlns:info="http://cayenne.apache.org/schema/10/info" name="comment" value="comment for test attribute"/>
+		</obj-attribute>
 	</obj-entity>
 	<obj-entity name="TestExcludedEntity" className="pack.TestExcludedEntity" dbEntityName="TestExcludedEntity">
 		<obj-attribute name="name" type="java.lang.String" db-attribute-path="name"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testComplexChangeOrder.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testComplexChangeOrder.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testComplexChangeOrder.map.xml
index 20ccc69..e4cac0a 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testComplexChangeOrder.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testComplexChangeOrder.map.xml
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
 
 
@@ -50,7 +50,7 @@
     </obj-entity>
 
 
-    <db-relationship name="parent" source="CHILD" target="PARENT" toMany="false">
+    <db-relationship name="parent" source="CHILD" target="PARENT">
         <db-attribute-pair source="parent_id" target="id"/>
     </db-relationship>
     <db-relationship name="children" source="PARENT" target="CHILD" toMany="true">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testComplexChangeOrder.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testComplexChangeOrder.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testComplexChangeOrder.map.xml-result
index d68faf1..79cb6de 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testComplexChangeOrder.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testComplexChangeOrder.map.xml-result
@@ -17,10 +17,10 @@
   ~  specific language governing permissions and limitations
   ~  under the License.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
 
     <db-entity name="ADDRESS" schema="SCHEMA_01">
@@ -44,7 +44,7 @@
     <db-relationship name="children" source="ADDRESS" target="CHILD" toMany="true">
         <db-attribute-pair source="id" target="ADDRESS_ID"/>
     </db-relationship>
-    <db-relationship name="address" source="CHILD" target="ADDRESS" toMany="false">
+    <db-relationship name="address" source="CHILD" target="ADDRESS">
         <db-attribute-pair source="ADDRESS_ID" target="id"/>
     </db-relationship>
     <obj-relationship name="children" source="Address" target="Child" deleteRule="Deny" db-relationship-path="children"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testCustomObjectLayerSettings.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testCustomObjectLayerSettings.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testCustomObjectLayerSettings.map.xml
index acbc62c..dc8b01e 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testCustomObjectLayerSettings.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testCustomObjectLayerSettings.map.xml
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
     <db-entity name="EXISTING_TABLE" schema="SCHEMA_01">
         <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testCustomObjectLayerSettings.map.xml-result
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testCustomObjectLayerSettings.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testCustomObjectLayerSettings.map.xml-result
index 9f36c0f..882922d 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testCustomObjectLayerSettings.map.xml-result
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testCustomObjectLayerSettings.map.xml-result
@@ -17,10 +17,10 @@
 	specific language governing permissions and limitations
 	under the License.
 -->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
     <property name="defaultSchema" value="SCHEMA_01"/>
     <db-entity name="EXISTING_TABLE" schema="SCHEMA_01">
     	<db-attribute name="COL2" type="INTEGER" length="10"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aab05f3c/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDbAttributeChange.map.xml
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDbAttributeChange.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDbAttributeChange.map.xml
index 759090a..48ddac1 100644
--- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDbAttributeChange.map.xml
+++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testDbAttributeChange.map.xml
@@ -17,10 +17,10 @@
   ~  specific language governing permissions and limitations
   ~  under the License.
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
+          xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+          project-version="10">
 
     <db-entity name="parent" schema="SCHEMA_01">
         <db-attribute name="COL2" type="CHAR" length="25"/>
@@ -50,7 +50,7 @@
         <obj-attribute name="col5" type="java.util.Date" db-attribute-path="COL5"/>
     </obj-entity>
 
-    <db-relationship name="parent" source="CHILD" target="parent" toMany="false">
+    <db-relationship name="parent" source="CHILD" target="parent">
         <db-attribute-pair source="parent_id" target="ID"/>
     </db-relationship>
     <db-relationship name="children" source="parent" target="CHILD" toMany="true">

[15/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - new XML loader for DataMap

Posted by nt...@apache.org.
CAY-2335: New XML loading/saving mechanics with support of plugable handlers
  - new XML loader for DataMap


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

Branch: refs/heads/master
Commit: 70ca3567cf6c53536e9f7b3a9f795964058b2c29
Parents: aab05f3
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Jul 25 12:59:45 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Jul 25 12:59:45 2017 +0300

----------------------------------------------------------------------
 .../cayenne/tools/CayenneGeneratorTask.java     |  8 +++++-
 .../org/apache/cayenne/tools/CayenneTask.java   | 11 ++++----
 .../apache/cayenne/tools/DbGeneratorTask.java   |  2 +-
 .../tools/CayenneGeneratorMapLoaderAction.java  | 26 ++++++++++++------
 .../cayenne/gen/ClassGenerationActionTest.java  |  7 +++--
 .../reverse/configuration/ToolsModule.java      | 12 +++++++-
 .../java/org/apache/cayenne/tools/CgenTask.java |  9 +++++-
 .../apache/cayenne/tools/DbGenerateTask.java    | 13 +++++----
 .../cayenne/tools/CayenneGeneratorMojo.java     | 12 +++++++-
 .../apache/cayenne/tools/DbGeneratorMojo.java   | 11 ++++----
 .../cayenne/wocompat/EOModelProcessorTest.java  | 29 ++++++++------------
 11 files changed, 90 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/70ca3567/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
----------------------------------------------------------------------
diff --git a/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java b/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
index d57b350..d468cc9 100644
--- a/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
+++ b/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
@@ -20,6 +20,9 @@ package org.apache.cayenne.tools;
 
 import foundrylogic.vpp.VPPConfig;
 import org.apache.cayenne.dbsync.filter.NamePatternMatcher;
+import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.gen.ArtifactsGenerationMode;
 import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.gen.ClientClassGenerationAction;
@@ -27,6 +30,7 @@ import org.apache.cayenne.map.DataMap;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.types.Path;
 import org.apache.velocity.VelocityContext;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 
@@ -102,8 +106,10 @@ public class CayenneGeneratorTask extends CayenneTask {
     public void execute() throws BuildException {
         validateAttributes();
 
+        Injector injector = DIBootstrap.createInjector(new ToolsModule(LoggerFactory.getLogger(CayenneGeneratorTask.class)));
+
         AntLogger logger = new AntLogger(this);
-        CayenneGeneratorMapLoaderAction loadAction = new CayenneGeneratorMapLoaderAction();
+        CayenneGeneratorMapLoaderAction loadAction = new CayenneGeneratorMapLoaderAction(injector);
 
         loadAction.setMainDataMapFile(map);
         loadAction.setAdditionalDataMapFiles(additionalMaps);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/70ca3567/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneTask.java
----------------------------------------------------------------------
diff --git a/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneTask.java b/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneTask.java
index 2bff0e3..33efff4 100644
--- a/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneTask.java
+++ b/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneTask.java
@@ -20,19 +20,20 @@
 package org.apache.cayenne.tools;
 
 import java.io.File;
+import java.net.URL;
 
 import javax.sql.DataSource;
 
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.server.DbAdapterFactory;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.MapLoader;
+import org.apache.cayenne.resource.URLResource;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
-import org.xml.sax.InputSource;
 
 /**
  * Base task for all Cayenne ant tasks, providing support for common
@@ -142,9 +143,9 @@ public abstract class CayenneTask extends Task {
     }
 
     /** Loads and returns DataMap based on <code>map</code> attribute. */
-    protected DataMap loadDataMap() throws Exception {
-        InputSource in = new InputSource(map.getCanonicalPath());
-        return new MapLoader().loadDataMap(in);
+    protected DataMap loadDataMap(Injector injector) throws Exception {
+        DataMapLoader loader = injector.getInstance(DataMapLoader.class);
+        return loader.load(new URLResource(new URL(map.getCanonicalPath())));
     }
 
     protected DbAdapter getAdapter(Injector injector, DataSource dataSource)

http://git-wip-us.apache.org/repos/asf/cayenne/blob/70ca3567/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java
----------------------------------------------------------------------
diff --git a/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java b/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java
index 0e537f7..e781f6f 100644
--- a/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java
+++ b/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java
@@ -75,7 +75,7 @@ public class DbGeneratorTask extends CayenneTask {
 			Thread.currentThread().setContextClassLoader(DbGeneratorTask.class.getClassLoader());
 
 			// Load the data map and run the db generator.
-			DataMap dataMap = loadDataMap();
+			DataMap dataMap = loadDataMap(injector);
 
 			// load driver taking custom CLASSPATH into account...
 			DriverDataSource dataSource = new DriverDataSource((Driver) Class.forName(driver).newInstance(), url,

http://git-wip-us.apache.org/repos/asf/cayenne/blob/70ca3567/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMapLoaderAction.java
----------------------------------------------------------------------
diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMapLoaderAction.java b/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMapLoaderAction.java
index 1a0a098..0e98e77 100644
--- a/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMapLoaderAction.java
+++ b/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMapLoaderAction.java
@@ -21,10 +21,11 @@ package org.apache.cayenne.tools;
 import java.io.File;
 import java.net.MalformedURLException;
 
+import org.apache.cayenne.configuration.DataMapLoader;
+import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.MapLoader;
-import org.xml.sax.InputSource;
+import org.apache.cayenne.resource.URLResource;
 
 /**
  * Loads a DataMap and a shared entity namespace.
@@ -37,11 +38,17 @@ class CayenneGeneratorMapLoaderAction {
     private File[] additionalDataMapFiles;
     private DataMap mainDataMap;
 
+    private transient Injector injector;
+
+    CayenneGeneratorMapLoaderAction(Injector injector) {
+        this.injector = injector;
+    }
+
     DataMap getMainDataMap() throws MalformedURLException {
         if (mainDataMap == null) {
-            MapLoader mapLoader = new MapLoader();
+            DataMapLoader loader = createLoader();
 
-            DataMap mainDataMap = loadDataMap(mapLoader, mainDataMapFile);
+            DataMap mainDataMap = loadDataMap(loader, mainDataMapFile);
 
             if (additionalDataMapFiles != null) {
 
@@ -51,7 +58,7 @@ class CayenneGeneratorMapLoaderAction {
 
                 for (File additionalDataMapFile : additionalDataMapFiles) {
 
-                    DataMap dataMap = loadDataMap(mapLoader, additionalDataMapFile);
+                    DataMap dataMap = loadDataMap(loader, additionalDataMapFile);
                     entityResolver.addDataMap(dataMap);
                     dataMap.setNamespace(entityResolver);
                 }
@@ -63,9 +70,12 @@ class CayenneGeneratorMapLoaderAction {
         return mainDataMap;
     }
 
-    protected DataMap loadDataMap(MapLoader mapLoader, File dataMapFile) throws MalformedURLException {
-        InputSource in = new InputSource(dataMapFile.toURI().toURL().toString());
-        return mapLoader.loadDataMap(in);
+    DataMapLoader createLoader() {
+        return injector.getInstance(DataMapLoader.class);
+    }
+
+    protected DataMap loadDataMap(DataMapLoader mapLoader, File dataMapFile) throws MalformedURLException {
+        return mapLoader.load(new URLResource(dataMapFile.toURI().toURL()));
     }
 
     void setMainDataMapFile(File mainDataMapFile) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/70ca3567/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java
----------------------------------------------------------------------
diff --git a/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java b/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java
index c6e1885..2f911e4 100644
--- a/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java
+++ b/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java
@@ -46,8 +46,8 @@ public class ClassGenerationActionTest {
 
 	@Before
 	public void setUp() throws Exception {
-		this.writers = new ArrayList<StringWriter>(3);
-		this.action = new ClassGenerationAction() {
+		writers = new ArrayList<>(3);
+		action = new ClassGenerationAction() {
 
 			@Override
 			protected Writer openWriter(TemplateType templateType) throws Exception {
@@ -56,6 +56,7 @@ public class ClassGenerationActionTest {
 				return writer;
 			}
 		};
+
 	}
 
 	@After
@@ -247,7 +248,7 @@ public class ClassGenerationActionTest {
 
 		action.execute(artifact);
 
-		List<String> strings = new ArrayList<String>(writers.size());
+		List<String> strings = new ArrayList<>(writers.size());
 		for (StringWriter writer : writers) {
 			strings.add(writer.toString());
 		}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/70ca3567/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
index 0c8cb2c..dc057dc 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -24,12 +24,17 @@ import org.apache.cayenne.access.translator.batch.DefaultBatchTranslatorFactory;
 import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
 import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
 import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DefaultRuntimeProperties;
 import org.apache.cayenne.configuration.RuntimeProperties;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
 import org.apache.cayenne.configuration.server.DbAdapterFactory;
 import org.apache.cayenne.configuration.server.DefaultDbAdapterFactory;
 import org.apache.cayenne.configuration.server.ServerModule;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultDataChannelMetaData;
+import org.apache.cayenne.configuration.xml.HandlerFactory;
+import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
 import org.apache.cayenne.dba.db2.DB2Sniffer;
 import org.apache.cayenne.dba.derby.DerbySniffer;
 import org.apache.cayenne.dba.firebird.FirebirdSniffer;
@@ -53,6 +58,7 @@ import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
 import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
 import org.apache.cayenne.log.Slf4jJdbcEventLogger;
 import org.apache.cayenne.log.JdbcEventLogger;
+import org.apache.cayenne.project.extension.ExtensionAwareHandlerFactory;
 import org.apache.cayenne.resource.ClassLoaderResourceLocator;
 import org.apache.cayenne.resource.ResourceLocator;
 import org.slf4j.Logger;
@@ -82,11 +88,11 @@ public class ToolsModule implements Module {
 
         // configure empty global stack properties
         ServerModule.contributeProperties(binder);
-
         ServerModule.contributeDefaultTypes(binder);
         ServerModule.contributeUserTypes(binder);
         ServerModule.contributeTypeFactories(binder);
         ServerModule.contributeValueObjectTypes(binder);
+
         binder.bind(ValueObjectTypeRegistry.class).to(DefaultValueObjectTypeRegistry.class);
 
         binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
@@ -106,6 +112,10 @@ public class ToolsModule implements Module {
 
         binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
         binder.bind(DataSourceFactory.class).to(DriverDataSourceFactory.class);
+
+        binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
+        binder.bind(HandlerFactory.class).to(ExtensionAwareHandlerFactory.class);
+        binder.bind(DataChannelMetaData.class).to(DefaultDataChannelMetaData.class);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/70ca3567/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/CgenTask.java
----------------------------------------------------------------------
diff --git a/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/CgenTask.java b/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/CgenTask.java
index 6b4f4c4..ee39a1c 100644
--- a/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/CgenTask.java
+++ b/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/CgenTask.java
@@ -25,6 +25,9 @@ import java.util.Set;
 
 import groovy.lang.Reference;
 import org.apache.cayenne.dbsync.filter.NamePatternMatcher;
+import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.gen.ClientClassGenerationAction;
 import org.apache.cayenne.map.DataMap;
@@ -39,6 +42,7 @@ import org.gradle.api.tasks.Optional;
 import org.gradle.api.tasks.OutputDirectory;
 import org.gradle.api.tasks.SourceSetContainer;
 import org.gradle.api.tasks.TaskAction;
+import org.slf4j.LoggerFactory;
 
 /**
  * @since 4.0
@@ -109,7 +113,10 @@ public class CgenTask extends BaseCayenneTask {
     @TaskAction
     public void generate() {
         File dataMapFile = getDataMapFile();
-        CayenneGeneratorMapLoaderAction loaderAction = new CayenneGeneratorMapLoaderAction();
+
+        Injector injector = DIBootstrap.createInjector(new ToolsModule(LoggerFactory.getLogger(CgenTask.class)));
+
+        CayenneGeneratorMapLoaderAction loaderAction = new CayenneGeneratorMapLoaderAction(injector);
         loaderAction.setMainDataMapFile(dataMapFile);
 
         CayenneGeneratorEntityFilterAction filterAction = new CayenneGeneratorEntityFilterAction();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/70ca3567/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbGenerateTask.java
----------------------------------------------------------------------
diff --git a/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbGenerateTask.java b/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbGenerateTask.java
index 4e5ec39..c562654 100644
--- a/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbGenerateTask.java
+++ b/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbGenerateTask.java
@@ -21,6 +21,7 @@ package org.apache.cayenne.tools;
 
 import groovy.lang.Closure;
 import org.apache.cayenne.access.DbGenerator;
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.datasource.DataSourceBuilder;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.JdbcAdapter;
@@ -31,7 +32,7 @@ import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.log.NoopJdbcEventLogger;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.MapLoader;
+import org.apache.cayenne.resource.URLResource;
 import org.apache.cayenne.tools.model.DataSourceConfig;
 import org.apache.cayenne.util.Util;
 import org.gradle.api.GradleException;
@@ -40,7 +41,6 @@ import org.gradle.api.tasks.InputFile;
 import org.gradle.api.tasks.Internal;
 import org.gradle.api.tasks.Optional;
 import org.gradle.api.tasks.TaskAction;
-import org.xml.sax.InputSource;
 
 import java.io.File;
 import javax.sql.DataSource;
@@ -94,8 +94,10 @@ public class DbGenerateTask extends BaseCayenneTask {
                         "[dropTables: {}, dropPK: {}, createTables: {}, createPK: {}, createFK: {}]",
                 dropTables, dropPK, createTables, createPK, createFK);
 
+        Injector injector = DIBootstrap.createInjector(new DbSyncModule(), new ToolsModule(getLogger()));
+
         try {
-            DbGenerator generator = createGenerator(loadDataMap());
+            DbGenerator generator = createGenerator(loadDataMap(injector));
             generator.runGenerator(createDataSource());
         } catch (Exception ex) {
             Throwable th = Util.unwindException(ex);
@@ -136,10 +138,9 @@ public class DbGenerateTask extends BaseCayenneTask {
                 .build();
     }
 
-    DataMap loadDataMap() throws Exception {
+    DataMap loadDataMap(Injector injector) throws Exception {
         File dataMapFile = getDataMapFile();
-        InputSource inputSource = new InputSource(dataMapFile.getCanonicalPath());
-        return new MapLoader().loadDataMap(inputSource);
+        return injector.getInstance(DataMapLoader.class).load(new URLResource(dataMapFile.toURI().toURL()));
     }
 
     // setters and getters that will be used by .gradle scripts

http://git-wip-us.apache.org/repos/asf/cayenne/blob/70ca3567/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java b/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
index 3736cef..6af8b0a 100644
--- a/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
+++ b/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
@@ -20,6 +20,9 @@
 package org.apache.cayenne.tools;
 
 import org.apache.cayenne.dbsync.filter.NamePatternMatcher;
+import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.gen.ClientClassGenerationAction;
 import org.apache.cayenne.map.DataMap;
@@ -30,6 +33,7 @@ import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.io.FilenameFilter;
@@ -181,6 +185,8 @@ public class CayenneGeneratorMojo extends AbstractMojo {
     @Parameter(defaultValue = "false")
     private boolean createPropertyNames;
 
+    private transient Injector injector;
+
 	public void execute() throws MojoExecutionException, MojoFailureException {
 		// Create the destination directory if necessary.
 		// TODO: (KJM 11/2/06) The destDir really should be added as a
@@ -189,8 +195,10 @@ public class CayenneGeneratorMojo extends AbstractMojo {
 			destDir.mkdirs();
 		}
 
+		injector = DIBootstrap.createInjector(new ToolsModule(LoggerFactory.getLogger(CayenneGeneratorMojo.class)));
+
 		Logger logger = new MavenLogger(this);
-		CayenneGeneratorMapLoaderAction loaderAction = new CayenneGeneratorMapLoaderAction();
+		CayenneGeneratorMapLoaderAction loaderAction = new CayenneGeneratorMapLoaderAction(injector);
 		loaderAction.setMainDataMapFile(map);
 
 		CayenneGeneratorEntityFilterAction filterAction = new CayenneGeneratorEntityFilterAction();
@@ -256,6 +264,8 @@ public class CayenneGeneratorMojo extends AbstractMojo {
 			action = new ClassGenerationAction();
 		}
 
+		injector.injectMembers(action);
+
 		action.setDestDir(destDir);
 		action.setEncoding(encoding);
 		action.setMakePairs(makePairs);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/70ca3567/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java
----------------------------------------------------------------------
diff --git a/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java b/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java
index 131f3de..cd47dc3 100644
--- a/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java
+++ b/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java
@@ -20,6 +20,7 @@
 package org.apache.cayenne.tools;
 
 import org.apache.cayenne.access.DbGenerator;
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.datasource.DriverDataSource;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.JdbcAdapter;
@@ -29,8 +30,8 @@ import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.log.NoopJdbcEventLogger;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
+import org.apache.cayenne.resource.URLResource;
 import org.apache.cayenne.util.Util;
 import org.slf4j.Logger;
 import org.apache.maven.plugin.AbstractMojo;
@@ -39,7 +40,6 @@ import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
-import org.xml.sax.InputSource;
 
 import java.io.File;
 import java.sql.Driver;
@@ -140,7 +140,7 @@ public class DbGeneratorMojo extends AbstractMojo {
                     objectFactory.newInstance(DbAdapter.class, adapter);
 
             // Load the data map and run the db generator.
-            DataMap dataMap = loadDataMap();
+            DataMap dataMap = loadDataMap(injector);
             DbGenerator generator = new DbGenerator(adapterInst, dataMap, NoopJdbcEventLogger.getInstance());
             generator.setShouldCreateFKConstraints(createFK);
             generator.setShouldCreatePKSupport(createPK);
@@ -165,9 +165,8 @@ public class DbGeneratorMojo extends AbstractMojo {
     }
 
     /** Loads and returns DataMap based on <code>map</code> attribute. */
-    private DataMap loadDataMap() throws Exception {
-        InputSource in = new InputSource(map.getCanonicalPath());
-        return new MapLoader().loadDataMap(in);
+    private DataMap loadDataMap(Injector injector) throws Exception {
+        return injector.getInstance(DataMapLoader.class).load(new URLResource(map.toURI().toURL()));
     }
 
     @Deprecated

http://git-wip-us.apache.org/repos/asf/cayenne/blob/70ca3567/modeler/cayenne-wocompat/src/test/java/org/apache/cayenne/wocompat/EOModelProcessorTest.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-wocompat/src/test/java/org/apache/cayenne/wocompat/EOModelProcessorTest.java b/modeler/cayenne-wocompat/src/test/java/org/apache/cayenne/wocompat/EOModelProcessorTest.java
index 4010a9b..e1faf72 100644
--- a/modeler/cayenne-wocompat/src/test/java/org/apache/cayenne/wocompat/EOModelProcessorTest.java
+++ b/modeler/cayenne-wocompat/src/test/java/org/apache/cayenne/wocompat/EOModelProcessorTest.java
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne.wocompat;
 
+import org.apache.cayenne.configuration.EmptyConfigurationNodeVisitor;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
@@ -65,8 +66,7 @@ public class EOModelProcessorTest {
 
     @Test
     public void testLoadModelWithDependencies() throws Exception {
-        URL url = getClass().getClassLoader().getResource(
-                "wotests/cross-model-relationships.eomodeld/");
+        URL url = getClass().getClassLoader().getResource("wotests/cross-model-relationships.eomodeld/");
         assertNotNull(url);
 
         DataMap map = processor.loadEOModel(url);
@@ -74,7 +74,7 @@ public class EOModelProcessorTest {
         ObjEntity entity = map.getObjEntity("CrossModelRelTest");
         assertNotNull(entity);
 
-        ObjAttribute a1 = (ObjAttribute) entity.getAttribute("testAttribute");
+        ObjAttribute a1 = entity.getAttribute("testAttribute");
         assertNotNull(a1);
 
         DbAttribute da1 = a1.getDbAttribute();
@@ -115,11 +115,8 @@ public class EOModelProcessorTest {
         // - Db loaded as two-way, obj - as one-way
 
         ObjEntity exhibitEntity = map.getObjEntity("Exhibit");
-        ObjRelationship toTypeObject = (ObjRelationship) exhibitEntity
-                .getRelationship("toExhibitType");
-        DbRelationship toTypeDB = (DbRelationship) exhibitEntity
-                .getDbEntity()
-                .getRelationship("toExhibitType");
+        ObjRelationship toTypeObject = exhibitEntity.getRelationship("toExhibitType");
+        DbRelationship toTypeDB = exhibitEntity.getDbEntity().getRelationship("toExhibitType");
         assertNotNull(toTypeObject);
         assertNotNull(toTypeDB);
         assertNull(toTypeObject.getReverseRelationship());
@@ -144,11 +141,11 @@ public class EOModelProcessorTest {
         ObjEntity customTypes = map.getObjEntity("CustomTypes");
         assertNotNull(customTypes);
 
-        ObjAttribute pk = (ObjAttribute) customTypes.getAttribute("pk");
+        ObjAttribute pk = customTypes.getAttribute("pk");
         assertNotNull(pk);
         assertEquals("CustomType1", pk.getType());
 
-        ObjAttribute other = (ObjAttribute) customTypes.getAttribute("other");
+        ObjAttribute other = customTypes.getAttribute("other");
         assertNotNull(other);
         assertEquals("CustomType2", other.getType());
     }
@@ -168,7 +165,7 @@ public class EOModelProcessorTest {
         assertSame(artistDE, artistDE1);
 
         // check attributes
-        ObjAttribute a1 = (ObjAttribute) artistE.getAttribute("artistName");
+        ObjAttribute a1 = artistE.getAttribute("artistName");
         assertNotNull(a1);
 
         DbAttribute da1 = a1.getDbAttribute();
@@ -176,25 +173,23 @@ public class EOModelProcessorTest {
         assertSame(da1, artistDE.getAttribute("ARTIST_NAME"));
 
         // check ObjRelationships
-        ObjRelationship rel = (ObjRelationship) artistE
-                .getRelationship("artistExhibitArray");
+        ObjRelationship rel = artistE.getRelationship("artistExhibitArray");
         assertNotNull(rel);
         assertEquals(1, rel.getDbRelationships().size());
 
         // check DbRelationships
-        DbRelationship drel = (DbRelationship) artistDE
-                .getRelationship("artistExhibitArray");
+        DbRelationship drel = artistDE.getRelationship("artistExhibitArray");
         assertNotNull(drel);
         assertSame(drel, rel.getDbRelationships().get(0));
 
         // flattened relationships
-        ObjRelationship frel = (ObjRelationship) artistE.getRelationship("exhibitArray");
+        ObjRelationship frel = artistE.getRelationship("exhibitArray");
         assertNotNull(frel);
         assertEquals(2, frel.getDbRelationships().size());
 
         // storing data map may uncover some inconsistencies
         PrintWriter mockupWriter = new NullPrintWriter();
-        map.encodeAsXML(new XMLEncoder(mockupWriter));
+        map.encodeAsXML(new XMLEncoder(mockupWriter), new EmptyConfigurationNodeVisitor());
     }
 
     class NullPrintWriter extends PrintWriter {


[07/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - new XML loader for DataMap - new project version - updated test projects

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/Attribute.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/Attribute.java b/cayenne-server/src/main/java/org/apache/cayenne/map/Attribute.java
index 34b4596..8c8a48e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/Attribute.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/Attribute.java
@@ -21,6 +21,7 @@ package org.apache.cayenne.map;
 
 import java.io.Serializable;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.util.CayenneMapEntry;
 import org.apache.cayenne.util.ToStringBuilder;
 import org.apache.cayenne.util.XMLEncoder;
@@ -54,7 +55,8 @@ public abstract class Attribute implements CayenneMapEntry, XMLSerializable, Ser
         return new ToStringBuilder(this).append("name", getName()).toString();
     }
 
-    public abstract void encodeAsXML(XMLEncoder encoder);
+    @Override
+    public abstract void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate);
 
     /**
      * Returns parent entity that holds this attribute.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/CallbackMap.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/CallbackMap.java b/cayenne-server/src/main/java/org/apache/cayenne/map/CallbackMap.java
index 9cc4b18..b355f43 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/CallbackMap.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/CallbackMap.java
@@ -106,11 +106,7 @@ public class CallbackMap implements Serializable {
             XMLEncoder encoder) {
 
         for (String methodName : descriptor.getCallbackMethods()) {
-            encoder.print("<");
-            encoder.print(stringCallbackName);
-            encoder.print(" method-name=\"");
-            encoder.print(methodName);
-            encoder.println("\"/>");
+            encoder.start(stringCallbackName).attribute("method-name", methodName).end();
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/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 b3002df..1cffde2 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
@@ -19,7 +19,6 @@
 
 package org.apache.cayenne.map;
 
-import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.configuration.ConfigurationNode;
@@ -120,7 +119,7 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable
 	 * The namespace in which the data map XML file will be created. This is
 	 * also the URI to locate a copy of the schema document.
 	 */
-	public static final String SCHEMA_XSD = "http://cayenne.apache.org/schema/9/modelMap";
+	public static final String SCHEMA_XSD = "http://cayenne.apache.org/schema/10/modelMap";
 
 	protected String name;
 	protected String location;
@@ -147,8 +146,7 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable
 	private SortedMap<String, SQLResult> results;
 
 	/**
-	 * @deprecated since 4.0 unused as listeners are no longer tied to a
-	 *             DataMap.
+	 * @deprecated since 4.0 unused as listeners are no longer tied to a DataMap.
 	 */
 	private List<EntityListener> defaultEntityListeners;
 
@@ -177,13 +175,13 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable
 	}
 
 	public DataMap(String mapName, Map<String, Object> properties) {
-		embeddablesMap = new TreeMap<String, Embeddable>();
-		objEntityMap = new TreeMap<String, ObjEntity>();
-		dbEntityMap = new TreeMap<String, DbEntity>();
-		procedureMap = new TreeMap<String, Procedure>();
+		embeddablesMap = new TreeMap<>();
+		objEntityMap = new TreeMap<>();
+		dbEntityMap = new TreeMap<>();
+		procedureMap = new TreeMap<>();
 		queryDescriptorMap = new TreeMap<>();
 		defaultEntityListeners = new ArrayList<>(3);
-		results = new TreeMap<String, SQLResult>();
+		results = new TreeMap<>();
 		setName(mapName);
 		initWithProperties(properties);
 	}
@@ -265,8 +263,7 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable
 				: ObjEntity.LOCK_TYPE_NONE;
 
 		this.defaultPackage = (packageName != null) ? packageName.toString() : null;
-		this.quotingSQLIdentifiers = (quoteSqlIdentifier != null) ? "true".equalsIgnoreCase(quoteSqlIdentifier
-				.toString()) : false;
+		this.quotingSQLIdentifiers = (quoteSqlIdentifier != null) ? "true".equalsIgnoreCase(quoteSqlIdentifier.toString()) : false;
 		this.defaultSchema = (schema != null) ? schema.toString() : null;
 		this.defaultCatalog = (catalog != null) ? catalog.toString() : null;
 		this.defaultSuperclass = (superclass != null) ? superclass.toString() : null;
@@ -310,96 +307,58 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable
 	 * 
 	 * @since 1.1
 	 */
-	public void encodeAsXML(XMLEncoder encoder) {
-		encoder.println("<data-map xmlns=\"http://cayenne.apache.org/schema/9/modelMap\"");
-
-		encoder.indent(1);
-		encoder.println(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
-		encoder.println(" xsi:schemaLocation=\"" + SCHEMA_XSD + " " + SCHEMA_XSD + ".xsd\"");
-
-		encoder.printProjectVersion();
-		encoder.println(">");
-
-		// properties
-		if (defaultLockType == ObjEntity.LOCK_TYPE_OPTIMISTIC) {
-			encoder.printProperty(DEFAULT_LOCK_TYPE_PROPERTY, "optimistic");
-		}
-
-		if (!Util.isEmptyString(defaultPackage)) {
-			encoder.printProperty(DEFAULT_PACKAGE_PROPERTY, defaultPackage);
-		}
-
-		if (!Util.isEmptyString(defaultCatalog)) {
-			encoder.printProperty(DEFAULT_CATALOG_PROPERTY, defaultCatalog);
-		}
-
-		if (!Util.isEmptyString(defaultSchema)) {
-			encoder.printProperty(DEFAULT_SCHEMA_PROPERTY, defaultSchema);
-		}
-
-		if (!Util.isEmptyString(defaultSuperclass)) {
-			encoder.printProperty(DEFAULT_SUPERCLASS_PROPERTY, defaultSuperclass);
-		}
-
-		if (quotingSQLIdentifiers) {
-			encoder.printProperty(DEFAULT_QUOTE_SQL_IDENTIFIERS_PROPERTY, quotingSQLIdentifiers);
-		}
-
-		if (clientSupported) {
-			encoder.printProperty(CLIENT_SUPPORTED_PROPERTY, "true");
-		}
-
-		if (!Util.isEmptyString(defaultClientPackage)) {
-			encoder.printProperty(DEFAULT_CLIENT_PACKAGE_PROPERTY, defaultClientPackage);
-		}
-
-		if (!Util.isEmptyString(defaultClientSuperclass)) {
-			encoder.printProperty(DEFAULT_CLIENT_SUPERCLASS_PROPERTY, defaultClientSuperclass);
-		}
-
-		// embeddables
-		encoder.print(getEmbeddableMap());
-
-		// procedures
-		encoder.print(getProcedureMap());
-
-		// DbEntities
-		for (DbEntity dbe : getDbEntityMap().values()) {
-			dbe.encodeAsXML(encoder);
-		}
-
-		// others...
-		encoder.print(getObjEntityMap());
-		encodeDBRelationshipsAsXML(getDbEntityMap(), encoder);
-		encodeOBJRelationshipsAsXML(getObjEntityMap(), encoder);
-
-		for (QueryDescriptor query : getQueryDescriptors()) {
-			query.encodeAsXML(encoder);
-		}
-
-		encoder.indent(-1);
-		encoder.println("</data-map>");
+	public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+		encoder.start("data-map")
+				.attribute("xmlns", SCHEMA_XSD)
+				.attribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance", true)
+				.attribute("xsi:schemaLocation", SCHEMA_XSD + " " + SCHEMA_XSD + ".xsd", true)
+				.projectVersion()
+				// properties
+				.property(DEFAULT_LOCK_TYPE_PROPERTY, defaultLockType)
+				.property(DEFAULT_PACKAGE_PROPERTY, defaultPackage)
+				.property(DEFAULT_CATALOG_PROPERTY, defaultCatalog)
+				.property(DEFAULT_SCHEMA_PROPERTY, defaultSchema)
+				.property(DEFAULT_SUPERCLASS_PROPERTY, defaultSuperclass)
+				.property(DEFAULT_QUOTE_SQL_IDENTIFIERS_PROPERTY, quotingSQLIdentifiers)
+				.property(CLIENT_SUPPORTED_PROPERTY, clientSupported)
+				.property(DEFAULT_CLIENT_PACKAGE_PROPERTY, defaultClientPackage)
+				.property(DEFAULT_CLIENT_SUPERCLASS_PROPERTY, defaultClientSuperclass)
+				// elements
+				.nested(getEmbeddableMap(), delegate)
+				.nested(getProcedureMap(), delegate)
+				.nested(getDbEntityMap(), delegate)
+				.nested(getObjEntityMap(), delegate);
+
+		// and finally relationships
+		encodeDbRelationshipsAsXML(encoder, delegate);
+		encodeObjRelationshipsAsXML(encoder, delegate);
+
+		// descriptors at the end just to keep logic from older versions
+		encoder.nested(getQueryDescriptors(), delegate);
+
+		delegate.visitDataMap(this);
+		encoder.end();
 	}
 
 	// stores relationships for the map of entities
-	private final void encodeDBRelationshipsAsXML(Map<String, DbEntity> entityMap, XMLEncoder encoder) {
-		for (Entity entity : entityMap.values()) {
+	private void encodeDbRelationshipsAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+		for (Entity entity : getDbEntityMap().values()) {
 			for (Relationship relationship : entity.getRelationships()) {
 				// filter out synthetic
 				if (!relationship.isRuntime()) {
-					relationship.encodeAsXML(encoder);
+					relationship.encodeAsXML(encoder, delegate);
 				}
 			}
 		}
 	}
 
 	// stores relationships for the map of entities
-	private final void encodeOBJRelationshipsAsXML(Map<String, ObjEntity> entityMap, XMLEncoder encoder) {
-		for (ObjEntity entity : entityMap.values()) {
+	private void encodeObjRelationshipsAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+		for (ObjEntity entity : getObjEntityMap().values()) {
 			for (Relationship relationship : entity.getDeclaredRelationships()) {
 				// filter out synthetic
 				if (!relationship.isRuntime()) {
-					relationship.encodeAsXML(encoder);
+					relationship.encodeAsXML(encoder, delegate);
 				}
 			}
 		}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java
index 796d69c..37bbc60 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java
@@ -24,7 +24,6 @@ import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.map.event.AttributeEvent;
 import org.apache.cayenne.map.event.DbAttributeListener;
-import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
 
 /**
@@ -99,49 +98,40 @@ public class DbAttribute extends Attribute implements ConfigurationNode {
      * @since 1.1
      */
     @Override
-    public void encodeAsXML(XMLEncoder encoder) {
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
 
-        encoder.print("<db-attribute name=\"");
-        encoder.print(Util.encodeXmlAttribute(getName()));
-        encoder.print('\"');
+        encoder.start("db-attribute").attribute("name", getName());
 
         String type = TypesMapping.getSqlNameByType(getType());
-        if (type != null) {
-            encoder.print(" type=\"" + type + '\"');
-        }
+        encoder.attribute("type", type);
 
         if (isPrimaryKey()) {
-            encoder.print(" isPrimaryKey=\"true\"");
+            encoder.attribute("isPrimaryKey", true);
 
             // only allow generated if an attribute is a PK.
             if (isGenerated()) {
-                encoder.print(" isGenerated=\"true\"");
+                encoder.attribute("isGenerated", true);
             }
         }
 
         if (isMandatory()) {
-            encoder.print(" isMandatory=\"true\"");
+            encoder.attribute("isMandatory", true);
         }
 
         if (getMaxLength() > 0) {
-            encoder.print(" length=\"");
-            encoder.print(getMaxLength());
-            encoder.print('\"');
+            encoder.attribute("length", getMaxLength());
         }
 
         if (getScale() > 0) {
-            encoder.print(" scale=\"");
-            encoder.print(getScale());
-            encoder.print('\"');
+            encoder.attribute("scale", getScale());
         }
 
         if (getAttributePrecision() > 0) {
-            encoder.print(" attributePrecision=\"");
-            encoder.print(getAttributePrecision());
-            encoder.print('\"');
+            encoder.attribute("attributePrecision", getAttributePrecision());
         }
 
-        encoder.println("/>");
+        delegate.visitDbAttribute(this);
+        encoder.end();
     }
 
     public String getAliasedName(String alias) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java
index 3c3af26..d3dda7e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java
@@ -34,7 +34,6 @@ import org.apache.cayenne.map.event.EntityEvent;
 import org.apache.cayenne.map.event.MapEvent;
 import org.apache.cayenne.map.event.RelationshipEvent;
 import org.apache.cayenne.util.CayenneMapEntry;
-import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.commons.collections.Transformer;
 
@@ -114,40 +113,30 @@ public class DbEntity extends Entity implements ConfigurationNode, DbEntityListe
      * @since 1.1
      */
     @Override
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<db-entity name=\"");
-        encoder.print(Util.encodeXmlAttribute(getName()));
-        encoder.print('\"');
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("db-entity").attribute("name", getName());
 
         if (getSchema() != null && getSchema().trim().length() > 0) {
-            encoder.print(" schema=\"");
-            encoder.print(Util.encodeXmlAttribute(getSchema().trim()));
-            encoder.print('\"');
+            encoder.attribute("schema", getSchema().trim());
         }
-
         if (getCatalog() != null && getCatalog().trim().length() > 0) {
-            encoder.print(" catalog=\"");
-            encoder.print(Util.encodeXmlAttribute(getCatalog().trim()));
-            encoder.print('\"');
+            encoder.attribute("catalog", getCatalog().trim());
         }
 
-        encoder.println('>');
-
-        encoder.indent(1);
-        encoder.print(getAttributeMap());
+        encoder.nested(getAttributeMap(), delegate);
 
         if (getPrimaryKeyGenerator() != null) {
-            getPrimaryKeyGenerator().encodeAsXML(encoder);
+            getPrimaryKeyGenerator().encodeAsXML(encoder, delegate);
         }
 
         if (getQualifier() != null) {
-            encoder.print("<qualifier>");
-            getQualifier().encodeAsXML(encoder);
-            encoder.println("</qualifier>");
+            encoder.start("qualifier");
+            getQualifier().encodeAsXML(encoder, delegate);
+            encoder.end();
         }
 
-        encoder.indent(-1);
-        encoder.println("</db-entity>");
+        delegate.visitDbEntity(this);
+        encoder.end();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/DbJoin.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbJoin.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbJoin.java
index ecb9ab8..d0de023 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbJoin.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbJoin.java
@@ -22,6 +22,7 @@ package org.apache.cayenne.map;
 import java.io.Serializable;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.util.ToStringBuilder;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
@@ -95,23 +96,12 @@ public class DbJoin implements XMLSerializable, Serializable {
     /**
      * Prints itself as XML to the provided XMLEncoder.
      */
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<db-attribute-pair");
-
-        // sanity check
-        if (getSourceName() != null) {
-            encoder.print(" source=\"");
-            encoder.print(getSourceName());
-            encoder.print("\"");
-        }
-
-        if (getTargetName() != null) {
-            encoder.print(" target=\"");
-            encoder.print(getTargetName());
-            encoder.print("\"");
-        }
-
-        encoder.println("/>");
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("db-attribute-pair")
+                .attribute("source", getSourceName())
+                .attribute("target", getTargetName())
+                .end();
     }
 
     public DbRelationship getRelationship() {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/DbKeyGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbKeyGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbKeyGenerator.java
index f6cd94e..d91e787 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbKeyGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbKeyGenerator.java
@@ -22,6 +22,7 @@ package org.apache.cayenne.map;
 
 import java.io.Serializable;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.util.CayenneMapEntry;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
@@ -77,32 +78,22 @@ public class DbKeyGenerator implements CayenneMapEntry, XMLSerializable, Seriali
      * 
      * @since 1.1
      */
-    public void encodeAsXML(XMLEncoder encoder) {
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
         if (getGeneratorType() == null) {
             return;
         }
 
-        encoder.println("<db-key-generator>");
-        encoder.indent(1);
-
-        encoder.print("<db-generator-type>");
-        encoder.print(getGeneratorType());
-        encoder.println("</db-generator-type>");
+        encoder.start("db-key-generator")
+                .start("db-generator-type").cdata(getGeneratorType()).end();
 
         if (getGeneratorName() != null) {
-            encoder.print("<db-generator-name>");
-            encoder.print(getGeneratorName());
-            encoder.println("</db-generator-name>");
+            encoder.start("db-generator-name").cdata(getGeneratorName()).end();
         }
-
         if (getKeyCacheSize() != null) {
-            encoder.print("<db-key-cache-size>");
-            encoder.print(String.valueOf(getKeyCacheSize()));
-            encoder.println("</db-key-cache-size>");
+            encoder.start("db-key-cache-size").cdata(String.valueOf(getKeyCacheSize())).end();
         }
-
-        encoder.indent(-1);
-        encoder.println("</db-key-generator>");
+        encoder.end();
     }
 
     public DbEntity getDbEntity() {
@@ -117,8 +108,8 @@ public class DbKeyGenerator implements CayenneMapEntry, XMLSerializable, Seriali
         this.generatorType = generatorType;
         if (this.generatorType != null) {
             this.generatorType = this.generatorType.trim().toUpperCase();
-            if (!(ORACLE_TYPE.equals(this.generatorType) || NAMED_SEQUENCE_TABLE_TYPE
-                    .equals(this.generatorType)))
+            if (!(ORACLE_TYPE.equals(this.generatorType)
+                    || NAMED_SEQUENCE_TABLE_TYPE.equals(this.generatorType)))
                 this.generatorType = null;
         }
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/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 0d58cd0..53d4c73 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
@@ -74,30 +74,22 @@ public class DbRelationship extends Relationship implements ConfigurationNode {
      * 
      * @since 1.1
      */
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<db-relationship name=\"");
-        encoder.print(Util.encodeXmlAttribute(getName()));
-        encoder.print("\" source=\"");
-        encoder.print(Util.encodeXmlAttribute(getSourceEntity().getName()));
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("db-relationship")
+                .attribute("name", getName())
+                .attribute("source", getSourceEntity().getName());
 
         if (getTargetEntityName() != null && getTargetEntity() != null) {
-            encoder.print("\" target=\"");
-            encoder.print(Util.encodeXmlAttribute(getTargetEntityName()));
+            encoder.attribute("target", getTargetEntityName());
         }
 
-        if (isToDependentPK() && isValidForDepPk()) {
-            encoder.print("\" toDependentPK=\"true");
-        }
-
-        encoder.print("\" toMany=\"");
-        encoder.print(isToMany());
-        encoder.println("\">");
+        encoder.attribute("toDependentPK", isToDependentPK() && isValidForDepPk());
+        encoder.attribute("toMany", isToMany());
 
-        encoder.indent(1);
-        encoder.print(getJoins());
-        encoder.indent(-1);
+        encoder.nested(getJoins(), delegate);
 
-        encoder.println("</db-relationship>");
+        delegate.visitDbRelationship(this);
+        encoder.end();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/EJBQLQueryDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/EJBQLQueryDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/map/EJBQLQueryDescriptor.java
index d3adde5..ed7f2e0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/EJBQLQueryDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/EJBQLQueryDescriptor.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.map;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.query.EJBQLQuery;
 import org.apache.cayenne.util.XMLEncoder;
 
@@ -59,25 +60,17 @@ public class EJBQLQueryDescriptor extends QueryDescriptor {
     }
 
     @Override
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<query name=\"");
-        encoder.print(getName());
-        encoder.print("\" type=\"");
-        encoder.print(type);
-        encoder.println("\">");
-
-        encoder.indent(1);
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("query").attribute("name", getName()).attribute("type", type);
 
         // print properties
         encodeProperties(encoder);
 
         if (ejbql != null) {
-            encoder.print("<ejbql><![CDATA[");
-            encoder.print(ejbql);
-            encoder.println("]]></ejbql>");
+            encoder.start("ejbql").cdata(ejbql, true).end();
         }
 
-        encoder.indent(-1);
-        encoder.println("</query>");
+        delegate.visitQuery(this);
+        encoder.end();
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/Embeddable.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/Embeddable.java b/cayenne-server/src/main/java/org/apache/cayenne/map/Embeddable.java
index 744a5cc..d6a354e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/Embeddable.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/Embeddable.java
@@ -168,18 +168,12 @@ public class Embeddable implements ConfigurationNode, XMLSerializable, Serializa
 	/**
 	 * {@link XMLSerializable} implementation that generates XML for embeddable.
 	 */
-	public void encodeAsXML(XMLEncoder encoder) {
-		encoder.print("<embeddable");
-		if (getClassName() != null) {
-			encoder.print(" className=\"");
-			encoder.print(getClassName());
-			encoder.print("\"");
-		}
-		encoder.println(">");
-
-		encoder.indent(1);
-		encoder.print(attributes);
-		encoder.indent(-1);
-		encoder.println("</embeddable>");
+	@Override
+	public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+		encoder.start("embeddable")
+				.attribute("className", getClassName())
+				.nested(attributes, delegate);
+		delegate.visitEmbeddable(this);
+		encoder.end();
 	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/EmbeddableAttribute.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/EmbeddableAttribute.java b/cayenne-server/src/main/java/org/apache/cayenne/map/EmbeddableAttribute.java
index 27a8da7..197b7dc 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/EmbeddableAttribute.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/EmbeddableAttribute.java
@@ -22,7 +22,6 @@ import java.io.Serializable;
 
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
-import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
 
@@ -55,23 +54,14 @@ public class EmbeddableAttribute implements ConfigurationNode, XMLSerializable,
         return visitor.visitEmbeddableAttribute(this);
     }
 
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<embeddable-attribute name=\"" + getName() + '\"');
-
-        if (getType() != null) {
-            encoder.print(" type=\"");
-            encoder.print(getType());
-            encoder.print('\"');
-        }
-
-        // If this obj attribute is mapped to db attribute
-        if (dbAttributeName != null) {
-            encoder.print(" db-attribute-name=\"");
-            encoder.print(Util.encodeXmlAttribute(dbAttributeName));
-            encoder.print('\"');
-        }
-
-        encoder.println("/>");
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("embeddable-attribute")
+                .attribute("name", getName())
+                .attribute("type", getType())
+                .attribute("db-attribute-name", dbAttributeName);
+        delegate.visitEmbeddableAttribute(this);
+        encoder.end();
     }
 
     public String getDbAttributeName() {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/EmbeddedAttribute.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/EmbeddedAttribute.java b/cayenne-server/src/main/java/org/apache/cayenne/map/EmbeddedAttribute.java
index 1eeaa2e..3be89e5 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/EmbeddedAttribute.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/EmbeddedAttribute.java
@@ -19,6 +19,7 @@
 package org.apache.cayenne.map;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
 
@@ -55,33 +56,19 @@ public class EmbeddedAttribute extends ObjAttribute {
     }
 
     @Override
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<embedded-attribute name=\"" + getName() + '\"');
-        if (getType() != null) {
-            encoder.print(" type=\"");
-            encoder.print(getType());
-            encoder.print('\"');
-        }
-
-        if (attributeOverrides.isEmpty()) {
-            encoder.println("/>");
-            return;
-        }
-
-        encoder.println('>');
-
-        encoder.indent(1);
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("embedded-attribute")
+                .attribute("name", getName())
+                .attribute("type", getType());
 
         for (Map.Entry<String, String> e : attributeOverrides.entrySet()) {
-            encoder.print("<embeddable-attribute-override name=\"");
-            encoder.print(e.getKey());
-            encoder.print("\" db-attribute-path=\"");
-            encoder.print(e.getValue());
-            encoder.println("\"/>");
+            encoder.start("embeddable-attribute-override")
+                    .attribute("name", e.getKey())
+                    .attribute("db-attribute-path", e.getValue())
+                    .end();
         }
 
-        encoder.indent(-1);
-        encoder.println("</embedded-attribute>");
+        encoder.end();
     }
 
     public Map<String, String> getAttributeOverrides() {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/EntityListener.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/EntityListener.java b/cayenne-server/src/main/java/org/apache/cayenne/map/EntityListener.java
index 84e172d..f9486bc 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/EntityListener.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/EntityListener.java
@@ -20,6 +20,7 @@ package org.apache.cayenne.map;
 
 import java.io.Serializable;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
 
@@ -63,7 +64,8 @@ public class EntityListener implements Serializable, XMLSerializable {
         return callbacks;
     }
 
-    public void encodeAsXML(XMLEncoder encoder) {
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
         encoder.print("<entity-listener class=\"");
         encoder.print(className);
         encoder.println("\">");

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/MapLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/MapLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/map/MapLoader.java
deleted file mode 100644
index 2ea7a6f..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/MapLoader.java
+++ /dev/null
@@ -1,1261 +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.map;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.util.Util;
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.DefaultHandler;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * Default MapLoader. Its responsibilities include reading DataMaps from XML
- * files and saving DataMap objects back to XML.
- */
-public class MapLoader extends DefaultHandler {
-
-	// TODO: andrus, 7/17/2006 - move upgrade logic out of here
-	final static String _1_2_PACKAGE_PREFIX = "org.objectstyle.cayenne.";
-	final static String _2_0_PACKAGE_PREFIX = "org.apache.cayenne.";
-
-	public static final String DATA_MAP_TAG = "data-map";
-
-	public static final String PROPERTY_TAG = "property";
-
-	/**
-	 * @since 3.0
-	 */
-	public static final String EMBEDDABLE_TAG = "embeddable";
-
-	/**
-	 * @since 3.0
-	 */
-	public static final String EMBEDDABLE_ATTRIBUTE_TAG = "embeddable-attribute";
-
-	/**
-	 * @since 3.0
-	 */
-	public static final String EMBEDDED_ATTRIBUTE_TAG = "embedded-attribute";
-
-	/**
-	 * @since 3.0
-	 */
-	public static final String EMBEDDABLE_ATTRIBUTE_OVERRIDE_TAG = "embeddable-attribute-override";
-
-	public static final String DB_ENTITY_TAG = "db-entity";
-	public static final String OBJ_ENTITY_TAG = "obj-entity";
-	public static final String DB_ATTRIBUTE_TAG = "db-attribute";
-	public static final String OBJ_ATTRIBUTE_TAG = "obj-attribute";
-	public static final String OBJ_ATTRIBUTE_OVERRIDE_TAG = "attribute-override";
-	public static final String OBJ_RELATIONSHIP_TAG = "obj-relationship";
-	public static final String DB_RELATIONSHIP_TAG = "db-relationship";
-	public static final String DB_RELATIONSHIP_REF_TAG = "db-relationship-ref";
-	public static final String DB_ATTRIBUTE_PAIR_TAG = "db-attribute-pair";
-	public static final String PROCEDURE_TAG = "procedure";
-	public static final String PROCEDURE_PARAMETER_TAG = "procedure-parameter";
-
-	// lifecycle listeners and callbacks related
-	public static final String POST_ADD_TAG = "post-add";
-	public static final String PRE_PERSIST_TAG = "pre-persist";
-	public static final String POST_PERSIST_TAG = "post-persist";
-	public static final String PRE_UPDATE_TAG = "pre-update";
-	public static final String POST_UPDATE_TAG = "post-update";
-	public static final String PRE_REMOVE_TAG = "pre-remove";
-	public static final String POST_REMOVE_TAG = "post-remove";
-	public static final String POST_LOAD_TAG = "post-load";
-
-	// Query-related
-	public static final String QUERY_TAG = "query";
-
-	public static final String QUERY_SQL_TAG = "sql";
-	public static final String QUERY_EJBQL_TAG = "ejbql";
-	public static final String QUERY_QUALIFIER_TAG = "qualifier";
-	public static final String QUERY_ORDERING_TAG = "ordering";
-	public static final String QUERY_PREFETCH_TAG = "prefetch";
-
-	public static final String TRUE = "true";
-	public static final String FALSE = "false";
-
-	public static final String DB_KEY_GENERATOR_TAG = "db-key-generator";
-	public static final String DB_GENERATOR_TYPE_TAG = "db-generator-type";
-	public static final String DB_GENERATOR_NAME_TAG = "db-generator-name";
-	public static final String DB_KEY_CACHE_SIZE_TAG = "db-key-cache-size";
-
-	/**
-	 * @since 3.0
-	 */
-	public static final String OBJ_ENTITY_ROOT = "obj-entity";
-
-	/**
-	 * @since 3.0
-	 */
-	public static final String DB_ENTITY_ROOT = "db-entity";
-
-	/**
-	 * @since 3.0
-	 */
-	public static final String PROCEDURE_ROOT = "procedure";
-
-	/**
-	 * @since 3.0
-	 */
-	public static final String DATA_MAP_ROOT = "data-map";
-
-	/**
-	 * @since 3.0
-	 */
-	public static final String JAVA_CLASS_ROOT = "java-class";
-
-	private static final String DATA_MAP_LOCATION_SUFFIX = ".map.xml";
-
-	// Reading from XML
-	private String mapVersion;
-	private DataMap dataMap;
-	private DbEntity dbEntity;
-	private ObjEntity objEntity;
-	private Embeddable embeddable;
-	private EmbeddedAttribute embeddedAttribute;
-	private DbRelationship dbRelationship;
-	private ObjRelationship objRelationship;
-	private DbAttribute attrib;
-	private Procedure procedure;
-	private QueryDescriptorLoader queryBuilder;
-	private String sqlKey;
-
-	private String descending;
-	private String ignoreCase;
-
-	private Map<String, StartClosure> startTagOpMap;
-	private Map<String, EndClosure> endTagOpMap;
-	private String currentTag;
-	private Attributes currentAttributes;
-	private StringBuilder charactersBuffer;
-	private Map<String, Object> mapProperties;
-
-	public MapLoader() {
-		// compile tag processors.
-		startTagOpMap = new HashMap<>(40);
-		endTagOpMap = new HashMap<>(40);
-
-		startTagOpMap.put(DATA_MAP_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartDataMap(attributes);
-			}
-		});
-		
-		startTagOpMap.put(DB_ENTITY_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartDbEntity(attributes);
-			}
-		});
-
-		startTagOpMap.put(DB_ATTRIBUTE_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartDbAttribute(attributes);
-			}
-		});
-
-		startTagOpMap.put(OBJ_ENTITY_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartObjEntity(attributes);
-			}
-		});
-
-		startTagOpMap.put(OBJ_ATTRIBUTE_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartObjAttribute(attributes);
-			}
-		});
-
-		startTagOpMap.put(OBJ_ATTRIBUTE_OVERRIDE_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartAttributeOverride(attributes);
-			}
-		});
-
-		startTagOpMap.put(EMBEDDABLE_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartEmbeddable(attributes);
-			}
-		});
-
-		startTagOpMap.put(EMBEDDABLE_ATTRIBUTE_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartEmbeddableAttribute(attributes);
-			}
-		});
-
-		startTagOpMap.put(EMBEDDABLE_ATTRIBUTE_OVERRIDE_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartEmbeddableAttributeOverride(attributes);
-			}
-		});
-
-		startTagOpMap.put(EMBEDDED_ATTRIBUTE_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartEmbeddedAttribute(attributes);
-			}
-		});
-
-		startTagOpMap.put(DB_RELATIONSHIP_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartDbRelationship(attributes);
-			}
-		});
-
-		startTagOpMap.put(DB_ATTRIBUTE_PAIR_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartDbAttributePair(attributes);
-			}
-		});
-
-		startTagOpMap.put(OBJ_RELATIONSHIP_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartObjRelationship(attributes);
-			}
-		});
-
-		startTagOpMap.put(DB_RELATIONSHIP_REF_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartDbRelationshipRef(attributes);
-			}
-		});
-
-		startTagOpMap.put(PROCEDURE_PARAMETER_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartProcedureParameter(attributes);
-			}
-		});
-
-		startTagOpMap.put(PROCEDURE_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartProcedure(attributes);
-			}
-		});
-
-		startTagOpMap.put(QUERY_EJBQL_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				charactersBuffer = new StringBuilder();
-			}
-		});
-
-		startTagOpMap.put(QUERY_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartQuery(attributes);
-			}
-		});
-
-		startTagOpMap.put(QUERY_SQL_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				charactersBuffer = new StringBuilder();
-				processStartQuerySQL(attributes);
-			}
-		});
-
-		startTagOpMap.put(QUERY_ORDERING_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				charactersBuffer = new StringBuilder();
-				processStartQueryOrdering(attributes);
-			}
-		});
-
-		startTagOpMap.put(DB_KEY_GENERATOR_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartDbKeyGenerator(attributes);
-			}
-		});
-
-		startTagOpMap.put(PROPERTY_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				// properties can belong to query or DataMap
-				if (queryBuilder != null) {
-					processStartQueryProperty(attributes);
-				} else {
-					processStartDataMapProperty(attributes);
-				}
-			}
-		});
-
-		startTagOpMap.put(POST_ADD_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartPostAdd(attributes);
-			}
-		});
-
-		startTagOpMap.put(PRE_PERSIST_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartPrePersist(attributes);
-			}
-		});
-
-		startTagOpMap.put(POST_PERSIST_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartPostPersist(attributes);
-			}
-		});
-
-		startTagOpMap.put(PRE_UPDATE_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartPreUpdate(attributes);
-			}
-		});
-
-		startTagOpMap.put(POST_UPDATE_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartPostUpdate(attributes);
-			}
-		});
-
-		startTagOpMap.put(PRE_REMOVE_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartPreRemove(attributes);
-			}
-		});
-
-		startTagOpMap.put(POST_REMOVE_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartPostRemove(attributes);
-			}
-		});
-
-		startTagOpMap.put(POST_LOAD_TAG, new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				processStartPostLoad(attributes);
-			}
-		});
-
-		StartClosure resetBuffer = new StartClosure() {
-
-			@Override
-			void execute(Attributes attributes) throws SAXException {
-				charactersBuffer = new StringBuilder();
-			}
-		};
-
-		startTagOpMap.put(QUERY_PREFETCH_TAG, resetBuffer);
-		startTagOpMap.put(QUERY_QUALIFIER_TAG, resetBuffer);
-		startTagOpMap.put(DB_GENERATOR_TYPE_TAG, resetBuffer);
-		startTagOpMap.put(DB_GENERATOR_NAME_TAG, resetBuffer);
-		startTagOpMap.put(DB_KEY_CACHE_SIZE_TAG, resetBuffer);
-
-		endTagOpMap.put(DATA_MAP_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndDataMap();
-			}
-		});
-		endTagOpMap.put(DB_ENTITY_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndDbEntity();
-			}
-		});
-		endTagOpMap.put(OBJ_ENTITY_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndObjEntity();
-			}
-		});
-		endTagOpMap.put(EMBEDDABLE_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndEmbeddable();
-			}
-		});
-		endTagOpMap.put(EMBEDDABLE_ATTRIBUTE_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndEmbeddedAttribute();
-			}
-		});
-
-		endTagOpMap.put(DB_ATTRIBUTE_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndDbAttribute();
-			}
-		});
-
-		endTagOpMap.put(DB_RELATIONSHIP_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndDbRelationship();
-			}
-		});
-		endTagOpMap.put(OBJ_RELATIONSHIP_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndObjRelationship();
-			}
-		});
-		endTagOpMap.put(DB_GENERATOR_TYPE_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndDbGeneratorType();
-			}
-		});
-		endTagOpMap.put(DB_GENERATOR_NAME_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndDbGeneratorName();
-			}
-		});
-		endTagOpMap.put(DB_KEY_CACHE_SIZE_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndDbKeyCacheSize();
-			}
-		});
-		endTagOpMap.put(PROCEDURE_PARAMETER_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndProcedureParameter();
-			}
-		});
-		endTagOpMap.put(PROCEDURE_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndProcedure();
-			}
-		});
-		endTagOpMap.put(QUERY_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndQuery();
-			}
-		});
-		endTagOpMap.put(QUERY_SQL_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndQuerySQL();
-			}
-		});
-
-		endTagOpMap.put(QUERY_EJBQL_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndEjbqlQuery();
-			}
-		});
-
-		endTagOpMap.put(QUERY_QUALIFIER_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndQualifier();
-			}
-		});
-		endTagOpMap.put(QUERY_ORDERING_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndQueryOrdering();
-			}
-		});
-		endTagOpMap.put(QUERY_PREFETCH_TAG, new EndClosure() {
-
-			@Override
-			void execute() throws SAXException {
-				processEndQueryPrefetch();
-			}
-		});
-	}
-	
-	private void processStartDataMap(Attributes attributes) {
-		this.mapVersion = attributes.getValue("", "project-version");
-	}
-
-	private void processStartPostAdd(Attributes attributes) {
-		String methodName = attributes.getValue("", "method-name");
-		if (objEntity != null) {
-			// new callback tags - children of "obj-entity"
-			objEntity.getCallbackMap().getPostAdd().addCallbackMethod(methodName);
-		}
-	}
-
-	private void processStartPrePersist(Attributes attributes) {
-
-		// 3.0 -> 3.0.0.1 upgrade hack... treat pre-persist as post-add
-		// only 3.0 used "pre-persist" in a "post-add" sense
-		if ("3.0".equals(mapVersion)) {
-			processStartPostAdd(attributes);
-		} else {
-
-			String methodName = attributes.getValue("", "method-name");
-
-			if (objEntity != null) {
-				// new callback tags - children of "obj-entity"
-				objEntity.getCallbackMap().getPrePersist().addCallbackMethod(methodName);
-			}
-		}
-	}
-
-	private void processStartPostPersist(Attributes attributes) {
-		String methodName = attributes.getValue("", "method-name");
-		if (objEntity != null) {
-			objEntity.getCallbackMap().getPostPersist().addCallbackMethod(methodName);
-		}
-	}
-
-	private void processStartPreUpdate(Attributes attributes) {
-		String methodName = attributes.getValue("", "method-name");
-		if (objEntity != null) {
-			objEntity.getCallbackMap().getPreUpdate().addCallbackMethod(methodName);
-		}
-	}
-
-	private void processStartPostUpdate(Attributes attributes) {
-		String methodName = attributes.getValue("", "method-name");
-		if (objEntity != null) {
-			objEntity.getCallbackMap().getPostUpdate().addCallbackMethod(methodName);
-		}
-	}
-
-	private void processStartPreRemove(Attributes attributes) {
-		String methodName = attributes.getValue("", "method-name");
-		if (objEntity != null) {
-			objEntity.getCallbackMap().getPreRemove().addCallbackMethod(methodName);
-		}
-	}
-
-	private void processStartPostRemove(Attributes attributes) {
-		String methodName = attributes.getValue("", "method-name");
-		if (objEntity != null) {
-			objEntity.getCallbackMap().getPostRemove().addCallbackMethod(methodName);
-		}
-	}
-
-	private void processStartPostLoad(Attributes attributes) {
-		String methodName = attributes.getValue("", "method-name");
-		if (objEntity != null) {
-			objEntity.getCallbackMap().getPostLoad().addCallbackMethod(methodName);
-		}
-	}
-
-	/**
-	 * Loads a DataMap from XML input source.
-	 */
-	public synchronized DataMap loadDataMap(InputSource src) throws CayenneRuntimeException {
-		if (src == null) {
-			throw new NullPointerException("Null InputSource.");
-		}
-
-		try {
-			String mapName = mapNameFromLocation(src.getSystemId());
-			dataMap = new DataMap(mapName);
-			XMLReader parser = Util.createXmlReader();
-
-			parser.setContentHandler(this);
-			parser.setErrorHandler(this);
-			parser.parse(src);
-		} catch (SAXException e) {
-			dataMap = null;
-			throw new CayenneRuntimeException("Wrong DataMap format, last processed tag: "
-					+ constructCurrentStateString(), Util.unwindException(e));
-		} catch (Exception e) {
-			dataMap = null;
-			throw new CayenneRuntimeException("Error loading DataMap, last processed tag: "
-					+ constructCurrentStateString(), Util.unwindException(e));
-		}
-		return dataMap;
-	}
-
-	/**
-	 * Constructs error message for displaying as exception message
-	 */
-	private Appendable constructCurrentStateString() {
-		StringBuilder sb = new StringBuilder();
-		sb.append("<").append(currentTag);
-
-		if (currentAttributes != null) {
-			for (int i = 0; i < currentAttributes.getLength(); i++) {
-				sb.append(" ").append(currentAttributes.getLocalName(i)).append("=").append("\"")
-						.append(currentAttributes.getValue(i)).append("\"");
-			}
-		}
-		sb.append(">");
-
-		return sb;
-	}
-
-	/**
-	 * Helper method to guess the map name from its location.
-	 */
-	protected String mapNameFromLocation(String location) {
-		if (location == null) {
-			return "Untitled";
-		}
-
-		int lastSlash = location.lastIndexOf('/');
-		if (lastSlash < 0) {
-			lastSlash = location.lastIndexOf('\\');
-		}
-
-		if (lastSlash >= 0 && lastSlash + 1 < location.length()) {
-			location = location.substring(lastSlash + 1);
-		}
-
-		if (location.endsWith(DATA_MAP_LOCATION_SUFFIX)) {
-			location = location.substring(0, location.length() - DATA_MAP_LOCATION_SUFFIX.length());
-		}
-
-		return location;
-	}
-
-	@Override
-	public void startElement(String namespaceUri, String localName, String qName, Attributes attributes)
-			throws SAXException {
-
-		rememberCurrentState(localName, attributes);
-
-		StartClosure op = startTagOpMap.get(localName);
-		if (op != null) {
-			op.execute(attributes);
-		}
-	}
-
-	@Override
-	public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
-
-		EndClosure op = endTagOpMap.get(localName);
-		if (op != null) {
-			op.execute();
-		}
-
-		resetCurrentState();
-		charactersBuffer = null;
-	}
-
-	private void processStartEmbeddable(Attributes atts) {
-		embeddable = new Embeddable(atts.getValue("", "className"));
-		dataMap.addEmbeddable(embeddable);
-	}
-
-	private void processStartEmbeddableAttribute(Attributes atts) {
-		String name = atts.getValue("", "name");
-		String type = atts.getValue("", "type");
-		String dbName = atts.getValue("", "db-attribute-name");
-
-		EmbeddableAttribute ea = new EmbeddableAttribute(name);
-		ea.setType(type);
-		ea.setDbAttributeName(dbName);
-		embeddable.addAttribute(ea);
-	}
-
-	private void processStartEmbeddedAttribute(Attributes atts) {
-
-		String name = atts.getValue("", "name");
-		String type = atts.getValue("", "type");
-
-		embeddedAttribute = new EmbeddedAttribute(name);
-		embeddedAttribute.setType(type);
-		objEntity.addAttribute(embeddedAttribute);
-	}
-
-	private void processStartEmbeddableAttributeOverride(Attributes atts) {
-		String name = atts.getValue("", "name");
-		String dbName = atts.getValue("", "db-attribute-path");
-		embeddedAttribute.addAttributeOverride(name, dbName);
-	}
-
-	private void processStartDbEntity(Attributes atts) {
-		String name = atts.getValue("", "name");
-
-		dbEntity = new DbEntity(name);
-		dbEntity.setSchema(atts.getValue("", "schema"));
-		dbEntity.setCatalog(atts.getValue("", "catalog"));
-
-		dataMap.addDbEntity(dbEntity);
-	}
-
-	private void processStartDbAttribute(Attributes atts) {
-		String name = atts.getValue("", "name");
-		String type = atts.getValue("", "type");
-
-		attrib = new DbAttribute(name);
-		attrib.setType(TypesMapping.getSqlTypeByName(type));
-		dbEntity.addAttribute(attrib);
-
-		String length = atts.getValue("", "length");
-		if (length != null) {
-			attrib.setMaxLength(Integer.parseInt(length));
-		}
-
-		// this is an obsolete 1.2 'precision' attribute that really meant
-		// 'scale'
-		String pseudoPrecision = atts.getValue("", "precision");
-		if (pseudoPrecision != null) {
-			attrib.setScale(Integer.parseInt(pseudoPrecision));
-		}
-
-		String precision = atts.getValue("", "attributePrecision");
-		if (precision != null) {
-			attrib.setAttributePrecision(Integer.parseInt(precision));
-		}
-
-		String scale = atts.getValue("", "scale");
-		if (scale != null) {
-			attrib.setScale(Integer.parseInt(scale));
-		}
-
-		attrib.setPrimaryKey(TRUE.equalsIgnoreCase(atts.getValue("", "isPrimaryKey")));
-		attrib.setMandatory(TRUE.equalsIgnoreCase(atts.getValue("", "isMandatory")));
-		attrib.setGenerated(TRUE.equalsIgnoreCase(atts.getValue("", "isGenerated")));
-	}
-
-	private void processStartDbKeyGenerator(Attributes atts) {
-		DbKeyGenerator pkGenerator = new DbKeyGenerator();
-		dbEntity.setPrimaryKeyGenerator(pkGenerator);
-	}
-
-	private void processStartQuerySQL(Attributes atts) {
-		this.sqlKey = convertClassNameFromV1_2(atts.getValue("", "adapter-class"));
-	}
-
-	private void processStartObjEntity(Attributes atts) {
-		objEntity = new ObjEntity(atts.getValue("", "name"));
-		objEntity.setClassName(atts.getValue("", "className"));
-		objEntity.setClientClassName(atts.getValue("", "clientClassName"));
-
-		String isAbstract = atts.getValue("", "abstract");
-		objEntity.setAbstract(TRUE.equalsIgnoreCase(isAbstract));
-
-		String readOnly = atts.getValue("", "readOnly");
-		objEntity.setReadOnly(TRUE.equalsIgnoreCase(readOnly));
-
-		String serverOnly = atts.getValue("", "serverOnly");
-		objEntity.setServerOnly(TRUE.equalsIgnoreCase(serverOnly));
-
-		String excludeSuperclassListeners = atts.getValue("", "exclude-superclass-listeners");
-		objEntity.setExcludingSuperclassListeners(TRUE.equalsIgnoreCase(excludeSuperclassListeners));
-
-		String excludeDefaultListeners = atts.getValue("", "exclude-default-listeners");
-		objEntity.setExcludingDefaultListeners(TRUE.equalsIgnoreCase(excludeDefaultListeners));
-
-		String lockType = atts.getValue("", "lock-type");
-		if ("optimistic".equals(lockType)) {
-			objEntity.setDeclaredLockType(ObjEntity.LOCK_TYPE_OPTIMISTIC);
-		}
-
-		String superEntityName = atts.getValue("", "superEntityName");
-		if (superEntityName != null) {
-			objEntity.setSuperEntityName(superEntityName);
-		} else {
-			objEntity.setSuperClassName(atts.getValue("", "superClassName"));
-			objEntity.setClientSuperClassName(atts.getValue("", "clientSuperClassName"));
-		}
-
-		objEntity.setDbEntityName(atts.getValue("", "dbEntityName"));
-
-		dataMap.addObjEntity(objEntity);
-	}
-
-	private void processStartObjAttribute(Attributes atts) {
-		String name = atts.getValue("", "name");
-		String type = atts.getValue("", "type");
-
-		String lock = atts.getValue("", "lock");
-
-		ObjAttribute oa = new ObjAttribute(name);
-		oa.setType(type);
-		oa.setUsedForLocking(TRUE.equalsIgnoreCase(lock));
-		objEntity.addAttribute(oa);
-		String dbPath = atts.getValue("", "db-attribute-path");
-		if (dbPath == null) {
-			dbPath = atts.getValue("", "db-attribute-name");
-		}
-		oa.setDbAttributePath(dbPath);
-	}
-
-	private void processStartAttributeOverride(Attributes atts) {
-		String name = atts.getValue("", "name");
-		String dbPath = atts.getValue("", "db-attribute-path");
-
-		objEntity.addAttributeOverride(name, dbPath);
-	}
-
-	private void processStartDbRelationship(Attributes atts) throws SAXException {
-		String name = atts.getValue("", "name");
-		if (name == null) {
-			throw new SAXException("MapLoader::processStartDbRelationship()," + " Unable to parse name. Attributes:\n"
-					+ printAttributes(atts));
-		}
-
-		String sourceName = atts.getValue("", "source");
-		if (sourceName == null) {
-			throw new SAXException("MapLoader::processStartDbRelationship() - null source entity");
-		}
-
-		DbEntity source = dataMap.getDbEntity(sourceName);
-		if (source == null) {
-			return;
-		}
-
-		String toManyString = atts.getValue("", "toMany");
-		boolean toMany = toManyString != null && toManyString.equalsIgnoreCase(TRUE);
-
-		String toDependPkString = atts.getValue("", "toDependentPK");
-		boolean toDependentPK = toDependPkString != null && toDependPkString.equalsIgnoreCase(TRUE);
-
-		dbRelationship = new DbRelationship(name);
-		dbRelationship.setSourceEntity(source);
-		dbRelationship.setTargetEntityName(atts.getValue("", "target"));
-		dbRelationship.setToMany(toMany);
-		dbRelationship.setToDependentPK(toDependentPK);
-
-		source.addRelationship(dbRelationship);
-	}
-
-	private void processStartDbRelationshipRef(Attributes atts) throws SAXException {
-		// db-relationship-ref element is deprecated and is supported for
-		// backwards
-		// compatibility only
-
-		String name = atts.getValue("", "name");
-		if (name == null) {
-			throw new SAXException("MapLoader::processStartDbRelationshipRef()" + ", Null DbRelationship name for "
-					+ objRelationship.getName());
-		}
-
-		String path = objRelationship.getDbRelationshipPath();
-		path = (path != null) ? path + "." + name : name;
-		objRelationship.setDbRelationshipPath(path);
-	}
-
-	private void processStartDbAttributePair(Attributes atts) {
-		DbJoin join = new DbJoin(dbRelationship);
-		join.setSourceName(atts.getValue("", "source"));
-		join.setTargetName(atts.getValue("", "target"));
-		dbRelationship.addJoin(join);
-	}
-
-	private void processStartObjRelationship(Attributes atts) throws SAXException {
-		String name = atts.getValue("", "name");
-		if (null == name) {
-			throw new SAXException("MapLoader::processStartObjRelationship(),"
-					+ " Unable to parse target. Attributes:\n" + printAttributes(atts));
-		}
-
-		String collectionType = atts.getValue("", "collection-type");
-		String mapKey = atts.getValue("", "map-key");
-
-		String sourceName = atts.getValue("", "source");
-		if (sourceName == null) {
-			throw new SAXException("MapLoader::processStartObjRelationship(),"
-					+ " Unable to parse source. Attributes:\n" + printAttributes(atts));
-		}
-
-		ObjEntity source = dataMap.getObjEntity(sourceName);
-		if (source == null) {
-			throw new SAXException("MapLoader::processStartObjRelationship()," + " Unable to find source " + sourceName);
-		}
-
-		String deleteRuleName = atts.getValue("", "deleteRule");
-		int deleteRule = (deleteRuleName != null) ? DeleteRule.deleteRuleForName(deleteRuleName) : DeleteRule.NO_ACTION;
-
-		objRelationship = new ObjRelationship(name);
-		objRelationship.setSourceEntity(source);
-		objRelationship.setTargetEntityName(atts.getValue("", "target"));
-		objRelationship.setDeleteRule(deleteRule);
-		objRelationship.setUsedForLocking(TRUE.equalsIgnoreCase(atts.getValue("", "lock")));
-		objRelationship.setDeferredDbRelationshipPath((atts.getValue("", "db-relationship-path")));
-		objRelationship.setCollectionType(collectionType);
-		objRelationship.setMapKey(mapKey);
-		source.addRelationship(objRelationship);
-	}
-
-	private void processStartProcedure(Attributes attributes) throws SAXException {
-
-		String name = attributes.getValue("", "name");
-		if (null == name) {
-			throw new SAXException("MapLoader::processStartProcedure()," + " no procedure name.");
-		}
-
-		String schema = attributes.getValue("", "schema");
-		String catalog = attributes.getValue("", "catalog");
-		String returningValue = attributes.getValue("", "returningValue");
-
-		procedure = new Procedure(name);
-		procedure.setReturningValue(returningValue != null && returningValue.equalsIgnoreCase(TRUE));
-		procedure.setSchema(schema);
-		procedure.setCatalog(catalog);
-		dataMap.addProcedure(procedure);
-	}
-
-	private void processStartProcedureParameter(Attributes attributes) throws SAXException {
-
-		String name = attributes.getValue("", "name");
-		if (name == null) {
-			throw new SAXException("MapLoader::processStartProcedureParameter()," + " no procedure parameter name.");
-		}
-
-		ProcedureParameter parameter = new ProcedureParameter(name);
-
-		String type = attributes.getValue("", "type");
-		if (type != null) {
-			parameter.setType(TypesMapping.getSqlTypeByName(type));
-		}
-
-		String length = attributes.getValue("", "length");
-		if (length != null) {
-			parameter.setMaxLength(Integer.parseInt(length));
-		}
-
-		String precision = attributes.getValue("", "precision");
-		if (precision != null) {
-			parameter.setPrecision(Integer.parseInt(precision));
-		}
-
-		String direction = attributes.getValue("", "direction");
-		if ("in".equals(direction)) {
-			parameter.setDirection(ProcedureParameter.IN_PARAMETER);
-		} else if ("out".equals(direction)) {
-			parameter.setDirection(ProcedureParameter.OUT_PARAMETER);
-		} else if ("in_out".equals(direction)) {
-			parameter.setDirection(ProcedureParameter.IN_OUT_PARAMETER);
-		}
-
-		procedure.addCallParameter(parameter);
-	}
-
-	private void processStartQuery(Attributes attributes) throws SAXException {
-		String name = attributes.getValue("", "name");
-		if (null == name) {
-			throw new SAXException("MapLoader::processStartQuery(), no query name.");
-		}
-
-		this.queryBuilder = new QueryDescriptorLoader();
-
-		String type = attributes.getValue("", "type");
-		// Legacy format support (v7 and older)
-		if(type == null) {
-			queryBuilder.setLegacyFactory(attributes.getValue("", "factory"));
-		} else {
-			queryBuilder.setQueryType(type);
-		}
-
-		String rootType = attributes.getValue("", "root");
-		String rootName = attributes.getValue("", "root-name");
-		String resultEntity = attributes.getValue("", "result-entity");
-
-		queryBuilder.setName(name);
-		queryBuilder.setRoot(dataMap, rootType, rootName);
-
-		// TODO: Andrus, 2/13/2006 'result-type' is only used in ProcedureQuery
-		// and is
-		// deprecated in 1.2
-		if (!Util.isEmptyString(resultEntity)) {
-			queryBuilder.setResultEntity(resultEntity);
-		}
-	}
-
-	private void processStartQueryProperty(Attributes attributes) throws SAXException {
-		String name = attributes.getValue("", "name");
-		if (null == name) {
-			throw new SAXException("MapLoader::processStartQueryProperty(), no property name.");
-		}
-
-		String value = attributes.getValue("", "value");
-		if (null == value) {
-			throw new SAXException("MapLoader::processStartQueryProperty(), no property value.");
-		}
-
-		queryBuilder.addProperty(name, value);
-	}
-
-	private void processStartDataMapProperty(Attributes attributes) throws SAXException {
-		String name = attributes.getValue("", "name");
-		if (null == name) {
-			throw new SAXException("MapLoader::processStartDataMapProperty(), no property name.");
-		}
-
-		String value = attributes.getValue("", "value");
-		if (null == value) {
-			throw new SAXException("MapLoader::processStartDataMapProperty(), no property value.");
-		}
-
-		if (mapProperties == null) {
-			mapProperties = new TreeMap<String, Object>();
-		}
-
-		mapProperties.put(name, value);
-	}
-
-	private void processEndQueryPrefetch() {
-		queryBuilder.addPrefetch(charactersBuffer.toString());
-	}
-
-	private void processStartQueryOrdering(Attributes attributes) {
-		descending = attributes.getValue("", "descending");
-		ignoreCase = attributes.getValue("", "ignore-case");
-	}
-
-	private void processEndQuery() {
-		dataMap.addQueryDescriptor(queryBuilder.buildQueryDescriptor());
-		queryBuilder = null;
-	}
-
-	private void processEndEjbqlQuery() throws SAXException {
-		queryBuilder.setEjbql(charactersBuffer.toString());
-	}
-
-	private void processEndQuerySQL() {
-		queryBuilder.addSql(charactersBuffer.toString(), sqlKey);
-		sqlKey = null;
-	}
-
-	private void processEndQualifier() {
-		String qualifier = charactersBuffer.toString();
-		if (qualifier.trim().length() == 0) {
-			return;
-		}
-
-		// qualifier can belong to ObjEntity, DbEntity or a query
-		if (objEntity != null) {
-			objEntity.setDeclaredQualifier(ExpressionFactory.exp(qualifier));
-		} else if (dbEntity != null) {
-			dbEntity.setQualifier(ExpressionFactory.exp(qualifier));
-		} else {
-			queryBuilder.setQualifier(qualifier);
-		}
-	}
-
-	private void processEndQueryOrdering() {
-		String path = charactersBuffer.toString();
-		queryBuilder.addOrdering(path, descending, ignoreCase);
-	}
-
-	private void processEndDbAttribute() {
-		attrib = null;
-	}
-
-	private void processEndDbEntity() {
-		dbEntity = null;
-	}
-
-	private void processEndProcedure() {
-		procedure = null;
-	}
-
-	private void processEndProcedureParameter() {
-	}
-
-	private void processEndDbGeneratorType() {
-		if (dbEntity == null)
-			return;
-		DbKeyGenerator pkGenerator = dbEntity.getPrimaryKeyGenerator();
-		if (pkGenerator == null)
-			return;
-		pkGenerator.setGeneratorType(charactersBuffer.toString());
-		if (pkGenerator.getGeneratorType() == null) {
-			dbEntity.setPrimaryKeyGenerator(null);
-		}
-	}
-
-	private void processEndDbGeneratorName() {
-		if (dbEntity == null)
-			return;
-		DbKeyGenerator pkGenerator = dbEntity.getPrimaryKeyGenerator();
-		if (pkGenerator == null)
-			return;
-		pkGenerator.setGeneratorName(charactersBuffer.toString());
-	}
-
-	private void processEndDbKeyCacheSize() {
-		if (dbEntity == null)
-			return;
-		DbKeyGenerator pkGenerator = dbEntity.getPrimaryKeyGenerator();
-		if (pkGenerator == null)
-			return;
-		try {
-			pkGenerator.setKeyCacheSize(new Integer(charactersBuffer.toString().trim()));
-		} catch (Exception ex) {
-			pkGenerator.setKeyCacheSize(null);
-		}
-	}
-
-	private void processEndDataMap() {
-		if (mapProperties != null) {
-			dataMap.initWithProperties(mapProperties);
-		}
-
-		mapProperties = null;
-		mapVersion = null;
-	}
-
-	private void processEndObjEntity() {
-		objEntity = null;
-	}
-
-	private void processEndEmbeddable() {
-		embeddable = null;
-	}
-
-	private void processEndEmbeddedAttribute() {
-		embeddedAttribute = null;
-	}
-
-	private void processEndDbRelationship() {
-		dbRelationship = null;
-	}
-
-	private void processEndObjRelationship() {
-		objRelationship = null;
-	}
-
-	/** Prints the attributes. Used for error reporting purposes. */
-	private StringBuffer printAttributes(Attributes atts) {
-		StringBuffer sb = new StringBuffer();
-		String name, value;
-		for (int i = 0; i < atts.getLength(); i++) {
-			value = atts.getQName(i);
-			name = atts.getValue(i);
-			sb.append("Name: ").append(name).append("\tValue: ").append(value).append("\n");
-		}
-		return sb;
-	}
-
-	@Override
-	public void characters(char[] text, int start, int length) throws org.xml.sax.SAXException {
-		if (charactersBuffer != null) {
-			charactersBuffer.append(text, start, length);
-		}
-	}
-
-	private void rememberCurrentState(String tag, Attributes attrs) {
-		currentTag = tag;
-		currentAttributes = attrs;
-	}
-
-	private void resetCurrentState() {
-		currentTag = null;
-		currentAttributes = null;
-	}
-
-	/**
-	 * @since 2.0
-	 */
-	String convertClassNameFromV1_2(String name) {
-		if (name == null) {
-			return null;
-		}
-
-		// upgrade from v. <= 1.2
-		if (name.startsWith(_1_2_PACKAGE_PREFIX)) {
-			return _2_0_PACKAGE_PREFIX + name.substring(_1_2_PACKAGE_PREFIX.length());
-		}
-
-		return name;
-	}
-
-	abstract class StartClosure {
-
-		abstract void execute(Attributes attributes) throws SAXException;
-	}
-
-	abstract class EndClosure {
-
-		abstract void execute() throws SAXException;
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java
index 57bfca3..ae03d13 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java
@@ -24,7 +24,6 @@ import java.util.Iterator;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
-import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.util.CayenneMapEntry;
 import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
@@ -100,28 +99,15 @@ public class ObjAttribute extends Attribute implements ConfigurationNode {
      * @since 1.1
      */
     @Override
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<obj-attribute name=\"" + getName() + '\"');
-
-        if (getType() != null) {
-            encoder.print(" type=\"");
-            encoder.print(Util.encodeXmlAttribute(getType()));
-            encoder.print('\"');
-        }
-
-        if (isUsedForLocking()) {
-            encoder.print(" lock=\"true\"");
-        }
-
-        // If this obj attribute is mapped to db attribute
-        if (/*getDbAttribute() != null
-                || (((ObjEntity) getEntity()).isAbstract() && */!Util.isEmptyString(getDbAttributePath())) {
-            encoder.print(" db-attribute-path=\"");
-            encoder.print(Util.encodeXmlAttribute(getDbAttributePath()));
-            encoder.print('\"');
-        }
-
-        encoder.println("/>");
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("obj-attribute")
+                .attribute("name", getName())
+                .attribute("type", getType())
+                .attribute("lock", isUsedForLocking())
+                .attribute("db-attribute-path", getDbAttributePath());
+
+        delegate.visitObjAttribute(this);
+        encoder.end();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/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 fee79a3..311f5ed 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
@@ -118,103 +118,59 @@ public class ObjEntity extends Entity implements ObjEntityListener, Configuratio
      * @since 1.1
      */
     @Override
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<obj-entity name=\"");
-        encoder.print(getName());
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("obj-entity").attribute("name", getName());
 
-        // additionally validate that superentity exists
+        // additionally validate that super entity exists
         if (getSuperEntityName() != null && getSuperEntity() != null) {
-            encoder.print("\" superEntityName=\"");
-            encoder.print(getSuperEntityName());
+            encoder.attribute("superEntityName", getSuperEntityName());
         }
 
-        if (isAbstract()) {
-            encoder.print("\" abstract=\"true");
-        }
-
-        if (isServerOnly()) {
-            encoder.print("\" serverOnly=\"true");
-        }
-
-        if (getClassName() != null) {
-            encoder.print("\" className=\"");
-            encoder.print(getClassName());
-        }
-
-        if (getClientClassName() != null) {
-            encoder.print("\" clientClassName=\"");
-            encoder.print(getClientClassName());
-        }
-
-        if (isReadOnly()) {
-            encoder.print("\" readOnly=\"true");
-        }
+        encoder.attribute("abstract", isAbstract())
+                .attribute("serverOnly", isServerOnly())
+                .attribute("className", getClassName())
+                .attribute("clientClassName", getClientClassName())
+                .attribute("readOnly", isReadOnly());
 
         if (getDeclaredLockType() == LOCK_TYPE_OPTIMISTIC) {
-            encoder.print("\" lock-type=\"optimistic");
+            encoder.attribute("lock-type", "optimistic");
         }
 
         if (getDbEntityName() != null && getDbEntity() != null) {
-
             // not writing DbEntity name if sub entity has same DbEntity
             // as super entity, see CAY-1477
             if (!(getSuperEntity() != null && getSuperEntity().getDbEntity() == getDbEntity())) {
-                encoder.print("\" dbEntityName=\"");
-                encoder.print(Util.encodeXmlAttribute(getDbEntityName()));
+                encoder.attribute("dbEntityName", getDbEntityName());
             }
         }
 
         if (getSuperEntityName() == null && getSuperClassName() != null) {
-            encoder.print("\" superClassName=\"");
-            encoder.print(getSuperClassName());
+            encoder.attribute("superClassName", getSuperClassName());
         }
 
         if (getSuperEntityName() == null && getClientSuperClassName() != null) {
-            encoder.print("\" clientSuperClassName=\"");
-            encoder.print(getClientSuperClassName());
-        }
-
-        // deprecated
-        if (isExcludingSuperclassListeners()) {
-            encoder.print("\" exclude-superclass-listeners=\"true");
-        }
-
-        // deprecated
-        if (isExcludingDefaultListeners()) {
-            encoder.print("\" exclude-default-listeners=\"true");
+            encoder.attribute("clientSuperClassName", getClientSuperClassName());
         }
 
-        encoder.println("\">");
-        encoder.indent(1);
-
         if (qualifier != null) {
-            encoder.print("<qualifier>");
-            qualifier.encodeAsXML(encoder);
-            encoder.println("</qualifier>");
+            encoder.start("qualifier").nested(qualifier, delegate).end();
         }
 
         // store attributes
-        encoder.print(getDeclaredAttributes());
+        encoder.nested(getDeclaredAttributes(), delegate);
 
         for (Map.Entry<String, String> override : attributeOverrides.entrySet()) {
-            encoder.print("<attribute-override name=\"" + override.getKey() + '\"');
-            encoder.print(" db-attribute-path=\"");
-            encoder.print(Util.encodeXmlAttribute(override.getValue()));
-            encoder.print('\"');
-            encoder.println("/>");
-        }
-
-        // deprecated
-        // write entity listeners
-        for (EntityListener entityListener : entityListeners) {
-            entityListener.encodeAsXML(encoder);
+            encoder.start("attribute-override")
+                    .attribute("name", override.getKey())
+                    .attribute("db-attribute-path", override.getValue())
+                    .end();
         }
 
         // write entity-level callbacks
         getCallbackMap().encodeCallbacksAsXML(encoder);
 
-        encoder.indent(-1);
-        encoder.println("</obj-entity>");
+        delegate.visitObjEntity(this);
+        encoder.end();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java
index 6163684..0fa0812 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java
@@ -104,51 +104,43 @@ public class ObjRelationship extends Relationship implements ConfigurationNode {
      * 
      * @since 1.1
      */
-    public void encodeAsXML(XMLEncoder encoder) {
-        ObjEntity source = (ObjEntity) getSourceEntity();
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        ObjEntity source = getSourceEntity();
         if (source == null) {
             return;
         }
 
-        encoder.print("<obj-relationship name=\"" + getName());
-        encoder.print("\" source=\"" + source.getName());
+        encoder.start("obj-relationship")
+                .attribute("name", getName())
+                .attribute("source", source.getName());
 
         // looking up a target entity ensures that bogus names are not saved...
-        // whether
-        // this is good or bad is debatable, as users may want to point to
-        // non-existent
-        // entities on purpose.
-        ObjEntity target = (ObjEntity) getTargetEntity();
+        // whether this is good or bad is debatable, as users may want to point to
+        // non-existent entities on purpose.
+        ObjEntity target = getTargetEntity();
         if (target != null) {
-            encoder.print("\" target=\"" + target.getName());
+            encoder.attribute("target", target.getName());
         }
 
         if (getCollectionType() != null && !DEFAULT_COLLECTION_TYPE.equals(getCollectionType())) {
-            encoder.print("\" collection-type=\"" + getCollectionType());
+            encoder.attribute("collection-type", getCollectionType());
         }
 
-        if (getMapKey() != null) {
-            encoder.print("\" map-key=\"" + getMapKey());
-        }
-
-        if (isUsedForLocking()) {
-            encoder.print("\" lock=\"true");
-        }
+        encoder.attribute("lock", isUsedForLocking())
+                .attribute("map-key", getMapKey());
 
         String deleteRule = DeleteRule.deleteRuleName(getDeleteRule());
-        if (getDeleteRule() != DeleteRule.NO_ACTION && deleteRule != null) {
-            encoder.print("\" deleteRule=\"" + deleteRule);
+        if (deleteRule != null && getDeleteRule() != DeleteRule.NO_ACTION) {
+            encoder.attribute("deleteRule", deleteRule);
         }
 
         // quietly get rid of invalid path... this is not the best way of doing
-        // things,
-        // but it is consistent across map package
-        String path = getValidRelationshipPath();
-        if (path != null) {
-            encoder.print("\" db-relationship-path=\"" + path);
-        }
+        // things, but it is consistent across map package
+        encoder.attribute("db-relationship-path", getValidRelationshipPath());
 
-        encoder.println("\"/>");
+        delegate.visitObjRelationship(this);
+        encoder.end();
     }
 
     /**
@@ -563,8 +555,9 @@ public class ObjRelationship extends Relationship implements ConfigurationNode {
     /**
      * Sets relationship path, but does not trigger its conversion to
      * List<DbRelationship> For internal purposes, primarily datamap loading
+     * @since 4.1 this method is public as it is used by new XML loaders
      */
-    void setDeferredDbRelationshipPath(String relationshipPath) {
+    public void setDeferredDbRelationshipPath(String relationshipPath) {
         if (!Util.nullSafeEquals(getDbRelationshipPath(), relationshipPath)) {
             deferredPath = relationshipPath;
         }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/Procedure.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/Procedure.java b/cayenne-server/src/main/java/org/apache/cayenne/map/Procedure.java
index 8ec25cb..5358178 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/Procedure.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/Procedure.java
@@ -22,7 +22,6 @@ package org.apache.cayenne.map;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.util.CayenneMapEntry;
-import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
 
@@ -90,34 +89,16 @@ public class Procedure implements ConfigurationNode, CayenneMapEntry, XMLSeriali
      * 
      * @since 1.1
      */
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<procedure name=\"");
-        encoder.print(Util.encodeXmlAttribute(getName()));
-        encoder.print('\"');
-
-        if (getSchema() != null && getSchema().trim().length() > 0) {
-            encoder.print(" schema=\"");
-            encoder.print(getSchema().trim());
-            encoder.print('\"');
-        }
-
-        if (getCatalog() != null && getCatalog().trim().length() > 0) {
-            encoder.print(" catalog=\"");
-            encoder.print(getCatalog().trim());
-            encoder.print('\"');
-        }
-
-        if (isReturningValue()) {
-            encoder.print(" returningValue=\"true\"");
-        }
-
-        encoder.println('>');
-
-        encoder.indent(1);
-        encoder.print(getCallParameters());
-        encoder.indent(-1);
-
-        encoder.println("</procedure>");
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("procedure")
+                .attribute("name", getName())
+                .attribute("schema", getSchema())
+                .attribute("catalog", getCatalog())
+                .attribute("returningValue", isReturningValue())
+                .nested(getCallParameters(), delegate);
+        delegate.visitProcedure(this);
+        encoder.end();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/ProcedureParameter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/ProcedureParameter.java b/cayenne-server/src/main/java/org/apache/cayenne/map/ProcedureParameter.java
index 1180f30..b9fb55a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/ProcedureParameter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/ProcedureParameter.java
@@ -25,7 +25,6 @@ import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.util.CayenneMapEntry;
-import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
 
@@ -85,8 +84,7 @@ public class ProcedureParameter implements ConfigurationNode, CayenneMapEntry,
 
     public void setParent(Object parent) {
         if (parent != null && !(parent instanceof Procedure)) {
-            throw new IllegalArgumentException("Expected null or Procedure, got: "
-                    + parent);
+            throw new IllegalArgumentException("Expected null or Procedure, got: " + parent);
         }
 
         setProcedure((Procedure) parent);
@@ -97,40 +95,25 @@ public class ProcedureParameter implements ConfigurationNode, CayenneMapEntry,
      * 
      * @since 1.1
      */
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<procedure-parameter name=\""
-                + Util.encodeXmlAttribute(getName())
-                + '\"');
-
-        String type = TypesMapping.getSqlNameByType(getType());
-        if (type != null) {
-            encoder.print(" type=\"" + type + '\"');
-        }
-
-        if (getMaxLength() > 0) {
-            encoder.print(" length=\"");
-            encoder.print(getMaxLength());
-            encoder.print('\"');
-        }
-
-        if (getPrecision() > 0) {
-            encoder.print(" precision=\"");
-            encoder.print(getPrecision());
-            encoder.print('\"');
-        }
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("procedure-parameter")
+                .attribute("name", getName())
+                .attribute("type", TypesMapping.getSqlNameByType(getType()))
+                .attribute("length", getMaxLength() > 0 ? getMaxLength() : 0)
+                .attribute("precision", getPrecision() > 0 ? getPrecision() : 0);
 
         int direction = getDirection();
         if (direction == ProcedureParameter.IN_PARAMETER) {
-            encoder.print(" direction=\"in\"");
-        }
-        else if (direction == ProcedureParameter.IN_OUT_PARAMETER) {
-            encoder.print(" direction=\"in_out\"");
-        }
-        else if (direction == ProcedureParameter.OUT_PARAMETER) {
-            encoder.print(" direction=\"out\"");
+            encoder.attribute("direction", "in");
+        } else if (direction == ProcedureParameter.IN_OUT_PARAMETER) {
+            encoder.attribute("direction", "in_out");
+        } else if (direction == ProcedureParameter.OUT_PARAMETER) {
+            encoder.attribute("direction", "out");
         }
 
-        encoder.println("/>");
+        delegate.visitProcedureParameter(this);
+        encoder.end();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/ProcedureQueryDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/ProcedureQueryDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/map/ProcedureQueryDescriptor.java
index fa1a087..a3ad9cf 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/ProcedureQueryDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/ProcedureQueryDescriptor.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.map;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.query.ProcedureQuery;
 import org.apache.cayenne.util.XMLEncoder;
 
@@ -65,41 +66,26 @@ public class ProcedureQueryDescriptor extends QueryDescriptor {
     }
 
     @Override
-    public void encodeAsXML(XMLEncoder encoder) {
-        encoder.print("<query name=\"");
-        encoder.print(getName());
-        encoder.print("\" type=\"");
-        encoder.print(type);
-
-        encoder.print("\" root=\"");
-        encoder.print(MapLoader.PROCEDURE_ROOT);
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+        encoder.start("query")
+                .attribute("name", getName())
+                .attribute("type", getType())
+                .attribute("root", QueryDescriptor.PROCEDURE_ROOT);
 
         String rootString = null;
-
         if (root instanceof String) {
             rootString = root.toString();
-        }
-        else if (root instanceof Procedure) {
+        } else if (root instanceof Procedure) {
             rootString = ((Procedure) root).getName();
         }
 
-        if (rootString != null) {
-            encoder.print("\" root-name=\"");
-            encoder.print(rootString);
-        }
-
-        if (resultEntityName != null) {
-            encoder.print("\" result-entity=\"");
-            encoder.print(resultEntityName);
-        }
-
-        encoder.println("\">");
-        encoder.indent(1);
+        encoder.attribute("root-name", rootString)
+                .attribute("result-entity", resultEntityName);
 
         // print properties
         encodeProperties(encoder);
 
-        encoder.indent(-1);
-        encoder.println("</query>");
+        delegate.visitQuery(this);
+        encoder.end();
     }
 }

[05/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - new XML loader for DataMap - new project version - updated test projects

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoaderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoaderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoaderTest.java
deleted file mode 100644
index a9c88b6..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoaderTest.java
+++ /dev/null
@@ -1,165 +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.configuration;
-
-import org.apache.cayenne.ConfigurationException;
-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.resource.URLResource;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.net.URL;
-import java.util.Collection;
-import java.util.Iterator;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
-public class XMLDataChannelDescriptorLoaderTest {
-
-    private Injector injector;
-
-    @Before
-    public void setUp() throws Exception {
-        Module testModule = new Module() {
-
-            public void configure(Binder binder) {
-                binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
-                binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
-                binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
-                binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-            }
-        };
-
-        this.injector = DIBootstrap.createInjector(testModule);
-    }
-
-    @Test
-    public void testLoadEmpty() {
-
-        // create and initialize loader instance to test
-        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
-        injector.injectMembers(loader);
-
-        String testConfigName = "testConfig1";
-
-        URL url = getClass().getResource("cayenne-" + testConfigName + ".xml");
-        ConfigurationTree<DataChannelDescriptor> tree = loader.load(new URLResource(url));
-
-        assertNotNull(tree);
-        assertNotNull(tree.getRootNode());
-        assertEquals(testConfigName, tree.getRootNode().getName());
-    }
-
-    @Test
-    public void testLoad_MissingConfig() throws Exception {
-
-        // create and initialize loader instance to test
-        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
-        injector.injectMembers(loader);
-
-        try {
-            loader.load(new URLResource(new URL("file:///no_such_resource")));
-            fail("No exception was thrown on bad absent config name");
-        } catch (ConfigurationException e) {
-            // expected
-        }
-    }
-
-    @Test
-    public void testLoadDataMap() {
-
-        // create and initialize loader instance to test
-        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
-        injector.injectMembers(loader);
-
-        String testConfigName = "testConfig2";
-        URL url = getClass().getResource("cayenne-" + testConfigName + ".xml");
-
-        ConfigurationTree<DataChannelDescriptor> tree = loader.load(new URLResource(url));
-
-        assertNotNull(tree);
-        assertNotNull(tree.getRootNode());
-
-        assertEquals(testConfigName, tree.getRootNode().getName());
-
-        Collection<DataMap> maps = tree.getRootNode().getDataMaps();
-        assertEquals(1, maps.size());
-        assertEquals("testConfigMap2", maps.iterator().next().getName());
-    }
-
-    @Test
-    public void testLoadDataEverything() {
-
-        // create and initialize loader instance to test
-        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
-        injector.injectMembers(loader);
-
-        String testConfigName = "testConfig3";
-        URL url = getClass().getResource("cayenne-" + testConfigName + ".xml");
-
-        ConfigurationTree<DataChannelDescriptor> tree = loader.load(new URLResource(url));
-
-        assertNotNull(tree);
-
-        DataChannelDescriptor descriptor = tree.getRootNode();
-        assertNotNull(descriptor);
-        assertEquals(testConfigName, descriptor.getName());
-
-        Collection<DataMap> maps = descriptor.getDataMaps();
-        assertEquals(2, maps.size());
-
-        Iterator<DataMap> mapsIt = maps.iterator();
-
-        DataMap map1 = mapsIt.next();
-        DataMap map2 = mapsIt.next();
-
-        assertEquals("testConfigMap3_1", map1.getName());
-        assertEquals("testConfigMap3_2", map2.getName());
-
-        Collection<DataNodeDescriptor> nodes = descriptor.getNodeDescriptors();
-        assertEquals(1, nodes.size());
-
-        DataNodeDescriptor node1 = nodes.iterator().next();
-        assertEquals("testConfigNode3", node1.getName());
-        assertNull(node1.getParameters());
-        assertNotNull(node1.getDataSourceDescriptor());
-        assertEquals(1, node1.getDataSourceDescriptor().getMinConnections());
-        assertEquals(1, node1.getDataSourceDescriptor().getMaxConnections());
-
-        assertEquals("org.example.test.Adapter", node1.getAdapterType());
-        assertEquals("org.example.test.DataSourceFactory", node1.getDataSourceFactoryType());
-        assertEquals("org.example.test.SchemaUpdateStartegy", node1.getSchemaUpdateStrategyType());
-        assertNotNull(node1.getDataMapNames());
-
-        assertEquals(1, node1.getDataMapNames().size());
-
-        assertEquals("testConfigMap3_2", node1.getDataMapNames().iterator().next());
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/BaseHandlerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/BaseHandlerTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/BaseHandlerTest.java
new file mode 100644
index 0000000..4cefbff
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/BaseHandlerTest.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.configuration.xml;
+
+import java.io.InputStream;
+
+import org.apache.cayenne.util.Util;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * @since 4.1
+ */
+public abstract class BaseHandlerTest {
+
+    protected void parse(String tag, HandlerFactory factory) throws Exception {
+        try(InputStream in = DbKeyGeneratorHandlerTest.class.getResource(getClass().getSimpleName() + ".xml").openStream()) {
+            XMLReader parser = Util.createXmlReader();
+            DefaultHandler handler = new TestRootHandler(parser, tag, factory);
+            parser.setContentHandler(handler);
+            parser.parse(new InputSource(in));
+        }
+    }
+
+    public interface HandlerFactory {
+        NamespaceAwareNestedTagHandler createHandler(NamespaceAwareNestedTagHandler parent);
+    }
+
+    public static class TestRootHandler extends NamespaceAwareNestedTagHandler {
+
+        private String rootTag;
+        private BaseHandlerTest.HandlerFactory factory;
+
+        public TestRootHandler(XMLReader parser, String rootTag, BaseHandlerTest.HandlerFactory factory) {
+            super(new LoaderContext(parser, new DefaultHandlerFactory()));
+            setTargetNamespace("");
+            this.rootTag = rootTag;
+            this.factory = factory;
+        }
+
+        @Override
+        protected boolean processElement(String namespaceURI, String localName, Attributes attributes) throws SAXException {
+            return false;
+        }
+
+        @Override
+        protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String qName, Attributes attributes) {
+            if(localName.equals(rootTag)) {
+                return factory.createHandler(this);
+            }
+            return super.createChildTagHandler(namespaceURI, localName, qName, attributes);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/DbEntityHandlerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/DbEntityHandlerTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/DbEntityHandlerTest.java
new file mode 100644
index 0000000..1a7da41
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/DbEntityHandlerTest.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.configuration.xml;
+
+import java.sql.Types;
+
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.1
+ */
+public class DbEntityHandlerTest extends BaseHandlerTest {
+
+    @Test
+    public void testLoad() throws Exception {
+
+        final DataMap map = new DataMap();
+        assertTrue(map.getDbEntities().isEmpty());
+
+        parse("db-entity", new HandlerFactory() {
+            @Override
+            public NamespaceAwareNestedTagHandler createHandler(NamespaceAwareNestedTagHandler parent) {
+                return new DbEntityHandler(parent, map);
+            }
+        });
+
+        assertEquals(1, map.getDbEntities().size());
+
+        DbEntity entity = map.getDbEntity("ARTGROUP");
+        assertNotNull(entity);
+        assertNull(entity.getPrimaryKeyGenerator());
+        assertEquals(3, entity.getAttributes().size());
+        assertEquals("catalog", entity.getCatalog());
+        assertEquals("schema", entity.getSchema());
+        assertEquals("name = \"test\"", entity.getQualifier().toString());
+
+        DbAttribute attribute = entity.getAttribute("GROUP_ID");
+        assertNotNull(attribute);
+        assertTrue(attribute.isMandatory());
+        assertTrue(attribute.isPrimaryKey());
+        assertTrue(attribute.isGenerated());
+        assertEquals(Types.INTEGER, attribute.getType());
+
+        attribute = entity.getAttribute("NAME");
+        assertNotNull(attribute);
+        assertTrue(attribute.isMandatory());
+        assertFalse(attribute.isPrimaryKey());
+        assertFalse(attribute.isGenerated());
+        assertEquals(100, attribute.getMaxLength());
+        assertEquals(Types.VARCHAR, attribute.getType());
+
+        attribute = entity.getAttribute("PARENT_GROUP_ID");
+        assertNotNull(attribute);
+        assertFalse(attribute.isMandatory());
+        assertFalse(attribute.isPrimaryKey());
+        assertFalse(attribute.isGenerated());
+        assertEquals(10, attribute.getScale());
+        assertEquals(Types.BIT, attribute.getType());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/DbKeyGeneratorHandlerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/DbKeyGeneratorHandlerTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/DbKeyGeneratorHandlerTest.java
new file mode 100644
index 0000000..157f8d0
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/DbKeyGeneratorHandlerTest.java
@@ -0,0 +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
+ *
+ *    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.configuration.xml;
+
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbKeyGenerator;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.1
+ */
+public class DbKeyGeneratorHandlerTest extends BaseHandlerTest {
+
+    @Test
+    public void testParsing()throws Exception {
+        final DbEntity dbEntity = new DbEntity("TEST");
+
+        parse("db-key-generator", new HandlerFactory() {
+            @Override
+            public NamespaceAwareNestedTagHandler createHandler(NamespaceAwareNestedTagHandler parent) {
+                return new DbKeyGeneratorHandler(parent, dbEntity);
+            }
+        });
+
+        assertNotNull(dbEntity.getPrimaryKeyGenerator());
+        assertEquals("gallery_seq", dbEntity.getPrimaryKeyGenerator().getGeneratorName());
+        assertEquals(20, (int)dbEntity.getPrimaryKeyGenerator().getKeyCacheSize());
+        assertEquals(DbKeyGenerator.ORACLE_TYPE, dbEntity.getPrimaryKeyGenerator().getGeneratorType());
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/DbRelationshipHandlerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/DbRelationshipHandlerTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/DbRelationshipHandlerTest.java
new file mode 100644
index 0000000..4aba0cb
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/DbRelationshipHandlerTest.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.configuration.xml;
+
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.1
+ */
+public class DbRelationshipHandlerTest extends BaseHandlerTest {
+
+    @Test
+    public void testParsing()throws Exception {
+        final DataMap map = new DataMap();
+        DbEntity entity = new DbEntity("ARTIST");
+        map.addDbEntity(entity);
+        assertEquals(0, entity.getRelationships().size());
+
+        parse("db-relationship", new HandlerFactory() {
+            @Override
+            public NamespaceAwareNestedTagHandler createHandler(NamespaceAwareNestedTagHandler parent) {
+                return new DbRelationshipHandler(parent, map);
+            }
+        });
+
+        assertEquals(1, entity.getRelationships().size());
+        DbRelationship relationship = entity.getRelationship("artistPaintings");
+        assertNotNull(relationship);
+
+        assertEquals("PAINTING", relationship.getTargetEntityName());
+        assertTrue(relationship.isToDependentPK());
+        assertTrue(relationship.isToMany());
+        assertEquals("ID", relationship.getJoins().get(0).getSourceName());
+        assertEquals("ARTIST_ID", relationship.getJoins().get(0).getTargetName());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/ObjEntityHandlerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/ObjEntityHandlerTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/ObjEntityHandlerTest.java
new file mode 100644
index 0000000..963bb9a
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/ObjEntityHandlerTest.java
@@ -0,0 +1,86 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.1
+ */
+public class ObjEntityHandlerTest extends BaseHandlerTest {
+
+    @Test
+    public void testLoad() throws Exception {
+
+        final DataMap map = new DataMap();
+        assertEquals(0, map.getObjEntities().size());
+
+        parse("obj-entity", new HandlerFactory() {
+            @Override
+            public NamespaceAwareNestedTagHandler createHandler(NamespaceAwareNestedTagHandler parent) {
+                return new ObjEntityHandler(parent, map);
+            }
+        });
+
+        assertEquals(1, map.getObjEntities().size());
+        ObjEntity entity = map.getObjEntity("ArtistCallback");
+        assertNotNull(entity);
+        assertTrue(entity.isAbstract());
+        assertTrue(entity.isReadOnly());
+        assertTrue(entity.isServerOnly());
+        assertFalse(entity.isClientAllowed());
+        assertEquals(3, entity.getAttributes().size());
+        assertEquals(8, entity.getCallbackMethods().size());
+        assertEquals(ObjEntity.LOCK_TYPE_OPTIMISTIC, entity.getDeclaredLockType());
+        assertEquals("org.apache.cayenne.testdo.testmap.ArtistCallback", entity.getClassName());
+        assertNull("super.class should be suppressed by super entity", entity.getSuperClassName());
+        assertEquals("Artist", entity.getSuperEntityName());
+        assertEquals("client.class", entity.getClientClassName());
+        assertNull("client.super.class should be suppressed by super entity", entity.getClientSuperClassName());
+        assertEquals("ARTIST_CT", entity.getDbEntityName());
+
+        ObjAttribute attribute = entity.getAttribute("artistName");
+        assertNotNull(attribute);
+        assertEquals("NAME", attribute.getDbAttributeName());
+        assertEquals("java.lang.String", attribute.getType());
+        assertTrue(attribute.isUsedForLocking());
+
+        attribute = entity.getAttribute("dateOfBirth");
+        assertNotNull(attribute);
+        assertNull(attribute.getDbAttributeName());
+        assertEquals("java.util.Date", attribute.getType());
+        assertFalse(attribute.isUsedForLocking());
+
+        attribute = entity.getAttribute("embeddable1");
+        assertNotNull(attribute);
+        assertNull(attribute.getDbAttributeName());
+        assertEquals("org.apache.cayenne.testdo.embeddable.Embeddable1", attribute.getType());
+        assertFalse(attribute.isUsedForLocking());
+
+        String override = entity.getDeclaredAttributeOverrides().get("name");
+        assertEquals("parent.child.name", override);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/ObjRelationshipHandlerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/ObjRelationshipHandlerTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/ObjRelationshipHandlerTest.java
new file mode 100644
index 0000000..2765955
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/ObjRelationshipHandlerTest.java
@@ -0,0 +1,61 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DeleteRule;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.1
+ */
+public class ObjRelationshipHandlerTest extends BaseHandlerTest {
+
+    @Test
+    public void testLoad() throws Exception {
+
+        final DataMap map = new DataMap();
+        ObjEntity entity = new ObjEntity("ArtGroup");
+        map.addObjEntity(entity);
+        assertEquals(0, entity.getRelationships().size());
+
+
+        parse("obj-relationship", new HandlerFactory() {
+            @Override
+            public NamespaceAwareNestedTagHandler createHandler(NamespaceAwareNestedTagHandler parent) {
+                return new ObjRelationshipHandler(parent, map);
+            }
+        });
+
+        assertEquals(1, entity.getRelationships().size());
+        ObjRelationship relationship = entity.getRelationship("artistArray");
+        assertNotNull(relationship);
+
+        assertEquals(DeleteRule.CASCADE, relationship.getDeleteRule());
+        assertEquals("java.util.Map", relationship.getCollectionType());
+        assertEquals("artistName", relationship.getMapKey());
+        assertEquals("Artist", relationship.getTargetEntityName());
+        assertTrue(relationship.isUsedForLocking());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoaderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoaderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoaderTest.java
new file mode 100644
index 0000000..fab4129
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/XMLDataChannelDescriptorLoaderTest.java
@@ -0,0 +1,171 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import org.apache.cayenne.ConfigurationException;
+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.DataNodeDescriptor;
+import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
+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.resource.URLResource;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.URL;
+import java.util.Collection;
+import java.util.Iterator;
+
+import static org.junit.Assert.*;
+
+public class XMLDataChannelDescriptorLoaderTest {
+
+    private Injector injector;
+
+    @Before
+    public void setUp() throws Exception {
+        Module testModule = new Module() {
+
+            public void configure(Binder binder) {
+                binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
+                binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
+                binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
+                binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
+                binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
+                binder.bind(DataChannelMetaData.class).to(NoopDataChannelMetaData.class);
+
+            }
+        };
+
+        this.injector = DIBootstrap.createInjector(testModule);
+    }
+
+    @Test
+    public void testLoadEmpty() {
+
+        // create and initialize loader instance to test
+        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
+        injector.injectMembers(loader);
+
+        String testConfigName = "testConfig1";
+
+        URL url = getClass().getResource("cayenne-" + testConfigName + ".xml");
+        ConfigurationTree<DataChannelDescriptor> tree = loader.load(new URLResource(url));
+
+        assertNotNull(tree);
+        assertNotNull(tree.getRootNode());
+        assertEquals(testConfigName, tree.getRootNode().getName());
+    }
+
+    @Test
+    public void testLoad_MissingConfig() throws Exception {
+
+        // create and initialize loader instance to test
+        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
+        injector.injectMembers(loader);
+
+        try {
+            loader.load(new URLResource(new URL("file:///no_such_resource")));
+            fail("No exception was thrown on bad absent config name");
+        } catch (ConfigurationException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testLoadDataMap() {
+
+        // create and initialize loader instance to test
+        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
+        injector.injectMembers(loader);
+
+        String testConfigName = "testConfig2";
+        URL url = getClass().getResource("cayenne-" + testConfigName + ".xml");
+
+        ConfigurationTree<DataChannelDescriptor> tree = loader.load(new URLResource(url));
+
+        assertNotNull(tree);
+        assertNotNull(tree.getRootNode());
+
+        assertEquals(testConfigName, tree.getRootNode().getName());
+
+        Collection<DataMap> maps = tree.getRootNode().getDataMaps();
+        assertEquals(1, maps.size());
+        assertEquals("testConfigMap2", maps.iterator().next().getName());
+    }
+
+    @Test
+    public void testLoadDataEverything() {
+
+        // create and initialize loader instance to test
+        XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
+        injector.injectMembers(loader);
+
+        String testConfigName = "testConfig3";
+        URL url = getClass().getResource("cayenne-" + testConfigName + ".xml");
+
+        ConfigurationTree<DataChannelDescriptor> tree = loader.load(new URLResource(url));
+
+        assertNotNull(tree);
+
+        DataChannelDescriptor descriptor = tree.getRootNode();
+        assertNotNull(descriptor);
+        assertEquals(testConfigName, descriptor.getName());
+
+        Collection<DataMap> maps = descriptor.getDataMaps();
+        assertEquals(2, maps.size());
+
+        Iterator<DataMap> mapsIt = maps.iterator();
+
+        DataMap map1 = mapsIt.next();
+        DataMap map2 = mapsIt.next();
+
+        assertEquals("testConfigMap3_1", map1.getName());
+        assertEquals("testConfigMap3_2", map2.getName());
+
+        Collection<DataNodeDescriptor> nodes = descriptor.getNodeDescriptors();
+        assertEquals(1, nodes.size());
+
+        DataNodeDescriptor node1 = nodes.iterator().next();
+        assertEquals("testConfigNode3", node1.getName());
+        assertNull(node1.getParameters());
+        assertNotNull(node1.getDataSourceDescriptor());
+        assertEquals(1, node1.getDataSourceDescriptor().getMinConnections());
+        assertEquals(1, node1.getDataSourceDescriptor().getMaxConnections());
+
+        assertEquals("org.example.test.Adapter", node1.getAdapterType());
+        assertEquals("org.example.test.DataSourceFactory", node1.getDataSourceFactoryType());
+        assertEquals("org.example.test.SchemaUpdateStartegy", node1.getSchemaUpdateStrategyType());
+        assertNotNull(node1.getDataMapNames());
+
+        assertEquals(1, node1.getDataMapNames().size());
+
+        assertEquals("testConfigMap3_2", node1.getDataMapNames().iterator().next());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/XMLDataMapLoaderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/XMLDataMapLoaderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/XMLDataMapLoaderTest.java
new file mode 100644
index 0000000..e416774
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/xml/XMLDataMapLoaderTest.java
@@ -0,0 +1,158 @@
+/*****************************************************************
+ *   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.configuration.xml;
+
+import java.net.URL;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.ConfigurationNameMapper;
+import org.apache.cayenne.configuration.DataMapLoader;
+import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
+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.DbAttribute;
+import org.apache.cayenne.map.SQLTemplateDescriptor;
+import org.apache.cayenne.resource.URLResource;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class XMLDataMapLoaderTest {
+
+    private Injector injector;
+
+    private DataMapLoader loader;
+
+    @Before
+    public void setUp() throws Exception {
+        Module testModule = new Module() {
+
+            public void configure(Binder binder) {
+                binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
+                binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
+                binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
+                binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
+                binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
+                binder.bind(DataChannelMetaData.class).to(NoopDataChannelMetaData.class);
+            }
+        };
+
+        injector = DIBootstrap.createInjector(testModule);
+        loader = injector.getInstance(DataMapLoader.class);
+    }
+
+    @Test(expected = CayenneRuntimeException.class)
+    public void loadMissingConfig() throws Exception {
+        loader.load(new URLResource(new URL("file:/no_such_file_for_map_xml")));
+    }
+
+    @Test
+    public void loadEmptyConfig() throws Exception {
+        URL url = getClass().getResource("testConfigMap2.map.xml");
+        DataMap map = loader.load(new URLResource(url));
+
+        assertNotNull(map);
+        assertEquals("testConfigMap2", map.getName());
+        assertTrue(map.getDbEntities().isEmpty());
+        assertTrue(map.getObjEntities().isEmpty());
+        assertTrue(map.getProcedures().isEmpty());
+        assertTrue(map.getQueryDescriptors().isEmpty());
+        assertTrue(map.getEmbeddables().isEmpty());
+        assertNull(map.getDefaultCatalog());
+        assertNull(map.getDefaultSchema());
+        assertNull(map.getDefaultPackage());
+        assertFalse(map.isClientSupported());
+    }
+
+    @Test
+    public void loadFullDataMap() {
+        URL url = getClass().getResource("testConfigMap4.map.xml");
+        DataMap map = loader.load(new URLResource(url));
+
+        assertNotNull(map);
+        assertEquals("testConfigMap4", map.getName());
+
+        // check general state
+        assertEquals(12, map.getDbEntities().size());
+        assertEquals(17, map.getObjEntities().size());
+        assertEquals(4, map.getProcedures().size());
+        assertEquals(14, map.getQueryDescriptors().size());
+        assertEquals(1, map.getEmbeddables().size());
+        assertEquals("TEST_CATALOG", map.getDefaultCatalog());
+        assertNull(map.getDefaultSchema());
+        assertEquals("org.apache.cayenne.testdo.testmap", map.getDefaultPackage());
+        assertTrue(map.isClientSupported());
+
+        // check some loaded content
+        assertEquals("org.apache.cayenne.testdo.testmap.Artist",
+                map.getObjEntity("Artist").getClassName());
+        assertEquals(5,
+                map.getObjEntity("CompoundPainting").getAttributes().size());
+        assertEquals(3,
+                map.getObjEntity("Artist").getRelationships().size());
+        assertEquals(7,
+                map.getObjEntity("ArtistCallback").getCallbackMethods().size());
+
+        assertEquals("name = \"test\"",
+                map.getDbEntity("ARTGROUP").getQualifier().toString());
+        assertEquals(4,
+                map.getDbEntity("EXHIBIT").getAttributes().size());
+        assertEquals(3,
+                map.getDbEntity("PAINTING").getRelationships().size());
+        assertEquals("gallery_seq",
+                map.getDbEntity("GALLERY").getPrimaryKeyGenerator().getGeneratorName());
+
+        DbAttribute pk1 = map.getDbEntity("EXHIBIT").getAttribute("EXHIBIT_ID");
+        assertFalse(pk1.isGenerated());
+        assertTrue(pk1.isPrimaryKey());
+
+        DbAttribute pk2 = map.getDbEntity("GENERATED_COLUMN").getAttribute("GENERATED_COLUMN");
+        assertTrue(pk2.isGenerated());
+        assertTrue(pk2.isPrimaryKey());
+
+        assertEquals(true,
+                map.getProcedure("cayenne_tst_out_proc").isReturningValue());
+        assertEquals(1,
+                map.getProcedure("cayenne_tst_out_proc").getCallOutParameters().size());
+        assertEquals(2,
+                map.getProcedure("cayenne_tst_out_proc").getCallParameters().size());
+
+        assertEquals("true",
+                map.getQueryDescriptor("EjbqlQueryTest")
+                        .getProperty("cayenne.GenericSelectQuery.fetchingDataRows"));
+
+        SQLTemplateDescriptor descriptor = (SQLTemplateDescriptor)map.getQueryDescriptor("NonSelectingQuery");
+        assertEquals("INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ESTIMATED_PRICE) " +
+                        "VALUES (512, 'No Painting Like This', 12.5)",
+                descriptor.getAdapterSql().get("org.apache.cayenne.dba.db2.DB2Adapter"));
+
+        assertEquals("TEST",
+                map.getEmbeddable("org.apache.cayenne.testdo.Embeddable")
+                        .getAttribute("test").getDbAttributeName());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/map/DataMapTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/DataMapTest.java b/cayenne-server/src/test/java/org/apache/cayenne/map/DataMapTest.java
index 87be992..cf81326 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/DataMapTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/DataMapTest.java
@@ -19,16 +19,21 @@
 
 package org.apache.cayenne.map;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.configuration.EmptyConfigurationNodeVisitor;
+import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
+import org.apache.cayenne.resource.URLResource;
 import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
 import org.junit.Test;
-import org.xml.sax.InputSource;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
+import java.net.URL;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -40,6 +45,8 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 /**
  * DataMap unit tests.
@@ -187,7 +194,7 @@ public class DataMapTest {
         try {
             map.addObjEntity(e2);
             fail("Should not be able to add more than one entity with the same name");
-        } catch (Exception e) {
+        } catch (Exception ignored) {
         }
     }
 
@@ -403,10 +410,10 @@ public class DataMapTest {
         assertNotNull(proceduresCollection);
         assertEquals(len, proceduresCollection.size());
 
-        for (int i = 0; i < len; i++) {
-            Procedure proc = map.getProcedure(expectedNames[i]);
+        for (String expectedName : expectedNames) {
+            Procedure proc = map.getProcedure(expectedName);
             assertNotNull(proc);
-            assertEquals(expectedNames[i], proc.getName());
+            assertEquals(expectedName, proc.getName());
         }
     }
 
@@ -416,32 +423,38 @@ public class DataMapTest {
         map.setQuotingSQLIdentifiers(true);
         StringWriter w = new StringWriter();
         XMLEncoder encoder = new XMLEncoder(new PrintWriter(w));
-        map.encodeAsXML(encoder);
+        map.encodeAsXML(encoder, new EmptyConfigurationNodeVisitor());
 
         assertTrue(map.quotingSQLIdentifiers);
 
-        MapLoader loader = new MapLoader();
+        XMLDataMapLoader loader = new XMLDataMapLoader();
         try {
+            URL url = mock(URL.class);
             InputStream is = new ByteArrayInputStream(w.getBuffer().toString().getBytes("UTF-8"));
-            DataMap newMap = loader.loadDataMap(new InputSource(is));
+            when(url.openStream()).thenReturn(is);
+
+            DataMap newMap = loader.load(new URLResource(url));
             assertTrue(newMap.quotingSQLIdentifiers);
 
-        } catch (UnsupportedEncodingException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
 
         map.setQuotingSQLIdentifiers(false);
         StringWriter w2 = new StringWriter();
         XMLEncoder encoder2 = new XMLEncoder(new PrintWriter(w2));
-        map.encodeAsXML(encoder2);
+        map.encodeAsXML(encoder2, new EmptyConfigurationNodeVisitor());
 
         assertFalse(map.quotingSQLIdentifiers);
         try {
-            InputStream is = new ByteArrayInputStream(w2.getBuffer().toString().getBytes("UTF-8"));
-            DataMap newMap = loader.loadDataMap(new InputSource(is));
+            URL url = mock(URL.class);
+            InputStream is = new ByteArrayInputStream(w.getBuffer().toString().getBytes("UTF-8"));
+            when(url.openStream()).thenReturn(is);
+
+            DataMap newMap = loader.load(new URLResource(url));
             assertFalse(newMap.quotingSQLIdentifiers);
 
-        } catch (UnsupportedEncodingException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/map/MapLoaderLoadTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/MapLoaderLoadTest.java b/cayenne-server/src/test/java/org/apache/cayenne/map/MapLoaderLoadTest.java
deleted file mode 100644
index 41529da..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/MapLoaderLoadTest.java
+++ /dev/null
@@ -1,175 +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.map;
-
-import org.apache.cayenne.query.*;
-import org.apache.cayenne.test.file.FileUtil;
-import org.apache.cayenne.testdo.embeddable.Embeddable1;
-import org.apache.cayenne.testdo.testmap.Artist;
-import org.apache.cayenne.testdo.testmap.Gallery;
-import org.apache.cayenne.util.XMLEncoder;
-import org.junit.Test;
-import org.xml.sax.InputSource;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintWriter;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class MapLoaderLoadTest {
-
-    private InputSource getMapXml(String mapName) {
-        return new InputSource(getClass().getClassLoader().getResourceAsStream(mapName));
-    }
-
-    @Test
-    public void testLoadEmbeddableMap() throws Exception {
-        MapLoader mapLoader = new MapLoader();
-        DataMap map = mapLoader.loadDataMap(getMapXml("embeddable.map.xml"));
-        assertNotNull(map);
-
-        assertEquals(1, map.getEmbeddables().size());
-        Embeddable e = map.getEmbeddable(Embeddable1.class.getName());
-        assertNotNull(e);
-        assertEquals(Embeddable1.class.getName(), e.getClassName());
-
-        assertEquals(2, e.getAttributes().size());
-        EmbeddableAttribute ea1 = e.getAttribute("embedded10");
-        assertNotNull(ea1);
-        assertEquals("embedded10", ea1.getName());
-        assertEquals("java.lang.String", ea1.getType());
-        assertEquals("EMBEDDED10", ea1.getDbAttributeName());
-
-        EmbeddableAttribute ea2 = e.getAttribute("embedded20");
-        assertNotNull(ea2);
-        assertEquals("embedded20", ea2.getName());
-        assertEquals("java.lang.String", ea2.getType());
-        assertEquals("EMBEDDED20", ea2.getDbAttributeName());
-
-        ObjEntity oe = map.getObjEntity("EmbedEntity1");
-        assertNotNull(oe);
-        assertEquals(3, oe.getDeclaredAttributes().size());
-
-        EmbeddedAttribute oea1 = (EmbeddedAttribute) oe.getAttribute("embedded1");
-        assertNotNull(oea1);
-        assertEquals(Embeddable1.class.getName(), oea1.getType());
-        assertEquals(0, oea1.getAttributeOverrides().size());
-
-        EmbeddedAttribute oea2 = (EmbeddedAttribute) oe.getAttribute("embedded2");
-        assertNotNull(oea2);
-        assertEquals(Embeddable1.class.getName(), oea2.getType());
-        assertEquals(2, oea2.getAttributeOverrides().size());
-    }
-
-    @Test
-    public void testLoadTestMap() throws Exception {
-        MapLoader mapLoader = new MapLoader();
-        DataMap map = mapLoader.loadDataMap(getMapXml("testmap.map.xml"));
-        assertNotNull(map);
-
-        // test procedures
-        Procedure procedure = map.getProcedure("cayenne_tst_upd_proc");
-        assertNotNull(procedure);
-        List<ProcedureParameter> params = procedure.getCallParameters();
-        assertNotNull(params);
-        assertEquals(1, params.size());
-        ProcedureParameter param = params.get(0);
-        assertNotNull(param);
-        assertEquals("paintingPrice", param.getName());
-        assertEquals(ProcedureParameter.IN_PARAMETER, param.getDirection());
-
-        // test super class name
-        // We expect the artist entity to have a super class name... test map should be
-        // set up in that way.
-        // No other assertions can be made (the actual super class may change)
-        ObjEntity ent = map.getObjEntity("Painting");
-        assertNotNull(ent.getSuperClassName());
-
-        //text exclude... parameters
-        ObjEntity artistCallbackTestEntity = map.getObjEntity("ArtistCallback");
-        assertTrue(artistCallbackTestEntity.isExcludingDefaultListeners());
-        assertTrue(artistCallbackTestEntity.isExcludingSuperclassListeners());
-
-        checkLoadedQueries(map);
-    }
-
-    @Test
-    public void testEncodeAsXML() throws FileNotFoundException {
-        // load map
-        MapLoader mapLoader = new MapLoader();
-        DataMap map = mapLoader.loadDataMap(getMapXml("testmap.map.xml"));
-        assertNotNull(map);
-
-        // encode map
-        File file = new File(FileUtil.baseTestDirectory(), "testmap_generated.map.xml");
-        PrintWriter pw = new PrintWriter(new FileOutputStream(file));
-        map.encodeAsXML(new XMLEncoder(pw));
-        pw.close();
-    }
-
-    private void checkLoadedQueries(DataMap map) throws Exception {
-        SelectQueryDescriptor queryWithQualifier = (SelectQueryDescriptor) map.getQueryDescriptor("QueryWithQualifier");
-        assertNotNull(queryWithQualifier);
-        assertTrue(queryWithQualifier.getRoot() instanceof ObjEntity);
-        assertEquals("Artist", ((Entity) queryWithQualifier.getRoot()).getName());
-        assertNotNull(queryWithQualifier.getQualifier());
-
-        SelectQueryDescriptor queryWithOrdering = (SelectQueryDescriptor) map.getQueryDescriptor("QueryWithOrdering");
-        assertNotNull(queryWithOrdering);
-        assertTrue(queryWithOrdering.getRoot() instanceof ObjEntity);
-        assertEquals("Artist", ((Entity) queryWithOrdering.getRoot()).getName());
-        assertEquals(2, queryWithOrdering.getOrderings().size());
-
-        Ordering artistNameOrdering = queryWithOrdering.getOrderings().get(0);
-        assertEquals(Artist.ARTIST_NAME.getName(), artistNameOrdering.getSortSpecString());
-        assertFalse(artistNameOrdering.isAscending());
-        assertTrue(artistNameOrdering.isCaseInsensitive());
-
-        Ordering dobOrdering = queryWithOrdering.getOrderings().get(1);
-        assertEquals(Artist.DATE_OF_BIRTH.getName(), dobOrdering.getSortSpecString());
-        assertTrue(dobOrdering.isAscending());
-        assertFalse(dobOrdering.isCaseInsensitive());
-
-        SelectQueryDescriptor queryWithPrefetch = (SelectQueryDescriptor) map.getQueryDescriptor("QueryWithPrefetch");
-        assertNotNull(queryWithPrefetch);
-        assertTrue(queryWithPrefetch.getRoot() instanceof ObjEntity);
-        assertEquals("Gallery", ((Entity) queryWithPrefetch.getRoot()).getName());
-        assertNotNull(queryWithPrefetch.getPrefetches());
-        assertEquals(1, queryWithPrefetch.getPrefetches().size());
-        assertTrue(queryWithPrefetch.getPrefetches().contains(Gallery.PAINTING_ARRAY.getName()));
-
-        QueryDescriptor nonSelectingQuery = map.getQueryDescriptor("NonSelectingQuery");
-        assertNotNull(nonSelectingQuery);
-        assertEquals("NonSelectingQuery", nonSelectingQuery.getName());
-        assertEquals("UPPER", nonSelectingQuery.getProperties().get("cayenne.SQLTemplate.columnNameCapitalization"));
-        
-        EJBQLQueryDescriptor ejbqlQueryTest = (EJBQLQueryDescriptor) map.getQueryDescriptor("EjbqlQueryTest");
-        assertNotNull(ejbqlQueryTest);
-        assertEquals("EjbqlQueryTest", ejbqlQueryTest.getName());
-        assertNotNull(ejbqlQueryTest.getEjbql());
-        assertEquals("SHARED_CACHE", ejbqlQueryTest.getProperties().get("cayenne.GenericSelectQuery.cacheStrategy"));
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/map/MockAttribute.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/MockAttribute.java b/cayenne-server/src/test/java/org/apache/cayenne/map/MockAttribute.java
index 22ce347..238b58b 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/MockAttribute.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/MockAttribute.java
@@ -19,7 +19,7 @@
 
 package org.apache.cayenne.map;
 
-import org.apache.cayenne.map.Attribute;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.util.XMLEncoder;
 
 /**
@@ -35,7 +35,7 @@ public class MockAttribute extends Attribute {
     }
 
     @Override
-    public void encodeAsXML(XMLEncoder encoder) {
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/map/MockEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/MockEntity.java b/cayenne-server/src/test/java/org/apache/cayenne/map/MockEntity.java
index 26840aa..cfbb739 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/MockEntity.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/MockEntity.java
@@ -22,6 +22,7 @@ package org.apache.cayenne.map;
 import java.util.Iterator;
 import java.util.Map;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionException;
 import org.apache.cayenne.util.XMLEncoder;
@@ -56,7 +57,8 @@ public class MockEntity extends Entity {
         return null;
     }
 
-    public void encodeAsXML(XMLEncoder encoder) {
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/map/MockRelationship.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/MockRelationship.java b/cayenne-server/src/test/java/org/apache/cayenne/map/MockRelationship.java
index 2150bcf..2b89a34 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/MockRelationship.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/MockRelationship.java
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne.map;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.util.XMLEncoder;
 
 public class MockRelationship extends Relationship {
@@ -36,7 +37,8 @@ public class MockRelationship extends Relationship {
         return null;
     }
 
-    public void encodeAsXML(XMLEncoder encoder) {
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/map/ObjRelationshipIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/ObjRelationshipIT.java b/cayenne-server/src/test/java/org/apache/cayenne/map/ObjRelationshipIT.java
index bc8f7a5..29bfa35 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/ObjRelationshipIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/ObjRelationshipIT.java
@@ -20,7 +20,11 @@
 package org.apache.cayenne.map;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.DataMapLoader;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.configuration.EmptyConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.exp.ExpressionException;
@@ -89,7 +93,7 @@ public class ObjRelationshipIT extends ServerCase {
         r.setCollectionType("java.util.Map");
         r.setMapKey("bla");
 
-        r.encodeAsXML(encoder);
+        r.encodeAsXML(encoder, new EmptyConfigurationNodeVisitor());
         out.close();
 
         String lineBreak = System.getProperty("line.separator");

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/map/QueryDescriptorLoaderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/QueryDescriptorLoaderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/map/QueryDescriptorLoaderTest.java
index 4ca4843..757acc3 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/QueryDescriptorLoaderTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/QueryDescriptorLoaderTest.java
@@ -47,7 +47,7 @@ public class QueryDescriptorLoaderTest {
         DbEntity entity = new DbEntity("DB1");
         map.addDbEntity(entity);
 
-        builder.setRoot(map, MapLoader.DB_ENTITY_ROOT, "DB1");
+        builder.setRoot(map, QueryDescriptor.DB_ENTITY_ROOT, "DB1");
         assertSame(entity, builder.getRoot());
     }
 
@@ -57,7 +57,7 @@ public class QueryDescriptorLoaderTest {
         ObjEntity entity = new ObjEntity("OBJ1");
         map.addObjEntity(entity);
 
-        builder.setRoot(map, MapLoader.OBJ_ENTITY_ROOT, "OBJ1");
+        builder.setRoot(map, QueryDescriptor.OBJ_ENTITY_ROOT, "OBJ1");
         assertSame(entity, builder.getRoot());
     }
 
@@ -65,7 +65,7 @@ public class QueryDescriptorLoaderTest {
     public void testSetRootDataMap() throws Exception {
         DataMap map = new DataMap("map");
 
-        builder.setRoot(map, MapLoader.DATA_MAP_ROOT, null);
+        builder.setRoot(map, QueryDescriptor.DATA_MAP_ROOT, null);
         assertSame(map, builder.getRoot());
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java
index b1b2495..dbf4bde 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/EJBQLQueryIT.java
@@ -20,11 +20,13 @@ package org.apache.cayenne.query;
 
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.access.DataContext;
+import org.apache.cayenne.configuration.EmptyConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.ejbql.EJBQLCompiledExpression;
 import org.apache.cayenne.ejbql.EJBQLException;
 import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.map.EJBQLQueryDescriptor;
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
@@ -307,28 +309,16 @@ public class EJBQLQueryIT extends ServerCase {
         XMLEncoder e = new XMLEncoder(new PrintWriter(w));
 
         String separator = System.getProperty("line.separator");
+        String s = "<query name=\"" + name + "\" type=\"EJBQLQuery\">" + separator +
+                "<ejbql><![CDATA[" + ejbql + "]]></ejbql>" + separator +
+                "</query>" + separator;
 
-        StringBuffer s = new StringBuffer("<query name=\"");
-        s.append(name);
-        s.append("\" factory=\"");
-        s.append("org.apache.cayenne.map.EjbqlBuilder");
-        s.append("\">");
-        s.append(separator);
+        EJBQLQueryDescriptor descriptor = new EJBQLQueryDescriptor();
+        descriptor.setEjbql(ejbql);
+        descriptor.setName(name);
+        descriptor.encodeAsXML(e, new EmptyConfigurationNodeVisitor());
 
-        EJBQLQuery query = new EJBQLQuery(ejbql);
-
-        if (query.getEjbqlStatement() != null) {
-            s.append("<ejbql><![CDATA[");
-            s.append(query.getEjbqlStatement());
-            s.append("]]></ejbql>");
-        }
-        s.append(separator);
-        s.append("</query>");
-        s.append(separator);
-        query.setName(name);
-        query.encodeAsXML(e);
-
-        assertEquals(w.getBuffer().toString(), s.toString());
+        assertEquals(w.getBuffer().toString(), s);
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/DBCleaner.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/DBCleaner.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/DBCleaner.java
index af12a3d..04f8629 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/DBCleaner.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/DBCleaner.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.unit.di.server;
 
 import org.apache.cayenne.configuration.ConfigurationTree;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader;
+import org.apache.cayenne.configuration.xml.XMLDataChannelDescriptorLoader;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.map.DataMap;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
index 69c4400..a8d6ad0 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
@@ -28,6 +28,8 @@ import org.apache.cayenne.access.translator.batch.DefaultBatchTranslatorFactory;
 import org.apache.cayenne.access.translator.select.DefaultSelectTranslatorFactory;
 import org.apache.cayenne.ashwood.AshwoodEntitySorter;
 import org.apache.cayenne.cache.MapQueryCache;
+import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
+import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.event.DefaultEventManager;
@@ -35,15 +37,14 @@ import org.apache.cayenne.log.JdbcEventLogger;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.resource.URLResource;
 import org.apache.cayenne.testdo.extended_type.StringET1ExtendedType;
 import org.apache.cayenne.unit.UnitDbAdapter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.xml.sax.InputSource;
 
-import java.io.InputStream;
+import java.net.URL;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
@@ -113,10 +114,11 @@ public class SchemaBuilder {
 		DataMap[] maps = new DataMap[MAPS_REQUIRING_SCHEMA_SETUP.length];
 
 		for (int i = 0; i < maps.length; i++) {
-			InputStream stream = getClass().getClassLoader().getResourceAsStream(MAPS_REQUIRING_SCHEMA_SETUP[i]);
-			InputSource in = new InputSource(stream);
-			in.setSystemId(MAPS_REQUIRING_SCHEMA_SETUP[i]);
-			maps[i] = new MapLoader().loadDataMap(in);
+			URL mapURL = getClass().getClassLoader().getResource(MAPS_REQUIRING_SCHEMA_SETUP[i]);
+			XMLDataMapLoader loader = new XMLDataMapLoader();
+			loader.setHandlerFactory(new DefaultHandlerFactory());
+			maps[i] = loader.load(new URLResource(mapURL));
+
 		}
 
 		this.domain = new DataDomain("temp");

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
index ae4e01b..3386c1b 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
@@ -52,10 +52,14 @@ import org.apache.cayenne.configuration.DefaultObjectStoreFactory;
 import org.apache.cayenne.configuration.DefaultRuntimeProperties;
 import org.apache.cayenne.configuration.ObjectStoreFactory;
 import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.configuration.XMLDataMapLoader;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
 import org.apache.cayenne.configuration.server.ServerModule;
 import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
+import org.apache.cayenne.configuration.xml.HandlerFactory;
+import org.apache.cayenne.configuration.xml.NoopDataChannelMetaData;
+import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
 import org.apache.cayenne.conn.DataSourceInfo;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.JdbcAdapter;
@@ -198,6 +202,8 @@ public class ServerCaseModule implements Module {
         binder.bind(ObjectStoreFactory.class).to(DefaultObjectStoreFactory.class);
         binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
         binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
+        binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
+        binder.bind(DataChannelMetaData.class).to(NoopDataChannelMetaData.class);
 
         // test-scoped objects
         binder.bind(EntityResolver.class).toProvider(ServerCaseEntityResolverProvider.class).in(testScope);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/array-type.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/array-type.map.xml b/cayenne-server/src/test/resources/array-type.map.xml
index 8cc8f27..d5165eb 100644
--- a/cayenne-server/src/test/resources/array-type.map.xml
+++ b/cayenne-server/src/test/resources/array-type.map.xml
@@ -1,18 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.array_type"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="ARRAY_TEST">
-        <db-attribute name="DOUBLE_ARRAY" type="VARBINARY" length="1024"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <obj-entity name="ArrayTestEntity" className="org.apache.cayenne.testdo.array_type.ArrayTestEntity" dbEntityName="ARRAY_TEST">
-        <obj-attribute name="doubleArray" type="java.lang.Double[]" db-attribute-path="DOUBLE_ARRAY"/>
-    </obj-entity>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.array_type"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="ARRAY_TEST">
+		<db-attribute name="DOUBLE_ARRAY" type="VARBINARY" length="1024"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<obj-entity name="ArrayTestEntity" className="org.apache.cayenne.testdo.array_type.ArrayTestEntity" dbEntityName="ARRAY_TEST">
+		<obj-attribute name="doubleArray" type="java.lang.Double[]" db-attribute-path="DOUBLE_ARRAY"/>
+	</obj-entity>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/binary-pk.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/binary-pk.map.xml b/cayenne-server/src/test/resources/binary-pk.map.xml
index cd53ff2..775b10f 100644
--- a/cayenne-server/src/test/resources/binary-pk.map.xml
+++ b/cayenne-server/src/test/resources/binary-pk.map.xml
@@ -1,34 +1,34 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-          project-version="9">
-    <property name="defaultPackage" value="org.apache.cayenne.testdo.binary_pk"/>
-    <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
-    <property name="clientSupported" value="true"/>
-    <property name="defaultClientPackage" value="test.client"/>
-    <property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
-    <db-entity name="BINARY_PK_TEST1">
-        <db-attribute name="BIN_ID" type="VARBINARY" isPrimaryKey="true" isMandatory="true" length="32"/>
-        <db-attribute name="NAME" type="VARCHAR" length="10"/>
-    </db-entity>
-    <db-entity name="BINARY_PK_TEST2">
-        <db-attribute name="DETAIL_NAME" type="VARCHAR" length="10"/>
-        <db-attribute name="FK_ID" type="VARBINARY" length="32"/>
-        <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
-    </db-entity>
-    <obj-entity name="BinaryPKTest1" className="org.apache.cayenne.testdo.binary_pk.BinaryPKTest1" dbEntityName="BINARY_PK_TEST1">
-        <obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
-    </obj-entity>
-    <obj-entity name="BinaryPKTest2" className="org.apache.cayenne.testdo.binary_pk.BinaryPKTest2" dbEntityName="BINARY_PK_TEST2">
-        <obj-attribute name="detailName" type="java.lang.String" db-attribute-path="DETAIL_NAME"/>
-    </obj-entity>
-    <db-relationship name="binaryPKDetails" source="BINARY_PK_TEST1" target="BINARY_PK_TEST2" toMany="true">
-        <db-attribute-pair source="BIN_ID" target="FK_ID"/>
-    </db-relationship>
-    <db-relationship name="toBinaryPKMaster" source="BINARY_PK_TEST2" target="BINARY_PK_TEST1" toMany="false">
-        <db-attribute-pair source="FK_ID" target="BIN_ID"/>
-    </db-relationship>
-    <obj-relationship name="binaryPKDetails" source="BinaryPKTest1" target="BinaryPKTest2" db-relationship-path="binaryPKDetails"/>
-    <obj-relationship name="toBinaryPKMaster" source="BinaryPKTest2" target="BinaryPKTest1" db-relationship-path="toBinaryPKMaster"/>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.binary_pk"/>
+	<property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+	<property name="clientSupported" value="true"/>
+	<property name="defaultClientPackage" value="test.client"/>
+	<property name="defaultClientSuperclass" value="org.apache.cayenne.PersistentObject"/>
+	<db-entity name="BINARY_PK_TEST1">
+		<db-attribute name="BIN_ID" type="VARBINARY" isPrimaryKey="true" isMandatory="true" length="32"/>
+		<db-attribute name="NAME" type="VARCHAR" length="10"/>
+	</db-entity>
+	<db-entity name="BINARY_PK_TEST2">
+		<db-attribute name="DETAIL_NAME" type="VARCHAR" length="10"/>
+		<db-attribute name="FK_ID" type="VARBINARY" length="32"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<obj-entity name="BinaryPKTest1" className="org.apache.cayenne.testdo.binary_pk.BinaryPKTest1" dbEntityName="BINARY_PK_TEST1">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
+	<obj-entity name="BinaryPKTest2" className="org.apache.cayenne.testdo.binary_pk.BinaryPKTest2" dbEntityName="BINARY_PK_TEST2">
+		<obj-attribute name="detailName" type="java.lang.String" db-attribute-path="DETAIL_NAME"/>
+	</obj-entity>
+	<db-relationship name="binaryPKDetails" source="BINARY_PK_TEST1" target="BINARY_PK_TEST2" toMany="true">
+		<db-attribute-pair source="BIN_ID" target="FK_ID"/>
+	</db-relationship>
+	<db-relationship name="toBinaryPKMaster" source="BINARY_PK_TEST2" target="BINARY_PK_TEST1">
+		<db-attribute-pair source="FK_ID" target="BIN_ID"/>
+	</db-relationship>
+	<obj-relationship name="binaryPKDetails" source="BinaryPKTest1" target="BinaryPKTest2" db-relationship-path="binaryPKDetails"/>
+	<obj-relationship name="toBinaryPKMaster" source="BinaryPKTest2" target="BinaryPKTest1" db-relationship-path="toBinaryPKMaster"/>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cay-2032.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cay-2032.map.xml b/cayenne-server/src/test/resources/cay-2032.map.xml
index 9a3b380..00b3875 100644
--- a/cayenne-server/src/test/resources/cay-2032.map.xml
+++ b/cayenne-server/src/test/resources/cay-2032.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.cay_2032"/>
 	<db-entity name="TEAM">
 		<db-attribute name="team_id" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
@@ -15,8 +15,7 @@
 		<db-attribute name="team_id" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="user_id" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 	</db-entity>
-	<obj-entity name="Team" className="org.apache.cayenne.testdo.cay_2032.Team" dbEntityName="TEAM">
-	</obj-entity>
+	<obj-entity name="Team" className="org.apache.cayenne.testdo.cay_2032.Team" dbEntityName="TEAM"/>
 	<obj-entity name="User" className="org.apache.cayenne.testdo.cay_2032.User" dbEntityName="USERS">
 		<obj-attribute name="name" type="byte[]" db-attribute-path="name"/>
 	</obj-entity>
@@ -26,10 +25,10 @@
 	<db-relationship name="userHasTeam" source="USERS" target="USER_HAS_TEAM" toMany="true">
 		<db-attribute-pair source="user_id" target="user_id"/>
 	</db-relationship>
-	<db-relationship name="team" source="USER_HAS_TEAM" target="TEAM" toMany="false">
+	<db-relationship name="team" source="USER_HAS_TEAM" target="TEAM">
 		<db-attribute-pair source="team_id" target="team_id"/>
 	</db-relationship>
-	<db-relationship name="user" source="USER_HAS_TEAM" target="USERS" toMany="false">
+	<db-relationship name="user" source="USER_HAS_TEAM" target="USERS">
 		<db-attribute-pair source="user_id" target="user_id"/>
 	</db-relationship>
 	<obj-relationship name="teamUsers" source="Team" target="User" deleteRule="Deny" db-relationship-path="userHasTeam.user"/>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cay743/cayenne-domain.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cay743/cayenne-domain.xml b/cayenne-server/src/test/resources/cay743/cayenne-domain.xml
index 5909898..b69e50c 100644
--- a/cayenne-server/src/test/resources/cay743/cayenne-domain.xml
+++ b/cayenne-server/src/test/resources/cay743/cayenne-domain.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain project-version="10">
 	<map name="map1"/>
 	<map name="map2"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cay743/map1.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cay743/map1.map.xml b/cayenne-server/src/test/resources/cay743/map1.map.xml
index d13c6d5..07a0754 100644
--- a/cayenne-server/src/test/resources/cay743/map1.map.xml
+++ b/cayenne-server/src/test/resources/cay743/map1.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<obj-entity name="Entity11">
 	</obj-entity>
 	<obj-entity name="Entity12" superEntityName="Entity22">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cay743/map2.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cay743/map2.map.xml b/cayenne-server/src/test/resources/cay743/map2.map.xml
index 43b5d19..aab2c64 100644
--- a/cayenne-server/src/test/resources/cay743/map2.map.xml
+++ b/cayenne-server/src/test/resources/cay743/map2.map.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/9/modelMap"
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	 xsi:schemaLocation="http://cayenne.apache.org/schema/9/modelMap http://cayenne.apache.org/schema/9/modelMap.xsd"
-	 project-version="9">
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
 	<obj-entity name="Entity21" superEntityName="Entity11">
 	</obj-entity>
 	<obj-entity name="Entity22">

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-array-type.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-array-type.xml b/cayenne-server/src/test/resources/cayenne-array-type.xml
index fdf8c4e..424431b 100644
--- a/cayenne-server/src/test/resources/cayenne-array-type.xml
+++ b/cayenne-server/src/test/resources/cayenne-array-type.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="array-type"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="array-type"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-binary-pk.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-binary-pk.xml b/cayenne-server/src/test/resources/cayenne-binary-pk.xml
index d6d21b2..ff071fa 100644
--- a/cayenne-server/src/test/resources/cayenne-binary-pk.xml
+++ b/cayenne-server/src/test/resources/cayenne-binary-pk.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="binary-pk"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="binary-pk"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-cay-2032.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-cay-2032.xml b/cayenne-server/src/test/resources/cayenne-cay-2032.xml
index f9427a7..5b19286 100644
--- a/cayenne-server/src/test/resources/cayenne-cay-2032.xml
+++ b/cayenne-server/src/test/resources/cayenne-cay-2032.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
 	<map name="cay-2032"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-compound.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-compound.xml b/cayenne-server/src/test/resources/cayenne-compound.xml
index b82d21f..1445b53 100644
--- a/cayenne-server/src/test/resources/cayenne-compound.xml
+++ b/cayenne-server/src/test/resources/cayenne-compound.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="compound"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="compound"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-date-time.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-date-time.xml b/cayenne-server/src/test/resources/cayenne-date-time.xml
index 3fda070..9e67951 100644
--- a/cayenne-server/src/test/resources/cayenne-date-time.xml
+++ b/cayenne-server/src/test/resources/cayenne-date-time.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="date-time"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="date-time"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-delete-rules.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-delete-rules.xml b/cayenne-server/src/test/resources/cayenne-delete-rules.xml
index 606e583..7dd2bb4 100644
--- a/cayenne-server/src/test/resources/cayenne-delete-rules.xml
+++ b/cayenne-server/src/test/resources/cayenne-delete-rules.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="delete-rules"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="delete-rules"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-embeddable.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-embeddable.xml b/cayenne-server/src/test/resources/cayenne-embeddable.xml
index 8aa7459..aedacf3 100644
--- a/cayenne-server/src/test/resources/cayenne-embeddable.xml
+++ b/cayenne-server/src/test/resources/cayenne-embeddable.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="embeddable"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="embeddable"/>
 </domain>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/test/resources/cayenne-empty.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/cayenne-empty.xml b/cayenne-server/src/test/resources/cayenne-empty.xml
index 3ee43c4..b0b7614 100644
--- a/cayenne-server/src/test/resources/cayenne-empty.xml
+++ b/cayenne-server/src/test/resources/cayenne-empty.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<domain project-version="9">
-    <map name="empty"/>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 project-version="10">
+	<map name="empty"/>
 </domain>