openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dez...@apache.org
Subject svn commit: r889871 - in /openjpa/branches/1.1.x: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-kernel/src/main/java/org/apache/openjpa/conf/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ openjpa-persistence-jd...
Date Sat, 12 Dec 2009 00:50:59 GMT
Author: dezzio
Date: Sat Dec 12 00:50:58 2009
New Revision: 889871

URL: http://svn.apache.org/viewvc?rev=889871&view=rev
Log:
OpenJPA-1200: Applied patch supplied by Ravi Palacherla.  Also changed EOL to native for modified files JDBCStoreManager and Compatibility.

Added:
    openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/
    openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/
    openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Artist.java   (with props)
    openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Book.java   (with props)
    openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Item.java   (with props)
    openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Movie.java   (with props)
    openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/TestQuerySubclass.java   (with props)
Modified:
    openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
    openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java   (contents, props changed)
    openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/AbstractUnenhancedClassTest.java   (contents, props changed)

Modified: openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java?rev=889871&r1=889870&r2=889871&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java (original)
+++ openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java Sat Dec 12 00:50:58 2009
@@ -38,6 +38,7 @@
 import org.apache.openjpa.jdbc.meta.Discriminator;
 import org.apache.openjpa.jdbc.meta.FieldMapping;
 import org.apache.openjpa.jdbc.meta.ValueMapping;
+import org.apache.openjpa.jdbc.meta.strats.SuperclassDiscriminatorStrategy;
 import org.apache.openjpa.jdbc.sql.DBDictionary;
 import org.apache.openjpa.jdbc.sql.JoinSyntaxes;
 import org.apache.openjpa.jdbc.sql.Joins;
@@ -898,13 +899,9 @@
         OpenJPAStateManager sm, BitSet fields, JDBCFetchConfiguration fetch,
         int eager, boolean ident, boolean outer) {
         // add class conditions so that they're cloned for any batched selects
-        boolean joinedSupers = false;
-        if ((sm == null || sm.getPCState() == PCState.TRANSIENT)
-            && (subs == Select.SUBS_JOINABLE || subs == Select.SUBS_NONE)) {
-            loadSubclasses(mapping); 
-            Joins joins = (outer) ? sel.newOuterJoins() : null;
-            joinedSupers = mapping.getDiscriminator().addClassConditions(sel,
-                subs == Select.SUBS_JOINABLE, joins);
+     boolean joinedSupers = false;    
+     if(needClassCondition(mapping, subs, sm)) {
+         joinedSupers = getJoinedSupers(sel, mapping, subs, outer);
         }
 
         // create all our eager selects so that those fields are reserved
@@ -935,6 +932,32 @@
         return seld > 0;
     }
 
+    private boolean getJoinedSupers(Select sel, ClassMapping mapping, int subs, boolean outer) {
+        loadSubclasses(mapping); 
+        Joins joins = (outer) ? sel.newOuterJoins() : null;
+        return mapping.getDiscriminator().addClassConditions(sel, subs == Select.SUBS_JOINABLE, joins);
+    }
+        
+    private boolean needClassCondition(ClassMapping mapping, int subs,
+        OpenJPAStateManager sm) {
+        boolean retVal = false;
+        if(sm == null || sm.getPCState() == PCState.TRANSIENT) {
+            if(subs == Select.SUBS_JOINABLE || subs == Select.SUBS_NONE) {
+                retVal = true;
+            }
+            else {
+                if (mapping.getDiscriminator() != null
+                    && SuperclassDiscriminatorStrategy.class.isInstance(mapping.getDiscriminator().getStrategy())
+                    && mapping.getMappingRepository().getConfiguration().getCompatibilityInstance()
+                        .getSuperclassDiscriminatorStrategyByDefault()) {
+                    retVal = true;
+                }
+            }
+        }
+        return retVal;
+    }
+    
+    
     /**
      * Mark the fields of this mapping as reserved so that eager fetches can't
      * get into infinite recursive situations.

Modified: openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java?rev=889871&r1=889870&r2=889871&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java (original)
+++ openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java Sat Dec 12 00:50:58 2009
@@ -57,6 +57,7 @@
     private boolean _storeMapCollectionInEntityAsBlob = false;
     private boolean _flushBeforeDetach = true; 
     private boolean _autoOff = true;
+    private boolean _superclassDiscriminatorStrategyByDefault = true;
 
     /**
      * Whether to require exact identity value types when creating object
@@ -89,6 +90,22 @@
     public void setAutoOff(boolean autoOff) {
         _autoOff = autoOff;
     }
+    
+    /**
+     * Whether to add class criteria for super class discreminator strategy.
+     * Defaults to false.
+     */
+    public boolean getSuperclassDiscriminatorStrategyByDefault() {
+        return _superclassDiscriminatorStrategyByDefault;
+    }
+    
+    /**
+     * Whether to add class criteria for super class discreminator strategy.
+     * Defaults to false.
+     */
+    public void setSuperclassDiscriminatorStrategyByDefault(boolean superclassDiscriminatorStrategyByDefault) {
+        _superclassDiscriminatorStrategyByDefault = superclassDiscriminatorStrategyByDefault;
+    }
 
     /**
      * Whether to interpret quoted numbers in query strings as numbers.

Propchange: openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/AbstractUnenhancedClassTest.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/AbstractUnenhancedClassTest.java?rev=889871&r1=889870&r2=889871&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/AbstractUnenhancedClassTest.java (original)
+++ openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/AbstractUnenhancedClassTest.java Sat Dec 12 00:50:58 2009
@@ -1,610 +1,611 @@
-/*
- * 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.openjpa.enhance;
-
-import java.io.IOException;
-import java.io.ByteArrayOutputStream;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
-import java.io.ByteArrayInputStream;
-import java.util.List;
-import java.util.Collections;
-import java.lang.reflect.Field;
-
-import org.apache.openjpa.persistence.test.SingleEMFTestCase;
-import org.apache.openjpa.persistence.OpenJPAEntityManager;
-import org.apache.openjpa.persistence.JPAFacadeHelper;
-import org.apache.openjpa.kernel.OpenJPAStateManager;
-import org.apache.openjpa.meta.ClassMetaData;
-import org.apache.openjpa.util.ImplHelper;
-import org.apache.openjpa.event.AbstractLifecycleListener;
-import org.apache.openjpa.event.LifecycleEvent;
-
-public abstract class AbstractUnenhancedClassTest
-    extends SingleEMFTestCase {
-
-    // ##### To do:
-    // - clearing in pnew property-access without redefinition
-    // - figure out how to auto-test the redefinition code, either in Java 5
-    //   or in Java 6
-    // - run CTS in the following combinations:
-    //   * Java 6
-    //   * Java 5 with javaagent
-    //   * Java 5 without javaagent
-
-    public void setUp() {
-        setUp(getUnenhancedClass(), getUnenhancedSubclass(), CLEAR_TABLES);
-        // trigger class redefinition
-        emf.createEntityManager().close();
-    }
-
-    protected abstract Class<? extends UnenhancedType> getUnenhancedClass();
-
-    protected abstract UnenhancedType newUnenhancedInstance();
-
-    protected abstract Class<? extends UnenhancedSubtype> getUnenhancedSubclass();
-
-    protected abstract UnenhancedSubtype newUnenhancedSubclassInstance();
-
-    private UnenhancedType newInstance(boolean sub) {
-        return sub ? newUnenhancedSubclassInstance()
-            : newUnenhancedInstance();
-    }
-
-    public void testMetaData() {
-        ClassMetaData meta = JPAFacadeHelper.getMetaData(emf,
-            getUnenhancedClass());
-        assertEquals(ClassRedefiner.canRedefineClasses(),
-            meta.isIntercepting());
-    }
-
-    public void testImplHelperCalls() {
-        assertTrue(ImplHelper.isManagedType(null, getUnenhancedClass()));
-
-        UnenhancedType un = newUnenhancedInstance();
-        assertFalse(un instanceof PersistenceCapable);
-        PersistenceCapable pc = ImplHelper.toPersistenceCapable(un,
-            emf.getConfiguration());
-        assertNotNull(pc);
-        assertTrue(ImplHelper.isManageable(un));
-    }
-
-    public void testBasicPersistenceCapableBehavior() {
-        UnenhancedType un = newUnenhancedInstance();
-        un.setStringField("bar");
-        PersistenceCapable pc = ImplHelper.toPersistenceCapable(un,
-            emf.getConfiguration());
-        assertFalse(pc.pcIsDeleted());
-        assertFalse(pc.pcIsDirty());
-        assertFalse(pc.pcIsNew());
-        assertFalse(pc.pcIsPersistent());
-        assertFalse(pc.pcIsTransactional());
-    }
-
-    public void testPCRegistry() {
-        assertTrue(PCRegistry.isRegistered(getUnenhancedClass()));
-        PersistenceCapable pc = PCRegistry.newInstance(
-            getUnenhancedClass(), null, false);
-        assertNotNull(pc);
-        assertEquals(pc.getClass(), PCRegistry.getPCType(getUnenhancedClass()));
-    }
-
-    public void testClearingOnSubtypeInstance() {
-        // the boolean at the end of newInstance will cause clear to be invoked
-        UnenhancedType un = (UnenhancedType)
-            PCRegistry.newInstance(getUnenhancedClass(), null, true);
-        assertEquals(null, un.getStringField());
-    }
-
-    public void testGetObjectIdOnOpenJPAType() {
-        getObjectIdHelper(true, false);
-    }
-
-    public void testGetObjectIdOnOpenJPATypeSubclass() {
-        getObjectIdHelper(false, false);
-    }
-
-    public void testGetObjectIdOnUserDefined() {
-        getObjectIdHelper(true, true);
-    }
-
-    public void testGetObjectIdOnUserDefinedSubclass() {
-        getObjectIdHelper(false, true);
-    }
-
-    private void getObjectIdHelper(boolean sub, boolean userDefined) {
-        OpenJPAEntityManager em = emf.createEntityManager();
-        em.getTransaction().begin();
-        UnenhancedType un = newInstance(sub);
-        em.persist(un);
-        em.getTransaction().commit();
-
-        if (!userDefined) {
-            em.close();
-            em = emf.createEntityManager();
-            un = em.find(getUnenhancedClass(), un.getId());
-        }
-
-        assertNotNull(em.getObjectId(un));
-    }
-
-    public void testOperationsOnUserDefined() {
-        opsHelper(false, true);
-    }
-
-    public void testSubclassOperationsOnUserDefined() {
-        opsHelper(true, true);
-    }
-
-    public void testOperationsOnOpenJPADefined() {
-        opsHelper(false, false);
-    }
-
-    public void testSubclassOperationsOnOpenJPADefined() {
-        opsHelper(true, false);
-    }
-
-    private void opsHelper(boolean sub, boolean userDefined) {
-        OpenJPAEntityManager em = null;
-        try {
-            UnenhancedType un = newInstance(sub);
-            em = emf.createEntityManager();
-
-            em.getTransaction().begin();
-            em.persist(un);
-            un.setStringField("bar");
-            assertEquals("bar", un.getStringField());
-            assertPersistenceContext(em, un, true, true, sub);
-            em.flush();
-            assertPersistenceContext(em, un, true, true, sub);
-            assertTrue(un.getId() != 0);
-            UnenhancedType un2 = em.find(getUnenhancedClass(), un.getId());
-            assertSame(un, un2);
-            em.getTransaction().commit();
-            assertPersistenceContext(em, un, false, false, sub);
-            un2 = em.find(getUnenhancedClass(), un.getId());
-            assertSame(un, un2);
-
-            if (!userDefined) {
-                em.close();
-                em = emf.createEntityManager();
-            }
-
-            un = em.find(getUnenhancedClass(), un.getId());
-            assertNotNull(un);
-            if (!userDefined)
-                assertTrue(un instanceof PersistenceCapable);
-            assertEquals("bar", un.getStringField());
-            em.getTransaction().begin();
-            un.setStringField("baz");
-            assertPersistenceContext(em, un, true, true, sub);
-            assertEquals("baz", un.getStringField());
-
-            if (sub)
-                ((UnenhancedSubtype) un).setIntField(17);
-
-            assertTrue(em.isDirty(un));
-            
-            em.getTransaction().commit();
-
-            // make sure that the values are still up-to-date after
-            // the commit happens
-            assertEquals("baz", un.getStringField());
-            
-            em.close();
-
-            em = emf.createEntityManager();
-            un = em.find(getUnenhancedClass(), un.getId());
-            assertNotNull(un);
-            assertTrue(un instanceof PersistenceCapable);
-            assertEquals("baz", un.getStringField());
-            if (sub)
-                assertEquals(17, ((UnenhancedSubtype) un).getIntField());
-            em.close();
-        } finally {
-            if (em != null && em.getTransaction().isActive())
-                em.getTransaction().rollback();
-            if (em != null && em.isOpen())
-                em.close();
-        }
-    }
-
-    private void assertPersistenceContext(OpenJPAEntityManager em,
-        UnenhancedType un, boolean transactional, boolean dirty, boolean sub) {
-        assertEquals(transactional, em.getTransactionalObjects().contains(un));
-        assertEquals(dirty, em.getDirtyObjects().contains(un));
-        if (dirty) {
-            Class cls = sub ? getUnenhancedSubclass() : getUnenhancedClass();
-            assertTrue(em.getUpdatedClasses().contains(cls)
-                || em.getPersistedClasses().contains(cls));
-        }
-    }
-
-    public void testRelations() {
-        OpenJPAEntityManager em = emf.createEntityManager();
-        em.getTransaction().begin();
-        UnenhancedSubtype un = newUnenhancedSubclassInstance();
-        em.persist(un);
-        un.setStringField("aoeu");
-        UnenhancedSubtype related = newUnenhancedSubclassInstance();
-        un.setRelated(related);
-        related.setStringField("snth");
-        em.getTransaction().commit();
-        em.close();
-
-        em = emf.createEntityManager();
-        un = (UnenhancedSubtype) em.find(getUnenhancedClass(), un.getId());
-        assertEquals("aoeu", un.getStringField());
-        assertNotNull(un.getRelated());
-        assertEquals("snth", un.getRelated().getStringField());
-        em.close();
-    }
-
-    public void testEnhancer() throws IOException {
-        List<Class> subs =  ManagedClassSubclasser.prepareUnenhancedClasses(
-            emf.getConfiguration(),
-            Collections.singleton(getUnenhancedClass()), null);
-        Class sub = subs.get(0);
-        assertNotNull(sub);
-        assertEquals("org.apache.openjpa.enhance."
-            + getUnenhancedClass().getName().replace('.', '$') + "$pcsubclass",
-            sub.getName());
-        assertTrue(PersistenceCapable.class.isAssignableFrom(sub));
-        assertTrue(getUnenhancedClass().isAssignableFrom(sub));
-    }
-
-    public void testPCSubclassName() {
-        assertEquals("org.apache.openjpa.enhance."
-            + getUnenhancedClass().getName().replace('.', '$') + "$pcsubclass",
-            PCEnhancer.toPCSubclassName(getUnenhancedClass()));
-    }
-
-    public void testEvictionInUserCreatedInstance()
-        throws NoSuchFieldException, IllegalAccessException {
-        evictionHelper(true);
-    }
-
-    public void testEvictionInOpenJPACreatedInstance()
-        throws NoSuchFieldException, IllegalAccessException {
-        evictionHelper(false);
-    }
-
-    private void evictionHelper(boolean userDefined)
-        throws NoSuchFieldException, IllegalAccessException {
-        OpenJPAEntityManager em = emf.createEntityManager();
-        UnenhancedType un = newUnenhancedInstance();
-        em.getTransaction().begin();
-        em.persist(un);
-        em.getTransaction().commit();
-
-        if (!userDefined) {
-            em.close();
-            em = emf.createEntityManager();
-            un = em.find(getUnenhancedClass(), un.getId());
-            assertTrue(getUnenhancedClass() != un.getClass());
-        }
-
-        em.evict(un);
-        OpenJPAStateManager sm = (OpenJPAStateManager)
-            ImplHelper.toPersistenceCapable(un, null).pcGetStateManager();
-
-        // we only expect lazy loading to work when we can redefine classes
-        // or when accessing a property-access record that OpenJPA created.
-        if (ClassRedefiner.canRedefineClasses()
-            || (!userDefined && sm.getMetaData().getAccessType()
-                != ClassMetaData.ACCESS_FIELD)) {
-
-            assertFalse(sm.getLoaded()
-                .get(sm.getMetaData().getField("stringField").getIndex()));
-
-            // make sure that the value was cleared...
-            Field field = getUnenhancedClass().getDeclaredField(
-                isFieldAccessTest() ? "stringField" : "sf");
-            field.setAccessible(true);
-            assertEquals(null, field.get(un));
-
-            // ... and that it gets reloaded properly
-            assertEquals("foo", un.getStringField());
-            assertTrue(sm.getLoaded()
-                .get(sm.getMetaData().getField("stringField").getIndex()));
-        } else {
-            // unredefined properties with user-defined instance, or any
-            // unredefined field access
-            assertTrue(sm.getLoaded()
-                .get(sm.getMetaData().getField("stringField").getIndex()));
-
-            // make sure that the value was not cleared
-            Field field = getUnenhancedClass().getDeclaredField(
-                isFieldAccessTest() ? "stringField" : "sf");
-            field.setAccessible(true);
-            assertEquals("foo", field.get(un));
-        }
-
-        em.close();
-    }
-
-    protected abstract boolean isFieldAccessTest();
-
-    public void testLazyLoading()
-        throws NoSuchFieldException, IllegalAccessException {
-        OpenJPAEntityManager em = emf.createEntityManager();
-        UnenhancedType un = newUnenhancedInstance();
-        em.getTransaction().begin();
-        em.persist(un);
-        em.getTransaction().commit();
-        em.close();
-
-        em = emf.createEntityManager();
-        un = em.find(getUnenhancedClass(), un.getId());
-        assertTrue(getUnenhancedClass() != un.getClass());
-        OpenJPAStateManager sm = (OpenJPAStateManager)
-            ImplHelper.toPersistenceCapable(un, null).pcGetStateManager();
-
-        // we only expect lazy loading to work when we can redefine classes
-        // or when accessing a property-access record that OpenJPA created.
-        if (ClassRedefiner.canRedefineClasses()
-            || (sm.getMetaData().getAccessType() != ClassMetaData.ACCESS_FIELD))
-        {
-            assertFalse(sm.getLoaded()
-                .get(sm.getMetaData().getField("lazyField").getIndex()));
-
-            // make sure that the value was cleared
-            Field field = getUnenhancedClass().getDeclaredField("lazyField");
-            field.setAccessible(true);
-            assertEquals(null, field.get(un));
-        } else {
-            // unredefined field access
-            assertTrue(sm.getLoaded()
-                .get(sm.getMetaData().getField("lazyField").getIndex()));
-
-            // make sure that the value was loaded already
-            Field field = getUnenhancedClass().getDeclaredField("lazyField");
-            field.setAccessible(true);
-            assertEquals("lazy", field.get(un));
-        }
-
-        // make sure that the value is available, one way or another
-        assertEquals("lazy", un.getLazyField());
-        assertTrue(sm.getLoaded()
-            .get(sm.getMetaData().getField("lazyField").getIndex()));
-
-        em.close();
-    }
-
-    public void testSerializationOfUserDefinedInstance()
-        throws IOException, ClassNotFoundException {
-        serializationHelper(true, false);
-    }
-
-    public void testSerializationOfUserDefinedSubclassInstance()
-        throws IOException, ClassNotFoundException {
-        serializationHelper(true, true);
-    }
-
-    public void testSerializationOfOpenJPADefinedInstance()
-        throws IOException, ClassNotFoundException {
-        serializationHelper(false, false);
-    }
-
-    public void testSerializationOfOpenJPADefinedSubclassInstance()
-        throws IOException, ClassNotFoundException {
-        serializationHelper(false, true);
-    }
-
-    private void serializationHelper(boolean userDefined, boolean sub)
-        throws IOException, ClassNotFoundException {
-        OpenJPAEntityManager em = emf.createEntityManager();
-        UnenhancedType un = newInstance(sub);
-        em.getTransaction().begin();
-        em.persist(un);
-
-        if (sub) {
-            UnenhancedType related = newInstance(false);
-            related.setStringField("related");
-            ((UnenhancedSubtype) un).setRelated(related);
-        }
-
-        em.getTransaction().commit();
-
-        if (!userDefined) {
-            em.close();
-            em = emf.createEntityManager();
-        }
-
-        un = em.find(getUnenhancedClass(), un.getId());
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        ObjectOutputStream oout = new ObjectOutputStream(out);
-        oout.writeObject(un);
-        oout.flush();
-        byte[] bytes = out.toByteArray();
-
-        ObjectInputStream oin = new ObjectInputStream(
-            new ByteArrayInputStream(bytes));
-        UnenhancedType deserialized = (UnenhancedType) oin.readObject();
-
-        copiedInstanceHelper(sub, em, un, deserialized, false);
-        em.close();
-    }
-
-    public void testCloningOfUserDefinedInstance()
-        throws IOException, ClassNotFoundException, CloneNotSupportedException {
-        cloneHelper(true, false);
-    }
-
-    public void testCloningOfUserDefinedSubclassInstance()
-        throws IOException, ClassNotFoundException, CloneNotSupportedException {
-        cloneHelper(true, true);
-    }
-
-    public void testCloningOfOpenJPADefinedInstance()
-        throws IOException, ClassNotFoundException, CloneNotSupportedException {
-        cloneHelper(false, false);
-    }
-
-    public void testCloningOfOpenJPADefinedSubclassInstance()
-        throws IOException, ClassNotFoundException, CloneNotSupportedException {
-        cloneHelper(false, true);
-    }
-
-    private void cloneHelper(boolean userDefined, boolean sub)
-        throws IOException, ClassNotFoundException, CloneNotSupportedException {
-        OpenJPAEntityManager em = emf.createEntityManager();
-        UnenhancedType un = newInstance(sub);
-        em.getTransaction().begin();
-        em.persist(un);
-
-        if (sub) {
-            UnenhancedType related = newInstance(false);
-            related.setStringField("related");
-            ((UnenhancedSubtype) un).setRelated(related);
-        }
-
-        em.getTransaction().commit();
-
-        if (!userDefined) {
-            em.close();
-            em = emf.createEntityManager();
-        }
-
-        un = em.find(getUnenhancedClass(), un.getId());
-        UnenhancedType cloned = (UnenhancedType) un.clone();
-
-        copiedInstanceHelper(sub, em, un, cloned, true);
-        em.close();
-    }
-
-    private void copiedInstanceHelper(boolean sub, OpenJPAEntityManager em,
-        UnenhancedType un, UnenhancedType copy, boolean viaClone) {
-        assertNotSame(un, copy);
-        if (!viaClone)
-            assertEquals(sub ? getUnenhancedSubclass() : getUnenhancedClass(),
-                copy.getClass());
-        assertEquals(un.getId(), copy.getId());
-        assertEquals(un.getStringField(), copy.getStringField());
-        if (sub) {
-            assertEquals(
-                ((UnenhancedSubtype) un).getIntField(),
-                ((UnenhancedSubtype) copy).getIntField());
-            assertNotSame(
-                ((UnenhancedSubtype) un).getRelated(),
-                ((UnenhancedSubtype) copy).getRelated());
-            assertEquals(
-                ((UnenhancedSubtype) un).getRelated().getId(),
-                ((UnenhancedSubtype) copy).getRelated().getId());
-        }
-
-        assertFalse(em.isDetached(un));
-        assertTrue(em.isDetached(copy));
-
-        /*
-        ##### need to make detachment algorithm in ReflectingPC smarter
-        // ensure that remove() cannot be invoked on a detached instance
-        try {
-            em.getTransaction().begin();
-            em.remove(copy);
-            fail("remove() cannot be invoked on detached instance");
-        } catch (IllegalArgumentException e) {
-            em.getTransaction().rollback();
-        }
-        */
-
-        copy.setStringField("offline update");
-
-        em.getTransaction().begin();
-        assertSame(un, em.merge(copy));
-        assertTrue(em.isDirty(un));
-        assertEquals("offline update", un.getStringField());
-        em.getTransaction().commit();
-    }
-
-    public void testListenersOnUserDefinedInstance()
-        throws IOException, ClassNotFoundException, CloneNotSupportedException {
-        listenerHelper(true, false);
-    }
-
-    public void testListenersOnUserDefinedSubclassInstance()
-        throws IOException, ClassNotFoundException, CloneNotSupportedException {
-        listenerHelper(true, true);
-    }
-
-    public void testListenersOnOpenJPADefinedInstance()
-        throws IOException, ClassNotFoundException, CloneNotSupportedException {
-        listenerHelper(false, false);
-    }
-
-    public void testListenersOnOpenJPADefinedSubclassInstance()
-        throws IOException, ClassNotFoundException, CloneNotSupportedException {
-        listenerHelper(false, true);
-    }
-
-    private void listenerHelper(boolean userDefined, boolean sub)
-        throws IOException, ClassNotFoundException, CloneNotSupportedException {
-        ListenerImpl listener = new ListenerImpl();
-        emf.addLifecycleListener(listener, (Class[]) null);
-        OpenJPAEntityManager em = emf.createEntityManager();
-        UnenhancedType un = newInstance(sub);
-        em.getTransaction().begin();
-        em.persist(un);
-        em.getTransaction().commit();
-
-        if (!userDefined) {
-            em.close();
-            em = emf.createEntityManager();
-        }
-
-        listener.invoked = false;
-
-        un = em.find(getUnenhancedClass(), un.getId());
-        em.getTransaction().begin();
-        un.setStringField("updated");
-        em.getTransaction().commit();
-        assertTrue(listener.invoked);
-        em.close();
-
-        assertEquals("updated", listener.stringField);
-    }
-
-    public void testGetMetaDataOfSubtype() {
-        ClassMetaData meta = JPAFacadeHelper.getMetaData(emf,
-            getUnenhancedClass());
-        List<Class> subs =  ManagedClassSubclasser.prepareUnenhancedClasses(
-            emf.getConfiguration(),
-            Collections.singleton(getUnenhancedClass()), null);
-        assertSame(meta, JPAFacadeHelper.getMetaData(emf, subs.get(0)));
-
-        meta = JPAFacadeHelper.getMetaData(emf, getUnenhancedSubclass());
-        subs =  ManagedClassSubclasser.prepareUnenhancedClasses(
-            emf.getConfiguration(),
-            Collections.singleton(getUnenhancedSubclass()), null);
-        assertSame(meta, JPAFacadeHelper.getMetaData(emf, subs.get(0)));
-    }
-
-    private class ListenerImpl
-        extends AbstractLifecycleListener {
-
-        String stringField;
-        boolean invoked;
-
-        @Override
-        public void afterStore(LifecycleEvent event) {
-            invoked = true;
-            stringField = ((UnenhancedType) event.getSource()).getStringField();
-        }
-    }
+/*
+ * 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.openjpa.enhance;
+
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ByteArrayInputStream;
+import java.util.List;
+import java.util.Collections;
+import java.lang.reflect.Field;
+
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+import org.apache.openjpa.persistence.OpenJPAEntityManager;
+import org.apache.openjpa.persistence.JPAFacadeHelper;
+import org.apache.openjpa.jdbc.kernel.A;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.util.ImplHelper;
+import org.apache.openjpa.event.AbstractLifecycleListener;
+import org.apache.openjpa.event.LifecycleEvent;
+
+public abstract class AbstractUnenhancedClassTest
+    extends SingleEMFTestCase {
+
+    // ##### To do:
+    // - clearing in pnew property-access without redefinition
+    // - figure out how to auto-test the redefinition code, either in Java 5
+    //   or in Java 6
+    // - run CTS in the following combinations:
+    //   * Java 6
+    //   * Java 5 with javaagent
+    //   * Java 5 without javaagent
+
+    public void setUp() {
+        setUp(getUnenhancedClass(), getUnenhancedSubclass(), CLEAR_TABLES, "openjpa.Compatibility", "superclassDiscriminatorStrategyByDefault=false");
+        // trigger class redefinition
+        emf.createEntityManager().close();
+    }
+
+    protected abstract Class<? extends UnenhancedType> getUnenhancedClass();
+
+    protected abstract UnenhancedType newUnenhancedInstance();
+
+    protected abstract Class<? extends UnenhancedSubtype> getUnenhancedSubclass();
+
+    protected abstract UnenhancedSubtype newUnenhancedSubclassInstance();
+
+    private UnenhancedType newInstance(boolean sub) {
+        return sub ? newUnenhancedSubclassInstance()
+            : newUnenhancedInstance();
+    }
+
+    public void testMetaData() {
+        ClassMetaData meta = JPAFacadeHelper.getMetaData(emf,
+            getUnenhancedClass());
+        assertEquals(ClassRedefiner.canRedefineClasses(),
+            meta.isIntercepting());
+    }
+
+    public void testImplHelperCalls() {
+        assertTrue(ImplHelper.isManagedType(null, getUnenhancedClass()));
+
+        UnenhancedType un = newUnenhancedInstance();
+        assertFalse(un instanceof PersistenceCapable);
+        PersistenceCapable pc = ImplHelper.toPersistenceCapable(un,
+            emf.getConfiguration());
+        assertNotNull(pc);
+        assertTrue(ImplHelper.isManageable(un));
+    }
+
+    public void testBasicPersistenceCapableBehavior() {
+        UnenhancedType un = newUnenhancedInstance();
+        un.setStringField("bar");
+        PersistenceCapable pc = ImplHelper.toPersistenceCapable(un,
+            emf.getConfiguration());
+        assertFalse(pc.pcIsDeleted());
+        assertFalse(pc.pcIsDirty());
+        assertFalse(pc.pcIsNew());
+        assertFalse(pc.pcIsPersistent());
+        assertFalse(pc.pcIsTransactional());
+    }
+
+    public void testPCRegistry() {
+        assertTrue(PCRegistry.isRegistered(getUnenhancedClass()));
+        PersistenceCapable pc = PCRegistry.newInstance(
+            getUnenhancedClass(), null, false);
+        assertNotNull(pc);
+        assertEquals(pc.getClass(), PCRegistry.getPCType(getUnenhancedClass()));
+    }
+
+    public void testClearingOnSubtypeInstance() {
+        // the boolean at the end of newInstance will cause clear to be invoked
+        UnenhancedType un = (UnenhancedType)
+            PCRegistry.newInstance(getUnenhancedClass(), null, true);
+        assertEquals(null, un.getStringField());
+    }
+
+    public void testGetObjectIdOnOpenJPAType() {
+        getObjectIdHelper(true, false);
+    }
+
+    public void testGetObjectIdOnOpenJPATypeSubclass() {
+        getObjectIdHelper(false, false);
+    }
+
+    public void testGetObjectIdOnUserDefined() {
+        getObjectIdHelper(true, true);
+    }
+
+    public void testGetObjectIdOnUserDefinedSubclass() {
+        getObjectIdHelper(false, true);
+    }
+
+    private void getObjectIdHelper(boolean sub, boolean userDefined) {
+        OpenJPAEntityManager em = emf.createEntityManager();
+        em.getTransaction().begin();
+        UnenhancedType un = newInstance(sub);
+        em.persist(un);
+        em.getTransaction().commit();
+
+        if (!userDefined) {
+            em.close();
+            em = emf.createEntityManager();
+            un = em.find(getUnenhancedClass(), un.getId());
+        }
+
+        assertNotNull(em.getObjectId(un));
+    }
+
+    public void testOperationsOnUserDefined() {
+        opsHelper(false, true);
+    }
+
+    public void testSubclassOperationsOnUserDefined() {
+        opsHelper(true, true);
+    }
+
+    public void testOperationsOnOpenJPADefined() {
+        opsHelper(false, false);
+    }
+
+    public void testSubclassOperationsOnOpenJPADefined() {
+        opsHelper(true, false);
+    }
+
+    private void opsHelper(boolean sub, boolean userDefined) {
+        OpenJPAEntityManager em = null;
+        try {
+            UnenhancedType un = newInstance(sub);
+            em = emf.createEntityManager();
+
+            em.getTransaction().begin();
+            em.persist(un);
+            un.setStringField("bar");
+            assertEquals("bar", un.getStringField());
+            assertPersistenceContext(em, un, true, true, sub);
+            em.flush();
+            assertPersistenceContext(em, un, true, true, sub);
+            assertTrue(un.getId() != 0);
+            UnenhancedType un2 = em.find(getUnenhancedClass(), un.getId());
+            assertSame(un, un2);
+            em.getTransaction().commit();
+            assertPersistenceContext(em, un, false, false, sub);
+            un2 = em.find(getUnenhancedClass(), un.getId());
+            assertSame(un, un2);
+
+            if (!userDefined) {
+                em.close();
+                em = emf.createEntityManager();
+            }
+
+            un = em.find(getUnenhancedClass(), un.getId());
+            assertNotNull(un);
+            if (!userDefined)
+                assertTrue(un instanceof PersistenceCapable);
+            assertEquals("bar", un.getStringField());
+            em.getTransaction().begin();
+            un.setStringField("baz");
+            assertPersistenceContext(em, un, true, true, sub);
+            assertEquals("baz", un.getStringField());
+
+            if (sub)
+                ((UnenhancedSubtype) un).setIntField(17);
+
+            assertTrue(em.isDirty(un));
+            
+            em.getTransaction().commit();
+
+            // make sure that the values are still up-to-date after
+            // the commit happens
+            assertEquals("baz", un.getStringField());
+            
+            em.close();
+
+            em = emf.createEntityManager();
+            un = em.find(getUnenhancedClass(), un.getId());
+            assertNotNull(un);
+            assertTrue(un instanceof PersistenceCapable);
+            assertEquals("baz", un.getStringField());
+            if (sub)
+                assertEquals(17, ((UnenhancedSubtype) un).getIntField());
+            em.close();
+        } finally {
+            if (em != null && em.getTransaction().isActive())
+                em.getTransaction().rollback();
+            if (em != null && em.isOpen())
+                em.close();
+        }
+    }
+
+    private void assertPersistenceContext(OpenJPAEntityManager em,
+        UnenhancedType un, boolean transactional, boolean dirty, boolean sub) {
+        assertEquals(transactional, em.getTransactionalObjects().contains(un));
+        assertEquals(dirty, em.getDirtyObjects().contains(un));
+        if (dirty) {
+            Class cls = sub ? getUnenhancedSubclass() : getUnenhancedClass();
+            assertTrue(em.getUpdatedClasses().contains(cls)
+                || em.getPersistedClasses().contains(cls));
+        }
+    }
+
+    public void testRelations() {
+        OpenJPAEntityManager em = emf.createEntityManager();
+        em.getTransaction().begin();
+        UnenhancedSubtype un = newUnenhancedSubclassInstance();
+        em.persist(un);
+        un.setStringField("aoeu");
+        UnenhancedSubtype related = newUnenhancedSubclassInstance();
+        un.setRelated(related);
+        related.setStringField("snth");
+        em.getTransaction().commit();
+        em.close();
+
+        em = emf.createEntityManager();
+        un = (UnenhancedSubtype) em.find(getUnenhancedClass(), un.getId());
+        assertEquals("aoeu", un.getStringField());
+        assertNotNull(un.getRelated());
+        assertEquals("snth", un.getRelated().getStringField());
+        em.close();
+    }
+
+    public void testEnhancer() throws IOException {
+        List<Class> subs =  ManagedClassSubclasser.prepareUnenhancedClasses(
+            emf.getConfiguration(),
+            Collections.singleton(getUnenhancedClass()), null);
+        Class sub = subs.get(0);
+        assertNotNull(sub);
+        assertEquals("org.apache.openjpa.enhance."
+            + getUnenhancedClass().getName().replace('.', '$') + "$pcsubclass",
+            sub.getName());
+        assertTrue(PersistenceCapable.class.isAssignableFrom(sub));
+        assertTrue(getUnenhancedClass().isAssignableFrom(sub));
+    }
+
+    public void testPCSubclassName() {
+        assertEquals("org.apache.openjpa.enhance."
+            + getUnenhancedClass().getName().replace('.', '$') + "$pcsubclass",
+            PCEnhancer.toPCSubclassName(getUnenhancedClass()));
+    }
+
+    public void testEvictionInUserCreatedInstance()
+        throws NoSuchFieldException, IllegalAccessException {
+        evictionHelper(true);
+    }
+
+    public void testEvictionInOpenJPACreatedInstance()
+        throws NoSuchFieldException, IllegalAccessException {
+        evictionHelper(false);
+    }
+
+    private void evictionHelper(boolean userDefined)
+        throws NoSuchFieldException, IllegalAccessException {
+        OpenJPAEntityManager em = emf.createEntityManager();
+        UnenhancedType un = newUnenhancedInstance();
+        em.getTransaction().begin();
+        em.persist(un);
+        em.getTransaction().commit();
+
+        if (!userDefined) {
+            em.close();
+            em = emf.createEntityManager();
+            un = em.find(getUnenhancedClass(), un.getId());
+            assertTrue(getUnenhancedClass() != un.getClass());
+        }
+
+        em.evict(un);
+        OpenJPAStateManager sm = (OpenJPAStateManager)
+            ImplHelper.toPersistenceCapable(un, null).pcGetStateManager();
+
+        // we only expect lazy loading to work when we can redefine classes
+        // or when accessing a property-access record that OpenJPA created.
+        if (ClassRedefiner.canRedefineClasses()
+            || (!userDefined && sm.getMetaData().getAccessType()
+                != ClassMetaData.ACCESS_FIELD)) {
+
+            assertFalse(sm.getLoaded()
+                .get(sm.getMetaData().getField("stringField").getIndex()));
+
+            // make sure that the value was cleared...
+            Field field = getUnenhancedClass().getDeclaredField(
+                isFieldAccessTest() ? "stringField" : "sf");
+            field.setAccessible(true);
+            assertEquals(null, field.get(un));
+
+            // ... and that it gets reloaded properly
+            assertEquals("foo", un.getStringField());
+            assertTrue(sm.getLoaded()
+                .get(sm.getMetaData().getField("stringField").getIndex()));
+        } else {
+            // unredefined properties with user-defined instance, or any
+            // unredefined field access
+            assertTrue(sm.getLoaded()
+                .get(sm.getMetaData().getField("stringField").getIndex()));
+
+            // make sure that the value was not cleared
+            Field field = getUnenhancedClass().getDeclaredField(
+                isFieldAccessTest() ? "stringField" : "sf");
+            field.setAccessible(true);
+            assertEquals("foo", field.get(un));
+        }
+
+        em.close();
+    }
+
+    protected abstract boolean isFieldAccessTest();
+
+    public void testLazyLoading()
+        throws NoSuchFieldException, IllegalAccessException {
+        OpenJPAEntityManager em = emf.createEntityManager();
+        UnenhancedType un = newUnenhancedInstance();
+        em.getTransaction().begin();
+        em.persist(un);
+        em.getTransaction().commit();
+        em.close();
+
+        em = emf.createEntityManager();
+        un = em.find(getUnenhancedClass(), un.getId());
+        assertTrue(getUnenhancedClass() != un.getClass());
+        OpenJPAStateManager sm = (OpenJPAStateManager)
+            ImplHelper.toPersistenceCapable(un, null).pcGetStateManager();
+
+        // we only expect lazy loading to work when we can redefine classes
+        // or when accessing a property-access record that OpenJPA created.
+        if (ClassRedefiner.canRedefineClasses()
+            || (sm.getMetaData().getAccessType() != ClassMetaData.ACCESS_FIELD))
+        {
+            assertFalse(sm.getLoaded()
+                .get(sm.getMetaData().getField("lazyField").getIndex()));
+
+            // make sure that the value was cleared
+            Field field = getUnenhancedClass().getDeclaredField("lazyField");
+            field.setAccessible(true);
+            assertEquals(null, field.get(un));
+        } else {
+            // unredefined field access
+            assertTrue(sm.getLoaded()
+                .get(sm.getMetaData().getField("lazyField").getIndex()));
+
+            // make sure that the value was loaded already
+            Field field = getUnenhancedClass().getDeclaredField("lazyField");
+            field.setAccessible(true);
+            assertEquals("lazy", field.get(un));
+        }
+
+        // make sure that the value is available, one way or another
+        assertEquals("lazy", un.getLazyField());
+        assertTrue(sm.getLoaded()
+            .get(sm.getMetaData().getField("lazyField").getIndex()));
+
+        em.close();
+    }
+
+    public void testSerializationOfUserDefinedInstance()
+        throws IOException, ClassNotFoundException {
+        serializationHelper(true, false);
+    }
+
+    public void testSerializationOfUserDefinedSubclassInstance()
+        throws IOException, ClassNotFoundException {
+        serializationHelper(true, true);
+    }
+
+    public void testSerializationOfOpenJPADefinedInstance()
+        throws IOException, ClassNotFoundException {
+        serializationHelper(false, false);
+    }
+
+    public void testSerializationOfOpenJPADefinedSubclassInstance()
+        throws IOException, ClassNotFoundException {
+        serializationHelper(false, true);
+    }
+
+    private void serializationHelper(boolean userDefined, boolean sub)
+        throws IOException, ClassNotFoundException {
+        OpenJPAEntityManager em = emf.createEntityManager();
+        UnenhancedType un = newInstance(sub);
+        em.getTransaction().begin();
+        em.persist(un);
+
+        if (sub) {
+            UnenhancedType related = newInstance(false);
+            related.setStringField("related");
+            ((UnenhancedSubtype) un).setRelated(related);
+        }
+
+        em.getTransaction().commit();
+
+        if (!userDefined) {
+            em.close();
+            em = emf.createEntityManager();
+        }
+
+        un = em.find(getUnenhancedClass(), un.getId());
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ObjectOutputStream oout = new ObjectOutputStream(out);
+        oout.writeObject(un);
+        oout.flush();
+        byte[] bytes = out.toByteArray();
+
+        ObjectInputStream oin = new ObjectInputStream(
+            new ByteArrayInputStream(bytes));
+        UnenhancedType deserialized = (UnenhancedType) oin.readObject();
+
+        copiedInstanceHelper(sub, em, un, deserialized, false);
+        em.close();
+    }
+
+    public void testCloningOfUserDefinedInstance()
+        throws IOException, ClassNotFoundException, CloneNotSupportedException {
+        cloneHelper(true, false);
+    }
+
+    public void testCloningOfUserDefinedSubclassInstance()
+        throws IOException, ClassNotFoundException, CloneNotSupportedException {
+        cloneHelper(true, true);
+    }
+
+    public void testCloningOfOpenJPADefinedInstance()
+        throws IOException, ClassNotFoundException, CloneNotSupportedException {
+        cloneHelper(false, false);
+    }
+
+    public void testCloningOfOpenJPADefinedSubclassInstance()
+        throws IOException, ClassNotFoundException, CloneNotSupportedException {
+        cloneHelper(false, true);
+    }
+
+    private void cloneHelper(boolean userDefined, boolean sub)
+        throws IOException, ClassNotFoundException, CloneNotSupportedException {
+        OpenJPAEntityManager em = emf.createEntityManager();
+        UnenhancedType un = newInstance(sub);
+        em.getTransaction().begin();
+        em.persist(un);
+
+        if (sub) {
+            UnenhancedType related = newInstance(false);
+            related.setStringField("related");
+            ((UnenhancedSubtype) un).setRelated(related);
+        }
+
+        em.getTransaction().commit();
+
+        if (!userDefined) {
+            em.close();
+            em = emf.createEntityManager();
+        }
+
+        un = em.find(getUnenhancedClass(), un.getId());
+        UnenhancedType cloned = (UnenhancedType) un.clone();
+
+        copiedInstanceHelper(sub, em, un, cloned, true);
+        em.close();
+    }
+
+    private void copiedInstanceHelper(boolean sub, OpenJPAEntityManager em,
+        UnenhancedType un, UnenhancedType copy, boolean viaClone) {
+        assertNotSame(un, copy);
+        if (!viaClone)
+            assertEquals(sub ? getUnenhancedSubclass() : getUnenhancedClass(),
+                copy.getClass());
+        assertEquals(un.getId(), copy.getId());
+        assertEquals(un.getStringField(), copy.getStringField());
+        if (sub) {
+            assertEquals(
+                ((UnenhancedSubtype) un).getIntField(),
+                ((UnenhancedSubtype) copy).getIntField());
+            assertNotSame(
+                ((UnenhancedSubtype) un).getRelated(),
+                ((UnenhancedSubtype) copy).getRelated());
+            assertEquals(
+                ((UnenhancedSubtype) un).getRelated().getId(),
+                ((UnenhancedSubtype) copy).getRelated().getId());
+        }
+
+        assertFalse(em.isDetached(un));
+        assertTrue(em.isDetached(copy));
+
+        /*
+        ##### need to make detachment algorithm in ReflectingPC smarter
+        // ensure that remove() cannot be invoked on a detached instance
+        try {
+            em.getTransaction().begin();
+            em.remove(copy);
+            fail("remove() cannot be invoked on detached instance");
+        } catch (IllegalArgumentException e) {
+            em.getTransaction().rollback();
+        }
+        */
+
+        copy.setStringField("offline update");
+
+        em.getTransaction().begin();
+        assertSame(un, em.merge(copy));
+        assertTrue(em.isDirty(un));
+        assertEquals("offline update", un.getStringField());
+        em.getTransaction().commit();
+    }
+
+    public void testListenersOnUserDefinedInstance()
+        throws IOException, ClassNotFoundException, CloneNotSupportedException {
+        listenerHelper(true, false);
+    }
+
+    public void testListenersOnUserDefinedSubclassInstance()
+        throws IOException, ClassNotFoundException, CloneNotSupportedException {
+        listenerHelper(true, true);
+    }
+
+    public void testListenersOnOpenJPADefinedInstance()
+        throws IOException, ClassNotFoundException, CloneNotSupportedException {
+        listenerHelper(false, false);
+    }
+
+    public void testListenersOnOpenJPADefinedSubclassInstance()
+        throws IOException, ClassNotFoundException, CloneNotSupportedException {
+        listenerHelper(false, true);
+    }
+
+    private void listenerHelper(boolean userDefined, boolean sub)
+        throws IOException, ClassNotFoundException, CloneNotSupportedException {
+        ListenerImpl listener = new ListenerImpl();
+        emf.addLifecycleListener(listener, (Class[]) null);
+        OpenJPAEntityManager em = emf.createEntityManager();
+        UnenhancedType un = newInstance(sub);
+        em.getTransaction().begin();
+        em.persist(un);
+        em.getTransaction().commit();
+
+        if (!userDefined) {
+            em.close();
+            em = emf.createEntityManager();
+        }
+
+        listener.invoked = false;
+
+        un = em.find(getUnenhancedClass(), un.getId());
+        em.getTransaction().begin();
+        un.setStringField("updated");
+        em.getTransaction().commit();
+        assertTrue(listener.invoked);
+        em.close();
+
+        assertEquals("updated", listener.stringField);
+    }
+
+    public void testGetMetaDataOfSubtype() {
+        ClassMetaData meta = JPAFacadeHelper.getMetaData(emf,
+            getUnenhancedClass());
+        List<Class> subs =  ManagedClassSubclasser.prepareUnenhancedClasses(
+            emf.getConfiguration(),
+            Collections.singleton(getUnenhancedClass()), null);
+        assertSame(meta, JPAFacadeHelper.getMetaData(emf, subs.get(0)));
+
+        meta = JPAFacadeHelper.getMetaData(emf, getUnenhancedSubclass());
+        subs =  ManagedClassSubclasser.prepareUnenhancedClasses(
+            emf.getConfiguration(),
+            Collections.singleton(getUnenhancedSubclass()), null);
+        assertSame(meta, JPAFacadeHelper.getMetaData(emf, subs.get(0)));
+    }
+
+    private class ListenerImpl
+        extends AbstractLifecycleListener {
+
+        String stringField;
+        boolean invoked;
+
+        @Override
+        public void afterStore(LifecycleEvent event) {
+            invoked = true;
+            stringField = ((UnenhancedType) event.getSource()).getStringField();
+        }
+    }
 }
\ No newline at end of file

Propchange: openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/AbstractUnenhancedClassTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Artist.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Artist.java?rev=889871&view=auto
==============================================================================
--- openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Artist.java (added)
+++ openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Artist.java Sat Dec 12 00:50:58 2009
@@ -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.openjpa.jdbc.persistence.classcriteria;
+
+import java.util.Collection;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "ARTIST")
+public class Artist {
+    @Id
+    @Column(name = "NAME")
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        if (name == null || name.trim().length() == 0)
+            throw new IllegalArgumentException("null or empty name not allowed");
+        this.name = name;
+    }
+
+    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "artist1")
+    public Collection<Book> books;
+
+    public Collection<Book> getBooks() {
+        return books;
+    }
+
+    public void setBooks(Collection<Book> books) {
+        this.books = books;
+    }
+
+    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "artist")
+    public Collection<Movie> movies;
+
+    public Collection<Movie> getMovies() {
+        return movies;
+    }
+
+    public void setMovies(Collection<Movie> movies) {
+        this.movies = movies;
+    }
+
+    public Artist() {
+    }
+
+    public Artist(String name) {
+        this.name = name;
+    }
+}

Propchange: openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Artist.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Book.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Book.java?rev=889871&view=auto
==============================================================================
--- openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Book.java (added)
+++ openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Book.java Sat Dec 12 00:50:58 2009
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.jdbc.persistence.classcriteria;
+
+import javax.persistence.*;
+
+@Entity
+@DiscriminatorValue(value = "BOOK")
+public class Book extends Item {
+    private static final long serialVersionUID = 7150584274453979159L;
+
+    @Column(name = "PAGE_COUNT")
+    private int pageCount;
+
+    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
+    @Column(name = "ARTIST")
+    private Artist artist1;
+
+    public Book() {
+        super();
+    }
+
+    public Book(String title) {
+        super(title);
+    }
+
+    public int getPageCount() {
+        return pageCount;
+    }
+
+    public void setPageCount(int d) {
+        if (d < 0) {
+            throw new IllegalArgumentException("Invalid page count " + d + " for " + this);
+        }
+
+        pageCount = d;
+    }
+
+    public Artist getArtist() {
+        return artist1;
+    }
+
+    public void setArtist(Artist artist1) {
+        this.artist1 = artist1;
+    }
+}

Propchange: openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Book.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Item.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Item.java?rev=889871&view=auto
==============================================================================
--- openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Item.java (added)
+++ openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Item.java Sat Dec 12 00:50:58 2009
@@ -0,0 +1,96 @@
+/*
+ * 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.openjpa.jdbc.persistence.classcriteria;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.DiscriminatorColumn;
+import javax.persistence.DiscriminatorType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+@Entity
+@Table(name = "ITEMTABLE")
+@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
+@DiscriminatorColumn(name = "ITEM_TYPE", discriminatorType = DiscriminatorType.STRING, length = 8)
+public class Item implements Serializable {
+    private static final long serialVersionUID = 3375001494950016360L;
+
+    @Id
+    @GeneratedValue
+    @Column(name = "UID1")
+    private int id;
+
+    @Column
+    private String title;
+
+    @Transient
+    private float rating;
+
+    protected Item() {
+        super();
+    }
+
+    public Item(String title) {
+        super();
+        this.title = title;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        if (title == null || title.trim().length() == 0) {
+            throw new IllegalArgumentException("null or empty title not allowed");
+        }
+        this.title = title;
+    }
+
+    public float getRating() {
+        return rating;
+    }
+
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        final Item item = (Item) o;
+
+        return id == item.id;
+    }
+
+    public int hashCode() {
+        return id;
+    }
+}

Propchange: openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Item.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Movie.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Movie.java?rev=889871&view=auto
==============================================================================
--- openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Movie.java (added)
+++ openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Movie.java Sat Dec 12 00:50:58 2009
@@ -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.openjpa.jdbc.persistence.classcriteria;
+
+import javax.persistence.*;
+
+@Entity
+@DiscriminatorValue(value = "MOVIE")
+public class Movie extends Item {
+    private static final long serialVersionUID = 5263476520279196994L;
+
+    @Column(name = "DURATION")
+    private Integer duration;
+
+    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
+    @Column(name = "ARTIST")
+    private Artist artist;
+
+    public Movie() {
+        super();
+    }
+
+    public Movie(String title) {
+        super(title);
+    }
+
+    public Integer getDuration() {
+        return duration;
+    }
+
+    public void setDuration(int d) {
+        if (d < 0) {
+            throw new IllegalArgumentException("Invalid duration " + d + " for " + this);
+        }
+
+        duration = d;
+    }
+
+    public Artist getArtist() {
+        return artist;
+    }
+
+    public void setArtist(Artist artist) {
+        this.artist = artist;
+    }
+
+}

Propchange: openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/Movie.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/TestQuerySubclass.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/TestQuerySubclass.java?rev=889871&view=auto
==============================================================================
--- openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/TestQuerySubclass.java (added)
+++ openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/TestQuerySubclass.java Sat Dec 12 00:50:58 2009
@@ -0,0 +1,65 @@
+/*
+ * 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.openjpa.jdbc.persistence.classcriteria;
+
+import java.util.Collection;
+import org.apache.openjpa.persistence.OpenJPAEntityManager;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+public class TestQuerySubclass extends SingleEMFTestCase {
+
+    private OpenJPAEntityManager em;
+
+    public void setUp() {
+        setUp("openjpa.Compatibility",
+            "superclassDiscriminatorStrategyByDefault=true", CLEAR_TABLES,
+            Artist.class, Book.class, Item.class, Movie.class);
+        em = emf.createEntityManager();
+        em.getTransaction().begin();
+        Book b = new Book("book");
+        Movie m = new Movie("movie");
+        Artist a = new Artist("Herman Hess");
+        b.setArtist(a);
+        m.setArtist(a);
+        em.persist(a);
+        em.persist(b);
+        em.persist(m);
+        em.getTransaction().commit();
+
+    }
+
+    public void testQuery() {
+        Collection<Book> books = null;
+        Collection<Movie> movies = null;
+        em = emf.createEntityManager();
+        Artist artist = em.find(Artist.class, "Herman Hess");
+        if (artist == null) {
+            System.out.println("No artist found with ID Herman Hess");
+        }
+        else {
+            books = artist.getBooks();
+            movies = artist.getMovies();
+        }
+        assertEquals(1, books.size());
+        assertEquals(1, movies.size());
+    }
+
+    public void tearDown() throws Exception {
+    }
+}

Propchange: openjpa/branches/1.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/persistence/classcriteria/TestQuerySubclass.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message