| /* |
| * 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 |
| * |
| * https://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 javax.jdo; |
| |
| import java.lang.reflect.InvocationHandler; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Proxy; |
| import javax.jdo.spi.PersistenceCapable; |
| import javax.jdo.util.AbstractTest; |
| import javax.jdo.util.BatchTestRunner; |
| |
| /* |
| * ObjectStateTest.java |
| * This test class verifies the proper returned ObjectState for |
| * each life cycle state. See Table 3 in section 7.4. |
| * |
| * @since 2.1 |
| */ |
| public class ObjectStateTest extends AbstractTest { |
| |
| static final int PERSISTENT = 1; |
| static final int TRANSACTIONAL = 2; |
| static final int DIRTY = 4; |
| static final int NEW = 8; |
| static final int DELETED = 16; |
| static final int DETACHED = 32; |
| |
| private static final Method jdoIsPersistent = |
| getDeclaredMethod(PersistenceCapable.class, "jdoIsPersistent", null); |
| private static final Method jdoIsTransactional = |
| getDeclaredMethod(PersistenceCapable.class, "jdoIsTransactional", null); |
| private static final Method jdoIsDirty = |
| getDeclaredMethod(PersistenceCapable.class, "jdoIsDirty", null); |
| private static final Method jdoIsNew = |
| getDeclaredMethod(PersistenceCapable.class, "jdoIsNew", null); |
| private static final Method jdoIsDeleted = |
| getDeclaredMethod(PersistenceCapable.class, "jdoIsDeleted", null); |
| private static final Method jdoIsDetached = |
| getDeclaredMethod(PersistenceCapable.class, "jdoIsDetached", null); |
| |
| /** */ |
| public static void main(String args[]) { |
| BatchTestRunner.run(ObjectStateTest.class); |
| } |
| |
| public void testNull() { |
| PersistenceCapable mock = null; |
| assertObjectState("null", null, mock); |
| } |
| |
| public void testTransient() { |
| PersistenceCapable mock = newMock(0); |
| assertObjectState("transient", ObjectState.TRANSIENT, mock); |
| } |
| |
| public void testTransientClean() { |
| PersistenceCapable mock = newMock(TRANSACTIONAL); |
| assertObjectState("transient-clean", ObjectState.TRANSIENT_CLEAN, mock); |
| } |
| |
| public void testTransientDirty() { |
| PersistenceCapable mock = newMock(TRANSACTIONAL + DIRTY); |
| assertObjectState("transient-dirty", ObjectState.TRANSIENT_DIRTY, mock); |
| } |
| |
| public void testPersistentNew() { |
| PersistenceCapable mock = newMock(PERSISTENT + TRANSACTIONAL + NEW + DIRTY); |
| assertObjectState("persistent-new", ObjectState.PERSISTENT_NEW, mock); |
| } |
| |
| public void testPersistentNontransactional() { |
| PersistenceCapable mock = newMock(PERSISTENT); |
| assertObjectState( |
| "persistent-nontransactional", ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL, mock); |
| } |
| |
| public void testPersistentNontransactionalDirty() { |
| PersistenceCapable mock = newMock(PERSISTENT + DIRTY); |
| assertObjectState( |
| "persistent-nontransactional-dirty", ObjectState.PERSISTENT_NONTRANSACTIONAL_DIRTY, mock); |
| } |
| |
| public void testPersistentClean() { |
| PersistenceCapable mock = newMock(PERSISTENT + TRANSACTIONAL); |
| assertObjectState("persistent-clean", ObjectState.PERSISTENT_CLEAN, mock); |
| } |
| |
| public void testPersistentDirty() { |
| PersistenceCapable mock = newMock(PERSISTENT + TRANSACTIONAL + DIRTY); |
| assertObjectState("persistent-dirty", ObjectState.PERSISTENT_DIRTY, mock); |
| } |
| |
| public void testPersistentDeleted() { |
| PersistenceCapable mock = newMock(PERSISTENT + TRANSACTIONAL + DIRTY + DELETED); |
| assertObjectState("persistent-deleted", ObjectState.PERSISTENT_DELETED, mock); |
| } |
| |
| public void testPersistentNewDeleted() { |
| PersistenceCapable mock = newMock(PERSISTENT + TRANSACTIONAL + NEW + DIRTY + DELETED); |
| assertObjectState("persistent-new-deleted", ObjectState.PERSISTENT_NEW_DELETED, mock); |
| } |
| |
| public void testDetachedClean() { |
| PersistenceCapable mock = newMock(DETACHED); |
| assertObjectState("detached-clean", ObjectState.DETACHED_CLEAN, mock); |
| } |
| |
| public void testDetachedDirty() { |
| PersistenceCapable mock = newMock(DETACHED + DIRTY); |
| assertObjectState("detached-dirty", ObjectState.DETACHED_DIRTY, mock); |
| } |
| |
| private void assertObjectState(String string, ObjectState expected, PersistenceCapable pc) { |
| ObjectState actual = JDOHelper.getObjectState(pc); |
| // test for == here because enums should be singleton |
| if (actual == expected) return; |
| fail( |
| "ObjectState failure for " + string + NL + "expected: " + expected + ", actual: " + actual); |
| } |
| |
| /** |
| * Construct a new mock instance of PersistenceCapable that responds to methods jdoIsXXX by |
| * returning the bit value of its constructor masked with the value of XXX. |
| * |
| * @param i the sum of bit masks representing the life cycle state |
| * @return a mock instance of PersistenceCapable |
| */ |
| private PersistenceCapable newMock(final int i) { |
| return (PersistenceCapable) |
| Proxy.newProxyInstance( |
| PersistenceCapable.class.getClassLoader(), |
| new Class[] {PersistenceCapable.class}, |
| new MockInvocationHandler(i)); |
| } |
| |
| private class MockInvocationHandler implements InvocationHandler { |
| /** States is the sum of all life cycle interrogatives. */ |
| private final int states; |
| |
| /** |
| * Constructs an invocation handler with the specified bit fields set according to the sum of |
| * values of PERSISTENT, TRANSACTIONAL, DIRTY, NEW, DELETED, and DETACHED. |
| * |
| * @param i the bit field values for the life cycle interrogatives |
| */ |
| private MockInvocationHandler(int i) { |
| states = i; |
| } |
| |
| /** |
| * @param object the PersistenceCapable instance |
| * @param method the method being invoked |
| * @param parameters parameters (should be null) |
| * @throws java.lang.Throwable unused |
| * @return for jdoIsXXX methods only, returns whether the bit field selected by the method is |
| * set in the mock handler |
| */ |
| public Object invoke(Object object, Method method, Object[] parameters) throws Throwable { |
| if (method.equals(jdoIsPersistent)) { |
| return (0 != (states & PERSISTENT)); |
| } |
| if (method.equals(jdoIsTransactional)) { |
| return (0 != (states & TRANSACTIONAL)); |
| } |
| if (method.equals(jdoIsDirty)) { |
| return (0 != (states & DIRTY)); |
| } |
| if (method.equals(jdoIsNew)) { |
| return (0 != (states & NEW)); |
| } |
| if (method.equals(jdoIsDeleted)) { |
| return (0 != (states & DELETED)); |
| } |
| if (method.equals(jdoIsDetached)) { |
| return (0 != (states & DETACHED)); |
| } |
| fail("Unexpected method called: " + method.getName()); |
| return Boolean.FALSE; // not reached |
| } |
| } |
| |
| private static Method getDeclaredMethod( |
| Class<?> clazz, String methodName, Class<?>[] parameters) { |
| try { |
| @SuppressWarnings("unchecked") |
| Method result = clazz.getDeclaredMethod(methodName, parameters); |
| return result; |
| } catch (Exception ex) { |
| // human-readable class.methodName(parameter[,parameter]) |
| StringBuffer sb = new StringBuffer(methodName); |
| String delimiter = "("; |
| for (Class<?> parameter : parameters) { |
| sb.append(delimiter); |
| sb.append(parameter.getName()); |
| delimiter = ","; |
| } |
| sb.append(")"); |
| throw new RuntimeException( |
| "getDeclaredMethod for " + clazz.getName() + "." + sb + " threw..." + ex); |
| } |
| } |
| } |