You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by cl...@apache.org on 2005/08/09 01:45:32 UTC
svn commit: r230925 - in /incubator/jdo/trunk/api20:
src/java/javax/jdo/JDOHelper.java src/java/javax/jdo/spi/JDOImplHelper.java
src/java/javax/jdo/spi/StateInterrogation.java
test/java/javax/jdo/spi/StateInterrogationTest.java
Author: clr
Date: Mon Aug 8 16:45:27 2005
New Revision: 230925
URL: http://svn.apache.org/viewcvs?rev=230925&view=rev
Log:
Implemented StateInterrogation for non-binary-compatible implementations
Added:
incubator/jdo/trunk/api20/test/java/javax/jdo/spi/StateInterrogationTest.java
Modified:
incubator/jdo/trunk/api20/src/java/javax/jdo/JDOHelper.java
incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOImplHelper.java
incubator/jdo/trunk/api20/src/java/javax/jdo/spi/StateInterrogation.java
Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/JDOHelper.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/JDOHelper.java?rev=230925&r1=230924&r2=230925&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/JDOHelper.java (original)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/JDOHelper.java Mon Aug 8 16:45:27 2005
@@ -37,7 +37,11 @@
import java.security.PrivilegedAction;
import javax.jdo.spi.I18NHelper;
+import javax.jdo.spi.JDOImplHelper;
+import javax.jdo.spi.JDOImplHelper.StateInterrogationBooleanReturn;
+import javax.jdo.spi.JDOImplHelper.StateInterrogationObjectReturn;
import javax.jdo.spi.PersistenceCapable;
+import javax.jdo.spi.StateInterrogation;
import javax.jdo.spi.StateManager; // for javadoc
import javax.naming.Context;
@@ -67,6 +71,118 @@
*/
private final static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N
+ /** The JDOImplHelper instance used for handling non-binary-compatible
+ * implementations.
+ */
+ private static JDOImplHelper implHelper = (JDOImplHelper)
+ AccessController.doPrivileged(
+ new PrivilegedAction () {
+ public Object run () {
+ return JDOImplHelper.getInstance();
+ }
+ }
+ );
+
+ /** The stateless instance used for handling non-binary-compatible
+ * implementations of getPersistenceManager.
+ */
+ static StateInterrogationObjectReturn getPersistenceManager =
+ new StateInterrogationObjectReturn() {
+ public Object get(Object pc, StateInterrogation si) {
+ return si.getPersistenceManager(pc);
+ }
+ };
+
+ /** The stateless instance used for handling non-binary-compatible
+ * implementations of getObjectId.
+ */
+ static StateInterrogationObjectReturn getObjectId =
+ new StateInterrogationObjectReturn() {
+ public Object get(Object pc, StateInterrogation si) {
+ return si.getObjectId(pc);
+ }
+ };
+
+ /** The stateless instance used for handling non-binary-compatible
+ * implementations of getTransactionalObjectId.
+ */
+ static StateInterrogationObjectReturn getTransactionalObjectId =
+ new StateInterrogationObjectReturn() {
+ public Object get(Object pc, StateInterrogation si) {
+ return si.getTransactionalObjectId(pc);
+ }
+ };
+
+ /** The stateless instance used for handling non-binary-compatible
+ * implementations of getVersion.
+ */
+ static StateInterrogationObjectReturn getVersion =
+ new StateInterrogationObjectReturn() {
+ public Object get(Object pc, StateInterrogation si) {
+ return si.getVersion(pc);
+ }
+ };
+
+ /** The stateless instance used for handling non-binary-compatible
+ * implementations of isPersistent.
+ */
+ static StateInterrogationBooleanReturn isPersistent =
+ new StateInterrogationBooleanReturn() {
+ public Boolean is(Object pc, StateInterrogation si) {
+ return si.isPersistent(pc);
+ }
+ };
+
+ /** The stateless instance used for handling non-binary-compatible
+ * implementations of isTransactional.
+ */
+ static StateInterrogationBooleanReturn isTransactional =
+ new StateInterrogationBooleanReturn() {
+ public Boolean is(Object pc, StateInterrogation si) {
+ return si.isTransactional(pc);
+ }
+ };
+
+ /** The stateless instance used for handling non-binary-compatible
+ * implementations of isDirty.
+ */
+ static StateInterrogationBooleanReturn isDirty =
+ new StateInterrogationBooleanReturn() {
+ public Boolean is(Object pc, StateInterrogation si) {
+ return si.isDirty(pc);
+ }
+ };
+
+ /** The stateless instance used for handling non-binary-compatible
+ * implementations of isNew.
+ */
+ static StateInterrogationBooleanReturn isNew =
+ new StateInterrogationBooleanReturn() {
+ public Boolean is(Object pc, StateInterrogation si) {
+ return si.isNew(pc);
+ }
+ };
+
+ /** The stateless instance used for handling non-binary-compatible
+ * implementations of isDeleted.
+ */
+ static StateInterrogationBooleanReturn isDeleted =
+ new StateInterrogationBooleanReturn() {
+ public Boolean is(Object pc, StateInterrogation si) {
+ return si.isDeleted(pc);
+ }
+ };
+
+ /** The stateless instance used for handling non-binary-compatible
+ * implementations of isDetached.
+ */
+ static StateInterrogationBooleanReturn isDetached =
+ new StateInterrogationBooleanReturn() {
+ public Boolean is(Object pc, StateInterrogation si) {
+ return si.isDetached(pc);
+ }
+ };
+
/** Return the associated <code>PersistenceManager</code> if there is one.
* Transactional and persistent instances return the associated
* <code>PersistenceManager</code>.
@@ -78,7 +194,12 @@
* @return the <code>PersistenceManager</code> associated with the parameter instance.
*/
public static PersistenceManager getPersistenceManager(Object pc) {
- return pc instanceof PersistenceCapable?((PersistenceCapable)pc).jdoGetPersistenceManager():null;
+ if (pc instanceof PersistenceCapable) {
+ return ((PersistenceCapable)pc).jdoGetPersistenceManager();
+ } else {
+ return (PersistenceManager)
+ implHelper.nonBinaryCompatibleGet(pc, getPersistenceManager);
+ }
}
/** Explicitly mark the parameter instance and field dirty.
@@ -95,8 +216,11 @@
* @param fieldName the name of the field to be marked dirty.
*/
public static void makeDirty(Object pc, String fieldName) {
- if (pc instanceof PersistenceCapable)
- ((PersistenceCapable)pc).jdoMakeDirty(fieldName);
+ if (pc instanceof PersistenceCapable) {
+ ((PersistenceCapable)pc).jdoMakeDirty(fieldName);
+ } else {
+ implHelper.nonBinaryCompatibleMakeDirty(pc, fieldName);
+ }
}
/** Return a copy of the JDO identity associated with the parameter instance.
@@ -127,7 +251,11 @@
* @return a copy of the ObjectId of the parameter instance as of the beginning of the transaction.
*/
public static Object getObjectId(Object pc) {
- return pc instanceof PersistenceCapable?((PersistenceCapable)pc).jdoGetObjectId():null;
+ if (pc instanceof PersistenceCapable) {
+ return ((PersistenceCapable)pc).jdoGetObjectId();
+ } else {
+ return implHelper.nonBinaryCompatibleGet(pc, getObjectId);
+ }
}
/** Return a copy of the JDO identity associated with the parameter instance.
@@ -138,7 +266,11 @@
* @return a copy of the ObjectId of the parameter instance as modified in this transaction.
*/
public static Object getTransactionalObjectId(Object pc) {
- return pc instanceof PersistenceCapable?((PersistenceCapable)pc).jdoGetTransactionalObjectId():null;
+ if (pc instanceof PersistenceCapable) {
+ return ((PersistenceCapable)pc).jdoGetTransactionalObjectId();
+ } else {
+ return implHelper.nonBinaryCompatibleGet(pc, getTransactionalObjectId);
+ }
}
/**
@@ -148,7 +280,11 @@
* @return the version of the instance
*/
public static Object getVersion (Object pc) {
- return pc instanceof PersistenceCapable?((PersistenceCapable)pc).jdoGetVersion():null;
+ if (pc instanceof PersistenceCapable) {
+ return ((PersistenceCapable)pc).jdoGetVersion();
+ } else {
+ return implHelper.nonBinaryCompatibleGet(pc, getVersion);
+ }
}
/** Tests whether the parameter instance is dirty.
*
@@ -164,7 +300,11 @@
* @return <code>true</code> if the parameter instance has been modified in the current transaction.
*/
public static boolean isDirty(Object pc) {
- return pc instanceof PersistenceCapable?((PersistenceCapable)pc).jdoIsDirty():false;
+ if (pc instanceof PersistenceCapable) {
+ return ((PersistenceCapable)pc).jdoIsDirty();
+ } else {
+ return implHelper.nonBinaryCompatibleIs(pc, isDirty);
+ }
}
/** Tests whether the parameter instance is transactional.
@@ -179,7 +319,11 @@
* @return <code>true</code> if the parameter instance is transactional.
*/
public static boolean isTransactional(Object pc) {
- return pc instanceof PersistenceCapable?((PersistenceCapable)pc).jdoIsTransactional():false;
+ if (pc instanceof PersistenceCapable) {
+ return ((PersistenceCapable)pc).jdoIsTransactional();
+ } else {
+ return implHelper.nonBinaryCompatibleIs(pc, isTransactional);
+ }
}
/** Tests whether the parameter instance is persistent.
@@ -196,7 +340,11 @@
* @return <code>true</code> if the parameter instance is persistent.
*/
public static boolean isPersistent(Object pc) {
- return pc instanceof PersistenceCapable?((PersistenceCapable)pc).jdoIsPersistent():false;
+ if (pc instanceof PersistenceCapable) {
+ return ((PersistenceCapable)pc).jdoIsPersistent();
+ } else {
+ return implHelper.nonBinaryCompatibleIs(pc, isPersistent);
+ }
}
/** Tests whether the parameter instance has been newly made persistent.
@@ -214,7 +362,11 @@
* in the current transaction.
*/
public static boolean isNew(Object pc) {
- return pc instanceof PersistenceCapable?((PersistenceCapable)pc).jdoIsNew():false;
+ if (pc instanceof PersistenceCapable) {
+ return ((PersistenceCapable)pc).jdoIsNew();
+ } else {
+ return implHelper.nonBinaryCompatibleIs(pc, isNew);
+ }
}
/** Tests whether the parameter instance has been deleted.
@@ -231,7 +383,11 @@
* in the current transaction.
*/
public static boolean isDeleted(Object pc) {
- return pc instanceof PersistenceCapable?((PersistenceCapable)pc).jdoIsDeleted():false;
+ if (pc instanceof PersistenceCapable) {
+ return ((PersistenceCapable)pc).jdoIsDeleted();
+ } else {
+ return implHelper.nonBinaryCompatibleIs(pc, isDeleted);
+ }
}
/**
@@ -247,7 +403,11 @@
* @param pc the instance
*/
public static boolean isDetached(Object pc) {
- return pc instanceof PersistenceCapable?((PersistenceCapable)pc).jdoIsDetached():false;
+ if (pc instanceof PersistenceCapable) {
+ return ((PersistenceCapable)pc).jdoIsDetached();
+ } else {
+ return implHelper.nonBinaryCompatibleIs(pc, isDetached);
+ }
}
/** Get a <code>PersistenceManagerFactory</code> based on a <code>Properties</code> instance, using
Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOImplHelper.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOImplHelper.java?rev=230925&r1=230924&r2=230925&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOImplHelper.java (original)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOImplHelper.java Mon Aug 8 16:45:27 2005
@@ -80,6 +80,10 @@
/** This list contains the registered listeners for <code>RegisterClassEvent</code>s.
*/
private static List listeners = new ArrayList();
+
+ /** The list of registered StateInterrogation instances
+ */
+ private static List stateInterrogations = new ArrayList();
/** The singleton <code>JDOImplHelper</code> instance.
*/
@@ -781,5 +785,93 @@
public String toString() {
return "Meta-" + pc.getClass().getName(); //NOI18N
}
+ }
+
+ /** Add a StateInterrogation to the list. Create a new list
+ * in case there is an iterator open on the original list.
+ */
+ public synchronized void addStateInterrogation(StateInterrogation si) {
+ List newList = new ArrayList(stateInterrogations);
+ newList.add(si);
+ stateInterrogations = newList;
+ }
+
+ /** Remove a StateInterrogation from the list. Create a new list
+ * in case there is an iterator open on the original list.
+ */
+ public synchronized void removeStateInterrogation(StateInterrogation si) {
+ List newList = new ArrayList(stateInterrogations);
+ newList.remove(si);
+ stateInterrogations = newList;
+ }
+
+ /** Return an Iterator over all StateInterrogation instances.
+ * Synchronize to avoid add/remove/iterate conflicts.
+ */
+ private synchronized Iterator getStateInterrogationIterator() {
+ return stateInterrogations.iterator();
+ }
+
+ /** Mark a non-binary-compatible instance dirty. Delegate to all
+ * registered StateInterrogation instances until one of them
+ * handles the call.
+ */
+ public void nonBinaryCompatibleMakeDirty(Object pc, String fieldName) {
+ Iterator sit = getStateInterrogationIterator();
+ while (sit.hasNext()) {
+ StateInterrogation si = (StateInterrogation)sit.next();
+ if (si.makeDirty(pc, fieldName)) return;
+ }
+ }
+
+ /** Determine the state of a non-binary-compatible instance.
+ * Delegate to all registered StateInterrogation instances until
+ * one of them handles the call (returns a non-null Boolean
+ * with the answer).
+ * The caller provides the stateless "method object" that does
+ * the actual call to the StateInterrogation instance.
+ */
+ public boolean nonBinaryCompatibleIs(Object pc,
+ StateInterrogationBooleanReturn sibr) {
+ Iterator sit = getStateInterrogationIterator();
+ while (sit.hasNext()) {
+ StateInterrogation si = (StateInterrogation)sit.next();
+ Boolean result = sibr.is(pc, si);
+ if (result != null) return result.booleanValue();
+ }
+ return false;
+ }
+
+ /** Return an object associated with a non-binary-compatible instance.
+ * Delegate to all registered StateInterrogation instances until
+ * one of them handles the call (returns a non-null answer).
+ * The caller provides the stateless "method object" that does
+ * the actual call to the StateInterrogation instance.
+ */
+ public Object nonBinaryCompatibleGet(Object pc,
+ StateInterrogationObjectReturn sibr) {
+ Iterator sit = getStateInterrogationIterator();
+ while (sit.hasNext()) {
+ StateInterrogation si = (StateInterrogation)sit.next();
+ Object result = sibr.get(pc, si);
+ if (result != null) return result;
+ }
+ return null;
+ }
+
+ /** This is an interface used to interrogate the state of an instance
+ * that does not implement PersistenceCapable. It is used for the
+ * methods that return a boolean value.
+ */
+ public static interface StateInterrogationBooleanReturn {
+ public Boolean is(Object pc, StateInterrogation si);
+ }
+
+ /** This is an interface used to interrogate the state of an instance
+ * that does not implement PersistenceCapable. It is used for the
+ * methods that return an Object value.
+ */
+ public static interface StateInterrogationObjectReturn {
+ public Object get(Object pc, StateInterrogation si);
}
}
Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/spi/StateInterrogation.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/spi/StateInterrogation.java?rev=230925&r1=230924&r2=230925&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/spi/StateInterrogation.java (original)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/spi/StateInterrogation.java Mon Aug 8 16:45:27 2005
@@ -27,7 +27,25 @@
* This interface is implemented by a non-binary-compatible JDO implementation
* to provide state interrogation for non-enhanced persistent classes.
*
- * An instance that implements this interface is registered with the
+ * <P>A call to JDOHelper to get the status of an instance is handled
+ * internally if the parameter instance implements PersistenceCapable.
+ * For non-binary-compatible implementations, there is no requirement
+ * that persistent instances implement PersistenceCapable. Therefore,
+ * if the parameter does not implement PersistenceCapable, JDOHelper
+ * delegates to all registered instances of StateInterrogation until
+ * an instance can handle the request.
+ * <P>For JDOHelper isXXX methods, which return boolean, the
+ * corresponding method in StateInterrogation returns Boolean. If the
+ * return value is <code>null</code> then the StateInterrogation does
+ * not recognize the parameter as being handled by it. A non-null return
+ * value indicates that the implementation has determined the answer.
+ * <P>For JDOHelper getXXX methods, which return an Object, each
+ * registered StateInterrogation is given the parameter until one of
+ * them returns a non-null value, which is passed to the caller.
+ * <P>For JDOHelper makeDirty, each
+ * registered StateInterrogation is given the parameter until one of
+ * them returns true, indicating that it has handled the call.
+ * An instance that implements this interface must be registered with the
* {@link JDOImplHelper}.
* @version 2.0
* @since 2.0
@@ -38,138 +56,193 @@
/** Tests whether the parameter instance is persistent.
*
* Instances that represent persistent objects in the data store
- * return <code>true</code>.
+ * return <code>Boolean.TRUE</code>.
+ *
+ * <P>Instances known by the implementation to be non-persistent
+ * return <code>Boolean.FALSE</code>.
+ *
+ * <P>Instances not recognized by the implementation return
+ * <code>null</code>.
*
- *<P>Transient instances and instances of classes
- * that do not implement <code>PersistenceCapable</code> return <code>false</code>.
- *<P>
* @see PersistenceManager#makePersistent(Object pc)
* @see PersistenceCapable#jdoIsPersistent()
- * @param pc the <code>PersistenceCapable</code> instance.
- * @return <code>true</code> if the parameter instance is persistent.
+ * @param pc the instance.
+ * @return <code>Boolean.TRUE</code> if the parameter instance is persistent.
*/
- Boolean isPersistent (Object pc);
+ Boolean isPersistent (Object pc);
/** Tests whether the parameter instance is transactional.
*
* Instances whose state is associated with the current transaction
- * return true.
+ * return <code>Boolean.TRUE</code>.
+ *
+ * <P>Instances known by the implementation to be non-transactional
+ * return <code>Boolean.FALSE</code>.
+ *
+ * <P>Instances not recognized by the implementation return
+ * <code>null</code>.
*
- *<P>Transient instances and instances of classes
- * that do not implement <code>PersistenceCapable</code> return <code>false</code>.
* @see PersistenceCapable#jdoIsTransactional()
- * @param pc the <code>PersistenceCapable</code> instance.
- * @return <code>true</code> if the parameter instance is transactional.
+ * @param pc the instance.
+ * @return <code>Boolean.TRUE</code> if the parameter instance is transactional.
*/
- Boolean isTransactional (Object pc);
+ Boolean isTransactional (Object pc);
/** Tests whether the parameter instance is dirty.
*
- * Instances that have been modified, deleted, or newly
- * made persistent in the current transaction return <code>true</code>.
+ * Instances that have been modified, deleted, newly
+ * made persistent in the current transaction,
+ * or modified while detached return <code>Boolean.TRUE</code>.
+ *
+ * <P>Instances known by the implementation to be non-dirty
+ * return <code>Boolean.FALSE</code>.
+ *
+ * <P>Instances not recognized by the implementation return
+ * <code>null</code>.
*
- *<P>Transient instances and instances of classes
- * that do not implement <code>PersistenceCapable</code> return <code>false</code>.
- *<P>
* @see StateManager#makeDirty(PersistenceCapable pc, String fieldName)
* @see PersistenceCapable#jdoIsDirty()
- * @param pc the <code>PersistenceCapable</code> instance.
- * @return <code>true</code> if the parameter instance has been modified in the current transaction.
+ * @param pc the instance.
+ * @return <code>Boolean.TRUE</code> if the parameter instance has been modified
+ * in the current transaction, or while detached.
*/
- Boolean isDirty (Object pc);
+ Boolean isDirty (Object pc);
/** Tests whether the parameter instance has been newly made persistent.
*
* Instances that have been made persistent in the current transaction
- * return <code>true</code>.
+ * return <code>Boolean.TRUE</code>.
+ *
+ * <P>Instances known by the implementation to be non-new
+ * return <code>Boolean.FALSE</code>.
+ *
+ * <P>Instances not recognized by the implementation return
+ * <code>null</code>.
*
- *<P>Transient instances and instances of classes
- * that do not implement <code>PersistenceCapable</code> return <code>false</code>.
- *<P>
* @see PersistenceManager#makePersistent(Object pc)
* @see PersistenceCapable#jdoIsNew()
- * @param pc the <code>PersistenceCapable</code> instance.
- * @return <code>true</code> if the parameter instance was made persistent
+ * @param pc the instance.
+ * @return <code>Boolean.TRUE</code> if the parameter instance was made persistent
* in the current transaction.
*/
- Boolean isNew (Object pc);
+ Boolean isNew (Object pc);
/** Tests whether the parameter instance has been deleted.
*
- * Instances that have been deleted in the current transaction return <code>true</code>.
+ * Instances that have been deleted in the current transaction
+ * return <code>Boolean.TRUE</code>.
+ *
+ * <P>Instances known by the implementation to be non-deleted
+ * return <code>Boolean.FALSE</code>.
+ *
+ * <P>Instances not recognized by the implementation return
+ * <code>null</code>.
*
- *<P>Transient instances and instances of classes
- * that do not implement <code>PersistenceCapable</code> return <code>false</code>.
- *<P>
* @see PersistenceManager#deletePersistent(Object pc)
* @see PersistenceCapable#jdoIsDeleted()
- * @param pc the <code>PersistenceCapable</code> instance.
- * @return <code>true</code> if the parameter instance was deleted
+ * @param pc the instance.
+ * @return <code>Boolean.TRUE</code> if the parameter instance was deleted
* in the current transaction.
*/
- Boolean isDeleted (Object pc);
-
+ Boolean isDeleted (Object pc);
+
+ /** Tests whether the parameter instance is detached.
+ *
+ * Instances that are detached return <code>Boolean.TRUE</code>.
+ *
+ * <P>Instances known by the implementation to be non-detached
+ * return <code>Boolean.FALSE</code>.
+ *
+ * <P>Instances not recognized by the implementation return
+ * <code>null</code>.
+ *
+ * @see PersistenceManager#detachCopy(Object pc)
+ * @see PersistenceCapable#jdoIsDeleted()
+ * @param pc the instance.
+ * @return <code>Boolean.TRUE</code> if the parameter instance is detached.
+ */
+ Boolean isDetached (Object pc);
+
/** Return the associated <code>PersistenceManager</code> if there is one.
* Transactional and persistent instances return the associated
* <code>PersistenceManager</code>.
*
- * <P>Transient non-transactional instances and instances of classes
- * that do not implement <code>PersistenceCapable</code> return <code>null</code>.
+ * <P>Transient non-transactional instances return <code>null</code>.
+ * <P>Instances unknown by the implementation return <code>null</code>.
* @see PersistenceCapable#jdoGetPersistenceManager()
- * @param pc the <code>PersistenceCapable</code> instance.
- * @return the <code>PersistenceManager</code> associated with the parameter instance.
+ * @param pc the instance.
+ * @return the <code>PersistenceManager</code> associated with the
+ * parameter instance.
*/
PersistenceManager getPersistenceManager (Object pc);
- /** Return a copy of the JDO identity associated with the parameter instance.
+ /** Return a copy of the JDO identity associated with the parameter
+ * instance.
*
- * <P>Persistent instances of <code>PersistenceCapable</code> classes have a JDO identity
- * managed by the <code>PersistenceManager</code>. This method returns a copy of the
+ * <P>Persistent instances of <code>PersistenceCapable</code> classes
+ * have a JDO identity
+ * managed by the <code>PersistenceManager</code>. This method returns
+ * a copy of the
* ObjectId that represents the JDO identity.
*
- * <P>Transient instances and instances of classes
- * that do not implement <code>PersistenceCapable</code> return <code>null</code>.
- *
+ * <P>Instances unknown by the implementation return <code>null</code>.
* <P>The ObjectId may be serialized
- * and later restored, and used with a <code>PersistenceManager</code> from the same JDO
+ * and later restored, and used with a <code>PersistenceManager</code>
+ * from the same JDO
* implementation to locate a persistent instance with the same data store
* identity.
*
- * <P>If the JDO identity is managed by the application, then the ObjectId may
- * be used with a <code>PersistenceManager</code> from any JDO implementation that supports
+ * <P>If the JDO identity is managed by the application, then the ObjectId
+ * may be used with a <code>PersistenceManager</code> from any JDO
+ * implementation that supports
* the <code>PersistenceCapable</code> class.
*
- * <P>If the JDO identity is not managed by the application or the data store,
- * then the ObjectId returned is only valid within the current transaction.
+ * <P>If the JDO identity is not managed by the application or the data
+ * store, then the ObjectId returned is only valid within the current
+ * transaction.
*<P>
* @see PersistenceManager#getObjectId(Object pc)
* @see PersistenceCapable#jdoGetObjectId()
* @see PersistenceManager#getObjectById(Object oid, boolean validate)
- * @param pc the PersistenceCapable instance.
- * @return a copy of the ObjectId of the parameter instance as of the beginning of the transaction.
+ * @param pc the instance.
+ * @return a copy of the ObjectId of the parameter instance as of the
+ * beginning of the transaction.
*/
Object getObjectId (Object pc);
- /** Return a copy of the JDO identity associated with the parameter instance.
+ /** Return a copy of the JDO identity associated with the parameter
+ * instance.
*
+ * <P>Instances unknown by the implementation return <code>null</code>.
* @see PersistenceCapable#jdoGetTransactionalObjectId()
* @see PersistenceManager#getObjectById(Object oid, boolean validate)
- * @param pc the <code>PersistenceCapable</code> instance.
- * @return a copy of the ObjectId of the parameter instance as modified in this transaction.
+ * @param pc the instance.
+ * @return a copy of the ObjectId of the parameter instance as modified
+ * in this transaction.
*/
Object getTransactionalObjectId (Object pc);
+ /** Return the version of the parameter instance.
+ *
+ * <P>Instances unknown by the implementation return <code>null</code>.
+ * @see PersistenceCapable#jdoGetVersion()
+ * @param pc the instance.
+ * @return a copy of the ObjectId of the parameter instance as modified
+ * in this transaction.
+ */
+ Object getVersion (Object pc);
+
/** Explicitly mark the parameter instance and field dirty.
- * Normally, <code>PersistenceCapable</code> classes are able to detect changes made
+ * Normally, <code>PersistenceCapable</code> classes are able to detect
+ * changes made
* to their fields. However, if a reference to an array is given to a
* method outside the class, and the array is modified, then the
* persistent instance is not aware of the change. This API allows the
* application to notify the instance that a change was made to a field.
*
- * <P>Transient instances and instances of classes
- * that do not implement <code>PersistenceCapable</code> ignore this method.
+ * <P>Instances unknown by the implementation are unaffected.
* @see PersistenceCapable#jdoMakeDirty(String fieldName)
- * @param pc the <code>PersistenceCapable</code> instance.
+ * @param pc the instance.
* @param fieldName the name of the field to be marked dirty.
*/
boolean makeDirty (Object pc, String fieldName);
Added: incubator/jdo/trunk/api20/test/java/javax/jdo/spi/StateInterrogationTest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/spi/StateInterrogationTest.java?rev=230925&view=auto
==============================================================================
--- incubator/jdo/trunk/api20/test/java/javax/jdo/spi/StateInterrogationTest.java (added)
+++ incubator/jdo/trunk/api20/test/java/javax/jdo/spi/StateInterrogationTest.java Mon Aug 8 16:45:27 2005
@@ -0,0 +1,540 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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.spi;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+
+import javax.jdo.JDOHelper;
+import javax.jdo.PersistenceManager;
+
+import javax.jdo.util.AbstractTest;
+import javax.jdo.util.BatchTestRunner;
+
+/**
+ * This class tests the StateInterrogation interface. The test is in
+ * several parts:
+ * <ul><li> Add and remove the StateInterrogation instance
+ * </li><li> test interrogatives to return the correct answer
+ * </li><li> test getters to return the correct answer
+ * </li><li> test makeDirty to return.
+ * </li></ul>
+ * We use an mock implementation of StateInterrogation interface to
+ * log when calls are received and to return the correct replies.
+ * We use a java.lang.reflect.Proxy for the getPersistenceManager call
+ * because it's too much work to mock it.
+ */
+public class StateInterrogationTest extends AbstractTest {
+
+ private JDOImplHelper implHelper = JDOImplHelper.getInstance();
+
+ private JDOHelper helper = new JDOHelper();
+
+ /** Creates a new instance of StateInterrogationTest */
+ public StateInterrogationTest() {
+ }
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ BatchTestRunner.run(StateInterrogationTest.class);
+ }
+
+ public void testGetObjectIdNull() {
+ Object id2 = helper.getObjectId(nbcpc2);
+ assertNull("ObjectId should be null before addStateInterrogations",
+ id2);
+ addStateInterrogations();
+ Object id = helper.getObjectId(Boolean.TRUE);
+ assertNull("ObjectId should be null for non-pc instances",
+ id);
+ }
+
+ public void testGetObjectId() {
+ addStateInterrogations();
+ Object id2 = helper.getObjectId(nbcpc2);
+ assertNotNull("ObjectId should not be null",
+ id2);
+ assertEquals("ObjectId should be 2",
+ 2, id2.hashCode());
+ Object id20 = helper.getObjectId(nbcpc2);
+ assertEquals("ObjectIds from same object should be equal",
+ id2, id20);
+ }
+
+ public void testRemoveStateInterrogation() {
+ addStateInterrogations();
+ Object id2 = helper.getObjectId(nbcpc2);
+ assertNotNull("ObjectId should not be null",
+ id2);
+ assertEquals("ObjectId should be 2",
+ 2, id2.hashCode());
+ implHelper.removeStateInterrogation(si2);
+ implHelper.removeStateInterrogation(si0);
+ Object id21 = helper.getObjectId(nbcpc2);
+ assertNull("ObjectId should be null after RemoveStateInterrogation",
+ id21);
+ Object id1 = helper.getObjectId(nbcpc1);
+ assertNotNull("ObjectId should not be null",
+ id1);
+ assertEquals("ObjectId should be 1",
+ 1, id1.hashCode());
+ }
+
+ public void testGetTransactionalObjectIdNull() {
+ Object id2 = helper.getTransactionalObjectId(nbcpc2);
+ assertNull("TransactionalObjectId should be null before addStateInterrogations",
+ id2);
+ addStateInterrogations();
+ Object id = helper.getTransactionalObjectId(Boolean.TRUE);
+ assertNull("TransactionalObjectId should be null for non-pc instances",
+ id);
+ }
+
+ public void testGetTransactionalObjectId() {
+ addStateInterrogations();
+ Object id2 = helper.getTransactionalObjectId(nbcpc2);
+ assertNotNull("TransactionalObjectId should not be null",
+ id2);
+ assertEquals("TransactionalObjectId should be 2",
+ 2, id2.hashCode());
+ Object id20 = helper.getTransactionalObjectId(nbcpc2);
+ assertEquals("TransactionalObjectIds from same object should be equal",
+ id2, id20);
+ }
+
+ public void testGetPersistenceManagerNull() {
+ Object pm2 = helper.getPersistenceManager(nbcpc2);
+ assertNull("PersistenceManager should be null before addStateInterrogations",
+ pm2);
+ addStateInterrogations();
+ Object pm = helper.getPersistenceManager(Boolean.TRUE);
+ assertNull("PersistenceManager should be null for non-pc instances",
+ pm);
+ }
+
+ public void testGetPersistenceManager() {
+ addStateInterrogations();
+ Object pm2 = helper.getPersistenceManager(nbcpc2);
+ assertNotNull("PersistenceManager should not be null",
+ pm2);
+ assertEquals("PersistenceManager should be 2",
+ 2, pm2.hashCode());
+ Object pm20 = helper.getPersistenceManager(nbcpc2);
+ assertEquals("PersistenceManagers from same object should be equal",
+ pm2, pm20);
+ }
+
+ public void testGetVersionNull() {
+ Object id2 = helper.getVersion(nbcpc2);
+ assertNull("Version should be null before addStateInterrogations",
+ id2);
+ addStateInterrogations();
+ Object id = helper.getVersion(Boolean.TRUE);
+ assertNull("Version should be null for non-pc instances",
+ id);
+ }
+
+ public void testGetVersion() {
+ addStateInterrogations();
+ Object id2 = helper.getVersion(nbcpc2);
+ assertNotNull("Version should not be null",
+ id2);
+ assertEquals("Version should be 2",
+ 2, id2.hashCode());
+ Object id20 = helper.getVersion(nbcpc2);
+ assertEquals("Versions from same object should be equal",
+ id2, id20);
+ }
+
+ public void testIsDeletedFalse() {
+ assertFalse("IsDeleted should be false before addStateInterrogations",
+ helper.isDeleted(nbcpc2));
+ addStateInterrogations();
+ assertFalse("IsDeleted should be false for non-pc instances",
+ helper.isDeleted(Boolean.TRUE));
+ implHelper.removeStateInterrogation(si2);
+ assertFalse("IsDeleted should be false after removeStateInterrogations",
+ helper.isDeleted(nbcpc2));
+ }
+
+ public void testIsDeletedMine() {
+ addStateInterrogations();
+ assertTrue("IsDeleted should be true for nbcpc1",
+ helper.isDeleted(nbcpc1));
+ assertFalse("IsDeleted should be false for nbcpc2",
+ helper.isDeleted(nbcpc2));
+ }
+
+ public void testIsDetachedFalse() {
+ assertFalse("IsDetached should be false before addStateInterrogations",
+ helper.isDetached(nbcpc2));
+ addStateInterrogations();
+ assertFalse("IsDetached should be false for non-pc instances",
+ helper.isDetached(Boolean.TRUE));
+ implHelper.removeStateInterrogation(si2);
+ assertFalse("IsDetached should be false after removeStateInterrogations",
+ helper.isDetached(nbcpc2));
+ }
+
+ public void testIsDetachedMine() {
+ addStateInterrogations();
+ assertTrue("IsDetached should be true for nbcpc1",
+ helper.isDetached(nbcpc1));
+ assertFalse("IsDetached should be false for nbcpc2",
+ helper.isDetached(nbcpc2));
+ }
+
+ public void testIsDirtyFalse() {
+ assertFalse("IsDirty should be false before addStateInterrogations",
+ helper.isDirty(nbcpc2));
+ addStateInterrogations();
+ assertFalse("IsDirty should be false for non-pc instances",
+ helper.isDirty(Boolean.TRUE));
+ implHelper.removeStateInterrogation(si2);
+ nbcpc2.setDirty(true);
+ assertFalse("IsDirty should be false after removeStateInterrogations",
+ helper.isDirty(nbcpc2));
+ nbcpc2.setDirty(false);
+ }
+
+ public void testIsDirtyMine() {
+ addStateInterrogations();
+ nbcpc1.setDirty(true);
+ assertTrue("IsDirty should be true for nbcpc1 after setDirty(true)",
+ helper.isDirty(nbcpc1));
+ nbcpc1.setDirty(false);
+ assertFalse("IsDirty should be false for nbcpc1 after setDirty(false)",
+ helper.isDirty(nbcpc1));
+ assertFalse("IsDirty should be false for nbcpc2",
+ helper.isDirty(nbcpc2));
+ }
+
+ public void testIsNewFalse() {
+ assertFalse("IsNew should be false before addStateInterrogations",
+ helper.isNew(nbcpc2));
+ addStateInterrogations();
+ assertFalse("IsNew should be false for non-pc instances",
+ helper.isNew(Boolean.TRUE));
+ implHelper.removeStateInterrogation(si2);
+ assertFalse("IsNew should be false after removeStateInterrogations",
+ helper.isNew(nbcpc2));
+ }
+
+ public void testIsNewMine() {
+ addStateInterrogations();
+ assertTrue("IsNew should be true for nbcpc1",
+ helper.isNew(nbcpc1));
+ assertFalse("IsNew should be false for nbcpc2",
+ helper.isNew(nbcpc2));
+ }
+
+ public void testIsPersistentFalse() {
+ assertFalse("IsPersistent should be false before addStateInterrogations",
+ helper.isPersistent(nbcpc2));
+ addStateInterrogations();
+ assertFalse("IsPersistent should be false for non-pc instances",
+ helper.isPersistent(Boolean.TRUE));
+ implHelper.removeStateInterrogation(si2);
+ assertFalse("IsPersistent should be false after removeStateInterrogations",
+ helper.isPersistent(nbcpc2));
+ }
+
+ public void testIsPersistentMine() {
+ addStateInterrogations();
+ assertTrue("IsPersistent should be true for nbcpc1",
+ helper.isPersistent(nbcpc1));
+ assertFalse("IsPersistent should be false for nbcpc2",
+ helper.isPersistent(nbcpc2));
+ }
+
+ public void testIsTransactionalFalse() {
+ assertFalse("IsTransactional should be false before addStateInterrogations",
+ helper.isTransactional(nbcpc2));
+ addStateInterrogations();
+ assertFalse("IsTransactional should be false for non-pc instances",
+ helper.isTransactional(Boolean.TRUE));
+ implHelper.removeStateInterrogation(si2);
+ assertFalse("IsTransactional should be false after removeStateInterrogations",
+ helper.isTransactional(nbcpc2));
+ }
+
+ public void testIsTransactionalMine() {
+ addStateInterrogations();
+ assertTrue("IsTransactional should be true for nbcpc1",
+ helper.isTransactional(nbcpc1));
+ assertFalse("IsTransactional should be false for nbcpc2",
+ helper.isTransactional(nbcpc2));
+ }
+
+ public void testMakeDirtyFalse() {
+ helper.makeDirty(nbcpc2, "");
+ nbcpc2.setDirty(true);
+ assertFalse("IsDirty should be false before addStateInterrogations",
+ helper.isDirty(nbcpc2));
+ addStateInterrogations();
+ implHelper.removeStateInterrogation(si2);
+ nbcpc2.setDirty(false);
+ helper.makeDirty(nbcpc2, "");
+ assertFalse("IsDirty should be false after removeStateInterrogations",
+ helper.isDirty(nbcpc2));
+ }
+
+ public void testMakeDirtyMine() {
+ addStateInterrogations();
+ helper.makeDirty(nbcpc1, "");
+ assertTrue("IsDirty should be true for nbcpc1",
+ helper.isDirty(nbcpc1));
+ nbcpc1.setDirty(false);
+ assertFalse("IsDirty should be false after setDirty(false)",
+ helper.isDirty(nbcpc1));
+ }
+
+ public void tearDown() {
+ removeStateInterrogations();
+ }
+
+ public void addStateInterrogations() {
+ implHelper.addStateInterrogation(si0);
+ implHelper.addStateInterrogation(si1);
+ implHelper.addStateInterrogation(si2);
+ }
+
+ public void removeStateInterrogations() {
+ implHelper.removeStateInterrogation(si0);
+ implHelper.removeStateInterrogation(si1);
+ implHelper.removeStateInterrogation(si2);
+ }
+
+ /**
+ * The non-binary-compatible PersistenceManager class instances.
+ */
+ static private PersistenceManager pmProxy0 = (PersistenceManager)
+ Proxy.newProxyInstance(
+ PersistenceManager.class.getClassLoader(),
+ new Class[] {PersistenceManager.class},
+ new InvocationHandlerImpl(0));
+
+ /**
+ * The non-binary-compatible PersistenceManager class instances.
+ */
+ static private PersistenceManager pmProxy1 = (PersistenceManager)
+ Proxy.newProxyInstance(
+ PersistenceManager.class.getClassLoader(),
+ new Class[] {PersistenceManager.class},
+ new InvocationHandlerImpl(1));
+
+ /**
+ * The non-binary-compatible PersistenceManager class instances.
+ */
+ static private PersistenceManager pmProxy2 = (PersistenceManager)
+ Proxy.newProxyInstance(
+ PersistenceManager.class.getClassLoader(),
+ new Class[] {PersistenceManager.class},
+ new InvocationHandlerImpl(2));
+
+ /**
+ * The array of PersistenceManager proxies
+ */
+ static PersistenceManager[] pmProxies = {pmProxy0, pmProxy1, pmProxy2};
+
+ /**
+ * The array of NonBinaryCompatiblePersistenceCapable instances.
+ */
+ NonBinaryCompatiblePersistenceCapable nbcpc0 =
+ new NonBinaryCompatiblePersistenceCapable(0);
+ NonBinaryCompatiblePersistenceCapable nbcpc1 =
+ new NonBinaryCompatiblePersistenceCapable(1);
+ NonBinaryCompatiblePersistenceCapable nbcpc2 =
+ new NonBinaryCompatiblePersistenceCapable(2);
+
+ NonBinaryCompatiblePersistenceCapable[] nbcpcs = {nbcpc0, nbcpc1, nbcpc2};
+
+ /**
+ * The array of StateInterrogations
+ */
+ static StateInterrogation si0 = new StateInterrogationImpl(0);
+ static StateInterrogation si1 = new StateInterrogationImpl(1);
+ static StateInterrogation si2 = new StateInterrogationImpl(2);
+ static StateInterrogation[] sis = {si0, si1, si2};
+
+ /**
+ * The StateInterrogation implementation manages
+ * NonBinaryCompatiblePersistenceCapable instances that have a
+ * hashCode equal to their own.
+ *
+ * <P>For the methods returning Object, return null if the object
+ * is not managed by this StateInterrogation.
+ *
+ * <P>For the methods returning Boolean, return null if the object
+ * is not managed by this StateInterrogation.
+ *
+ * <P>For the makeDirty method, return false if the object
+ * is not managed by this StateInterrogation.
+ */
+ private static class StateInterrogationImpl implements StateInterrogation {
+
+ private int id;
+
+ public int hashCode() {
+ return id;
+ }
+
+ private StateInterrogationImpl(int id) {
+ this.id = id;
+ }
+
+ public boolean equals(Object other) {
+ if (other.getClass() != StateInterrogationImpl.class) return false;
+ return (other.hashCode() == id);
+ }
+
+ private boolean isMine(Object pc) {
+ return pc.hashCode() == id;
+ }
+
+ public javax.jdo.PersistenceManager getPersistenceManager(Object pc) {
+ return isMine(pc)?pmProxies[id]:null;
+ }
+
+ public Object getObjectId(Object pc) {
+ return isMine(pc)?new ObjectIdImpl(id):null;
+ }
+
+ public Object getTransactionalObjectId(Object pc) {
+ return isMine(pc)?new ObjectIdImpl(id):null;
+ }
+
+ public Object getVersion(Object pc) {
+ return isMine(pc)?new ObjectIdImpl(id):null;
+ }
+
+ public Boolean isDeleted(Object pc) {
+ if (isMine(pc)) {
+ return (pc.hashCode()==1)?Boolean.TRUE:Boolean.FALSE;
+ } else return null;
+ }
+
+ public Boolean isDetached(Object pc) {
+ if (isMine(pc)) {
+ return (pc.hashCode()==1)?Boolean.TRUE:Boolean.FALSE;
+ } else return null;
+ }
+
+ public Boolean isDirty(Object pc) {
+ if (isMine(pc)) {
+ return ((NonBinaryCompatiblePersistenceCapable)pc).isDirty()
+ ?Boolean.TRUE:Boolean.FALSE;
+ } else return null;
+ }
+
+ public Boolean isNew(Object pc) {
+ if (isMine(pc)) {
+ return (pc.hashCode()==1)?Boolean.TRUE:Boolean.FALSE;
+ } else return null;
+ }
+
+ public Boolean isPersistent(Object pc) {
+ if (isMine(pc)) {
+ return (pc.hashCode()==1)?Boolean.TRUE:Boolean.FALSE;
+ } else return null;
+ }
+
+ public Boolean isTransactional(Object pc) {
+ if (isMine(pc)) {
+ return (pc.hashCode()==1)?Boolean.TRUE:Boolean.FALSE;
+ } else return null;
+ }
+
+ public boolean makeDirty(Object pc, String fieldName) {
+ if (isMine(pc)) {
+ ((NonBinaryCompatiblePersistenceCapable)pc).setDirty(true);
+ return true;
+ } else return false;
+ }
+ }
+
+ /**
+ * The non-binary-compatible PersistenceCapable class.
+ */
+ public static class NonBinaryCompatiblePersistenceCapable {
+ private int id;
+ private boolean dirty = false;
+ private NonBinaryCompatiblePersistenceCapable(int id) {
+ this.id = id;
+ }
+ public int hashCode() {
+ return id;
+ }
+ public void setDirty(boolean dirty) {
+ this.dirty = dirty;
+ }
+ public boolean isDirty() {
+ return dirty;
+ }
+ }
+
+ /**
+ * The non-binary-compatible object id class.
+ */
+ public static class ObjectIdImpl {
+ private int id;
+ private ObjectIdImpl(int id) {
+ this.id = id;
+ }
+ public int hashCode() {
+ return id;
+ }
+ public boolean equals(Object other) {
+ if (other.getClass() != ObjectIdImpl.class) return false;
+ return (other.hashCode() == id);
+ }
+ }
+
+ /**
+ * The non-binary-compatible InvocationHandler class
+ * for PersistenceManager proxy.
+ */
+ private static class InvocationHandlerImpl implements InvocationHandler {
+ private int id;
+ private InvocationHandlerImpl(int id) {
+ this.id = id;
+ }
+ public int hashCode() {
+ return id;
+ }
+ public boolean equals(Object other) {
+ if (other.getClass() != ObjectIdImpl.class) return false;
+ return (other.hashCode() == id);
+ }
+ public Object invoke(Object obj, java.lang.reflect.Method method,
+ Object[] params) throws Throwable {
+ String name = method.getName();
+ if (name == "hashCode") {
+ return new Integer(id);
+ } else if (name == "equals") {
+ Object other = params[0];
+ if (!(other instanceof PersistenceManager)) return Boolean.FALSE;
+ int otherid = Proxy.getInvocationHandler(other).hashCode();
+ if (otherid == id) return Boolean.TRUE;
+ return Boolean.FALSE;
+ }
+ return null;
+ }
+ }
+}
\ No newline at end of file