You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by al...@apache.org on 2009/04/05 23:29:44 UTC

svn commit: r762161 [5/7] - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/kernel/ openjpa-kernel/src/main/ja...

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshException.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshException.java?rev=762161&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshException.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshException.java Sun Apr  5 21:29:42 2009
@@ -0,0 +1,289 @@
+/*
+ * 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.lockmgr;
+
+import javax.persistence.LockModeType;
+import javax.persistence.TransactionRequiredException;
+
+/**
+ * Test JPA 2.0 em.refresh(LockMode) exception behaviors with "mixed"
+ * lock manager.
+ */
+public class TestMixedLockManagerRefreshException extends SequencedActionsTest {
+    public void setUp() {
+        setUp(LockEmployee.class
+            , "openjpa.LockManager", "mixed"
+        );
+        commonSetUp();
+    }
+
+    /**
+     * TransactionRequiredException if there is no transaction
+     */
+    public void testRefreshNoTxReqExceptions() {
+        Object[][] threadMainTxReqTest = {
+            {Act.CreateEm},
+            {Act.Find},
+            {Act.SaveVersion},
+            {Act.TestEmployee, 1, Default_FirstName},
+            
+            {Act.Refresh, 1, LockModeType.NONE },
+            {Act.TestException, 0, null },
+            
+            {Act.Refresh, 1, LockModeType.READ },
+            {Act.TestException, 0, null },
+            
+            {Act.Refresh, 1, LockModeType.WRITE },
+            {Act.TestException, 0, null },
+            
+            {Act.Refresh, 1, LockModeType.OPTIMISTIC },
+            {Act.TestException, 0, null },
+            
+            {Act.Refresh, 1, LockModeType.OPTIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, null },
+            
+            {Act.Refresh, 1, LockModeType.PESSIMISTIC_READ},
+            {Act.TestException, 0, null },
+            
+            {Act.Refresh, 1, LockModeType.PESSIMISTIC_WRITE},
+            {Act.TestException, 0, null },
+            
+            {Act.Refresh, 1, LockModeType.PESSIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, null },
+        };
+        launchActionSequence("testLockTxReqExceptions()",
+            null, threadMainTxReqTest);
+    }
+
+    /**
+     * TransactionRequiredException if there is no transaction
+     */
+    public void testRefreshTxReqExceptions() {
+        Object[][] threadMainTxReqTest = {
+            {Act.CreateEm},
+            {Act.Find},
+            {Act.SaveVersion},
+            {Act.TestEmployee, 1, Default_FirstName},
+            
+            {Act.RefreshWithLock, 1, LockModeType.NONE },
+            {Act.TestException, 0, TransactionRequiredException.class },
+            
+            {Act.RefreshWithLock, 1, LockModeType.READ },
+            {Act.TestException, 0, TransactionRequiredException.class },
+            
+            {Act.RefreshWithLock, 1, LockModeType.WRITE },
+            {Act.TestException, 0, TransactionRequiredException.class },
+            
+            {Act.RefreshWithLock, 1, LockModeType.OPTIMISTIC },
+            {Act.TestException, 0, TransactionRequiredException.class },
+            
+            {Act.RefreshWithLock, 1, LockModeType.OPTIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, TransactionRequiredException.class },
+            
+            {Act.RefreshWithLock, 1, LockModeType.PESSIMISTIC_READ},
+            {Act.TestException, 0, TransactionRequiredException.class },
+            
+            {Act.RefreshWithLock, 1, LockModeType.PESSIMISTIC_WRITE},
+            {Act.TestException, 0, TransactionRequiredException.class },
+            
+            {Act.RefreshWithLock, 1, LockModeType.PESSIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, TransactionRequiredException.class },
+        };
+        launchActionSequence("testLockTxReqExceptions()",
+            null, threadMainTxReqTest);
+    }
+
+    /*
+     * IllegalArgumentException if the instance is not an entity or is a
+     *      detached entity
+     */
+    public void testRefreshIllegalArgrumentExceptions() {
+        // Test invalid entity argument throws IllegalArgumentException.
+        Object[][] threadMainInvEntityIllegalArgTest = {
+            {Act.CreateEm},
+            {Act.Find},
+            {Act.SaveVersion},
+            {Act.TestEmployee, 1, Default_FirstName},
+            {Act.StartTx},
+      
+            {Act.RefreshObject, null, LockModeType.NONE },
+            {Act.TestException, 0, IllegalArgumentException.class },
+            {Act.RefreshObject, "null", LockModeType.NONE },
+            {Act.TestException, 0, IllegalArgumentException.class },
+            
+            {Act.RefreshObject, null, LockModeType.READ },
+            {Act.TestException, 0, IllegalArgumentException.class },
+            {Act.RefreshObject, "null", LockModeType.READ },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.RefreshObject, null, LockModeType.WRITE },
+            {Act.TestException, 0, IllegalArgumentException.class },
+            {Act.RefreshObject, "null", LockModeType.WRITE },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.RefreshObject, null, LockModeType.OPTIMISTIC },
+            {Act.TestException, 0, IllegalArgumentException.class },
+            {Act.RefreshObject, "null", LockModeType.OPTIMISTIC },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.RefreshObject, null, 
+                LockModeType.OPTIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, IllegalArgumentException.class },
+            {Act.RefreshObject, "null", 
+                LockModeType.OPTIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.RefreshObject, null, LockModeType.PESSIMISTIC_READ },
+            {Act.TestException, 0, IllegalArgumentException.class },
+            {Act.RefreshObject, "null", LockModeType.PESSIMISTIC_READ },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.RefreshObject, null, LockModeType.PESSIMISTIC_WRITE },
+            {Act.TestException, 0, IllegalArgumentException.class },
+            {Act.RefreshObject, "null", LockModeType.PESSIMISTIC_WRITE },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.RefreshObject, null, 
+                LockModeType.PESSIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, IllegalArgumentException.class },
+            {Act.RefreshObject, "null", 
+                LockModeType.PESSIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, IllegalArgumentException.class },
+        };
+        launchActionSequence("testLockIllegalArgrumentExceptions()",
+            "Test invalid entity.", threadMainInvEntityIllegalArgTest);
+        
+        // Test detached entity argument throws IllegalArgumentException.
+        Object[][] threadMainDetachEntityIllegalArgTest = {
+            {Act.CreateEm},
+            {Act.Find},
+            {Act.SaveVersion},
+            {Act.TestEmployee, 1, Default_FirstName},
+            {Act.StartTx},
+            {Act.Detach, 1, 2},
+            
+            {Act.Refresh, 2, LockModeType.PESSIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, IllegalArgumentException.class },
+            
+            {Act.Refresh, 2, LockModeType.NONE },
+            {Act.TestException, 0, IllegalArgumentException.class },
+          
+            {Act.Refresh, 2, LockModeType.READ },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.Refresh, 2, LockModeType.WRITE },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.Refresh, 2, LockModeType.OPTIMISTIC },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.Refresh, 2, LockModeType.OPTIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.Refresh, 2, LockModeType.PESSIMISTIC_READ },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.Refresh, 2, LockModeType.PESSIMISTIC_WRITE },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.Refresh, 2, LockModeType.PESSIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, IllegalArgumentException.class },
+        };
+        launchActionSequence("testLockIllegalArgrumentExceptions()",
+            "Test detached entity.", threadMainDetachEntityIllegalArgTest);
+
+        // Test detached argument from serialized entity throws 
+        //  IllegalArgumentException.
+        Object[][] threadMainDetachSerializeIllegalArgTest = {
+            {Act.CreateEm},
+            {Act.Find},
+            {Act.SaveVersion},
+            {Act.TestEmployee, 1, Default_FirstName},
+            {Act.StartTx},
+            {Act.DetachSerialize, 1, 2},
+            
+            {Act.Refresh, 2, LockModeType.NONE },
+            {Act.TestException, 0, IllegalArgumentException.class },
+        
+            {Act.Refresh, 2, LockModeType.READ },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.Refresh, 2, LockModeType.WRITE },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.Refresh, 2, LockModeType.OPTIMISTIC },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.Refresh, 2, LockModeType.OPTIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.Refresh, 2, LockModeType.PESSIMISTIC_READ },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.Refresh, 2, LockModeType.PESSIMISTIC_WRITE },
+            {Act.TestException, 0, IllegalArgumentException.class },
+
+            {Act.Refresh, 2, LockModeType.PESSIMISTIC_FORCE_INCREMENT },
+            {Act.TestException, 0, IllegalArgumentException.class },
+        };        
+        launchActionSequence("testLockIllegalArgrumentExceptions()",
+            "Test detached entity using serialization.",
+            threadMainDetachSerializeIllegalArgTest);
+        
+        Object[][] threadMainRemoveIllegalArgTest = {
+            {Act.CreateEm},
+            {Act.Find},
+            {Act.SaveVersion},
+            {Act.TestEmployee, 1, Default_FirstName},
+            {Act.StartTx},
+            {Act.Remove},
+
+            {Act.Refresh, 1, LockModeType.NONE },
+            {Act.TestException},
+      
+            {Act.Refresh, 1, LockModeType.READ },
+            {Act.TestException},
+
+            {Act.Refresh, 1, LockModeType.WRITE },
+            {Act.TestException},
+
+            {Act.Refresh, 1, LockModeType.OPTIMISTIC },
+            {Act.TestException},
+
+            {Act.Refresh, 1, LockModeType.OPTIMISTIC_FORCE_INCREMENT },
+            {Act.TestException},
+
+            {Act.Refresh, 1, LockModeType.PESSIMISTIC_READ },
+            {Act.TestException},
+
+            {Act.Refresh, 1, LockModeType.PESSIMISTIC_WRITE },
+            {Act.TestException},
+
+            {Act.Refresh, 1, LockModeType.PESSIMISTIC_FORCE_INCREMENT },
+            {Act.TestException},
+            
+            {Act.RollbackTx},
+        };
+        launchActionSequence(
+            "testLockIllegalArgrumentExceptions()",
+            "Test removed entity - no exception since it is still "
+                + "in the context.",
+            threadMainRemoveIllegalArgTest);
+    }
+}

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

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshPermutation.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshPermutation.java?rev=762161&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshPermutation.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerRefreshPermutation.java Sun Apr  5 21:29:42 2009
@@ -0,0 +1,420 @@
+/*
+ * 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.lockmgr;
+
+import java.util.Arrays;
+
+import javax.persistence.LockModeType;
+
+/**
+ * Test JPA 2.0 LockMode type permutation behaviors with "mixed" lock manager.
+ */
+public class TestMixedLockManagerRefreshPermutation 
+    extends SequencedActionsTest {
+    public void setUp() {
+        setUp(LockEmployee.class
+            , "openjpa.LockManager", "mixed"
+        );
+        commonSetUp();
+    }
+
+    /* ======== Thread 1 : Read Lock ============*/
+    public void testRefreshReadRead() {
+        commonRefreshTest(
+            "testRefresh(Read,Commit/Read,Commit)",
+            LockModeType.READ, Act.CommitTx, 2, null, 
+            LockModeType.READ, Act.CommitTx, 2, ExpectingOptimisticLockExClass);
+        commonRefreshTest(
+            "testRefresh(Read,Commit/Read,Rollback)",
+            LockModeType.READ, Act.CommitTx, 2, null,
+            LockModeType.READ, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshReadWrite() {
+        commonRefreshTest(
+            "testRefresh(Read,Commit/Write,Commit)",
+            LockModeType.READ, Act.CommitTx, 2, null,
+            LockModeType.WRITE, Act.CommitTx, 2,
+                ExpectingOptimisticLockExClass);
+        commonRefreshTest(
+            "testRefresh(Read,Commit/Write,Rollback)",
+            LockModeType.READ, Act.CommitTx, 2, null,
+            LockModeType.WRITE, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshReadPessimisticRead() {
+        commonRefreshTest(
+            "testRefresh(Read,Commit/PessimisticRead,Commit)",
+            LockModeType.READ, Act.CommitTx, 2, null, // thread 2 tmo  
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null);
+        commonRefreshTest(
+            "testRefresh(Read,Commit/PessimisticRead,Rollback)",
+            LockModeType.READ, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_READ, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshReadPessimisticWrite() {
+        commonRefreshTest(
+            "testRefresh(Read,Commit/PessimisticWrite,Commit)",
+            LockModeType.READ, Act.CommitTx, 2, null, 
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null);
+        commonRefreshTest(
+            "testRefresh(Read,Commit/PessimisticWrite,Rollback)",
+            LockModeType.READ, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_WRITE, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshReadPessimisticForceInc() {
+        commonRefreshTest(
+            "testRefresh(Read,Commit/PessimisticForceInc,Commit)",
+            LockModeType.READ, Act.CommitTx, 2, ExpectingOptimisticLockExClass, 
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null);
+        commonRefreshTest(
+            "testRefresh(Read,Commit/PessimisticForceInc,Rollback)",
+            LockModeType.READ, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 2, null);
+    }
+    
+    /* ======== Thread 1 : Write Lock ============*/
+    public void testRefreshWriteRead() {
+        commonRefreshTest(
+            "testRefresh(Write,Commit/Read,Commit)",
+            LockModeType.WRITE, Act.CommitTx, 2, null, 
+            LockModeType.READ, Act.CommitTx, 2, ExpectingOptimisticLockExClass);
+        commonRefreshTest(
+            "testRefresh(Write,Commit/Read,Rollback)",
+            LockModeType.WRITE, Act.CommitTx, 2, null,
+            LockModeType.READ, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshWriteWrite() {
+        commonRefreshTest(
+            "testRefresh(Write,Commit/Write,Commit)",
+            LockModeType.WRITE, Act.CommitTx, 2, null,
+            LockModeType.WRITE, Act.CommitTx, 2,
+                ExpectingOptimisticLockExClass);
+        commonRefreshTest(
+            "testRefresh(Write,Commit/Write,Rollback)",
+            LockModeType.WRITE, Act.CommitTx, 2, null,
+            LockModeType.WRITE, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshWritePessimisticRead() {
+        commonRefreshTest(
+            "testRefresh(Write,Commit/PessimisticRead,Commit)",
+            LockModeType.WRITE, Act.CommitTx, 2, null, 
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null);
+        commonRefreshTest(
+            "testRefresh(Write,Commit/PessimisticRead,Rollback)",
+            LockModeType.WRITE, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_READ, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshWritePessimisticWrite() {
+        commonRefreshTest(
+            "testRefresh(Write,Commit/PessimisticWrite,Commit)",
+            LockModeType.WRITE, Act.CommitTx, 2, null, 
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null);
+        commonRefreshTest(
+            "testRefresh(Write,Commit/PessimisticWrite,Rollback)",
+            LockModeType.WRITE, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_WRITE, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshWritePessimisticForceInc() {
+        commonRefreshTest(
+            "testRefresh(Write,Commit/PessimisticForceInc,Commit)",
+            LockModeType.WRITE, Act.CommitTx, 2, ExpectingOptimisticLockExClass, 
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null);
+        commonRefreshTest(
+            "testRefresh(Write,Commit/PessimisticForceInc,Rollback)",
+            LockModeType.WRITE, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 2, null);
+    }
+    
+    /* ======== Thread 1 : PessimisticRead Lock ============*/
+    public void testRefreshPessimisticReadRead() {
+        commonRefreshTest(
+            "testRefresh(PessimisticRead,Commit/Read,Commit)",
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null, 
+            LockModeType.READ, Act.CommitTx, 2, ExpectingOptimisticLockExClass);
+        commonRefreshTest(
+            "testRefresh(PessimisticRead,Commit/Read,Rollback)",
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null,
+            LockModeType.READ, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshPessimisticReadWrite() {
+        commonRefreshTest(
+            "testRefresh(PessimisticRead,Commit/Write,Commit)",
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null,
+            LockModeType.WRITE, Act.CommitTx, 2, 
+                ExpectingOptimisticLockExClass);
+        commonRefreshTest(
+            "testRefresh(PessimisticRead,Commit/Write,Rollback)",
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null,
+            LockModeType.WRITE, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshPessimisticReadPessimisticRead() {
+        commonRefreshTest(
+            "testRefresh(PessimisticRead,Commit/PessimisticRead,Commit)",
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null, 
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null);
+        commonRefreshTest(
+            "testRefresh(PessimisticRead,Commit/PessimisticRead,Rollback)",
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_READ, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshPessimisticReadPessimisticWrite() {
+        commonRefreshTest(
+            "testRefresh(PessimisticRead,Commit/PessimisticWrite,Commit)",
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null, 
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null); 
+        commonRefreshTest(
+            "testRefresh(PessimisticRead,Commit/PessimisticWrite,Rollback)",
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_WRITE, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshPessimisticReadPessimisticForceInc() {
+        commonRefreshTest(
+            "testRefresh(PessimisticRead,Commit/PessimisticForceInc,Commit)",
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 3, null, 
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 3, null);
+        commonRefreshTest(
+            "testRefresh(PessimisticRead,Commit/PessimisticForceInc,Rollback)",
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 2, null);
+    }
+    
+    /* ======== Thread 1 : Pessimsitic Write Lock ============*/
+    public void testRefreshPessimsiticWriteRead() {
+        commonRefreshTest(
+            "testRefresh(PessimsiticWrite,Commit/Read,Commit)",
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null, 
+            LockModeType.READ, Act.CommitTx, 2, ExpectingOptimisticLockExClass);
+        commonRefreshTest(
+            "testRefresh(PessimsiticWrite,Commit/Read,Rollback)",
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null,
+            LockModeType.READ, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshPessimsiticWriteWrite() {
+        commonRefreshTest(
+            "testRefresh(PessimsiticWrite,Commit/Write,Commit)",
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null,
+            LockModeType.WRITE, Act.CommitTx, 2, 
+                ExpectingOptimisticLockExClass);
+        commonRefreshTest(
+            "testRefresh(PessimsiticWrite,Commit/Write,Rollback)",
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null,
+            LockModeType.WRITE, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshPessimsiticWritePessimisticRead() {
+        commonRefreshTest(
+            "testRefresh(PessimsiticWrite,Commit/PessimisticRead,Commit)",
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null, 
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null); 
+        commonRefreshTest(
+            "testRefresh(PessimsiticWrite,Commit/PessimisticRead,Rollback)",
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_READ, Act.RollbackTx, 2, null); 
+    }
+    
+    public void testRefreshPessimsiticWritePessimisticWrite() {
+        commonRefreshTest(
+            "testRefresh(PessimsiticWrite,Commit/PessimisticWrite,Commit)",
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null, 
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null);
+        commonRefreshTest(
+            "testRefresh(PessimsiticWrite,Commit/PessimisticWrite,Rollback)",
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_WRITE, Act.RollbackTx, 2, null); 
+    }
+    
+    public void testRefreshPessimsiticWritePessimisticForceInc() {
+        commonRefreshTest(
+            "testRefresh(PessimsiticWrite,Commit/PessimisticForceInc,Commit)",
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 3, null, 
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 3, null); 
+        commonRefreshTest(
+            "testRefresh(PessimsiticWrite,Commit/PessimisticForceInc,Rollback)",
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 2, null);
+    }
+    
+    /* ======== Thread 1 : Pessimistic Force Increment Lock ============*/
+    public void testRefreshPessimsiticForceIncRead() {
+        commonRefreshTest(
+            "testRefresh(PessimsiticForceInc,Commit/Read,Commit)",
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null, 
+            LockModeType.READ, Act.CommitTx, 0, ExpectingOptimisticLockExClass);
+        commonRefreshTest(
+            "testRefresh(PessimsiticForceInc,Commit/Read,Rollback)",
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null,
+            LockModeType.READ, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshPessimsiticForceIncWrite() {
+        commonRefreshTest(
+            "testRefresh(PessimsiticForceInc,Commit/Write,Commit)",
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null,
+            LockModeType.WRITE, Act.CommitTx, 0,
+                ExpectingOptimisticLockExClass);
+        commonRefreshTest(
+            "testRefresh(PessimsiticForceInc,Commit/Write,Rollback)",
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null,
+            LockModeType.WRITE, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshPessimsiticForceIncPessimisticRead() {
+        commonRefreshTest(
+            "testRefresh(PessimsiticForceInc,Commit/PessimisticRead,Commit)",
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null, 
+            LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null); 
+        commonRefreshTest(
+            "testRefresh(PessimsiticForceInc,Commit/PessimisticRead,Rollback)",
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_READ, Act.RollbackTx, 2, null); 
+    }
+    
+    public void testRefreshPessimsiticForceIncPessimisticWrite() {
+        commonRefreshTest(
+            "testRefresh(PessimsiticForceInc,Commit/PessimisticWrite,Commit)",
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null, 
+            LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null); 
+        commonRefreshTest(
+            "testRefresh(PessimsiticForceInc,Commit/PessimisticWrite,Rollback)",
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_WRITE, Act.RollbackTx, 2, null);
+    }
+    
+    public void testRefreshPessimsiticForceIncPessimisticForceInc() {
+        commonRefreshTest(
+            "testRefresh(PessimsiticForceInc,Commit/" 
+                + "PessimisticForceInc,Commit)",
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 3, null, 
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 3, null);
+        commonRefreshTest(
+            "testRefresh(PessimsiticForceInc,Commit/"
+                + "PessimisticForceInc,Rollback)",
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null,
+            LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 2, null); 
+    }
+
+    private void commonRefreshTest( String testName, 
+        LockModeType t1Lock, Act t1IsCommit, int t1VersionInc, 
+            Class<?>[] t1Exceptions, 
+        LockModeType t2Lock, Act t2IsCommit, int t2VersionInc,
+            Class<?>[] t2Exceptions ) {
+        String[] parameters = new String[] {
+            "Thread 1: lock= " + t1Lock + ", isCommit= " + t1IsCommit +
+                ", versionInc= +" + t1VersionInc +
+                ", expectedEx= " + Arrays.toString(t1Exceptions),
+            "Thread 2: lock= " + t2Lock + ", isCommit= " + t2IsCommit + 
+                ", versionInc= +" + t2VersionInc +
+                ", expectedEx= " + Arrays.toString(t2Exceptions)};
+            
+        String t1Message1 = "Refresh in Thread 1";
+        String t1Message2 = "Refresh in Thread 1 Again";
+        String t2Message1 = "Refresh in Thread 2";
+        
+        Object[][] threadMain = {
+            {Act.CreateEm},
+            {Act.Find},
+            {Act.SaveVersion},
+            {Act.TestEmployee, 1, Default_FirstName},
+            
+            {Act.NewThread, 1 },
+            {Act.NewThread, 2 },
+            
+            {Act.StartThread, 1 },
+            {Act.Wait},
+            
+            {Act.StartThread, 2 },            
+            {Act.WaitAllChildren},
+            
+            {Act.Find},
+            {Act.TestEmployee, 1},
+            {Act.TestException, 1, t1Exceptions },
+            {Act.TestException, 2, t2Exceptions },
+        };
+        Object[][] thread1 = {
+            {Act.CreateEm},
+            {Act.Find, 1},
+            {Act.SaveVersion},
+            {Act.TestEmployee, 1, Default_FirstName},
+            {Act.Notify, 0},
+            {Act.Wait},
+            
+            {Act.StartTx},
+            {Act.UpdateEmployee, 1, t1Message1},
+            {Act.TestEmployee, 1, t1Message1},
+            {Act.CommitTx},
+            {Act.TestException},
+            {Act.Notify, 2},
+            {Act.Wait},
+            
+            {Act.StartTx},
+            {Act.RefreshWithLock, 1, t1Lock },
+            {Act.TestLockMode, 1, t1Lock},
+            {Act.TestEmployee, 1, t1Message1},
+            {Act.UpdateEmployee, 1, t1Message2},
+            {Act.TestEmployee, 1, t1Message2},
+            
+            {t1IsCommit},
+            {Act.Notify, 2},
+            {Act.Notify, 2},
+            
+            {Act.Clear},
+            {Act.Find},
+            {Act.TestEmployee, 1, null, t1VersionInc}
+        };
+        Object[][] thread2 = {
+            {Act.CreateEm},
+            {Act.Find, 1},
+            {Act.SaveVersion},
+            {Act.TestEmployee, 1, Default_FirstName},
+            {Act.Notify, 1},
+            {Act.Wait},
+
+            {Act.StartTx},
+            {Act.UpdateEmployee, 1, t2Message1},
+            {Act.TestEmployee, 1, t2Message1},
+            {Act.RefreshWithLock, 1, t2Lock },
+            {Act.TestLockMode, 1, t2Lock},
+            {Act.TestEmployee, 1, t1Message1},
+            
+            {Act.Notify, 1},
+            {Act.Wait},
+            {t2IsCommit},
+            {Act.Wait},
+            
+            {Act.Clear},
+            {Act.Find},
+            {Act.TestEmployee, 1, null, t2VersionInc},
+        };
+        
+        launchActionSequence(testName, parameters, threadMain, thread1,
+            thread2);
+    }
+}

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

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryTimeout.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryTimeout.java?rev=762161&r1=762160&r2=762161&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryTimeout.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryTimeout.java Sun Apr  5 21:29:42 2009
@@ -780,7 +780,7 @@
         } catch (Exception e) {
             // expected - setHint(-2000) should cause an IllegalArgumentException
             checkException("testQueryTimeout5()", e, 
-                IllegalArgumentException.class, "Invalid value" );
+                IllegalArgumentException.class, "invalid timeout of -2,000");
         } finally {
             if ((em != null) && em.isOpen()) {
                 em.close();

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java?rev=762161&r1=762160&r2=762161&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java Sun Apr  5 21:29:42 2009
@@ -56,7 +56,6 @@
 import org.apache.openjpa.kernel.DelegatingBroker;
 import org.apache.openjpa.kernel.FetchConfiguration;
 import org.apache.openjpa.kernel.FindCallbacks;
-import org.apache.openjpa.kernel.MixedLockLevels;
 import org.apache.openjpa.kernel.OpCallbacks;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.kernel.PreparedQuery;
@@ -65,16 +64,12 @@
 import org.apache.openjpa.kernel.QueryLanguages;
 import org.apache.openjpa.kernel.Seq;
 import org.apache.openjpa.kernel.jpql.JPQLParser;
-import org.apache.openjpa.lib.conf.Configuration;
-import org.apache.openjpa.lib.conf.IntValue;
 import org.apache.openjpa.lib.util.Closeable;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.meta.QueryMetaData;
 import org.apache.openjpa.meta.SequenceMetaData;
-import org.apache.openjpa.persistence.query.OpenJPAQueryBuilder;
-import org.apache.openjpa.persistence.query.QueryBuilderImpl;
 import org.apache.openjpa.util.Exceptions;
 import org.apache.openjpa.util.ImplHelper;
 import org.apache.openjpa.util.RuntimeExceptionTranslator;
@@ -469,19 +464,24 @@
         return find(cls, oid, mode, null);
     }
 
+    public <T> T find(Class<T> cls, Object oid, 
+        Map<String, Object> properties){
+        return find(cls, oid, null, properties);
+    }
+
     @SuppressWarnings("unchecked")
     public <T> T find(Class<T> cls, Object oid, LockModeType mode,
         Map<String, Object> properties) {
         assertNotCloseInvoked();
-        if (mode != LockModeType.NONE)
+        if (mode != null && mode != LockModeType.NONE)
             _broker.assertActiveTransaction();
 
-        boolean fcPushed = pushLockProperties(mode, properties);
+        processLockProperties(pushFetchPlan(), mode, properties);
         try {
             oid = _broker.newObjectId(cls, oid);
             return (T) _broker.find(oid, true, this);
         } finally {
-            popLockProperties(fcPushed);
+            popFetchPlan();
         }
     }
 
@@ -726,6 +726,10 @@
         refresh(entity, mode, null);
     }
 
+    public void refresh(Object entity, Map<String, Object> properties) {
+        refresh(entity, null, properties);
+    }
+
     public void refresh(Object entity, LockModeType mode,
         Map<String, Object> properties) {
         assertNotCloseInvoked();
@@ -733,11 +737,11 @@
         _broker.assertActiveTransaction();
         _broker.assertWriteOperation();
 
-        boolean fcPushed = pushLockProperties(mode, properties);
+        processLockProperties(pushFetchPlan(), mode, properties);
         try {
             _broker.refresh(entity, this);
         } finally {
-            popLockProperties(fcPushed);
+            popFetchPlan();
         }
     }
 
@@ -1096,9 +1100,7 @@
     }
 
     public void lock(Object entity, LockModeType mode) {
-        assertNotCloseInvoked();
-        assertValidAttchedEntity(entity);
-        _broker.lock(entity, MixedLockLevelsHelper.toLockLevel(mode), -1, this);
+        lock(entity, mode, -1);
     }
 
     public void lock(Object entity) {
@@ -1110,8 +1112,14 @@
     public void lock(Object entity, LockModeType mode, int timeout) {
         assertNotCloseInvoked();
         assertValidAttchedEntity(entity);
-        _broker.lock(entity, MixedLockLevelsHelper.toLockLevel(mode), timeout,
-             this);
+
+        processLockProperties(pushFetchPlan(), mode, null);
+        try {
+            _broker.lock(entity, MixedLockLevelsHelper.toLockLevel(mode),
+                timeout, this);
+        } finally {
+            popFetchPlan();
+        }
     }
 
     public void lock(Object entity, LockModeType mode,
@@ -1120,12 +1128,12 @@
         assertValidAttchedEntity(entity);
         _broker.assertActiveTransaction();
 
-        boolean fcPushed = pushLockProperties(mode, properties);
+        processLockProperties(pushFetchPlan(), mode, properties);
         try {
             _broker.lock(entity, MixedLockLevelsHelper.toLockLevel(mode),
                 _broker.getFetchConfiguration().getLockTimeout(), this);
         } finally {
-            popLockProperties(fcPushed);
+            popFetchPlan();
         }
     }
 
@@ -1542,8 +1550,7 @@
         throw new PersistenceException(_loc.get("unwrap-em-invalid", cls)
             .toString(), null, this, false);
     }
-    
-    
+
     public void setQuerySQLCache(boolean flag) {
         _broker.setCachePreparedQuery(flag);
     }
@@ -1556,154 +1563,26 @@
         return _ret;
     }
 
-    private enum FetchConfigProperty {
-        LockTimeout, ReadLockLevel, WriteLockLevel
-    };
-
-    private boolean setFetchConfigProperty(FetchConfigProperty[] validProps,
-        Map<String, Object> properties) {
-        boolean fcPushed = false;
-        if (properties != null && properties.size() > 0) {
-            Configuration conf = _broker.getConfiguration();
-            Set<String> inKeys = properties.keySet();
-            for (String inKey : inKeys) {
-                for (FetchConfigProperty validProp : validProps) {
-                    String validPropStr = validProp.toString();
-                    Set<String> validPropKeys = conf
-                        .getPropertyKeys(validPropStr);
-
-                    if (validPropKeys.contains(inKey)) {
-                        FetchConfiguration fCfg = _broker
-                            .getFetchConfiguration();
-                        IntValue intVal = new IntValue(inKey);
-                        try {
-                            Object setValue = properties.get(inKey);
-                            if (setValue instanceof String) {
-                                intVal.setString((String) setValue);
-                            } else if (Number.class.isAssignableFrom(setValue
-                                .getClass())) {
-                                intVal.setObject(setValue);
-                            } else {
-                                intVal.setString(setValue.toString());
-                            }
-                            int value = intVal.get();
-                            switch (validProp) {
-                            case LockTimeout:
-                                if (!fcPushed) {
-                                    fCfg = _broker.pushFetchConfiguration();
-                                    fcPushed = true;
-                                }
-                                fCfg.setLockTimeout(value);
-                                break;
-                            case ReadLockLevel:
-                                if (value != MixedLockLevels.LOCK_NONE
-                                    && value != fCfg.getReadLockLevel()) {
-                                    if (!fcPushed) {
-                                        fCfg = _broker.pushFetchConfiguration();
-                                        fcPushed = true;
-                                    }
-                                    fCfg.setReadLockLevel(value);
-                                }
-                                break;
-                            case WriteLockLevel:
-                                if (value != MixedLockLevels.LOCK_NONE
-                                    && value != fCfg.getWriteLockLevel()) {
-                                    if (!fcPushed) {
-                                        fCfg = _broker.pushFetchConfiguration();
-                                        fcPushed = true;
-                                    }
-                                    fCfg.setWriteLockLevel(value);
-                                }
-                                break;
-                            }
-                        } catch (Exception e) {
-                            // silently ignore the property
-                        }
-                        break; // for(String inKey : inKeys)
-                    }
-                }
-            }
-        }
-        return fcPushed;
-    }
-
-    private boolean pushLockProperties(LockModeType mode,
+    private void processLockProperties(FetchPlan fPlan, LockModeType mode,
         Map<String, Object> properties) {
-        boolean fcPushed = false;
         // handle properties in map first
-        if (properties != null) {
-            fcPushed = setFetchConfigProperty(new FetchConfigProperty[] {
-                FetchConfigProperty.LockTimeout,
-                FetchConfigProperty.ReadLockLevel,
-                FetchConfigProperty.WriteLockLevel }, properties);
-        }
+        fPlan.addHints(properties);
         // override with the specific lockMode, if needed.
-        int setReadLevel = MixedLockLevelsHelper.toLockLevel(mode);
-        if (setReadLevel != MixedLockLevels.LOCK_NONE) {
+        if (mode != null && mode != LockModeType.NONE) {
             // Set overriden read lock level
-            FetchConfiguration fCfg = _broker.getFetchConfiguration();
-            int curReadLevel = fCfg.getReadLockLevel();
-            if (setReadLevel != curReadLevel) {
-                if (!fcPushed) {
-                    fCfg = _broker.pushFetchConfiguration();
-                    fcPushed = true;
-                }
-                fCfg.setReadLockLevel(setReadLevel);
-            }
-            // Set overriden isolation level for pessimistic-read/write
-            switch (setReadLevel) {
-            case MixedLockLevels.LOCK_PESSIMISTIC_READ:
-                fcPushed = setIsolationForPessimisticLock(fCfg, fcPushed,
-                    Connection.TRANSACTION_REPEATABLE_READ);
-                break;
-
-            case MixedLockLevels.LOCK_PESSIMISTIC_WRITE:
-            case MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT:
-                fcPushed = setIsolationForPessimisticLock(fCfg, fcPushed,
-                    Connection.TRANSACTION_SERIALIZABLE);
-                break;
-
-            default:
-            }
-        }
-        return fcPushed;
-    }
-
-    private boolean setIsolationForPessimisticLock(FetchConfiguration fCfg,
-        boolean fcPushed, int level) {
-        if (!fcPushed) {
-            fCfg = _broker.pushFetchConfiguration();
-            fcPushed = true;
-        }
-        // TODO: refactoring under OPENJPA-957
-//        ((JDBCFetchConfiguration) fCfg).setIsolation(level);
-        return fcPushed;
-    }
-
-    private void popLockProperties(boolean fcPushed) {
-        if (fcPushed) {
-            _broker.popFetchConfiguration();
+            LockModeType curReadLockMode = fPlan.getReadLockMode();
+            if (mode != curReadLockMode)
+                fPlan.setReadLockMode(mode);
         }
     }
 
-
     public Metamodel getMetamodel() {
         throw new UnsupportedOperationException(
         "JPA 2.0 - Method not yet implemented");
     }
 
-    public void refresh(Object arg0, Map<String, Object> arg1) {
-        throw new UnsupportedOperationException(
-        "JPA 2.0 - Method not yet implemented");
-    }
-
     public void setProperty(String arg0, Object arg1) {
         throw new UnsupportedOperationException(
         "JPA 2.0 - Method not yet implemented");
     }
-
-    public <T> T find(Class<T> arg0, Object arg1, Map<String, Object> arg2) {
-        throw new UnsupportedOperationException(
-        "JPA 2.0 - Method not yet implemented");
-    }
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlan.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlan.java?rev=762161&r1=762160&r2=762161&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlan.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlan.java Sun Apr  5 21:29:42 2009
@@ -130,6 +130,29 @@
     public void setHint(String key, Object value);
     
     /**
+     * Sets the hint for the given key to the given value.
+     * 
+     * @since 2.0.0
+     */
+    public void setHint(String key, Object value, boolean validThrowException);
+
+    /**
+     * Adds the hint and the associated value to the list.
+     *
+     * @param name the name of the hint
+     * @param value the value of the hint
+     * @since 2.0.0
+     */
+    public void addHint(String name, Object value);
+
+    /**
+     * Sets the hint keys and values currently set of this receiver.
+     * 
+     * @since 2.0.0
+     */
+    public void addHints(Map<String, Object> hints);
+
+    /**
      * Gets the hint keys and values currently set of this receiver.
      * 
      * @since 2.0.0
@@ -291,10 +314,10 @@
     public int getLockTimeout();
 
     /**
-     * The number of milliseconds to wait for a query, or -1 for no
+     * The number of milliseconds to wait for an object lock, or -1 for no
      * limit.
      */
-    public FetchPlan setQueryTimeout(int timeout);
+    public FetchPlan setLockTimeout(int timeout);
 
     /**
      * The number of milliseconds to wait for a query, or -1 for no
@@ -303,11 +326,11 @@
     public int getQueryTimeout();
 
     /**
-     * The number of milliseconds to wait for an object lock, or -1 for no
+     * The number of milliseconds to wait for a query, or -1 for no
      * limit.
      */
+    public FetchPlan setQueryTimeout(int timeout);
 
-    public FetchPlan setLockTimeout(int timeout);
     /**
      * The lock level to use for locking loaded objects.
      */
@@ -327,7 +350,6 @@
      * The lock level to use for locking dirtied objects.
      */
     public FetchPlan setWriteLockMode(LockModeType mode);
-    
 
     /**
      * @deprecated cast to {@link FetchPlanImpl} instead. This

Added: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanHintHandler.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanHintHandler.java?rev=762161&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanHintHandler.java (added)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanHintHandler.java Sun Apr  5 21:29:42 2009
@@ -0,0 +1,214 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.LockModeType;
+
+import org.apache.openjpa.kernel.FetchConfigurationImpl;
+import org.apache.openjpa.kernel.AbstractHintHandler;
+import org.apache.openjpa.kernel.MixedLockLevels;
+import org.apache.openjpa.lib.conf.ProductDerivations;
+import org.apache.openjpa.lib.util.Localizer;
+
+/**
+ * Fetch plan hint handler. Handles openjpa.FetchPlan.*, 
+ * javax.persistence.lock.* and javax.persistence.query.* hints.
+ *
+ * @since 2.0.0
+ * @nojavadoc
+ */
+public class FetchPlanHintHandler extends AbstractHintHandler {
+
+    private static final Localizer _loc = Localizer
+        .forPackage(FetchPlanHintHandler.class);
+
+    protected static final String PREFIX_JPA = "javax.persistence.";
+    protected static final String PREFIX_FETCHPLAN = PREFIX_OPENJPA
+        + "FetchPlan.";
+
+    // Valid defined product derivation prefixes
+    protected static final Set<String> ValidProductPrefixes =
+        new HashSet<String>();
+    // JPA Specification 2.0 keys are mapped to equivalent FetchPlan keys
+    protected static final Map<String, String> JavaxHintsMap =
+        new HashMap<String, String>();
+    // hints precedent definitions
+    protected static final Map<String, String[]> PrecedenceMap =
+        new HashMap<String, String[]>();
+
+    static {
+        // Initialize valid product prefixes from available product derivations.
+        for (String prefix : ProductDerivations.getConfigurationPrefixes()) {
+            ValidProductPrefixes.add(prefix);
+        }
+        // Initiali javax.persistence to openjpa.FetchPlan hint mapping.
+        JavaxHintsMap.put(PREFIX_JPA + "lock.timeout", PREFIX_FETCHPLAN
+            + "LockTimeout");
+        JavaxHintsMap.put(PREFIX_JPA + "query.timeout", PREFIX_FETCHPLAN
+            + "QueryTimeout");
+        // Initialize hint precendent order mapping from list.
+        String[][] precedenceMapList = {
+            { PREFIX_JPA        + "lock.timeout",
+              PREFIX_FETCHPLAN  + "LockTimeout",
+              PREFIX_OPENJPA    + "LockTimeout" },
+
+            { PREFIX_JPA        + "query.timeout",
+              PREFIX_FETCHPLAN  + "QueryTimeout",
+              PREFIX_OPENJPA    + "QueryTimeout" },
+
+            { PREFIX_FETCHPLAN  + "Isolation",
+              PREFIX_JDBC       + "TransactionIsolation" },
+
+            { PREFIX_FETCHPLAN  + "EagerFetchMode",
+              PREFIX_JDBC       + "EagerFetchMode" },
+
+            { PREFIX_FETCHPLAN  + "FetchDirection",
+              PREFIX_JDBC       + "FetchDirection" },
+
+            { PREFIX_FETCHPLAN  + "JoinSyntax",
+              PREFIX_JDBC       + "JoinSyntax" },
+
+            { PREFIX_FETCHPLAN  + "LRSSizeAlgorithm",
+              PREFIX_FETCHPLAN  + "LRSSize",
+              PREFIX_JDBC       + "LRSSize" },
+
+            { PREFIX_FETCHPLAN  + "ResultSetType",
+              PREFIX_JDBC       + "ResultSetType" },
+
+            { PREFIX_FETCHPLAN  + "SubclassFetchMode",
+              PREFIX_JDBC       + "SubclassFetchMode" },
+
+            { PREFIX_FETCHPLAN  + "ReadLockMode",
+              PREFIX_OPENJPA    + "ReadLockLevel" },
+
+            { PREFIX_FETCHPLAN  + "WriteLockMode",
+              PREFIX_OPENJPA    + "WriteLockLevel" },
+
+            { PREFIX_FETCHPLAN  + "FetchBatchSize",
+              PREFIX_OPENJPA    + "FetchBatchSize" },
+
+            { PREFIX_FETCHPLAN  + "MaxFetchDepth",
+              PREFIX_OPENJPA    + "MaxFetchDepth" }
+        };
+        for (String[] list : precedenceMapList) {
+            for (String hint : list)
+                PrecedenceMap.put(hint, list);
+        }
+    }
+
+    protected FetchPlanImpl _fPlan;
+
+    /**
+     * Constructor; supply delegate.
+     */
+    public FetchPlanHintHandler(FetchPlanImpl fetchPlan) {
+        super((FetchConfigurationImpl) fetchPlan.getDelegate());
+        _fPlan = fetchPlan;
+    }
+
+    public boolean setHint(String hintName, Object value,
+        boolean validateThrowException) {
+        if (!hintName.startsWith(PREFIX_JPA)
+            && !ValidProductPrefixes.contains(getPrefixOf(hintName)))
+            return false;
+        return super.setHint(hintName, value, validateThrowException);
+    }
+
+    protected boolean setHintInternal(String hintName, Object value,
+        boolean validateThrowException) {
+        boolean valueSet = false;
+        if (hintName.startsWith(PREFIX_FETCHPLAN)) {
+            if (hintName.endsWith("LockMode")
+                && !_fConfig.getContext().isActive()) {
+                _fConfig.setHint(hintName + ".Defer", toLockLevel(value),
+                    false);
+                valueSet = true;
+            } else
+                valueSet = hintToSetter(_fPlan, hintName, value);
+        } else
+            _fConfig.setHint(hintName, value, validateThrowException);
+        return valueSet;
+    }
+
+    protected String hintToKey(String key) {
+        // transform product derived prefix to openjpa prefix
+        if (!key.startsWith(PREFIX_OPENJPA)
+            && ValidProductPrefixes.contains(getPrefixOf(key)))
+            key = PREFIX_OPENJPA + key.substring(key.indexOf('.') + 1);
+
+        // transform javax.persistence.* hints to fetch plan hints.
+        if (JavaxHintsMap.containsKey(key))
+            key = JavaxHintsMap.get(key);
+        return key;
+    }
+
+    protected boolean hasPrecedent(String key) {
+        boolean hasPrecedent = true;
+        String[] list = PrecedenceMap.get(key);
+        if (list != null) {
+            for (String hint : list) {
+                if (hint.equals(key))
+                    break;
+                // stop if a higher precedence hint has already defined 
+                if (_fConfig.getHint(hint) != null) {
+                    hasPrecedent = false;
+                    break;
+                }
+            }
+        }
+        return hasPrecedent;
+    }
+
+    protected void handleException(RuntimeException e) {
+        throw PersistenceExceptions.toPersistenceException(e);
+    }
+
+    private Integer toLockLevel(Object value) {
+        Object origValue = value;
+        if (value instanceof String) {
+            // to accomodate alias name input in relationship with enum values
+            //  e.g. "optimistic-force-increment" == 
+            //          LockModeType.OPTIMISTIC_FORCE_INCREMENT
+            String strValue = ((String) value).toUpperCase().replace('-', '_');
+            value = Enum.valueOf(LockModeType.class, strValue);
+        }
+        if (value instanceof LockModeType)
+            value = MixedLockLevelsHelper.toLockLevel((LockModeType) value);
+
+        Integer intValue = null;
+        if (value instanceof Integer)
+            intValue = (Integer) value;
+        if (intValue == null
+            || (intValue != MixedLockLevels.LOCK_NONE
+                && intValue != MixedLockLevels.LOCK_OPTIMISTIC
+                && intValue != MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT
+                && intValue != MixedLockLevels.LOCK_PESSIMISTIC_READ
+                && intValue != MixedLockLevels.LOCK_PESSIMISTIC_WRITE
+                && intValue != MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT)
+                )
+            throw new IllegalArgumentException(_loc.get("bad-lock-level",
+                origValue).getMessage());
+        return intValue;
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanHintHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanImpl.java?rev=762161&r1=762160&r2=762161&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/FetchPlanImpl.java Sun Apr  5 21:29:42 2009
@@ -28,7 +28,6 @@
 
 import org.apache.openjpa.kernel.DelegatingFetchConfiguration;
 import org.apache.openjpa.kernel.FetchConfiguration;
-import org.apache.openjpa.kernel.MixedLockLevels;
 
 /**
  * Implements FetchPlan via delegation to FetchConfiguration.
@@ -42,13 +41,14 @@
 	implements FetchPlan {
 
     private final DelegatingFetchConfiguration _fetch;
-
+    private FetchPlanHintHandler _hintHandler;
     
     /**
      * Constructor; supply delegate.
      */
     public FetchPlanImpl(FetchConfiguration fetch) {
         _fetch = newDelegatingFetchConfiguration(fetch);
+        _hintHandler = new FetchPlanHintHandler(this);
     }
 
     /**
@@ -275,8 +275,24 @@
         return _fetch.getHint(key);
     }
     
+    public void addHint(String key, Object value) {
+        _fetch.addHint(key, value);
+    }
+
     public void setHint(String key, Object value) {
-        _fetch.setHint(key, value);
+        setHint(key, value, true);
+    }
+
+    public void setHint(String key, Object value, boolean validThrowException) {
+        if( _hintHandler.setHint(key, value, validThrowException) )
+            _fetch.addHint(key, value);
+    }
+
+    public void addHints(Map<String, Object> hints) {
+        if (hints != null && hints.size() > 0) {
+            for (String name : hints.keySet())
+                setHint(name, hints.get(name), false);
+        }
     }
     
     public Map<String, Object> getHints() {

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java?rev=762161&r1=762160&r2=762161&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java Sun Apr  5 21:29:42 2009
@@ -1,11 +1,28 @@
+/*
+ * 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;
 
 import static org.apache.openjpa.kernel.QueryHints.HINT_IGNORE_PREPARED_QUERY;
-import static org.apache.openjpa.kernel.QueryHints.
-        HINT_INVALIDATE_PREPARED_QUERY;
+import static org.apache.openjpa.kernel.QueryHints
+                    .HINT_INVALIDATE_PREPARED_QUERY;
 import static org.apache.openjpa.kernel.QueryHints.HINT_RESULT_COUNT;
 
-import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Collections;
 import java.util.Comparator;
@@ -26,7 +43,6 @@
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.lib.util.StringDistance;
 
-
 /**
  * Manages query hint keys and handles their values on behalf of a owning
  * {@link QueryImpl}. Uses specific knowledge of hint keys declared in
@@ -81,15 +97,16 @@
  * 
  * @nojavadoc
  */
-public class HintHandler {
+public class HintHandler extends FetchPlanHintHandler {
+
+    private static final Localizer _loc = Localizer.forPackage(
+        HintHandler.class);
+
     private final QueryImpl owner;
     private Map<String, Object> _hints;
     private Set<String> _supportedKeys;
     private Set<String> _supportedPrefixes;
     
-    static final String PREFIX_JPA = "javax.persistence.";
-    static final String PREFIX_FETCHPLAN = "openjpa.FetchPlan.";
-    
     // These keys are directly handled in {@link QueryImpl} class.
     // Declaring a public static final String variable in this class will 
     // make it register as a supported hint key
@@ -103,21 +120,8 @@
     public static final String HINT_AGGREGATE_LISTENERS = 
         "openjpa.AggregateListeners";
     
-    // JPA Specification 2.0 keys are mapped to equivalent FetchPlan keys
-    public static Map<String,String> _jpaKeys = new TreeMap<String, String>();
-    static {
-        _jpaKeys.put(addPrefix(PREFIX_JPA, "query.timeout"), 
-            addPrefix(PREFIX_FETCHPLAN, "QueryTimeout"));
-        _jpaKeys.put(addPrefix(PREFIX_JPA, "lock.timeout"), 
-            addPrefix(PREFIX_FETCHPLAN, "LockTimeout"));
-    }
-    
-    private static final String DOT = ".";
-    private static final String BLANK = "";
-    private static final Localizer _loc = Localizer.forPackage(
-        HintHandler.class);
-    
     HintHandler(QueryImpl impl) {
+        super((FetchPlanImpl)impl.getFetchPlan());
         owner = impl;
     }
     
@@ -151,9 +155,8 @@
             .getLog(OpenJPAConfiguration.LOG_RUNTIME);
         String possible = StringDistance.getClosestLevenshteinDistance(hint, 
             getSupportedHints());
-        if (log.isWarnEnabled()) {
+        if (log.isWarnEnabled())
             log.warn(_loc.get("bad-query-hint", hint, possible));
-        }
         return (isKnownHintPrefix(hint)) ? null : Boolean.FALSE;
     }
     
@@ -176,7 +179,7 @@
                 Reflection.getBeanStylePropertyNames(
                     owner.getFetchPlan().getClass())));
 
-            _supportedKeys.addAll(_jpaKeys.keySet());
+            _supportedKeys.addAll(JavaxHintsMap.keySet());
 
             _supportedKeys.addAll(Reflection.getFieldValues(
                 HintHandler.class, 
@@ -212,157 +215,76 @@
         return getSupportedHints().contains(key);
     }
     
-    /**
-     * Affirms the given key has a prefix that matches with any of the 
-     * supported prefixes.
-     */
-    private boolean isSupportedPrefix(String key) {
-        return getKnownPrefixes().contains(getPrefixOf(key));
-    }
-    
-    static Set<String> addPrefix(String prefix, Set<String> original) {
-        Set<String> result = new TreeSet<String>();
-        String join = prefix.endsWith(DOT) ? BLANK : DOT;
-        for (String o : original)
-            result.add(prefix + join + o);
-        return result;
-    }
-    
-    static String addPrefix(String prefix, String original) {
-        String join = prefix.endsWith(DOT) ? BLANK : DOT;
-        return prefix + join + original;
-    }
-    
-    private static String removePrefix(String key, String prefix) {
-        if (prefix == null)
-            return key;
-        if (!prefix.endsWith(DOT))
-            prefix = prefix + DOT;
-        if (key != null && key.startsWith(prefix))
-            return key.substring(prefix.length());
-        return key;
-    }
-    
-    static String getPrefixOf(String key) {
-        int index = key == null ? -1 : key.indexOf(DOT);
-        return (index != -1) ? key.substring(0,index) : key;
-    }
-    
     private boolean isKnownHintPrefix(String key) {
         String prefix = getPrefixOf(key);
         return getKnownPrefixes().contains(prefix);
     }
-    
-    public static boolean hasPrefix(String key, String prefix) {
-        if (key == null || prefix == null)
-            return false;
-        if (!prefix.endsWith(DOT))
-            prefix = prefix + DOT;
-        return key.startsWith(prefix);
-    }
-    
+
     public void setHint(String key, Object value) {
         owner.lock();
         try {
-            setHintInternal(key, value);
+            Boolean record = record(key, value);
+            if (record == Boolean.FALSE)
+                return;
+            FetchPlan plan = owner.getFetchPlan();
+            if (record == null) {
+                plan.setHint(key, value);
+                return;
+            }
+            // request to throw IllegalArgumentException, if needed.
+            if (setHint(key, value, true))
+                plan.addHint(key, value);
         } finally {
             owner.unlock();
         }
     }
     
-    private void setHintInternal(String key, Object value) {
-        Boolean record = record(key, value);
-        FetchPlan plan = owner.getFetchPlan();
+    protected boolean setHintInternal(String key, Object value,
+        boolean validateThrowException) {
         ClassLoader loader = owner.getDelegate().getBroker().getClassLoader();
-        if (record == Boolean.FALSE)
-            return;
-        if (record == null) {
-            plan.setHint(key, value);
-            return;
-        }
-        try {
-            if (HINT_SUBCLASSES.equals(key)) {
-                if (value instanceof String)
-                    value = Boolean.valueOf((String) value);
-                owner.setSubclasses(((Boolean) value).booleanValue());
-            } else if (HINT_FILTER_LISTENER.equals(key))
-                owner.addFilterListener(Filters.hintToFilterListener(value, 
-                    loader));
-            else if (HINT_FILTER_LISTENERS.equals(key)) {
-                FilterListener[] arr = Filters.hintToFilterListeners(value, 
-                    loader);
-                for (int i = 0; i < arr.length; i++)
-                    owner.addFilterListener(arr[i]);
-            } else if (HINT_AGGREGATE_LISTENER.equals(key))
-                owner.addAggregateListener(Filters.hintToAggregateListener(
-                    value, loader));
-            else if (HINT_AGGREGATE_LISTENERS.equals(key)) {
-                AggregateListener[] arr = Filters.hintToAggregateListeners(
-                        value, loader);
-                for (int i = 0; i < arr.length; i++)
-                    owner.addAggregateListener(arr[i]);
-            } else if (isFetchPlanHint(key)) {
-                if (requiresTransaction(key))
-                    plan.setHint(key, value);
-                else 
-                    hintToSetter(plan, getFetchPlanProperty(key), value);
-            } else if (HINT_RESULT_COUNT.equals(key)) {
-                int v = (Integer)Filters.convert(value, Integer.class);
-                if (v < 0)
-                    throw new ArgumentException(_loc.get("bad-query-hint-value",
-                        key, value), null,  null, false);
-                    plan.setHint(key, v);
-            }  else if (HINT_INVALIDATE_PREPARED_QUERY.equals(key)) {
-                plan.setHint(key, Filters.convert(value, Boolean.class));
-                owner.invalidatePreparedQuery();
-            } else if (HINT_IGNORE_PREPARED_QUERY.equals(key)) {
-                plan.setHint(key, Filters.convert(value, Boolean.class));
-                owner.ignorePreparedQuery();
-            } else { // default 
-                plan.setHint(key, value);
-            }
-            return;
-        } catch (IllegalArgumentException iae) {
-            throw new ArgumentException(_loc.get("bad-query-hint-value", 
-                key, value), null,  null, false);
-        } catch (ClassCastException ce) {
-            throw new ArgumentException(_loc.get("bad-query-hint-value", 
-                key, ce.getMessage()), null,  null, false);
-        } catch (Exception e) {
-            throw PersistenceExceptions.toPersistenceException(e);
+        FetchPlan fPlan = owner.getFetchPlan();
+        boolean objectSet = true;
+        if (HINT_SUBCLASSES.equals(key)) {
+            if (value instanceof String)
+                value = Boolean.valueOf((String) value);
+            owner.setSubclasses(((Boolean) value).booleanValue());
+        } else if (HINT_FILTER_LISTENER.equals(key))
+            owner.addFilterListener(Filters.hintToFilterListener(value, 
+                loader));
+        else if (HINT_FILTER_LISTENERS.equals(key)) {
+            FilterListener[] arr = Filters.hintToFilterListeners(value, loader);
+            for (int i = 0; i < arr.length; i++)
+                owner.addFilterListener(arr[i]);
+        } else if (HINT_AGGREGATE_LISTENER.equals(key))
+            owner.addAggregateListener(Filters.hintToAggregateListener(value,
+                loader));
+        else if (HINT_AGGREGATE_LISTENERS.equals(key)) {
+            AggregateListener[] arr = Filters.hintToAggregateListeners(value,
+                loader);
+            for (int i = 0; i < arr.length; i++)
+                owner.addAggregateListener(arr[i]);
+        } else if (HINT_RESULT_COUNT.equals(key)) {
+            int v = (Integer) Filters.convert(value, Integer.class);
+            if (v < 0)
+                throw new ArgumentException(_loc.get("bad-query-hint-value",
+                    key, value), null, null, false);
+            fPlan.setHint(key, v);
+            objectSet = false;
+        } else if (HINT_INVALIDATE_PREPARED_QUERY.equals(key)) {
+            fPlan.setHint(key, Filters.convert(value, Boolean.class));
+            owner.invalidatePreparedQuery();
+            objectSet = false;
+        } else if (HINT_IGNORE_PREPARED_QUERY.equals(key)) {
+            fPlan.setHint(key, Filters.convert(value, Boolean.class));
+            owner.ignorePreparedQuery();
+            objectSet = false;
+        } else { // default 
+            fPlan.setHint(key, value);
+            objectSet = false;
         }
+        return objectSet;
     }
-    
-    private boolean isFetchPlanHint(String key) {
-        return key.startsWith(PREFIX_FETCHPLAN) 
-           || (_jpaKeys.containsKey(key) && isFetchPlanHint(_jpaKeys.get(key)));
-    }
-    
-    private boolean requiresTransaction(String key) {
-        return key.endsWith("LockMode");
-    }
-    
-    private String getFetchPlanProperty(String key) {
-        if (key.startsWith(PREFIX_FETCHPLAN))
-            return removePrefix(key, PREFIX_FETCHPLAN);
-        else if (_jpaKeys.containsKey(key))
-            return getFetchPlanProperty(_jpaKeys.get(key));
-        else
-            return key;
-    }
-    
-    private void hintToSetter(FetchPlan fetchPlan, String k, Object value) {
-        if (fetchPlan == null || k == null)
-            return;
-
-        Method setter = Reflection.findSetter(fetchPlan.getClass(), k, true);
-        Class paramType = setter.getParameterTypes()[0];
-        if (Enum.class.isAssignableFrom(paramType) && value instanceof String)
-            value = Enum.valueOf(paramType, (String) value);
 
-        Filters.hintToSetter(fetchPlan, k, value);
-    }
-    
     public static class HintKeyComparator implements Comparator<String> {
         public int compare(String s1, String s2) {
             if (getPrefixOf(s1).equals(getPrefixOf(s2))) {
@@ -372,12 +294,26 @@
             } else
                 return s1.compareTo(s2);
         }
-        
+
         public int countDots(String s) {
             if (s == null || s.length() == 0)
                 return 0;
             int index = s.indexOf(DOT);
-            return (index == -1) ? 0 : countDots(s.substring(index+1)) + 1;
+            return (index == -1) ? 0 : countDots(s.substring(index + 1)) + 1;
         }
     }
+
+    protected String hintToKey(String key) {
+        // Let superclass performs key transformation when fPlan.setHint() 
+        // is called.
+        return key;
+    }
+
+    private Set<String> addPrefix(String prefix, Set<String> original) {
+        Set<String> result = new TreeSet<String>();
+        String join = prefix.endsWith(DOT) ? BLANK : DOT;
+        for (String o : original)
+            result.add(prefix + join + o);
+        return result;
+    }
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MixedLockLevelsHelper.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MixedLockLevelsHelper.java?rev=762161&r1=762160&r2=762161&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MixedLockLevelsHelper.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MixedLockLevelsHelper.java Sun Apr  5 21:29:42 2009
@@ -37,10 +37,10 @@
         if (mode == null || mode == LockModeType.NONE)
             return MixedLockLevels.LOCK_NONE;
         if (mode == LockModeType.READ || mode == LockModeType.OPTIMISTIC)
-            return MixedLockLevels.LOCK_READ;
+            return MixedLockLevels.LOCK_OPTIMISTIC;
         if (mode == LockModeType.WRITE
             || mode == LockModeType.OPTIMISTIC_FORCE_INCREMENT)
-            return MixedLockLevels.LOCK_WRITE;
+            return MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT;
         if (mode == LockModeType.PESSIMISTIC_READ)
             return MixedLockLevels.LOCK_PESSIMISTIC_READ;
         if (mode == LockModeType.PESSIMISTIC_WRITE)
@@ -53,11 +53,11 @@
      */
     public static LockModeType fromLockLevel(int level) {
         if (level < MixedLockLevels.LOCK_OPTIMISTIC)
-            return null;
+            return LockModeType.NONE;
         if (level < MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT)
-            return LockModeType.READ;
+            return LockModeType.OPTIMISTIC;
         if (level < MixedLockLevels.LOCK_PESSIMISTIC_READ)
-            return LockModeType.WRITE;
+            return LockModeType.OPTIMISTIC_FORCE_INCREMENT;
         if (level < MixedLockLevels.LOCK_PESSIMISTIC_WRITE)
             return LockModeType.PESSIMISTIC_READ;
         if (level < MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT)