You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2006/04/26 22:58:50 UTC

svn commit: r396882 [9/11] - in /incubator/cayenne: branches/ tags/ trunk/ trunk/cayenne-jpa-tck/ trunk/cayenne-jpa-tck/.settings/ trunk/cayenne-jpa-tck/src/ trunk/cayenne-jpa-tck/src/main/ trunk/cayenne-jpa-tck/src/main/java/ trunk/cayenne-jpa-tck/src...

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/EntityMapAnnotationLoaderTest.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/EntityMapAnnotationLoaderTest.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/EntityMapAnnotationLoaderTest.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/EntityMapAnnotationLoaderTest.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,206 @@
+/* ====================================================================
+ * 
+ * The ObjectStyle Group Software License, version 1.1
+ * ObjectStyle Group - http://objectstyle.org/
+ * 
+ * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
+ * of the software. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * 3. The end-user documentation included with the redistribution, if any,
+ *    must include the following acknowlegement:
+ *    "This product includes software developed by independent contributors
+ *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ * 
+ * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
+ *    or promote products derived from this software without prior written
+ *    permission. For written permission, email
+ *    "andrus at objectstyle dot org".
+ * 
+ * 5. Products derived from this software may not be called "ObjectStyle"
+ *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
+ *    names without prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by many
+ * individuals and hosted on ObjectStyle Group web site.  For more
+ * information on the ObjectStyle Group, please see
+ * <http://objectstyle.org/>.
+ */
+package org.objectstyle.cayenne.jpa.conf;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.regex.Matcher;
+
+import javax.persistence.Entity;
+import javax.persistence.IdClass;
+import javax.persistence.NamedQuery;
+
+import junit.framework.TestCase;
+
+import org.objectstyle.cayenne.jpa.entity.MockEmbed1;
+import org.objectstyle.cayenne.jpa.entity.MockEmbed2;
+import org.objectstyle.cayenne.jpa.entity.MockEntity1;
+import org.objectstyle.cayenne.jpa.entity.MockEntity2;
+import org.objectstyle.cayenne.jpa.entity.MockEntity3;
+import org.objectstyle.cayenne.jpa.entity.MockEntity4;
+import org.objectstyle.cayenne.jpa.entity.MockEntity5;
+import org.objectstyle.cayenne.jpa.entity.MockEntityMap1;
+import org.objectstyle.cayenne.jpa.entity.MockEntityMap2;
+import org.objectstyle.cayenne.jpa.entity.MockMappedSuperclass1;
+import org.objectstyle.cayenne.jpa.entity.MockMappedSuperclass2;
+import org.objectstyle.cayenne.jpa.entity.MockMappedSuperclass3;
+import org.objectstyle.cayenne.jpa.map.JpaAttribute;
+import org.objectstyle.cayenne.jpa.map.JpaAttributeOverride;
+import org.objectstyle.cayenne.jpa.map.JpaEntity;
+import org.objectstyle.cayenne.jpa.map.JpaEntityMap;
+import org.objectstyle.cayenne.validation.ValidationResult;
+
+public class EntityMapAnnotationLoaderTest extends TestCase {
+
+    public void testGetterPattern() {
+        Matcher m1 = EntityMapAnnotationLoader.GETTER_PATTERN.matcher("xxx");
+        assertFalse(m1.matches());
+
+        Matcher m2 = EntityMapAnnotationLoader.GETTER_PATTERN.matcher("isA");
+        assertTrue(m2.matches());
+        assertEquals("A", m2.group(2));
+
+        Matcher m3 = EntityMapAnnotationLoader.GETTER_PATTERN.matcher("getThis");
+        assertTrue(m3.matches());
+        assertEquals("This", m3.group(2));
+    }
+
+    public void testSetterPattern() {
+        Matcher m1 = EntityMapAnnotationLoader.SETTER_PATTERN.matcher("xxx");
+        assertFalse(m1.matches());
+
+        Matcher m2 = EntityMapAnnotationLoader.SETTER_PATTERN.matcher("set");
+        assertFalse(m2.matches());
+
+        Matcher m3 = EntityMapAnnotationLoader.SETTER_PATTERN.matcher("setThis");
+        assertTrue(m3.matches());
+        assertEquals("This", m3.group(1));
+    }
+
+    public void testGetPropertyGetters() throws Exception {
+        EntityMapAnnotationLoader loader = new EntityMapAnnotationLoader(
+                new ValidationResult());
+
+        Collection<Method> validGetters = loader
+                .getPropertyGetters(MockPropertyRegressionBean.class);
+        assertEquals(2, validGetters.size());
+
+        assertTrue(validGetters.contains(MockPropertyRegressionBean.class
+                .getDeclaredMethod("getP2", new Class[] {})));
+
+        assertTrue(validGetters.contains(MockPropertyRegressionBean.class
+                .getDeclaredMethod("getP3", new Class[] {})));
+    }
+
+    public void testSortAnnotations() throws Exception {
+
+        EntityMapAnnotationLoader loader = new EntityMapAnnotationLoader(
+                new ValidationResult());
+
+        Annotation[] a1 = new Annotation[3];
+        a1[0] = MockAnnotatedBean1.class.getAnnotation(NamedQuery.class);
+        a1[1] = MockAnnotatedBean1.class.getAnnotation(IdClass.class);
+        a1[2] = MockAnnotatedBean1.class.getAnnotation(Entity.class);
+
+        Arrays.sort(a1, loader.typeAnnotationsSorter);
+
+        assertEquals(Entity.class, a1[0].annotationType());
+        assertEquals(NamedQuery.class, a1[1].annotationType());
+        assertEquals(IdClass.class, a1[2].annotationType());
+    }
+
+    /**
+     * Checks that class-level AttributeOverride and embedded property AttributeOverride
+     * are both processed correctly.
+     */
+    public void testAttributeOverride() {
+        JpaEntityMap map = new JpaEntityMap();
+        ValidationResult conflicts = new ValidationResult();
+        EntityMapAnnotationLoader loader = new EntityMapAnnotationLoader(conflicts);
+        loader.loadClassMapping(map, MockAnnotatedBean2.class);
+
+        assertEquals(1, map.getEntities().size());
+        JpaEntity entity = map.getEntities().iterator().next();
+        assertEquals(1, entity.getAttributeOverrides().size());
+        JpaAttributeOverride entityOverride = entity
+                .getAttributeOverrides()
+                .iterator()
+                .next();
+        assertEquals("entityAttribute", entityOverride.getName());
+
+        assertEquals(1, entity.getAttributes().size());
+        JpaAttribute attribute = entity.getAttributes().iterator().next();
+        assertEquals(1, attribute.getAttributeOverrides().size());
+        JpaAttributeOverride attributeOverride = attribute
+                .getAttributeOverrides()
+                .iterator()
+                .next();
+        assertEquals("embdeddedAttribute", attributeOverride.getName());
+    }
+
+    /**
+     * Tests loading of all supported annotations. Uses mock annotated objects from the
+     * "entity" package that roughly correspond to the XML mapping tested under
+     * {@link EntityMapXMLLoaderTest#testDetails()}.
+     */
+    public void testLoadClassMapping() throws Exception {
+        JpaEntityMap map = new JpaEntityMap();
+        ValidationResult conflicts = new ValidationResult();
+        EntityMapAnnotationLoader loader = new EntityMapAnnotationLoader(conflicts);
+
+        loader.loadClassMapping(map, MockEntity1.class);
+        loader.loadClassMapping(map, MockEntity2.class);
+        loader.loadClassMapping(map, MockEntity3.class);
+        loader.loadClassMapping(map, MockEntity4.class);
+        loader.loadClassMapping(map, MockEntity5.class);
+
+        loader.loadClassMapping(map, MockEmbed1.class);
+        loader.loadClassMapping(map, MockEmbed2.class);
+        
+        loader.loadClassMapping(map, MockMappedSuperclass1.class);
+        loader.loadClassMapping(map, MockMappedSuperclass2.class);
+        loader.loadClassMapping(map, MockMappedSuperclass3.class);
+        
+        loader.loadClassMapping(map, MockEntityMap1.class);
+        loader.loadClassMapping(map, MockEntityMap2.class);
+
+        assertFalse("Found conflicts: " + conflicts, conflicts.hasFailures());
+
+        new AnnotationMappingAssertion().testEntityMap(map);
+    }
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/EntityMapXMLLoaderTest.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/EntityMapXMLLoaderTest.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/EntityMapXMLLoaderTest.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/EntityMapXMLLoaderTest.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,103 @@
+/* ====================================================================
+ * 
+ * The ObjectStyle Group Software License, version 1.1
+ * ObjectStyle Group - http://objectstyle.org/
+ * 
+ * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
+ * of the software. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * 3. The end-user documentation included with the redistribution, if any,
+ *    must include the following acknowlegement:
+ *    "This product includes software developed by independent contributors
+ *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ * 
+ * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
+ *    or promote products derived from this software without prior written
+ *    permission. For written permission, email
+ *    "andrus at objectstyle dot org".
+ * 
+ * 5. Products derived from this software may not be called "ObjectStyle"
+ *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
+ *    names without prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by many
+ * individuals and hosted on ObjectStyle Group web site.  For more
+ * information on the ObjectStyle Group, please see
+ * <http://objectstyle.org/>.
+ */
+package org.objectstyle.cayenne.jpa.conf;
+
+import junit.framework.TestCase;
+
+import org.objectstyle.cayenne.jpa.map.JpaEntityMap;
+import org.xml.sax.SAXException;
+
+public class EntityMapXMLLoaderTest extends TestCase {
+
+    protected ClassLoader resourceLoader;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        this.resourceLoader = Thread.currentThread().getContextClassLoader();
+    }
+
+    public void testSampleSchemaHeadersValidating() throws Exception {
+
+        EntityMapXMLLoader loader = new EntityMapXMLLoader(true);
+
+        loader.getEntityMap(resourceLoader
+                .getResource("xml-samples/orm-schema-headers.xml"));
+        // no validation exception is thrown... good
+
+        try {
+            loader.getEntityMap(resourceLoader
+                    .getResource("xml-samples/orm-schema-headers-invalid1.xml"));
+            fail("Failed to throw an exception on invalid tag");
+        }
+        catch (RuntimeException e) {
+            assertTrue(e.getCause() instanceof SAXException);
+        }
+    }
+
+    public void testDetails() throws Exception {
+        EntityMapXMLLoader loader = new EntityMapXMLLoader(true);
+
+        // long t0 = System.currentTimeMillis();
+        JpaEntityMap map = loader.getEntityMap(resourceLoader
+                .getResource("xml-samples/orm-schema-headers-full.xml"));
+        // long t1 = System.currentTimeMillis();
+        // System.out.println("Load time: " + (t1 - t0));
+
+        new XMLMappingAssertion().testEntityMap(map);
+    }
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MappingAssertion.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MappingAssertion.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MappingAssertion.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MappingAssertion.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,672 @@
+/* ====================================================================
+ * 
+ * The ObjectStyle Group Software License, version 1.1
+ * ObjectStyle Group - http://objectstyle.org/
+ * 
+ * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
+ * of the software. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * 3. The end-user documentation included with the redistribution, if any,
+ *    must include the following acknowlegement:
+ *    "This product includes software developed by independent contributors
+ *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ * 
+ * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
+ *    or promote products derived from this software without prior written
+ *    permission. For written permission, email
+ *    "andrus at objectstyle dot org".
+ * 
+ * 5. Products derived from this software may not be called "ObjectStyle"
+ *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
+ *    names without prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by many
+ * individuals and hosted on ObjectStyle Group web site.  For more
+ * information on the ObjectStyle Group, please see
+ * <http://objectstyle.org/>.
+ */
+package org.objectstyle.cayenne.jpa.conf;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.DiscriminatorType;
+import javax.persistence.EnumType;
+import javax.persistence.FetchType;
+import javax.persistence.GenerationType;
+import javax.persistence.InheritanceType;
+import javax.persistence.TemporalType;
+
+import junit.framework.Assert;
+
+import org.objectstyle.cayenne.jpa.map.JpaAttribute;
+import org.objectstyle.cayenne.jpa.map.JpaAttributeOverride;
+import org.objectstyle.cayenne.jpa.map.JpaColumn;
+import org.objectstyle.cayenne.jpa.map.JpaColumnResult;
+import org.objectstyle.cayenne.jpa.map.JpaEmbeddable;
+import org.objectstyle.cayenne.jpa.map.JpaEmbeddableAttribute;
+import org.objectstyle.cayenne.jpa.map.JpaEmbeddedId;
+import org.objectstyle.cayenne.jpa.map.JpaEntity;
+import org.objectstyle.cayenne.jpa.map.JpaEntityListener;
+import org.objectstyle.cayenne.jpa.map.JpaEntityListeners;
+import org.objectstyle.cayenne.jpa.map.JpaEntityMap;
+import org.objectstyle.cayenne.jpa.map.JpaEntityResult;
+import org.objectstyle.cayenne.jpa.map.JpaFieldResult;
+import org.objectstyle.cayenne.jpa.map.JpaId;
+import org.objectstyle.cayenne.jpa.map.JpaJoinColumn;
+import org.objectstyle.cayenne.jpa.map.JpaMappedSuperclass;
+import org.objectstyle.cayenne.jpa.map.JpaNamedNativeQuery;
+import org.objectstyle.cayenne.jpa.map.JpaNamedQuery;
+import org.objectstyle.cayenne.jpa.map.JpaOneToMany;
+import org.objectstyle.cayenne.jpa.map.JpaPrimaryKeyJoinColumn;
+import org.objectstyle.cayenne.jpa.map.JpaQueryHint;
+import org.objectstyle.cayenne.jpa.map.JpaSecondaryTable;
+import org.objectstyle.cayenne.jpa.map.JpaSequenceGenerator;
+import org.objectstyle.cayenne.jpa.map.JpaSqlResultSetMapping;
+import org.objectstyle.cayenne.jpa.map.JpaTable;
+import org.objectstyle.cayenne.jpa.map.JpaTableGenerator;
+import org.objectstyle.cayenne.jpa.map.JpaUniqueConstraint;
+
+/**
+ * A helper test class that checks loaded entity map for processed annotations.
+ * 
+ * @author Andrus Adamchik
+ */
+public class MappingAssertion extends Assert {
+
+    public void testEntityMap(JpaEntityMap entityMap) throws Exception {
+
+        assertNotNull(entityMap.getEntities());
+        assertEquals(5, entityMap.getEntities().size());
+        Iterator<JpaEntity> entityIt = entityMap.getEntities().iterator();
+        assertEntity1(entityIt.next());
+        assertEntity2(entityIt.next());
+        assertEntity3(entityIt.next());
+        assertEntity4(entityIt.next());
+        assertEntity5(entityIt.next());
+
+        assertNotNull(entityMap.getEmbeddables());
+        assertEquals(2, entityMap.getEmbeddables().size());
+        Iterator<JpaEmbeddable> embedIt = entityMap.getEmbeddables().iterator();
+        assertEmbeddable1(embedIt.next());
+
+        assertNotNull(entityMap.getMappedSuperclasses());
+        assertEquals(3, entityMap.getMappedSuperclasses().size());
+        Iterator<JpaMappedSuperclass> mappedSuperclassIt = entityMap
+                .getMappedSuperclasses()
+                .iterator();
+        assertMappedSuperclass1(mappedSuperclassIt.next());
+        assertMappedSuperclass2(mappedSuperclassIt.next());
+        assertMappedSuperclass3(mappedSuperclassIt.next());
+
+        assertEntityListeners(entityMap.getDefaultEntityListeners());
+
+        assertEquals(2, entityMap.getNamedQueries().size());
+        Iterator<JpaNamedQuery> namedQueryIt = entityMap.getNamedQueries().iterator();
+        assertNamedQuery1(namedQueryIt.next());
+        assertNamedQuery2(namedQueryIt.next());
+
+        assertEquals(2, entityMap.getNamedNativeQueries().size());
+        Iterator<JpaNamedNativeQuery> namedNativeQueryIt = entityMap
+                .getNamedNativeQueries()
+                .iterator();
+        assertNativeNamedQuery3(namedNativeQueryIt.next());
+        assertNativeNamedQuery4(namedNativeQueryIt.next());
+
+        assertEquals(2, entityMap.getSqlResultSetMappings().size());
+        assertSqlResultSetMapping(entityMap.getSqlResultSetMappings().iterator().next());
+
+        assertEquals(2, entityMap.getSequenceGenerators().size());
+        assertSequenceGenerator1(entityMap.getSequenceGenerators().iterator().next());
+
+        assertEquals(2, entityMap.getTableGenerators().size());
+        assertTableGenerator(entityMap.getTableGenerators().iterator().next());
+    }
+
+    protected void assertEmbeddable1(JpaEmbeddable embeddable1) {
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockEmbed1", embeddable1
+                .getClassName());
+
+        assertEquals(2, embeddable1.getEmbeddableAttributes().size());
+        Iterator<JpaEmbeddableAttribute> it = embeddable1
+                .getEmbeddableAttributes()
+                .iterator();
+        JpaEmbeddableAttribute a1 = it.next();
+
+        assertEquals("ea1", a1.getName());
+        assertNotNull(a1.getBasic());
+        assertTrue(a1.getBasic().isOptional());
+        assertSame(FetchType.EAGER, a1.getBasic().getFetch());
+
+        assertTrue(a1.isLob());
+        assertEquals(TemporalType.DATE, a1.getTemporal());
+        assertEquals(EnumType.ORDINAL, a1.getEnumerated());
+        assertNotNull(a1.getColumn());
+        assertEquals("column9", a1.getColumn().getName());
+
+        JpaEmbeddableAttribute a2 = it.next();
+        assertEquals("ea2", a2.getName());
+        assertFalse(a2.isLob());
+    }
+
+    protected void assertEntity1(JpaEntity entity1) {
+        assertNotNull(entity1);
+        assertEquals("MockEntity1", entity1.getName());
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockEntity1", entity1
+                .getClassName());
+
+        assertTable(entity1.getTable());
+
+        assertEquals(2, entity1.getSecondaryTables().size());
+        Iterator<JpaSecondaryTable> secondaryTableIt = entity1
+                .getSecondaryTables()
+                .iterator();
+        assertSecondaryTable1(secondaryTableIt.next());
+
+        JpaSecondaryTable secondaryTable2 = secondaryTableIt.next();
+        assertEquals("secondary2", secondaryTable2.getName());
+
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockIdClass", entity1
+                .getIdClassName());
+
+        assertSequenceGenerator1(entity1.getSequenceGenerator());
+
+        assertNotNull(entity1.getTableGenerator());
+        assertTableGenerator(entity1.getTableGenerator());
+
+        assertEquals(2, entity1.getNamedQueries().size());
+        Iterator<JpaNamedQuery> namedQueryIt = entity1.getNamedQueries().iterator();
+        assertNamedQuery1(namedQueryIt.next());
+        assertNamedQuery2(namedQueryIt.next());
+
+        assertEquals(2, entity1.getNamedNativeQueries().size());
+        Iterator<JpaNamedNativeQuery> namedNativeQueryIt = entity1
+                .getNamedNativeQueries()
+                .iterator();
+        assertNativeNamedQuery3(namedNativeQueryIt.next());
+        assertNativeNamedQuery4(namedNativeQueryIt.next());
+
+        assertSqlResultSetMapping(entity1.getSqlResultSetMapping());
+
+        assertTrue(entity1.isExcludeDefaultListeners());
+        assertTrue(entity1.isExcludeSuperclassListeners());
+
+        assertEntityListeners(entity1.getEntityListeners());
+
+        assertNotNull(entity1.getPrePersist());
+        assertEquals("eprePersist", entity1.getPrePersist().getMethodName());
+        assertNotNull(entity1.getPostPersist());
+        assertEquals("epostPersist", entity1.getPostPersist().getMethodName());
+        assertNotNull(entity1.getPreUpdate());
+        assertEquals("epreUpdate", entity1.getPreUpdate().getMethodName());
+        assertNotNull(entity1.getPostUpdate());
+        assertEquals("epostUpdate", entity1.getPostUpdate().getMethodName());
+        assertNotNull(entity1.getPreRemove());
+        assertEquals("epreRemove", entity1.getPreRemove().getMethodName());
+        assertNotNull(entity1.getPostRemove());
+        assertEquals("epostRemove", entity1.getPostRemove().getMethodName());
+        assertNotNull(entity1.getPostLoad());
+        assertEquals("epostLoad", entity1.getPostLoad().getMethodName());
+
+        assertEquals(1, entity1.getIds().size());
+        assertId(entity1.getIds().iterator().next());
+
+        assertNull(entity1.getInheritance());
+    }
+
+    protected void assertEntity2(JpaEntity entity2) {
+        assertNotNull(entity2);
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockEntity2", entity2
+                .getClassName());
+        assertEquals("MockEntity2", entity2.getName());
+
+        assertEquals(2, entity2.getPrimaryKeyJoinColumns().size());
+        Iterator<JpaPrimaryKeyJoinColumn> pkJoinColumnIt = entity2
+                .getPrimaryKeyJoinColumns()
+                .iterator();
+
+        JpaPrimaryKeyJoinColumn pk1 = pkJoinColumnIt.next();
+        assertEquals("pk_column1", pk1.getName());
+        assertEquals("count(1)", pk1.getColumnDefinition());
+        assertEquals("super_column1", pk1.getReferencedColumnName());
+
+        assertNotNull(entity2.getInheritance());
+        assertEquals(InheritanceType.JOINED, entity2.getInheritance().getStrategy());
+
+        assertEquals(2, entity2.getAttributeOverrides().size());
+        List<JpaAttributeOverride> overrides = new ArrayList<JpaAttributeOverride>(
+                entity2.getAttributeOverrides());
+
+        assertEquals("attribute1", overrides.get(0).getName());
+        JpaColumn c1 = overrides.get(0).getColumn();
+        assertEquals("ao_column1", c1.getName());
+        assertEquals("count(1)", c1.getColumnDefinition());
+        assertEquals("ao_table1", c1.getTable());
+        assertEquals(3, c1.getLength());
+        assertEquals(4, c1.getPrecision());
+        assertEquals(5, c1.getScale());
+        assertTrue(c1.isInsertable());
+        assertTrue(c1.isNullable());
+        assertTrue(c1.isUnique());
+        assertTrue(c1.isUpdatable());
+
+        assertEquals("attribute2", overrides.get(1).getName());
+    }
+
+    protected void assertEntity3(JpaEntity entity3) {
+        assertNotNull(entity3);
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockEntity3", entity3
+                .getClassName());
+        assertEquals("MockEntity3", entity3.getName());
+
+        assertNotNull(entity3.getInheritance());
+        assertEquals(InheritanceType.SINGLE_TABLE, entity3.getInheritance().getStrategy());
+        assertEquals("DV", entity3.getDiscriminatorValue());
+        assertNotNull(entity3.getDiscriminatorColumn());
+        assertEquals("column1", entity3.getDiscriminatorColumn().getName());
+        assertEquals(DiscriminatorType.CHAR, entity3
+                .getDiscriminatorColumn()
+                .getDiscriminatorType());
+        assertEquals("count(1)", entity3.getDiscriminatorColumn().getColumnDefinition());
+        assertEquals(5, entity3.getDiscriminatorColumn().getLength());
+    }
+
+    protected void assertEntity4(JpaEntity entity4) {
+        assertNotNull(entity4);
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockEntity4", entity4
+                .getClassName());
+        assertEquals("MockEntity4", entity4.getName());
+        assertEmbeddedId(entity4.getEmbeddedId());
+    }
+
+    protected void assertEntity5(JpaEntity entity5) {
+
+        assertEquals("MockEntity5", entity5.getName());
+        assertNotNull(entity5.getAttributes());
+        assertEquals(17, entity5.getAttributes().size());
+        assertAttributes(new ArrayList<JpaAttribute>(entity5.getAttributes()));
+    }
+
+    protected void assertSequenceGenerator1(JpaSequenceGenerator generator) {
+        assertNotNull(generator);
+        assertEquals("sg-name", generator.getName());
+        assertEquals("seq-name", generator.getSequenceName());
+        assertEquals(10, generator.getAllocationSize());
+        assertEquals(5, generator.getInitialValue());
+    }
+
+    protected void assertTable(JpaTable table) {
+        assertNotNull(table);
+        assertEquals("mock_persistent_1", table.getName());
+        assertEquals("catalog1", table.getCatalog());
+        assertEquals("schema1", table.getSchema());
+
+        assertEquals(2, table.getUniqueConstraints().size());
+        Iterator<JpaUniqueConstraint> constraintsIt = table
+                .getUniqueConstraints()
+                .iterator();
+        JpaUniqueConstraint c1 = constraintsIt.next();
+        assertEquals(2, c1.getColumnNames().size());
+        assertTrue(c1.getColumnNames().contains("column1"));
+        assertTrue(c1.getColumnNames().contains("column2"));
+
+        JpaUniqueConstraint c2 = constraintsIt.next();
+        assertEquals(1, c2.getColumnNames().size());
+        assertTrue(c2.getColumnNames().contains("column3"));
+    }
+
+    protected void assertSecondaryTable1(JpaSecondaryTable secondaryTable1) {
+        assertEquals("secondary1", secondaryTable1.getName());
+        assertEquals("catalog1", secondaryTable1.getCatalog());
+        assertEquals("schema1", secondaryTable1.getSchema());
+
+        assertEquals(2, secondaryTable1.getPrimaryKeyJoinColumns().size());
+        Iterator<JpaPrimaryKeyJoinColumn> pkJoinColumnIt = secondaryTable1
+                .getPrimaryKeyJoinColumns()
+                .iterator();
+
+        JpaPrimaryKeyJoinColumn pk1 = pkJoinColumnIt.next();
+        assertEquals("secondary_column1", pk1.getName());
+        assertEquals("count(1)", pk1.getColumnDefinition());
+        assertEquals("column1", pk1.getReferencedColumnName());
+
+        assertEquals(1, secondaryTable1.getUniqueConstraints().size());
+        Iterator<JpaUniqueConstraint> constraintsIt = secondaryTable1
+                .getUniqueConstraints()
+                .iterator();
+        JpaUniqueConstraint c1 = constraintsIt.next();
+        assertTrue(c1.getColumnNames().contains("column1"));
+        assertTrue(c1.getColumnNames().contains("column2"));
+    }
+
+    protected void assertTableGenerator(JpaTableGenerator generator) {
+        assertEquals("table-generator", generator.getName());
+        assertEquals("auto_pk_table", generator.getTable());
+        assertEquals("catalog1", generator.getCatalog());
+        assertEquals("schema1", generator.getSchema());
+        assertEquals("next_id", generator.getPkColumnName());
+        assertEquals("x", generator.getValueColumnName());
+        assertEquals("y", generator.getPkColumnValue());
+        assertEquals(4, generator.getInitialValue());
+        assertEquals(20, generator.getAllocationSize());
+
+        assertEquals(1, generator.getUniqueConstraints().size());
+        Iterator<JpaUniqueConstraint> constraintsIt = generator
+                .getUniqueConstraints()
+                .iterator();
+        JpaUniqueConstraint c1 = constraintsIt.next();
+        assertTrue(c1.getColumnNames().contains("pk1"));
+    }
+
+    protected void assertNamedQuery1(JpaNamedQuery namedQuery) {
+        assertEquals("query1", namedQuery.getName());
+        assertEquals("select x", namedQuery.getQuery());
+        assertEquals(2, namedQuery.getHints().size());
+
+        Iterator<JpaQueryHint> hintIt = namedQuery.getHints().iterator();
+        JpaQueryHint h1 = hintIt.next();
+        assertEquals("hint1", h1.getName());
+        assertEquals("value1", h1.getValue());
+
+        JpaQueryHint h2 = hintIt.next();
+        assertEquals("hint2", h2.getName());
+        assertEquals("value2", h2.getValue());
+    }
+
+    protected void assertNamedQuery2(JpaNamedQuery namedQuery) {
+        assertEquals("query2", namedQuery.getName());
+        assertEquals("select y", namedQuery.getQuery());
+        assertEquals(0, namedQuery.getHints().size());
+    }
+
+    protected void assertNativeNamedQuery3(JpaNamedNativeQuery namedQuery) {
+        assertEquals("query3", namedQuery.getName());
+        assertEquals("select z", namedQuery.getQuery());
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockResultClass", namedQuery
+                .getResultClassName());
+        assertEquals("rs-mapping1", namedQuery.getResultSetMapping());
+        assertEquals(2, namedQuery.getHints().size());
+
+        Iterator<JpaQueryHint> hintIt = namedQuery.getHints().iterator();
+        JpaQueryHint h1 = hintIt.next();
+        assertEquals("hint3", h1.getName());
+        assertEquals("value3", h1.getValue());
+
+        JpaQueryHint h2 = hintIt.next();
+        assertEquals("hint4", h2.getName());
+        assertEquals("value4", h2.getValue());
+    }
+
+    protected void assertNativeNamedQuery4(JpaNamedNativeQuery namedQuery) {
+        assertEquals("query4", namedQuery.getName());
+        assertEquals("select a", namedQuery.getQuery());
+        assertEquals(0, namedQuery.getHints().size());
+    }
+
+    protected void assertSqlResultSetMapping(JpaSqlResultSetMapping mapping) {
+        assertNotNull(mapping);
+        assertEquals("result-map1", mapping.getName());
+        assertEquals(2, mapping.getEntityResults().size());
+
+        Iterator<JpaEntityResult> erIt = mapping.getEntityResults().iterator();
+        JpaEntityResult er1 = erIt.next();
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockEntityX", er1
+                .getEntityClassName());
+        assertEquals("column1", er1.getDiscriminatorColumn());
+        assertEquals(2, er1.getFieldResults().size());
+
+        Iterator<JpaFieldResult> frIt1 = er1.getFieldResults().iterator();
+        JpaFieldResult fr11 = frIt1.next();
+        assertEquals("field1", fr11.getName());
+        assertEquals("column1", fr11.getColumn());
+
+        JpaFieldResult fr12 = frIt1.next();
+        assertEquals("field2", fr12.getName());
+        assertEquals("column2", fr12.getColumn());
+
+        JpaEntityResult er2 = erIt.next();
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockEntityY", er2
+                .getEntityClassName());
+        assertEquals("column2", er2.getDiscriminatorColumn());
+        assertEquals(2, er2.getFieldResults().size());
+
+        Iterator<JpaFieldResult> frIt2 = er2.getFieldResults().iterator();
+        JpaFieldResult fr21 = frIt2.next();
+        assertEquals("field3", fr21.getName());
+        assertEquals("column3", fr21.getColumn());
+
+        JpaFieldResult fr22 = frIt2.next();
+        assertEquals("field4", fr22.getName());
+        assertEquals("column4", fr22.getColumn());
+
+        assertEquals(2, mapping.getColumnResults().size());
+        Iterator<JpaColumnResult> crIt = mapping.getColumnResults().iterator();
+        assertEquals("column-result1", crIt.next().getName());
+        assertEquals("column-result2", crIt.next().getName());
+    }
+
+    protected void assertEntityListeners(JpaEntityListeners listeners) {
+        assertNotNull(listeners);
+        assertEquals(2, listeners.getEntityListeners().size());
+        Iterator<JpaEntityListener> elIt = listeners.getEntityListeners().iterator();
+        JpaEntityListener listener1 = elIt.next();
+
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockEntityListener1", listener1
+                .getClassName());
+
+        assertNotNull(listener1.getPrePersist());
+        assertEquals("prePersist", listener1.getPrePersist().getMethodName());
+        assertNotNull(listener1.getPostPersist());
+        assertEquals("postPersist", listener1.getPostPersist().getMethodName());
+        assertNotNull(listener1.getPreUpdate());
+        assertEquals("preUpdate", listener1.getPreUpdate().getMethodName());
+        assertNotNull(listener1.getPostUpdate());
+        assertEquals("postUpdate", listener1.getPostUpdate().getMethodName());
+        assertNotNull(listener1.getPreRemove());
+        assertEquals("preRemove", listener1.getPreRemove().getMethodName());
+        assertNotNull(listener1.getPostRemove());
+        assertEquals("postRemove", listener1.getPostRemove().getMethodName());
+        assertNotNull(listener1.getPostLoad());
+        assertEquals("postLoad", listener1.getPostLoad().getMethodName());
+
+        JpaEntityListener listener2 = elIt.next();
+
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockEntityListener2", listener2
+                .getClassName());
+
+        assertNull(listener2.getPrePersist());
+        assertNotNull(listener2.getPostPersist());
+        assertEquals("postPersist", listener2.getPostPersist().getMethodName());
+        assertNull(listener2.getPreUpdate());
+        assertNull(listener2.getPostUpdate());
+        assertNull(listener2.getPreRemove());
+        assertNull(listener2.getPostRemove());
+        assertNull(listener2.getPostLoad());
+    }
+
+    protected void assertId(JpaId id) {
+        assertEquals("id1", id.getName());
+        assertNotNull(id.getColumn());
+        assertEquals("id_column", id.getColumn().getName());
+        assertNull("Expected null, got: " + id.getColumn().getColumnDefinition(), id
+                .getColumn()
+                .getColumnDefinition());
+        assertEquals("id_table", id.getColumn().getTable());
+        assertEquals(3, id.getColumn().getLength());
+        assertEquals(4, id.getColumn().getPrecision());
+        assertEquals(5, id.getColumn().getScale());
+        assertTrue(id.getColumn().isInsertable());
+        assertTrue(id.getColumn().isNullable());
+        assertTrue(id.getColumn().isUnique());
+        assertTrue(id.getColumn().isUpdatable());
+
+        assertNotNull(id.getGeneratedValue());
+        assertSame(GenerationType.SEQUENCE, id.getGeneratedValue().getStrategy());
+        assertEquals("id-generator", id.getGeneratedValue().getGenerator());
+
+        assertEquals(TemporalType.TIME, id.getTemporal());
+    }
+
+    protected void assertEmbeddedId(JpaEmbeddedId id) {
+        assertNotNull(id);
+        assertEquals("embeddedId", id.getName());
+
+        assertEquals(2, id.getAttributeOverrides().size());
+        List<JpaAttributeOverride> overrides = new ArrayList<JpaAttributeOverride>(id
+                .getAttributeOverrides());
+
+        assertEquals("attribute1", overrides.get(0).getName());
+        assertEquals("ao_column1", overrides.get(0).getColumn().getName());
+
+        assertEquals("attribute2", overrides.get(1).getName());
+        assertEquals("ao_column2", overrides.get(1).getColumn().getName());
+    }
+
+    protected void assertMappedSuperclass1(JpaMappedSuperclass mappedSuperclass1) {
+
+        assertNotNull(mappedSuperclass1);
+
+        assertEquals(
+                "org.objectstyle.cayenne.jpa.entity.MockMappedSuperclass1",
+                mappedSuperclass1.getClassName());
+
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockIdClass", mappedSuperclass1
+                .getIdClassName());
+
+        assertTrue(mappedSuperclass1.isExcludeDefaultListeners());
+        assertTrue(mappedSuperclass1.isExcludeSuperclassListeners());
+
+        assertNotNull(mappedSuperclass1.getEntityListeners());
+        JpaEntityListeners listeners = mappedSuperclass1.getEntityListeners();
+        assertEquals(1, listeners.getEntityListeners().size());
+        Iterator<JpaEntityListener> elIt = listeners.getEntityListeners().iterator();
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockEntityListener1", elIt
+                .next()
+                .getClassName());
+
+        assertEquals(1, mappedSuperclass1.getIds().size());
+        assertId(mappedSuperclass1.getIds().iterator().next());
+
+        assertNotNull(mappedSuperclass1.getPrePersist());
+        assertEquals("eprePersist", mappedSuperclass1.getPrePersist().getMethodName());
+        assertNotNull(mappedSuperclass1.getPostPersist());
+        assertEquals("epostPersist", mappedSuperclass1.getPostPersist().getMethodName());
+        assertNotNull(mappedSuperclass1.getPreUpdate());
+        assertEquals("epreUpdate", mappedSuperclass1.getPreUpdate().getMethodName());
+        assertNotNull(mappedSuperclass1.getPostUpdate());
+        assertEquals("epostUpdate", mappedSuperclass1.getPostUpdate().getMethodName());
+        assertNotNull(mappedSuperclass1.getPreRemove());
+        assertEquals("epreRemove", mappedSuperclass1.getPreRemove().getMethodName());
+        assertNotNull(mappedSuperclass1.getPostRemove());
+        assertEquals("epostRemove", mappedSuperclass1.getPostRemove().getMethodName());
+        assertNotNull(mappedSuperclass1.getPostLoad());
+        assertEquals("epostLoad", mappedSuperclass1.getPostLoad().getMethodName());
+    }
+
+    protected void assertMappedSuperclass2(JpaMappedSuperclass mappedSuperclass2) {
+        assertNotNull(mappedSuperclass2);
+        assertEquals(
+                "org.objectstyle.cayenne.jpa.entity.MockMappedSuperclass2",
+                mappedSuperclass2.getClassName());
+
+        assertEmbeddedId(mappedSuperclass2.getEmbeddedId());
+    }
+
+    protected void assertMappedSuperclass3(JpaMappedSuperclass mappedSuperclass3) {
+
+        assertNotNull(mappedSuperclass3.getAttributes());
+        assertEquals(17, mappedSuperclass3.getAttributes().size());
+        assertAttributes(new ArrayList<JpaAttribute>(mappedSuperclass3.getAttributes()));
+    }
+
+    protected void assertAttributes(List<JpaAttribute> attributes) {
+        // BASIC
+        assertNull(attributes.get(1).getBasic());
+        assertNotNull(attributes.get(0).getBasic());
+        assertEquals("attribute1", attributes.get(0).getName());
+        assertTrue(attributes.get(0).getBasic().isOptional());
+        assertSame(FetchType.EAGER, attributes.get(0).getBasic().getFetch());
+
+        // VERSION
+        assertFalse(attributes.get(0).isVersion());
+        assertTrue(attributes.get(1).isVersion());
+        assertEquals("attribute2", attributes.get(1).getName());
+
+        // ONE-TO_ONE
+        assertNull(attributes.get(1).getOneToOne());
+        assertNotNull(attributes.get(2).getOneToOne());
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockTargetEntity1", attributes
+                .get(2)
+                .getOneToOne()
+                .getTargetEntityName());
+        assertTrue(attributes.get(2).getOneToOne().isOptional());
+        assertSame(FetchType.LAZY, attributes.get(2).getOneToOne().getFetch());
+        assertEquals("mb1", attributes.get(2).getOneToOne().getMappedBy());
+        Collection<CascadeType> cascades = attributes.get(2).getOneToOne().getCascades();
+        assertEquals(2, cascades.size());
+        Iterator cascades1It = cascades.iterator();
+        assertSame(CascadeType.MERGE, cascades1It.next());
+        assertSame(CascadeType.PERSIST, cascades1It.next());
+
+        // ONE-TO-MANY
+        assertNull(attributes.get(2).getOneToMany());
+        assertNotNull(attributes.get(3).getOneToMany());
+        JpaOneToMany otm = attributes.get(3).getOneToMany();
+        assertEquals("org.objectstyle.cayenne.jpa.entity.MockTargetEntity2", otm
+                .getTargetEntityName());
+        assertSame(FetchType.LAZY, otm.getFetch());
+        assertEquals("mb2", otm.getMappedBy());
+        assertEquals(2, otm.getCascades().size());
+        Iterator cascades2It = otm.getCascades().iterator();
+        assertSame(CascadeType.MERGE, cascades2It.next());
+        assertSame(CascadeType.PERSIST, cascades2It.next());
+
+        // JOIN COLUMN
+        assertNotNull(attributes.get(9).getJoinColumns());
+        assertEquals(1, attributes.get(9).getJoinColumns().size());
+        JpaJoinColumn joinColumn = attributes.get(9).getJoinColumns().iterator().next();
+        assertEquals("join-column-10", joinColumn.getName());
+        assertEquals("x-def", joinColumn.getColumnDefinition());
+        assertEquals("x-ref", joinColumn.getReferencedColumnName());
+        assertEquals("jt1", joinColumn.getTable());
+        assertTrue(joinColumn.isInsertable());
+        assertTrue(joinColumn.isNullable());
+        assertTrue(joinColumn.isUnique());
+        assertTrue(joinColumn.isUpdatable());
+
+        // LOB
+        assertFalse(attributes.get(10).isLob());
+        assertTrue(attributes.get(11).isLob());
+    }
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MockAnnotatedBean1.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MockAnnotatedBean1.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MockAnnotatedBean1.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MockAnnotatedBean1.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,69 @@
+/* ====================================================================
+ * 
+ * The ObjectStyle Group Software License, version 1.1
+ * ObjectStyle Group - http://objectstyle.org/
+ * 
+ * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
+ * of the software. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * 3. The end-user documentation included with the redistribution, if any,
+ *    must include the following acknowlegement:
+ *    "This product includes software developed by independent contributors
+ *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ * 
+ * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
+ *    or promote products derived from this software without prior written
+ *    permission. For written permission, email
+ *    "andrus at objectstyle dot org".
+ * 
+ * 5. Products derived from this software may not be called "ObjectStyle"
+ *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
+ *    names without prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by many
+ * individuals and hosted on ObjectStyle Group web site.  For more
+ * information on the ObjectStyle Group, please see
+ * <http://objectstyle.org/>.
+ */
+package org.objectstyle.cayenne.jpa.conf;
+
+import javax.persistence.Entity;
+import javax.persistence.IdClass;
+import javax.persistence.NamedQuery;
+
+import org.objectstyle.cayenne.jpa.entity.MockIdClass;
+
+@NamedQuery(name = "x", query = "y")
+@IdClass(MockIdClass.class)
+@Entity
+public class MockAnnotatedBean1 {
+
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MockAnnotatedBean2.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MockAnnotatedBean2.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MockAnnotatedBean2.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MockAnnotatedBean2.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,68 @@
+/* ====================================================================
+ * 
+ * The ObjectStyle Group Software License, version 1.1
+ * ObjectStyle Group - http://objectstyle.org/
+ * 
+ * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
+ * of the software. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * 3. The end-user documentation included with the redistribution, if any,
+ *    must include the following acknowlegement:
+ *    "This product includes software developed by independent contributors
+ *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ * 
+ * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
+ *    or promote products derived from this software without prior written
+ *    permission. For written permission, email
+ *    "andrus at objectstyle dot org".
+ * 
+ * 5. Products derived from this software may not be called "ObjectStyle"
+ *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
+ *    names without prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by many
+ * individuals and hosted on ObjectStyle Group web site.  For more
+ * information on the ObjectStyle Group, please see
+ * <http://objectstyle.org/>.
+ */
+package org.objectstyle.cayenne.jpa.conf;
+
+import javax.persistence.AttributeOverride;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+
+@Entity
+@AttributeOverride(name = "entityAttribute", column = @Column(name = "c1"))
+public class MockAnnotatedBean2 {
+
+    @AttributeOverride(name = "embdeddedAttribute", column = @Column(name = "c2"))
+    protected Object property;
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MockPropertyRegressionBean.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MockPropertyRegressionBean.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MockPropertyRegressionBean.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/MockPropertyRegressionBean.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,105 @@
+/* ====================================================================
+ * 
+ * The ObjectStyle Group Software License, version 1.1
+ * ObjectStyle Group - http://objectstyle.org/
+ * 
+ * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
+ * of the software. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * 3. The end-user documentation included with the redistribution, if any,
+ *    must include the following acknowlegement:
+ *    "This product includes software developed by independent contributors
+ *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ * 
+ * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
+ *    or promote products derived from this software without prior written
+ *    permission. For written permission, email
+ *    "andrus at objectstyle dot org".
+ * 
+ * 5. Products derived from this software may not be called "ObjectStyle"
+ *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
+ *    names without prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by many
+ * individuals and hosted on ObjectStyle Group web site.  For more
+ * information on the ObjectStyle Group, please see
+ * <http://objectstyle.org/>.
+ */
+package org.objectstyle.cayenne.jpa.conf;
+
+public class MockPropertyRegressionBean {
+
+    public MockPropertyRegressionBean() {
+        // avoid eclipse warnings due to unused provate members
+        getP1();
+        setP1("x");
+    }
+
+    private String getP1() {
+        return null;
+    }
+
+    private void setP1(String value) {
+
+    }
+
+    protected String getP2() {
+        return null;
+    }
+
+    protected void setP2(String value) {
+
+    }
+
+    public String getP3() {
+        return null;
+    }
+
+    public void setP3(String value) {
+
+    }
+
+    public String getP4() {
+        return null;
+    }
+
+    public void setP4(String value, Object anotherValue) {
+
+    }
+
+    public String getP5() {
+        return null;
+    }
+
+    public Object setP5(String value) {
+        return null;
+    }
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/XMLMappingAssertion.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/XMLMappingAssertion.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/XMLMappingAssertion.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/conf/XMLMappingAssertion.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,103 @@
+/* ====================================================================
+ * 
+ * The ObjectStyle Group Software License, version 1.1
+ * ObjectStyle Group - http://objectstyle.org/
+ * 
+ * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
+ * of the software. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * 3. The end-user documentation included with the redistribution, if any,
+ *    must include the following acknowlegement:
+ *    "This product includes software developed by independent contributors
+ *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ * 
+ * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
+ *    or promote products derived from this software without prior written
+ *    permission. For written permission, email
+ *    "andrus at objectstyle dot org".
+ * 
+ * 5. Products derived from this software may not be called "ObjectStyle"
+ *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
+ *    names without prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by many
+ * individuals and hosted on ObjectStyle Group web site.  For more
+ * information on the ObjectStyle Group, please see
+ * <http://objectstyle.org/>.
+ */
+package org.objectstyle.cayenne.jpa.conf;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.persistence.CascadeType;
+import javax.persistence.FlushModeType;
+
+import org.objectstyle.cayenne.jpa.map.AccessType;
+import org.objectstyle.cayenne.jpa.map.JpaEmbeddable;
+import org.objectstyle.cayenne.jpa.map.JpaEntity;
+import org.objectstyle.cayenne.jpa.map.JpaEntityMap;
+
+class XMLMappingAssertion extends MappingAssertion {
+
+    @Override
+    public void testEntityMap(JpaEntityMap entityMap) throws Exception {
+
+        assertNotNull(entityMap);
+        assertEquals("default_package", entityMap.getPackageName());
+        assertEquals("default_catalog", entityMap.getCatalog());
+        assertEquals(AccessType.FIELD, entityMap.getAccess());
+        assertEquals(FlushModeType.COMMIT, entityMap.getFlushMode());
+
+        super.testEntityMap(entityMap);
+
+        // common annotations that are not per-entity
+        Collection<CascadeType> cascades = entityMap.getCascades();
+        assertNotNull(cascades);
+        assertEquals(3, cascades.size());
+        Iterator cascadesIt = cascades.iterator();
+        assertEquals(CascadeType.MERGE, cascadesIt.next());
+        assertEquals(CascadeType.PERSIST, cascadesIt.next());
+        assertEquals(CascadeType.REFRESH, cascadesIt.next());
+    }
+
+    @Override
+    protected void assertEntity1(JpaEntity entity1) {
+        super.assertEntity1(entity1);
+        assertSame(AccessType.PROPERTY, entity1.getAccess());
+    }
+
+    @Override
+    protected void assertEmbeddable1(JpaEmbeddable embeddable1) {
+        super.assertEmbeddable1(embeddable1);
+        assertSame(AccessType.FIELD, embeddable1.getAccess());
+    }
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/CjpaNativeQueryTest.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/CjpaNativeQueryTest.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/CjpaNativeQueryTest.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/CjpaNativeQueryTest.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,46 @@
+package org.objectstyle.cayenne.jpa.cspi;
+
+import org.objectstyle.cayenne.access.DataContext;
+
+import junit.framework.TestCase;
+
+public class CjpaNativeQueryTest extends TestCase {
+
+    public void testSetParameter1() {
+        CjpaNativeQuery q = new CjpaNativeQuery(
+                new DataContext(),
+                "select a from person where name = $name and id = $id ",
+                Object.class);
+        assertEquals("Should return same query", q, q.setParameter("name", ""));
+
+        /* TODO: uncomment when supported..
+        try {
+            q.setParameter("unexisting", "");
+            fail("Should throw on unexisting parameter");
+        }
+        catch (IllegalArgumentException e) {
+            // ok
+        }
+        */
+    }
+
+    public void testSetParameter2() {
+        CjpaNativeQuery q = new CjpaNativeQuery(
+                new DataContext(),
+                "select a from person where name = ?1 and id = ?2 and addr = ?123 ",
+                Object.class);
+        assertEquals("Should return same query", q, q.setParameter(1, ""));
+        q.setParameter(2, "");
+        q.setParameter(123, "");
+
+        /* TODO: uncomment when supported..
+        try {
+            q.setParameter(3, "");
+            fail("Should throw on unexisting parameter");
+        }
+        catch (IllegalArgumentException e) {
+            // ok
+        }
+        */
+    }
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/HelperEnhancingClassLoader.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/HelperEnhancingClassLoader.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/HelperEnhancingClassLoader.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/HelperEnhancingClassLoader.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,127 @@
+package org.objectstyle.cayenne.jpa.cspi;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.instrument.IllegalClassFormatException;
+import java.security.SecureClassLoader;
+import java.util.Collection;
+
+import javax.persistence.spi.ClassTransformer;
+
+/**
+ * A ClassLoader used in unit testing that passes configured classes through the
+ * ClassTransformer enhancer.
+ * 
+ * @author Andrus Adamchik
+ */
+public class HelperEnhancingClassLoader extends SecureClassLoader {
+
+    protected ClassTransformer transformer;
+    protected Collection classesToEnhance;
+
+    public HelperEnhancingClassLoader() {
+        this(null, null);
+    }
+
+    public HelperEnhancingClassLoader(ClassTransformer transformer,
+            Collection classesToEnhance) {
+        super(Thread.currentThread().getContextClassLoader());
+        this.transformer = transformer;
+        this.classesToEnhance = classesToEnhance;
+    }
+
+    /**
+     * Returns true if the class does not need to be enhanced.
+     */
+    protected boolean skipClassEnhancement(String className) {
+        return transformer == null || !classesToEnhance.contains(className);
+    }
+
+    @Override
+    protected synchronized Class<?> loadClass(String name, boolean resolve)
+            throws ClassNotFoundException {
+
+        if (skipClassEnhancement(name)) {
+            return super.loadClass(name, resolve);
+        }
+
+        Class c = findLoadedClass(name);
+
+        if (c == null) {
+            c = findClass(name);
+        }
+
+        if (resolve) {
+            resolveClass(c);
+        }
+
+        return c;
+    }
+
+    /**
+     * If a class name is one of the managed classes, loads it
+     */
+    @Override
+    protected Class<?> findClass(String name) throws ClassNotFoundException {
+        if (skipClassEnhancement(name)) {
+            return Class.forName(name, true, getParent());
+        }
+        else {
+            return findEnhancedClass(name);
+        }
+    }
+
+    /**
+     * Loads class bytes, and passes them through the registered ClassTransformers.
+     */
+    protected Class<?> findEnhancedClass(String name) throws ClassNotFoundException {
+        String path = name.replace('.', '/') + ".class";
+
+        InputStream in = getResourceAsStream(path);
+        if (in == null) {
+            return Class.forName(name, true, getParent());
+        }
+
+        try {
+
+            ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
+            byte[] buffer = new byte[1024];
+            int read;
+
+            while ((read = in.read(buffer, 0, 1024)) > 0) {
+                out.write(buffer, 0, read);
+            }
+
+            out.close();
+            byte[] classBytes = out.toByteArray();
+
+            byte[] bytes;
+            try {
+                bytes = transformer.transform(getParent(), name, null, null, classBytes);
+            }
+            catch (IllegalClassFormatException e) {
+                throw new ClassNotFoundException("Could not transform class '"
+                        + name
+                        + "' due to invalid format", e);
+            }
+
+            if (bytes != null) {
+                classBytes = bytes;
+            }
+
+            return defineClass(name, classBytes, 0, classBytes.length);
+        }
+        catch (IOException e) {
+            throw new ClassNotFoundException(name, e);
+        }
+        finally {
+            try {
+                in.close();
+            }
+            catch (IOException e) {
+                // ignore close exceptions...
+            }
+        }
+    }
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/PersistentEnhancerTest.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/PersistentEnhancerTest.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/PersistentEnhancerTest.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/PersistentEnhancerTest.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,39 @@
+package org.objectstyle.cayenne.jpa.cspi;
+
+import java.util.Collections;
+
+import junit.framework.TestCase;
+
+import org.objectstyle.cayenne.ObjectId;
+import org.objectstyle.cayenne.PersistenceState;
+import org.objectstyle.cayenne.Persistent;
+import org.objectstyle.cayenne.property.PropertyUtils;
+
+public class PersistentEnhancerTest extends TestCase {
+
+    public void testPOJOEnhancement() throws Exception {
+        String testPojoName = "org.objectstyle.cayenne.jpa.cspi.TestPojo";
+
+        PersistentEnhancer enhancer = new PersistentEnhancer();
+        ClassLoader testCl = new HelperEnhancingClassLoader(enhancer, Collections
+                .singleton(testPojoName));
+
+        Object object = Class.forName(testPojoName, true, testCl).newInstance();
+
+        // test POJO properties...
+        assertEquals(testPojoName, object.getClass().getName());
+        PropertyUtils.setProperty(object, "stringProperty", "XXXX");
+        assertEquals("XXXX", PropertyUtils.getProperty(object, "stringProperty"));
+
+        assertTrue(object instanceof Persistent);
+        Persistent p = (Persistent) object;
+
+        int state = PersistenceState.DELETED;
+        p.setPersistenceState(state);
+        assertEquals(PersistenceState.DELETED, p.getPersistenceState());
+
+        ObjectId id = new ObjectId("X", "R", 55);
+        p.setObjectId(id);
+        assertSame(id, p.getObjectId());
+    }
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/TestPojo.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/TestPojo.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/TestPojo.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/cspi/TestPojo.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,14 @@
+package org.objectstyle.cayenne.jpa.cspi;
+
+public class TestPojo {
+
+    protected String stringProperty;
+
+    public String getStringProperty() {
+        return stringProperty;
+    }
+
+    public void setStringProperty(String stringProperty) {
+        this.stringProperty = stringProperty;
+    }
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/entity/MockEmbed1.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/entity/MockEmbed1.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/entity/MockEmbed1.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/entity/MockEmbed1.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,80 @@
+/* ====================================================================
+ * 
+ * The ObjectStyle Group Software License, version 1.1
+ * ObjectStyle Group - http://objectstyle.org/
+ * 
+ * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
+ * of the software. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * 3. The end-user documentation included with the redistribution, if any,
+ *    must include the following acknowlegement:
+ *    "This product includes software developed by independent contributors
+ *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ * 
+ * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
+ *    or promote products derived from this software without prior written
+ *    permission. For written permission, email
+ *    "andrus at objectstyle dot org".
+ * 
+ * 5. Products derived from this software may not be called "ObjectStyle"
+ *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
+ *    names without prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by many
+ * individuals and hosted on ObjectStyle Group web site.  For more
+ * information on the ObjectStyle Group, please see
+ * <http://objectstyle.org/>.
+ */
+package org.objectstyle.cayenne.jpa.entity;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.Lob;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+@Embeddable
+public class MockEmbed1 {
+
+    @Basic(fetch=FetchType.EAGER, optional=true)
+    @Lob
+    @Temporal(TemporalType.DATE)
+    @Enumerated(EnumType.ORDINAL)
+    @Column(name="column9")
+    protected String ea1;
+    
+    @Basic
+    protected String ea2;
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/entity/MockEmbed2.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/entity/MockEmbed2.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/entity/MockEmbed2.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/entity/MockEmbed2.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,63 @@
+/* ====================================================================
+ * 
+ * The ObjectStyle Group Software License, version 1.1
+ * ObjectStyle Group - http://objectstyle.org/
+ * 
+ * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
+ * of the software. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * 3. The end-user documentation included with the redistribution, if any,
+ *    must include the following acknowlegement:
+ *    "This product includes software developed by independent contributors
+ *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ * 
+ * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
+ *    or promote products derived from this software without prior written
+ *    permission. For written permission, email
+ *    "andrus at objectstyle dot org".
+ * 
+ * 5. Products derived from this software may not be called "ObjectStyle"
+ *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
+ *    names without prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by many
+ * individuals and hosted on ObjectStyle Group web site.  For more
+ * information on the ObjectStyle Group, please see
+ * <http://objectstyle.org/>.
+ */
+package org.objectstyle.cayenne.jpa.entity;
+
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class MockEmbed2 {
+
+}

Added: incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/entity/MockEntity1.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/entity/MockEntity1.java?rev=396882&view=auto
==============================================================================
--- incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/entity/MockEntity1.java (added)
+++ incubator/cayenne/trunk/cayenne-jpa/src/test/java/org/objectstyle/cayenne/jpa/entity/MockEntity1.java Tue Apr 25 06:43:00 2006
@@ -0,0 +1,189 @@
+/* ====================================================================
+ * 
+ * The ObjectStyle Group Software License, version 1.1
+ * ObjectStyle Group - http://objectstyle.org/
+ * 
+ * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
+ * of the software. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * 3. The end-user documentation included with the redistribution, if any,
+ *    must include the following acknowlegement:
+ *    "This product includes software developed by independent contributors
+ *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ * 
+ * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
+ *    or promote products derived from this software without prior written
+ *    permission. For written permission, email
+ *    "andrus at objectstyle dot org".
+ * 
+ * 5. Products derived from this software may not be called "ObjectStyle"
+ *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
+ *    names without prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by many
+ * individuals and hosted on ObjectStyle Group web site.  For more
+ * information on the ObjectStyle Group, please see
+ * <http://objectstyle.org/>.
+ */
+package org.objectstyle.cayenne.jpa.entity;
+
+import javax.persistence.Column;
+import javax.persistence.ColumnResult;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.EntityResult;
+import javax.persistence.ExcludeDefaultListeners;
+import javax.persistence.ExcludeSuperclassListeners;
+import javax.persistence.FieldResult;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.NamedNativeQueries;
+import javax.persistence.NamedNativeQuery;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.PostLoad;
+import javax.persistence.PostPersist;
+import javax.persistence.PostRemove;
+import javax.persistence.PostUpdate;
+import javax.persistence.PrePersist;
+import javax.persistence.PreRemove;
+import javax.persistence.PreUpdate;
+import javax.persistence.PrimaryKeyJoinColumn;
+import javax.persistence.QueryHint;
+import javax.persistence.SecondaryTable;
+import javax.persistence.SecondaryTables;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.SqlResultSetMapping;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.UniqueConstraint;
+
+@IdClass(MockIdClass.class)
+@TableGenerator(name = "table-generator", table = "auto_pk_table", catalog = "catalog1", schema = "schema1", pkColumnName = "next_id", valueColumnName = "x", pkColumnValue = "y", initialValue = 4, allocationSize = 20, uniqueConstraints = {
+    @UniqueConstraint(columnNames = {
+        "pk1"
+    })
+})
+@Entity
+@Table(name = "mock_persistent_1", catalog = "catalog1", schema = "schema1", uniqueConstraints = {
+        @UniqueConstraint(columnNames = {
+                "column1", "column2"
+        }), @UniqueConstraint(columnNames = {
+            "column3"
+        })
+})
+@SecondaryTables(value = {
+        @SecondaryTable(name = "secondary1", catalog = "catalog1", schema = "schema1", pkJoinColumns = {
+                @PrimaryKeyJoinColumn(name = "secondary_column1", referencedColumnName = "column1", columnDefinition = "count(1)"),
+                @PrimaryKeyJoinColumn(name = "secondary_column2", referencedColumnName = "column2")
+        }, uniqueConstraints = {
+            @UniqueConstraint(columnNames = {
+                    "column1", "column2"
+            })
+        }), @SecondaryTable(name = "secondary2")
+})
+@SequenceGenerator(name = "sg-name", sequenceName = "seq-name", initialValue = 5, allocationSize = 10)
+@NamedQueries( {
+        @NamedQuery(name = "query1", query = "select x", hints = {
+                @QueryHint(name = "hint1", value = "value1"),
+                @QueryHint(name = "hint2", value = "value2")
+        }), @NamedQuery(name = "query2", query = "select y")
+})
+@NamedNativeQueries( {
+        @NamedNativeQuery(name = "query3", query = "select z", resultClass = MockResultClass.class, resultSetMapping = "rs-mapping1", hints = {
+                @QueryHint(name = "hint3", value = "value3"),
+                @QueryHint(name = "hint4", value = "value4")
+        }), @NamedNativeQuery(name = "query4", query = "select a")
+})
+@SqlResultSetMapping(name = "result-map1", entities = {
+        @EntityResult(entityClass = MockEntityX.class, discriminatorColumn = "column1", fields = {
+                @FieldResult(name = "field1", column = "column1"),
+                @FieldResult(name = "field2", column = "column2")
+        }),
+        @EntityResult(entityClass = MockEntityY.class, discriminatorColumn = "column2", fields = {
+                @FieldResult(name = "field3", column = "column3"),
+                @FieldResult(name = "field4", column = "column4")
+        })
+}, columns = {
+        @ColumnResult(name = "column-result1"), @ColumnResult(name = "column-result2")
+})
+@ExcludeDefaultListeners
+@ExcludeSuperclassListeners
+@EntityListeners(value = {
+        MockEntityListener1.class, MockEntityListener2.class
+})
+public class MockEntity1 {
+
+    @Id
+    @Temporal(TemporalType.TIME)
+    @Column(name = "id_column", unique = true, nullable = true, insertable = true, updatable = true, table = "id_table", length = 3, precision = 4, scale = 5)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id-generator")
+    protected int id1;
+
+    @PrePersist
+    protected void eprePersist() {
+
+    }
+
+    @PostPersist
+    protected void epostPersist() {
+
+    }
+
+    @PreRemove
+    protected void epreRemove() {
+
+    }
+
+    @PostRemove
+    protected void epostRemove() {
+
+    }
+
+    @PreUpdate
+    protected void epreUpdate() {
+
+    }
+
+    @PostUpdate
+    protected void epostUpdate() {
+
+    }
+
+    @PostLoad
+    protected void epostLoad() {
+
+    }
+}