db-jdo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From c..@apache.org
Subject 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
Date Mon, 08 Aug 2005 23:45:32 GMT
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



Mime
View raw message