blob: 058f181faa90eb5c78639b757f383f8c06b8daec [file] [log] [blame]
/*
* 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);
}
}
}