You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by jr...@apache.org on 2009/07/24 18:27:31 UTC

svn commit: r797551 - in /openjpa/trunk: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/ openjpa-persistence/src/main/java/org/apache/openjpa/persistence/

Author: jrbauer
Date: Fri Jul 24 16:27:30 2009
New Revision: 797551

URL: http://svn.apache.org/viewvc?rev=797551&view=rev
Log:
OPENJPA-1175 Initial implementation and tests for ProviderUtil and PerisistenceUnitUtil

Added:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/EagerEmbed.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/EagerEntity.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/LazyEmbed.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/LazyEntity.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/TestPersistenceUnitUtil.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/TestProviderUtil.java   (with props)
Modified:
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/EagerEmbed.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/EagerEmbed.java?rev=797551&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/EagerEmbed.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/EagerEmbed.java Fri Jul 24 16:27:30 2009
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.persistence.util;
+
+import java.sql.Date;
+
+import javax.persistence.Embeddable;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+@Embeddable
+public class EagerEmbed {
+
+    @Temporal(TemporalType.DATE)
+    private Date startDate;
+    
+    @Temporal(TemporalType.DATE)
+    private Date endDate;
+
+    public void setStartDate(Date startDate) {
+        this.startDate = startDate;
+    }
+
+    public Date getStartDate() {
+        return startDate;
+    }
+
+    public void setEndDate(Date endDate) {
+        this.endDate = endDate;
+    }
+
+    public Date getEndDate() {
+        return endDate;
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/EagerEmbed.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/EagerEntity.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/EagerEntity.java?rev=797551&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/EagerEntity.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/EagerEntity.java Fri Jul 24 16:27:30 2009
@@ -0,0 +1,73 @@
+/*
+ * 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.persistence.util;
+
+import javax.persistence.Basic;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Transient;
+
+@Entity
+public class EagerEntity {
+
+    @Id
+    private int id;
+    
+    @Basic
+    private String name;
+    
+    @Embedded    
+    private EagerEmbed eagerEmbed;
+    
+    @Transient
+    private String transField;
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setEagerEmbed(EagerEmbed eagerEmbed) {
+        this.eagerEmbed = eagerEmbed;
+    }
+
+    public EagerEmbed getEagerEmbed() {
+        return eagerEmbed;
+    }
+
+    public void setTransField(String transField) {
+        this.transField = transField;
+    }
+
+    public String getTransField() {
+        return transField;
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/EagerEntity.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/LazyEmbed.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/LazyEmbed.java?rev=797551&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/LazyEmbed.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/LazyEmbed.java Fri Jul 24 16:27:30 2009
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.persistence.util;
+
+import java.sql.Date;
+
+import javax.persistence.Basic;
+import javax.persistence.Embeddable;
+import javax.persistence.FetchType;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+@Embeddable
+public class LazyEmbed {
+
+    @Temporal(TemporalType.DATE)
+    @Basic(fetch=FetchType.LAZY)
+    private Date startDate;
+    
+    @Temporal(TemporalType.DATE)
+    @Basic(fetch=FetchType.LAZY)
+    private Date endDate;
+
+    public void setStartDate(Date startDate) {
+        this.startDate = startDate;
+    }
+
+    public Date getStartDate() {
+        return startDate;
+    }
+
+    public void setEndDate(Date endDate) {
+        this.endDate = endDate;
+    }
+
+    public Date getEndDate() {
+        return endDate;
+    }
+
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/LazyEmbed.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/LazyEntity.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/LazyEntity.java?rev=797551&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/LazyEntity.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/LazyEntity.java Fri Jul 24 16:27:30 2009
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.persistence.util;
+
+import javax.persistence.Basic;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.Transient;
+
+@Entity
+public class LazyEntity {
+
+    @Id
+    private int id;
+    
+    @Basic(fetch=FetchType.LAZY)
+    private String name;
+    
+    @Embedded    
+    private LazyEmbed lazyEmbed;
+    
+    @Transient
+    private String transField;
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setLazyEmbed(LazyEmbed lazyEmbed) {
+        this.lazyEmbed = lazyEmbed;
+    }
+
+    public LazyEmbed getLazyEmbed() {
+        return lazyEmbed;
+    }
+
+    public void setTransField(String transField) {
+        this.transField = transField;
+    }
+
+    public String getTransField() {
+        return transField;
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/LazyEntity.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/TestPersistenceUnitUtil.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/TestPersistenceUnitUtil.java?rev=797551&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/TestPersistenceUnitUtil.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/TestPersistenceUnitUtil.java Fri Jul 24 16:27:30 2009
@@ -0,0 +1,202 @@
+/*
+ * 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.persistence.util;
+
+import java.sql.Date;
+import java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceUnitUtil;
+import javax.persistence.spi.LoadState;
+import javax.persistence.spi.PersistenceProvider;
+import javax.persistence.spi.ProviderUtil;
+
+import org.apache.openjpa.persistence.PersistenceProviderImpl;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+public class TestPersistenceUnitUtil extends SingleEMFTestCase{
+    
+    public void setUp() {
+        setUp(CLEAR_TABLES, EagerEntity.class, LazyEmbed.class,
+            LazyEntity.class, EagerEmbed.class);
+    }
+
+    /*
+     * Verifies an entity and its persistent attributes are in the proper 
+     * load state.
+     */
+    public void testIsLoadedEager() {        
+        verifyIsLoadedEagerState(true);
+    }
+
+    /*
+     * Verifies an entity and its persistent attributes are in the proper 
+     * not loaded state.
+     */
+    public void testNotLoadedLazy() {
+        verifyIsLoadedEagerState(false);       
+    }
+
+    /*
+     * Verifies an entity and its persistent attributes are in the proper 
+     * loaded state.
+     */
+    public void testIsLoadedLazy() {        
+        verifyIsLoadedLazyState(true);
+    }
+
+    /*
+     * Verifies an entity and its persistent attributes are in the proper 
+     * NOT_LOADED state.
+     */
+    public void testNotLoadedEager() {
+        verifyIsLoadedEagerState(false);       
+    }
+
+    
+    private void verifyIsLoadedEagerState(boolean loaded) {
+        PersistenceUnitUtil puu = emf.getPersistenceUnitUtil();
+        assertSame(emf, puu);
+        EntityManager em = emf.createEntityManager();
+        EagerEntity ee = createEagerEntity();
+        
+        // Vfy LoadState is false for the unmanaged entity
+        assertEquals(false, puu.isLoaded(ee));
+        assertEquals(false, puu.isLoaded(ee, 
+            "id"));
+        
+        em.getTransaction().begin();
+        em.persist(ee);
+        em.getTransaction().commit();
+        em.clear();
+        
+        if (loaded)
+            ee = em.find(EagerEntity.class, ee.getId());
+        else
+            ee = em.getReference(EagerEntity.class, ee.getId());
+        
+        assertEquals(loaded, puu.isLoaded(ee));
+        assertEquals(loaded, puu.isLoaded(ee, "id"));
+        assertEquals(loaded, puu.isLoaded(ee, "name"));
+        assertEquals(loaded, puu.isLoaded(ee, "eagerEmbed"));
+        assertEquals(false, puu.isLoaded(ee, "transField"));
+        
+        em.close();
+    }
+
+    private void verifyIsLoadedLazyState(boolean loaded) {
+        PersistenceUnitUtil puu = emf.getPersistenceUnitUtil();
+        assertSame(emf, puu);
+        EntityManager em = emf.createEntityManager();
+        LazyEntity le = createLazyEntity();
+        
+        // Vfy LoadState is false for the unmanaged entity
+        assertEquals(false, puu.isLoaded(le));
+        assertEquals(false, puu.isLoaded(le,"id"));
+        
+        em.getTransaction().begin();
+        em.persist(le);
+        em.getTransaction().commit();
+        em.clear();
+        
+        // Use find or getReference based upon expected state
+        if (loaded)
+            le = em.find(LazyEntity.class, le.getId());
+        else
+            le = em.getReference(LazyEntity.class, le.getId());
+        
+        assertEquals(loaded, puu.isLoaded(le));
+        assertEquals(loaded, puu.isLoaded(le, "id"));
+
+        // Name is lazy fetch so it should not be loaded
+        assertEquals(false, puu.isLoaded(le, "name"));
+        assertEquals(loaded, puu.isLoaded(le, "lazyEmbed"));
+        assertEquals(false, puu.isLoaded(le, "transField"));
+        
+        em.close();
+    }
+
+    /*
+     * Verifies that an entity and attributes are considered loaded if they
+     * are assigned by the application.
+     */
+    public void testIsApplicationLoaded() {
+        PersistenceUnitUtil puu = emf.getPersistenceUnitUtil();
+        assertSame(emf, puu);
+        EntityManager em = emf.createEntityManager();
+        EagerEntity ee = createEagerEntity();
+        
+        em.getTransaction().begin();
+        em.persist(ee);
+        em.getTransaction().commit();
+        em.clear();
+        
+        ee = em.getReference(EagerEntity.class, ee.getId());
+        assertNotNull(ee);
+        assertEagerLoadState(puu, ee, false);
+        
+        ee.setName("AppEagerName");
+        EagerEmbed emb = createEagerEmbed();
+        ee.setEagerEmbed(emb);
+        // Assert fields are loaded via application loading
+        assertEagerLoadState(puu, ee, true);
+        // Vfy the set values are applied to the entity
+        assertEquals("AppEagerName", ee.getName());
+        assertEquals(emb, ee.getEagerEmbed());
+        
+        em.close();
+    }
+        
+    private EagerEntity createEagerEntity() {
+        EagerEntity ee = new EagerEntity();
+        ee.setId(new Random().nextInt());
+        ee.setName("EagerEntity");
+        EagerEmbed emb = createEagerEmbed();
+        ee.setEagerEmbed(emb);
+        return ee;
+    }
+
+    private EagerEmbed createEagerEmbed() {
+        EagerEmbed emb = new EagerEmbed();
+        emb.setEndDate(new Date(System.currentTimeMillis()));
+        emb.setStartDate(new Date(System.currentTimeMillis()));
+        return emb;
+    }
+
+    private LazyEntity createLazyEntity() {
+        LazyEntity le = new LazyEntity();
+        le.setId(new Random().nextInt());
+        le.setName("LazyEntity");
+        LazyEmbed emb = new LazyEmbed();
+        emb.setEndDate(new Date(System.currentTimeMillis()));
+        emb.setStartDate(new Date(System.currentTimeMillis()));
+        le.setLazyEmbed(emb);
+        return le;
+    }
+    
+    private void assertEagerLoadState(PersistenceUnitUtil pu, Object ent, 
+        boolean state) {
+        assertEquals(state, pu.isLoaded(ent));
+        assertEquals(state, pu.isLoaded(ent, "id"));
+        assertEquals(state, pu.isLoaded(ent, "name"));
+        assertEquals(state, pu.isLoaded(ent, "eagerEmbed"));
+        assertEquals(false, pu.isLoaded(ent, "transField"));
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/TestPersistenceUnitUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/TestProviderUtil.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/TestProviderUtil.java?rev=797551&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/TestProviderUtil.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/TestProviderUtil.java Fri Jul 24 16:27:30 2009
@@ -0,0 +1,259 @@
+/*
+ * 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.persistence.util;
+
+import java.sql.Date;
+import java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.persistence.spi.LoadState;
+import javax.persistence.spi.PersistenceProvider;
+import javax.persistence.spi.ProviderUtil;
+
+import org.apache.openjpa.persistence.PersistenceProviderImpl;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+public class TestProviderUtil extends SingleEMFTestCase{
+    
+    public void setUp() {
+        setUp(CLEAR_TABLES, EagerEntity.class, LazyEmbed.class,
+            LazyEntity.class, EagerEmbed.class);
+    }
+
+    /*
+     * Verifies an entity and its persistent attributes are in the proper 
+     * LOADED state.
+     */
+    public void testIsLoadedEager() {        
+        verifyIsLoadedEagerState(LoadState.LOADED);
+    }
+
+    /*
+     * Verifies an entity and its persistent attributes are in the proper 
+     * NOT_LOADED state.
+     */
+    public void testNotLoadedLazy() {
+        verifyIsLoadedEagerState(LoadState.NOT_LOADED);       
+    }
+
+    /*
+     * Verifies an entity and its persistent attributes are in the proper 
+     * LOADED state.
+     */
+    public void testIsLoadedLazy() {        
+        verifyIsLoadedLazyState(LoadState.LOADED);
+    }
+
+    /*
+     * Verifies an entity and its persistent attributes are in the proper 
+     * NOT_LOADED state.
+     */
+    public void testNotLoadedEager() {
+        verifyIsLoadedEagerState(LoadState.NOT_LOADED);       
+    }
+
+    
+    private void verifyIsLoadedEagerState(LoadState state) {
+        ProviderUtil pu = getProviderUtil();
+        EntityManager em = emf.createEntityManager();
+        EagerEntity ee = createEagerEntity();
+        
+        // Vfy LoadState is unknown for the unmanaged entity
+        assertEquals(LoadState.UNKNOWN, pu.isLoaded(ee));
+        assertEquals(LoadState.UNKNOWN, pu.isLoadedWithReference(ee, 
+            "id"));
+        assertEquals(LoadState.UNKNOWN, pu.isLoadedWithoutReference(ee,
+            "id"));
+        
+        em.getTransaction().begin();
+        em.persist(ee);
+        em.getTransaction().commit();
+        em.clear();
+        
+        if (state == LoadState.LOADED)
+            ee = em.find(EagerEntity.class, ee.getId());
+        else
+            ee = em.getReference(EagerEntity.class, ee.getId());
+        
+        assertEquals(state, pu.isLoaded(ee));
+        assertEquals(state, pu.isLoadedWithReference(ee, 
+            "id"));
+        assertEquals(state, pu.isLoadedWithoutReference(ee,
+            "id"));
+        assertEquals(state, pu.isLoadedWithReference(ee, 
+            "name"));
+        assertEquals(state, pu.isLoadedWithoutReference(ee,
+            "name"));
+        assertEquals(state, pu.isLoadedWithReference(ee, 
+            "eagerEmbed"));
+        assertEquals(state, pu.isLoadedWithoutReference(ee,
+            "eagerEmbed"));
+        assertEquals(LoadState.UNKNOWN, pu.isLoadedWithReference(ee, 
+            "transField"));
+        assertEquals(LoadState.UNKNOWN, pu.isLoadedWithoutReference(ee,
+            "transField"));
+        
+        em.close();
+    }
+
+    private void verifyIsLoadedLazyState(LoadState state) {
+        ProviderUtil pu = getProviderUtil();
+        EntityManager em = emf.createEntityManager();
+        LazyEntity le = createLazyEntity();
+        
+        // Vfy LoadState is unknown for the unmanaged entity
+        assertEquals(LoadState.UNKNOWN, pu.isLoaded(le));
+        assertEquals(LoadState.UNKNOWN, pu.isLoadedWithReference(le, 
+            "id"));
+        assertEquals(LoadState.UNKNOWN, pu.isLoadedWithoutReference(le,
+            "id"));
+        
+        em.getTransaction().begin();
+        em.persist(le);
+        em.getTransaction().commit();
+        em.clear();
+        
+        // Use find or getReference based upon expected state
+        if (state == LoadState.LOADED)
+            le = em.find(LazyEntity.class, le.getId());
+        else
+            le = em.getReference(LazyEntity.class, le.getId());
+        
+        assertEquals(state, pu.isLoaded(le));
+        assertEquals(state, pu.isLoadedWithReference(le, 
+            "id"));
+        assertEquals(state, pu.isLoadedWithoutReference(le,
+            "id"));
+        // Name is lazy fetch so it should not be loaded
+        assertEquals(LoadState.NOT_LOADED, pu.isLoadedWithReference(le, 
+            "name"));
+        assertEquals(LoadState.NOT_LOADED, pu.isLoadedWithoutReference(le,
+            "name"));
+        assertEquals(state, pu.isLoadedWithReference(le, 
+            "lazyEmbed"));
+        assertEquals(state, pu.isLoadedWithoutReference(le,
+            "lazyEmbed"));
+        assertEquals(LoadState.UNKNOWN, pu.isLoadedWithReference(le, 
+            "transField"));
+        assertEquals(LoadState.UNKNOWN, pu.isLoadedWithoutReference(le,
+            "transField"));
+        
+        em.close();
+    }
+
+    /*
+     * Verifies that an entity and attributes are considered loaded if they
+     * are assigned by the application.
+     */
+    public void testIsApplicationLoaded() {
+        ProviderUtil pu = getProviderUtil();
+        EntityManager em = emf.createEntityManager();
+        EagerEntity ee = createEagerEntity();
+        
+        em.getTransaction().begin();
+        em.persist(ee);
+        em.getTransaction().commit();
+        em.clear();
+        
+        ee = em.getReference(EagerEntity.class, ee.getId());
+        assertNotNull(ee);
+        assertEagerLoadState(pu, ee, LoadState.NOT_LOADED);
+        
+        ee.setName("AppEagerName");
+        EagerEmbed emb = createEagerEmbed();
+        ee.setEagerEmbed(emb);
+        // Assert fields are loaded via application loading
+        assertEagerLoadState(pu, ee, LoadState.LOADED);
+        // Vfy the set values are applied to the entity
+        assertEquals("AppEagerName", ee.getName());
+        assertEquals(emb, ee.getEagerEmbed());
+        
+        em.close();
+    }
+        
+    /*
+     * Verifies that an entity not managed by a PU 
+     */
+    public void testIsLoadedUnknown() {
+        ProviderUtil pu = getProviderUtil();
+        
+        EagerEntity ee = new EagerEntity();
+        
+        assertEquals(LoadState.UNKNOWN, pu.isLoaded(ee));
+        assertEquals(LoadState.UNKNOWN, pu.isLoadedWithReference(ee, 
+            "id"));
+        assertEquals(LoadState.UNKNOWN, pu.isLoadedWithoutReference(ee,
+            "id"));        
+    }
+
+    private EagerEntity createEagerEntity() {
+        EagerEntity ee = new EagerEntity();
+        ee.setId(new Random().nextInt());
+        ee.setName("EagerEntity");
+        EagerEmbed emb = createEagerEmbed();
+        ee.setEagerEmbed(emb);
+        return ee;
+    }
+
+    private EagerEmbed createEagerEmbed() {
+        EagerEmbed emb = new EagerEmbed();
+        emb.setEndDate(new Date(System.currentTimeMillis()));
+        emb.setStartDate(new Date(System.currentTimeMillis()));
+        return emb;
+    }
+
+    private LazyEntity createLazyEntity() {
+        LazyEntity le = new LazyEntity();
+        le.setId(new Random().nextInt());
+        le.setName("LazyEntity");
+        LazyEmbed emb = new LazyEmbed();
+        emb.setEndDate(new Date(System.currentTimeMillis()));
+        emb.setStartDate(new Date(System.currentTimeMillis()));
+        le.setLazyEmbed(emb);
+        return le;
+    }
+    
+    private void assertEagerLoadState(ProviderUtil pu, Object ent, 
+        LoadState state) {
+        assertEquals(state, pu.isLoaded(ent));
+        assertEquals(state, pu.isLoadedWithReference(ent, 
+            "id"));
+        assertEquals(state, pu.isLoadedWithoutReference(ent,
+            "id"));
+        assertEquals(state, pu.isLoadedWithReference(ent, 
+            "name"));
+        assertEquals(state, pu.isLoadedWithoutReference(ent,
+            "name"));
+        assertEquals(state, pu.isLoadedWithReference(ent, 
+            "eagerEmbed"));
+        assertEquals(state, pu.isLoadedWithoutReference(ent,
+            "eagerEmbed"));
+        assertEquals(LoadState.UNKNOWN, pu.isLoadedWithReference(ent, 
+            "transField"));
+        assertEquals(LoadState.UNKNOWN, pu.isLoadedWithoutReference(ent,
+            "transField"));        
+    }
+    
+    private ProviderUtil getProviderUtil() {
+        PersistenceProvider pp = new PersistenceProviderImpl(); 
+        ProviderUtil pu = pp.getProviderUtil();
+        return pu;
+    }
+
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/util/TestProviderUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java?rev=797551&r1=797550&r2=797551&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java Fri Jul 24 16:27:30 2009
@@ -21,6 +21,8 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.BitSet;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -32,22 +34,25 @@
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.PersistenceUnitUtil;
 import javax.persistence.criteria.QueryBuilder;
-import javax.persistence.metamodel.Metamodel;
 
 import org.apache.openjpa.conf.OpenJPAConfiguration;
+import org.apache.openjpa.enhance.PersistenceCapable;
 import org.apache.openjpa.enhance.Reflection;
+import org.apache.openjpa.enhance.StateManager;
+import org.apache.openjpa.kernel.AbstractBrokerFactory;
 import org.apache.openjpa.kernel.AutoDetach;
 import org.apache.openjpa.kernel.Broker;
 import org.apache.openjpa.kernel.BrokerFactory;
 import org.apache.openjpa.kernel.DelegatingBrokerFactory;
 import org.apache.openjpa.kernel.DelegatingFetchConfiguration;
 import org.apache.openjpa.kernel.FetchConfiguration;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.lib.conf.Configurations;
 import org.apache.openjpa.lib.conf.ProductDerivations;
 import org.apache.openjpa.lib.conf.Value;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.lib.util.Closeable;
-import org.apache.openjpa.meta.MetaDataRepository;
+import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.persistence.criteria.CriteriaBuilder;
 import org.apache.openjpa.persistence.meta.MetamodelImpl;
 import org.apache.openjpa.persistence.query.OpenJPAQueryBuilder;
@@ -64,7 +69,7 @@
  */
 public class EntityManagerFactoryImpl
     implements OpenJPAEntityManagerFactory, OpenJPAEntityManagerFactorySPI,
-    Closeable {
+    Closeable, PersistenceUnitUtil {
 
     private static final Localizer _loc = Localizer.forPackage
         (EntityManagerFactoryImpl.class);
@@ -379,7 +384,107 @@
     }
 
     public PersistenceUnitUtil getPersistenceUnitUtil() {
-        // TODO Auto-generated method stub
+        return this;
+    }
+
+    /**
+     * Get the identifier for the specified entity.  If not managed by any
+     * of the em's in this PU or not persistence capable, return null.
+     */
+    public Object getIdentifier(Object entity) {
+        if (entity instanceof PersistenceCapable) {
+            PersistenceCapable pc = (PersistenceCapable)entity;
+            // Per contract, if not managed by the owning emf, return null.
+            if (!isManagedBy(pc))
+                return null;
+            StateManager sm = pc.pcGetStateManager();
+            
+            if (sm != null && sm instanceof OpenJPAStateManager) {
+                OpenJPAStateManager osm = (OpenJPAStateManager)sm;
+                return osm.getObjectId();                
+            }
+        }
         return null;
     }
+
+    public boolean isLoaded(Object entity) {
+        return isLoaded(entity, null);
+    }
+
+    public boolean isLoaded(Object entity, String attribute) {
+        if (entity == null)
+            return false;
+               
+        if (entity instanceof PersistenceCapable) {
+            PersistenceCapable pc = (PersistenceCapable)entity;
+            if (!isManagedBy(pc))
+                return false;
+            StateManager sm = pc.pcGetStateManager();
+            if (sm != null && sm instanceof OpenJPAStateManager)
+                return isLoaded((OpenJPAStateManager)sm, attribute);
+        }        
+        return false;
+    }
+
+    /**
+     * Determines whether the specified state manager is managed by a broker
+     * within the persistence unit of this util instance.
+     * @param sm StateManager
+     * @return true if this state manager is managed by a broker within
+     * this persistence unit.
+     */
+    private boolean isManagedBy(PersistenceCapable entity) {
+        if (!isOpen())
+            return false;
+        Object abfobj = JPAFacadeHelper.toBrokerFactory(this);
+        if (abfobj == null)
+            return false;
+        if (abfobj instanceof AbstractBrokerFactory) {
+            AbstractBrokerFactory abf = (AbstractBrokerFactory)abfobj;
+            Collection<?> brokers = abf.getOpenBrokers();
+            if (brokers == null || brokers.size() == 0)
+                return false;
+            // Cycle through all brokers managed by this factory.  
+            Broker[] brokerArr = brokers.toArray(new Broker[brokers.size()]);
+            for (Broker broker : brokerArr) {
+                if (broker != null && !broker.isClosed() && 
+                    broker.isPersistent(entity))
+                    return true;
+            }
+        }
+        return false;
+    }
+    
+    /**
+     * Returns the load state for a given state manager and attribute.  If
+     * attr is null, only determines the load state based upon all persistent 
+     * attributes.  If an attribute is specified and not known to be 
+     * persistent by this provider, returns false.
+     */
+    private boolean isLoaded(OpenJPAStateManager sm, String attr) {
+        boolean isLoaded = true;
+        BitSet loadSet = sm.getLoaded();        
+        if (attr != null) {
+            FieldMetaData fmd = sm.getMetaData().getField(attr);
+            // Could not find field metadata for the specified attribute.
+            if (fmd == null)
+                return false;
+            // If the attribute is not loaded, return false.
+            if (!loadSet.get(fmd.getIndex()))
+                return false;
+        }
+        // Check load state of all persistent eager fetch attributes. Per
+        // contract, if any of them are not loaded, return false.
+        FieldMetaData[] fmds = sm.getMetaData().getFields();
+        for (FieldMetaData fmd : fmds) {
+            if (fmd.isInDefaultFetchGroup()) {
+                if (!loadSet.get(fmd.getIndex())) {
+                    isLoaded = false;
+                    break;
+                }
+                // TODO JRB: Complete contract for collections
+            }
+        } 
+        return isLoaded;        
+    }
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java?rev=797551&r1=797550&r2=797551&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java Fri Jul 24 16:27:30 2009
@@ -21,6 +21,7 @@
 import java.lang.instrument.ClassFileTransformer;
 import java.lang.instrument.IllegalClassFormatException;
 import java.security.ProtectionDomain;
+import java.util.BitSet;
 import java.util.Map;
 import javax.persistence.EntityManager;
 import javax.persistence.spi.ClassTransformer;
@@ -34,18 +35,22 @@
 import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
 import org.apache.openjpa.enhance.PCClassFileTransformer;
 import org.apache.openjpa.enhance.PCEnhancerAgent;
+import org.apache.openjpa.enhance.PersistenceCapable;
+import org.apache.openjpa.enhance.StateManager;
 import org.apache.openjpa.kernel.Bootstrap;
 import org.apache.openjpa.kernel.BrokerFactory;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.lib.conf.Configuration;
 import org.apache.openjpa.lib.conf.ConfigurationProvider;
 import org.apache.openjpa.lib.conf.Configurations;
 import org.apache.openjpa.lib.log.Log;
 import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashSet;
+import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.meta.MetaDataModes;
 import org.apache.openjpa.meta.MetaDataRepository;
 import org.apache.openjpa.persistence.validation.ValidationUtils;
 import org.apache.openjpa.util.ClassResolver;
-import org.apache.openjpa.validation.ValidationException;
 
 
 /**
@@ -56,7 +61,7 @@
  * @published
  */
 public class PersistenceProviderImpl
-    implements PersistenceProvider {
+    implements PersistenceProvider, ProviderUtil {
 
     static final String CLASS_TRANSFORMER_OPTIONS = "ClassTransformerOptions";
     private static final String EMF_POOL = "EntityManagerFactoryPool";
@@ -182,6 +187,14 @@
     }
 
     /*
+     * Returns a ProviderUtil for use with entities managed by this
+     * persistence provider.
+     */
+    public ProviderUtil getProviderUtil() {
+        return this;
+    }
+
+    /*
      * Returns a default Broker alias to be used when no openjpa.BrokerImpl
      *  is specified. This method allows PersistenceProvider subclass to
      *  override the default broker alias.
@@ -232,21 +245,6 @@
             return _trans.transform(cl, name, previousVersion, pd, bytes);
         }
 	}
-
-    public LoadState isLoaded(Object arg0) {
-        throw new UnsupportedOperationException(
-            "JPA 2.0 - Method not yet implemented");
-    }
-
-    public LoadState isLoadedWithReference(Object arg0, String arg1) {
-        throw new UnsupportedOperationException(
-        "JPA 2.0 - Method not yet implemented");
-    }
-
-    public LoadState isLoadedWithoutReference(Object arg0, String arg1) {
-        throw new UnsupportedOperationException(
-        "JPA 2.0 - Method not yet implemented");
-    }
     
     /**
      * This private worker method will attempt load the PCEnhancerAgent.
@@ -275,8 +273,99 @@
         }
     }
 
-    public ProviderUtil getProviderUtil() {
-        // TODO Auto-generated method stub
-        return null;
+    /**
+     * Determines whether the specified object is loaded.
+     * 
+     * @return LoadState.LOADED - if all implicit or explicit EAGER fetch
+     *         attributes are loaded
+     *         LoadState.NOT_LOADED - if any implicit or explicit EAGER fetch
+     *         attribute is not loaded
+     *         LoadState.UNKNOWN - if the entity is not managed by this
+     *         provider.
+     */
+    public LoadState isLoaded(Object obj) {
+        return isLoadedWithoutReference(obj, null);
+    }
+
+    /**
+     * Determines whether the attribute on the specified object is loaded.  This
+     * method may access the value of the attribute to determine load state (but
+     * currently does not).
+     * 
+     * @return LoadState.LOADED - if the attribute is loaded.
+     *         LoadState.NOT_LOADED - if the attribute is not loaded or any
+     *         EAGER fetch attributes of the entity are not loaded.
+     *         LoadState.UNKNOWN - if the entity is not managed by this
+     *         provider or if it does not contain the persistent
+     *         attribute.
+     */
+    public LoadState isLoadedWithReference(Object obj, String attr) {
+        // TODO: Are there be any cases where OpenJPA will need to examine
+        // the contents of a field to determine load state?  If so, per JPA 
+        // contract, this method permits that sort of access. In the extremely 
+        // unlikely case that the the entity is managed by multiple providers, 
+        // even if it doesn't trigger loading in OpenJPA, accessing field data 
+        // could trigger loading by an alternate provider.
+        return isLoadedWithoutReference(obj, attr);
+    }
+
+    /**
+     * Determines whether the attribute on the specified object is loaded.  This
+     * method does not access the value of the attribute to determine load 
+     * state.
+     * 
+     * @return LoadState.LOADED - if the attribute is loaded.
+     *         LoadState.NOT_LOADED - if the attribute is not loaded or any
+     *         EAGER fetch attributes of the entity are not loaded.
+     *         LoadState.UNKNOWN - if the entity is not managed by this
+     *         provider or if it does not contain the persistent
+     *         attribute.
+     */
+    public LoadState isLoadedWithoutReference(Object obj, String attr) {
+
+        if (obj == null)
+            return LoadState.UNKNOWN;
+        
+        // If the object has a state manager, call it directly.
+        if (obj instanceof PersistenceCapable) {
+            PersistenceCapable pc = (PersistenceCapable)obj;
+            StateManager sm = pc.pcGetStateManager();
+            if (sm != null && sm instanceof OpenJPAStateManager)
+                return isLoaded((OpenJPAStateManager)sm, attr);
+        }        
+        return LoadState.UNKNOWN;
+    }
+
+    /*
+     * Returns the load state for a given state manager and attribute.  If
+     * attr is null, determines the load state based upon all persistent 
+     * attributes of the state manager.  If an attribute is specified and not 
+     * known to be persistent by this provider, returns a load state of unknown,
+     * otherwise, returns the load state of the attribute.
+     */
+    private LoadState isLoaded(OpenJPAStateManager sm, String attr) {
+        boolean isLoaded = true;
+        BitSet loadSet = sm.getLoaded();
+        if (attr != null) {
+            FieldMetaData fmd = sm.getMetaData().getField(attr);
+            // Could not find field metadata for the specified attribute.
+            if (fmd == null)
+                return LoadState.UNKNOWN;
+            // Otherwise, return the load state
+            if(!loadSet.get(fmd.getIndex()))
+                return LoadState.NOT_LOADED;
+        }
+        FieldMetaData[] fmds = sm.getMetaData().getFields();
+        // Check load state of all persistent eager fetch attributes
+        for (FieldMetaData fmd : fmds) {
+            if (fmd.isInDefaultFetchGroup()) {
+                if (!loadSet.get(fmd.getIndex())) {
+                    isLoaded = false;
+                    break;
+                }
+                // TODO: Complete contract for collections
+            }
+        } 
+        return isLoaded ? LoadState.LOADED : LoadState.NOT_LOADED;        
     }
 }