1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package javax.jdo;
19
20 import java.lang.reflect.InvocationHandler;
21 import java.lang.reflect.Method;
22 import java.lang.reflect.Proxy;
23
24 import javax.jdo.spi.PersistenceCapable;
25
26 import javax.jdo.util.AbstractTest;
27 import javax.jdo.util.BatchTestRunner;
28
29
30
31
32
33
34
35
36 public class ObjectStateTest extends AbstractTest {
37
38 static final int PERSISTENT = 1;
39 static final int TRANSACTIONAL = 2;
40 static final int DIRTY = 4;
41 static final int NEW = 8;
42 static final int DELETED = 16;
43 static final int DETACHED = 32;
44
45 private static final Method jdoIsPersistent = getDeclaredMethod(
46 PersistenceCapable.class,
47 "jdoIsPersistent",
48 null);
49 private static final Method jdoIsTransactional = getDeclaredMethod(
50 PersistenceCapable.class,
51 "jdoIsTransactional",
52 null);
53 private static final Method jdoIsDirty = getDeclaredMethod(
54 PersistenceCapable.class,
55 "jdoIsDirty",
56 null);
57 private static final Method jdoIsNew = getDeclaredMethod(
58 PersistenceCapable.class,
59 "jdoIsNew",
60 null);
61 private static final Method jdoIsDeleted = getDeclaredMethod(
62 PersistenceCapable.class,
63 "jdoIsDeleted",
64 null);
65 private static final Method jdoIsDetached = getDeclaredMethod(
66 PersistenceCapable.class,
67 "jdoIsDetached",
68 null);
69
70 /** */
71 public static void main(String args[]) {
72 BatchTestRunner.run(ObjectStateTest.class);
73 }
74
75 public void testNull() {
76 PersistenceCapable mock = null;
77 assertObjectState("null", null, mock);
78 }
79
80 public void testTransient() {
81 PersistenceCapable mock = newMock(0);
82 assertObjectState("transient", ObjectState.TRANSIENT, mock);
83 }
84
85 public void testTransientClean() {
86 PersistenceCapable mock = newMock(TRANSACTIONAL);
87 assertObjectState("transient-clean", ObjectState.TRANSIENT_CLEAN, mock);
88 }
89
90 public void testTransientDirty() {
91 PersistenceCapable mock = newMock(TRANSACTIONAL+DIRTY);
92 assertObjectState("transient-dirty", ObjectState.TRANSIENT_DIRTY, mock);
93 }
94
95 public void testPersistentNew() {
96 PersistenceCapable mock = newMock(PERSISTENT+TRANSACTIONAL+NEW+DIRTY);
97 assertObjectState("persistent-new", ObjectState.PERSISTENT_NEW, mock);
98 }
99
100 public void testPersistentNontransactional() {
101 PersistenceCapable mock = newMock(PERSISTENT);
102 assertObjectState("persistent-nontransactional", ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL, mock);
103 }
104
105 public void testPersistentNontransactionalDirty() {
106 PersistenceCapable mock = newMock(PERSISTENT+DIRTY);
107 assertObjectState("persistent-nontransactional-dirty", ObjectState.PERSISTENT_NONTRANSACTIONAL_DIRTY, mock);
108 }
109
110 public void testPersistentClean() {
111 PersistenceCapable mock = newMock(PERSISTENT+TRANSACTIONAL);
112 assertObjectState("persistent-clean", ObjectState.PERSISTENT_CLEAN, mock);
113 }
114
115 public void testPersistentDirty() {
116 PersistenceCapable mock = newMock(PERSISTENT+TRANSACTIONAL+DIRTY);
117 assertObjectState("persistent-dirty", ObjectState.PERSISTENT_DIRTY, mock);
118 }
119
120 public void testPersistentDeleted() {
121 PersistenceCapable mock = newMock(PERSISTENT+TRANSACTIONAL+DIRTY+DELETED);
122 assertObjectState("persistent-deleted", ObjectState.PERSISTENT_DELETED, mock);
123 }
124
125 public void testPersistentNewDeleted() {
126 PersistenceCapable mock = newMock(PERSISTENT+TRANSACTIONAL+NEW+DIRTY+DELETED);
127 assertObjectState("persistent-new-deleted", ObjectState.PERSISTENT_NEW_DELETED, mock);
128 }
129
130 public void testDetachedClean() {
131 PersistenceCapable mock = newMock(DETACHED);
132 assertObjectState("detached-clean", ObjectState.DETACHED_CLEAN, mock);
133 }
134
135 public void testDetachedDirty() {
136 PersistenceCapable mock = newMock(DETACHED+DIRTY);
137 assertObjectState("detached-dirty", ObjectState.DETACHED_DIRTY, mock);
138 }
139
140 private void assertObjectState(String string,
141 ObjectState expected,
142 PersistenceCapable pc) {
143 ObjectState actual = JDOHelper.getObjectState(pc);
144
145 if (actual == expected)
146 return;
147 fail("ObjectState failure for " + string + NL +
148 "expected: " + expected +
149 ", actual: " + actual);
150 }
151
152 /**
153 * Construct a new mock instance of PersistenceCapable that responds
154 * to methods jdoIsXXX by returning the bit value of its constructor
155 * masked with the value of XXX.
156 * @param i the sum of bit masks representing the life cycle state
157 * @return a mock instance of PersistenceCapable
158 */
159 private PersistenceCapable newMock(final int i) {
160 return (PersistenceCapable)
161 Proxy.newProxyInstance(
162 PersistenceCapable.class.getClassLoader(),
163 new Class[] {PersistenceCapable.class},
164 new MockInvocationHandler(i));
165 }
166
167 private class MockInvocationHandler implements InvocationHandler {
168 /** States is the sum of all life cycle interrogatives.
169 */
170 private int states;
171
172 /**
173 * Constructs an invocation handler with the specified bit fields set
174 * according to the sum of values of PERSISTENT, TRANSACTIONAL, DIRTY,
175 * NEW, DELETED, and DETACHED.
176 * @param i the bit field values for the life cycle interrogatives
177 */
178 private MockInvocationHandler(int i) {
179 states = i;
180 }
181
182 /**
183 *
184 * @param object the PersistenceCapable instance
185 * @param method the method being invoked
186 * @param parameters parameters (should be null)
187 * @throws java.lang.Throwable unused
188 * @return for jdoIsXXX methods only, returns whether the
189 * bit field selected by the method is set in the
190 * mock handler
191 */
192 public Object invoke(Object object, Method method, Object[] parameters)
193 throws Throwable {
194 if (method.equals(jdoIsPersistent)) {
195 return (0 != (states & PERSISTENT));
196 }
197 if (method.equals(jdoIsTransactional)) {
198 return (0 != (states & TRANSACTIONAL));
199 }
200 if (method.equals(jdoIsDirty)) {
201 return (0 != (states & DIRTY));
202 }
203 if (method.equals(jdoIsNew)) {
204 return (0 != (states & NEW));
205 }
206 if (method.equals(jdoIsDeleted)) {
207 return (0 != (states & DELETED));
208 }
209 if (method.equals(jdoIsDetached)) {
210 return (0 != (states & DETACHED));
211 }
212 fail("Unexpected method called: " + method.getName());
213 return Boolean.FALSE;
214 }
215 }
216
217 private static Method getDeclaredMethod
218 (Class clazz, String methodName, Class[] parameters) {
219 try {
220 Method result = clazz.getDeclaredMethod(methodName, parameters);
221 return result;
222 } catch (Exception ex) {
223
224 StringBuffer sb = new StringBuffer(methodName);
225 String delimiter = "(";
226 for (Class parameter: parameters) {
227 sb.append(delimiter);
228 sb.append(parameter.getName());
229 delimiter = ",";
230 }
231 sb.append(")");
232 throw new RuntimeException
233 ("getDeclaredMethod for " + clazz.getName() + "." +
234 sb + " threw..." + ex);
235 }
236 }
237 }