/*
* 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 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 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);
}
}
}