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/07/08 03:17:42 UTC

svn commit: r209692 - in /incubator/jdo/trunk/api20: src/java/javax/jdo/ src/java/javax/jdo/identity/ src/java/javax/jdo/spi/ test/java/javax/jdo/identity/

Author: clr
Date: Thu Jul  7 18:17:40 2005
New Revision: 209692

URL: http://svn.apache.org/viewcvs?rev=209692&view=rev
Log:
JDO-76 added required methods to SingleFieldIdentity classes; added ObjectIdentity class for non-wrapper identity fields

Added:
    incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java
    incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java
    incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java
    incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java
Modified:
    incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties
    incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java
    incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java
    incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java
    incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java
    incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java
    incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java
    incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java
    incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOImplHelper.java
    incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java
    incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java
    incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java
    incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java
    incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java
    incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java

Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties (original)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties Thu Jul  7 18:17:40 2005
@@ -56,9 +56,10 @@
 has the wrong return type for the getPersistenceManagerFactory(Map props) method.
 EXC_StringWrongLength: There must be exactly one character in the id in the input String for CharIdentity.
 EXC_IllegalEventType:The event type is outside the range of valid event types.
-EXC_ObjectIdentityStringConstruction: The instance could not be constructed from \
-the parameter String "{0}". \nThe exception thrown was: "{1}". \n\
-Parsing the class name as "{2}" and key as "{3}".
+EXC_SingleFieldIdentityNullParameter: The identity must not be null.
+EXC_ObjectIdentityStringConstruction: The identity instance could not be constructed. \
+\nThe exception thrown was: "{0}". \
+\nParsed the class name as "{1}" and key as "{2}".
 EXC_ObjectIdentityStringConstructionNoDelimiter: Missing delimiter ":".
 EXC_ObjectIdentityStringConstructionTooShort: Parameter is too short.
 EXC_ObjectIdentityStringConstructionUsage: The instance could not be constructed \
@@ -66,3 +67,12 @@
 \nThe parameter String is of the form "<className>:<keyString>".
 EXC_CreateKeyAsObjectMustNotBeCalled: The method createKeyAsObject must not be called \
 because the keyAsObject field must never be null for this class.
+EXC_CurrencyStringConstructorIllegalArgument: The instance could not be constructed \
+with the argument "{0}". Try "USD".
+EXC_CurrencyStringConstructorException: An exception was thrown during construction \
+of the Currency instance.
+EXC_LocaleStringConstructorException: An exception was thrown during construction \
+of the Locale instance.
+EXC_DateStringConstructor: Error parsing Date string "{0}" at position {1} \
+using date format "{2}".
+MSG_unknown: unknown

Added: incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java?rev=209692&view=auto
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java (added)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java Thu Jul  7 18:17:40 2005
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+/*
+ * JDONullIdentityException.java
+ *
+ */
+
+package javax.jdo;
+
+/** An instance of this class is thrown when attempting to create an object id
+ *  when the object id constructor parameter is null. This might occur when 
+ *  creating an object id instance from a transient instance where an identity 
+ *  field is null.
+ *
+ * @since 2.0
+ * @version 2.0
+ */
+public class JDONullIdentityException extends JDOUserException {
+
+  /**
+   * Constructs a new <code>JDONullIdentityException</code> without a detail message.
+   */
+  public JDONullIdentityException() {
+  }
+
+  /**
+   * Constructs a new <code>JDONullIdentityException</code> with the specified detail message.
+   * @param msg the detail message.
+   */
+  public JDONullIdentityException(String msg) {
+    super(msg);
+  }
+
+  /** Constructs a new <code>JDONullIdentityException</code> with the specified detail message
+   * and failed object.
+   * @param msg the detail message.
+   * @param failed the failed object.
+   */
+  public JDONullIdentityException(String msg, Object failed) {
+    super(msg, failed);
+  }
+
+  /**
+   * Constructs a new <code>JDONullIdentityException</code> with the specified
+   * detail message and nested <code>Throwable</code>s.
+   * @param msg the detail message.
+   * @param nested the nested <code>Throwable[]</code>.
+   */
+  public JDONullIdentityException(String msg, Throwable[] nested) {
+    super(msg, nested);
+  }
+
+  /**
+   * Constructs a new <code>JDONullIdentityException</code> with the specified detail message
+   * and nested <code>Throwable</code>s.
+   * @param msg the detail message.
+   * @param nested the nested <code>Throwable</code>.
+   */
+  public JDONullIdentityException(String msg, Throwable nested) {
+    super(msg, nested);
+  }
+
+}

Added: incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java?rev=209692&view=auto
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java (added)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java Thu Jul  7 18:17:40 2005
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+/*
+ * JDOUserCallbackException.java
+ *
+ */
+
+package javax.jdo;
+
+/** This class represents exceptions caused by exceptions thrown
+ * during execution of callbacks or listeners.
+ *
+ * @version 2.0
+ */
+public class JDOUserCallbackException extends JDOUserException {
+
+  /**
+   * Constructs a new <code>JDOUserCallbackException</code> 
+   * without a detail message.
+   */
+  public JDOUserCallbackException() {
+  }
+
+  /**
+   * Constructs a new <code>JDOUserCallbackException</code> 
+   * with the specified detail message.
+   * @param msg the detail message.
+   */
+  public JDOUserCallbackException(String msg) {
+    super(msg);
+  }
+
+  /**
+   * Constructs a new <code>JDOUserCallbackException</code> with the
+   * specified detail message and nested <code>Throwable</code>s.
+   * @param msg the detail message.
+   * @param nested the nested <code>Throwable[]</code>.
+   */
+  public JDOUserCallbackException(String msg, Throwable[] nested) {
+    super(msg, nested);
+  }
+
+  /**
+   * Constructs a new <code>JDOUserCallbackException</code> with the
+   * specified detail message and nested <code>Throwable</code>s.
+   * @param msg the detail message.
+   * @param nested the nested <code>Throwable</code>.
+   */
+  public JDOUserCallbackException(String msg, Throwable nested) {
+    super(msg, nested);
+  }
+}
+

Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java (original)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java Thu Jul  7 18:17:40 2005
@@ -34,14 +34,20 @@
      */
     private byte key;
     
+    /** Construct this instance with the key value.
+     */
+    private void construct(byte key) {
+        this.key = key;
+        hashCode = super.hashClassName() ^ key;
+    }
+    
     /** Constructor with class and key.
      * @param pcClass the target class
      * @param key the key
      */
     public ByteIdentity(Class pcClass, byte key) {
-        super (pcClass);
-        this.key = key;
-        hashCode = super.hashClassName() ^ key;
+        super(pcClass);
+        construct(key);
     }
     
     /** Constructor with class and key.
@@ -49,7 +55,9 @@
      * @param key the key
      */
     public ByteIdentity(Class pcClass, Byte key) {
-        this (pcClass, key.byteValue());
+        super(pcClass);
+        setKeyAsObject(key);
+        construct(key.byteValue());
     }
 
     /** Constructor with class and key.
@@ -57,7 +65,9 @@
      * @param str the key
      */
     public ByteIdentity(Class pcClass, String str) {
-        this (pcClass, Byte.parseByte(str));
+        super(pcClass);
+        assertKeyNotNull(str);
+        construct(Byte.parseByte(str));
     }
 
     /** Constructor only for Externalizable.
@@ -94,6 +104,14 @@
         }
     }
 
+    /** Create the key as an Object.
+     * @return the key as an Object
+     * @since 2.0
+     */
+    protected Object createKeyAsObject() {
+        return new Byte(key);
+    }
+
     /** Write this object. Write the superclass first.
      * @param out the output
      */
@@ -109,6 +127,5 @@
 		throws IOException, ClassNotFoundException {
         super.readExternal (in);
         key = in.readByte ();
-        hashCode = super.hashCode() ^ key;
     }
 }

Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java (original)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java Thu Jul  7 18:17:40 2005
@@ -40,14 +40,18 @@
      */
     private char key;
 
+    private void construct(char key) {
+        this.key = key;
+        hashCode = hashClassName() ^ key;
+    }
+
     /** Constructor with class and key.
      * @param pcClass the target class
      * @param key the key
      */
     public CharIdentity (Class pcClass, char key) {
         super (pcClass);
-        this.key = key;
-        computeHashCode();
+        construct(key);
     }
 
     /** Constructor with class and key.
@@ -55,7 +59,9 @@
      * @param key the key
      */
     public CharIdentity (Class pcClass, Character key) {
-        this (pcClass, key.charValue ());
+        super (pcClass);
+        setKeyAsObject(key);
+        construct(key.charValue());
     }
 
     /** Constructor with class and key. The String must have exactly one
@@ -65,11 +71,11 @@
      */
     public CharIdentity (Class pcClass, String str) {
         super(pcClass);
+        assertKeyNotNull(str);
         if (str.length() != 1) 
             throw new IllegalArgumentException(
-                    msg.msg("EXC_StringWrongLength"));
-        this.key = str.charAt(0);
-        computeHashCode();
+                msg.msg("EXC_StringWrongLength")); //NOI18N
+        construct(str.charAt(0));
     }
 
     /** Constructor only for Externalizable.
@@ -104,6 +110,14 @@
             CharIdentity other = (CharIdentity) obj;
             return key == other.key;
         }
+    }
+
+    /** Create the key as an Object.
+     * @return the key as an Object
+     * @since 2.0
+     */
+    protected Object createKeyAsObject() {
+        return new Character(key);
     }
 
     /** Write this object. Write the superclass first.

Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java (original)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java Thu Jul  7 18:17:40 2005
@@ -29,16 +29,21 @@
  * @version 2.0
  */
 public class IntIdentity extends SingleFieldIdentity {
+
     private int key;
 
+    private void construct(int key) {
+        this.key = key;
+        hashCode = hashClassName() ^ key;
+    }
+
     /** Constructor with class and key.
      * @param pcClass the class
      * @param key the key
      */
     public IntIdentity (Class pcClass, int key) {
-        super (pcClass);
-        this.key = key;
-        hashCode = hashClassName() ^ key;
+        super(pcClass);
+        construct(key);
 	}
 
     /** Constructor with class and key.
@@ -46,7 +51,9 @@
      * @param key the key
      */
     public IntIdentity (Class pcClass, Integer key) {
-        this (pcClass, key.intValue ());
+        super(pcClass);
+        setKeyAsObject(key);
+        construct(key.intValue ());
     }
 
 
@@ -55,7 +62,9 @@
      * @param str the key
      */
     public IntIdentity (Class pcClass, String str) {
-        this (pcClass, Integer.parseInt(str));
+        super(pcClass);
+        assertKeyNotNull(str);
+        construct(Integer.parseInt(str));
     }
 
     /** Constructor only for Externalizable.
@@ -92,6 +101,14 @@
         }
     }
 
+    /** Create the key as an Object.
+     * @return the key as an Object
+     * @since 2.0
+     */
+    protected Object createKeyAsObject() {
+        return new Integer(key);
+    }
+
     /** Write this object. Write the superclass first.
      * @param out the output
      */
@@ -107,6 +124,5 @@
 		throws IOException, ClassNotFoundException {
         super.readExternal (in);
         key = in.readInt();
-        hashCode = hashClassName() ^ key;
     }
 }

Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java (original)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java Thu Jul  7 18:17:40 2005
@@ -34,14 +34,18 @@
      */
     private long key;
 
+    private void construct(long key) {
+        this.key = key;
+        hashCode = hashClassName() ^ (int)key;
+    }
+
     /** Constructor with class and key.
      * @param pcClass the class
      * @param key the key
      */
     public LongIdentity (Class pcClass, long key) {
         super (pcClass);
-        this.key = key;
-        hashCode = hashClassName() ^ (int)key;
+        construct(key);
     }
 
     /** Constructor with class and key.
@@ -49,7 +53,9 @@
      * @param key the key
      */
     public LongIdentity (Class pcClass, Long key) {
-        this (pcClass, key.longValue ());
+        super(pcClass);
+        setKeyAsObject(key);
+        construct(key.longValue());
     }
 
     /** Constructor with class and key.
@@ -57,7 +63,9 @@
      * @param str the key
      */
     public LongIdentity (Class pcClass, String str) {
-        this (pcClass, Long.parseLong(str));
+        super(pcClass);
+        assertKeyNotNull(str);
+        construct(Long.parseLong(str));
     }
 
     /** Constructor only for Externalizable.
@@ -94,6 +102,14 @@
         }
     }
 
+    /** Create the key as an Object.
+     * @return the key as an Object
+     * @since 2.0
+     */
+    protected Object createKeyAsObject() {
+        return new Long(key);
+    }
+
     /** Write this object. Write the superclass first.
      * @param out the output
      */
@@ -109,6 +125,6 @@
 		throws IOException, ClassNotFoundException {
         super.readExternal (in);
         key = in.readLong();
-        hashCode = hashClassName() ^ (int)key;
     }
+
 }

Added: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java?rev=209692&view=auto
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java (added)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java Thu Jul  7 18:17:40 2005
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+/*
+ * ObjectIdentity.java
+ *
+ */
+ 
+package javax.jdo.identity;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.jdo.JDOUserException;
+
+import javax.jdo.spi.JDOImplHelper;
+
+/** This class is for identity with a single Object type field.
+ * @version 2.0
+ */
+public class ObjectIdentity extends SingleFieldIdentity {
+    
+    /** The key is stored in the superclass field keyAsObject.
+     */
+    
+    /** The JDOImplHelper instance used for parsing the String to an Object.
+     */
+    private static JDOImplHelper helper = (JDOImplHelper)
+        AccessController.doPrivileged(
+            new PrivilegedAction () {
+                public Object run () {
+                    return JDOImplHelper.getInstance();
+                }
+            }
+        );
+    
+    /** The delimiter for String constructor.
+     */
+    public static String STRING_DELIMITER = ":"; //NOI18N
+    
+    /** Constructor with class and key.
+     * @param pcClass the class
+     * @param param the key
+     */
+    public ObjectIdentity (Class pcClass, Object param) {
+        super (pcClass);
+        assertKeyNotNull(param);
+        String paramString = null;
+        String keyString = null;
+        String className = null;
+        if (param instanceof String) {
+            /* The paramString is of the form "<className>:<keyString>" */
+            paramString = (String)param;
+            if (paramString.length() < 3) {
+                throw new JDOUserException(
+                    msg.msg("EXC_ObjectIdentityStringConstructionTooShort") + //NOI18N
+                    msg.msg("EXC_ObjectIdentityStringConstructionUsage", //NOI18N
+                        paramString));
+            }
+            int indexOfDelimiter = paramString.indexOf(STRING_DELIMITER);
+            if (indexOfDelimiter < 0) {
+                throw new JDOUserException(
+                    msg.msg("EXC_ObjectIdentityStringConstructionNoDelimiter") + //NOI18N
+                    msg.msg("EXC_ObjectIdentityStringConstructionUsage", //NOI18N
+                        paramString));
+            }
+            keyString = paramString.substring(indexOfDelimiter+1);
+            className = paramString.substring(0, indexOfDelimiter);
+            keyAsObject = helper.construct(className, keyString);
+        } else {
+            keyAsObject = param;
+        }
+        hashCode = hashClassName() ^ keyAsObject.hashCode();
+    }
+
+    /** Constructor only for Externalizable.
+     */
+    public ObjectIdentity () {
+    }
+
+    /** Return the key.
+     * @return the key
+     */
+    public Object getKey () {
+        return keyAsObject;
+    }
+
+    /** Return the String form of the object id. The class of the
+     * object id is written as the first part of the result so that
+     * the class can be reconstructed later. Then the toString
+     * of the key instance is appended. During construction, 
+     * this process is reversed. The class is extracted from 
+     * the first part of the String, and the String constructor
+     * of the key is used to construct the key itself.
+     * @return the String form of the key
+     */
+    public String toString () {
+        return keyAsObject.getClass().getName()
+                + STRING_DELIMITER
+                + keyAsObject.toString();
+    }
+
+    /** Determine if the other object represents the same object id.
+     * @param obj the other object
+     * @return true if both objects represent the same object id
+     */
+    public boolean equals (Object obj) {
+        if (this == obj) {
+            return true;
+        } else if (!super.equals (obj)) {
+            return false;
+        } else {
+            ObjectIdentity other = (ObjectIdentity) obj;
+            return keyAsObject.equals(other.keyAsObject);
+        }
+    }
+
+    /** Write this object. Write the superclass first.
+     * @param out the output
+     */
+    public void writeExternal(ObjectOutput out) throws IOException {
+        super.writeExternal (out);
+        out.writeObject(keyAsObject);
+    }
+
+    /** Read this object. Read the superclass first.
+     * @param in the input
+     */
+    public void readExternal(ObjectInput in)
+		throws IOException, ClassNotFoundException {
+        super.readExternal (in);
+        keyAsObject = in.readObject();
+    }
+    
+}

Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java (original)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java Thu Jul  7 18:17:40 2005
@@ -33,15 +33,18 @@
 {
 	private short key;
 
+    private void construct(short key) {
+        this.key = key;
+        hashCode = hashClassName() ^ key;
+    }
 
     /** Constructor with class and key.
      * @param pcClass the class
      * @param key the key
      */
     public ShortIdentity (Class pcClass, short key) {
-        super (pcClass);
-        this.key = key;
-        hashCode = hashClassName() ^ key;
+        super(pcClass);
+        construct(key);
     }
 
     /** Constructor with class and key.
@@ -49,7 +52,9 @@
      * @param key the key
      */
     public ShortIdentity (Class pcClass, Short key) {
-        this (pcClass, key.shortValue ());
+        super(pcClass);
+        setKeyAsObject(key);
+        construct(key.shortValue());
     }
 
     /** Constructor with class and key.
@@ -57,7 +62,9 @@
      * @param str the key
      */
     public ShortIdentity (Class pcClass, String str) {
-        this (pcClass, Short.parseShort (str));
+        super(pcClass);
+        assertKeyNotNull(str);
+        construct(Short.parseShort (str));
     }
 
     /** Constructor only for Externalizable.
@@ -94,6 +101,14 @@
         }
     }
 
+    /** Create the key as an Object.
+     * @return the key as an Object
+     * @since 2.0
+     */
+    protected Object createKeyAsObject() {
+        return new Short(key);
+    }
+
     /** Write this object. Write the superclass first.
      * @param out the output
      */
@@ -109,6 +124,5 @@
 		throws IOException, ClassNotFoundException {
         super.readExternal (in);
         key = in.readShort();
-        hashCode = hashClassName() ^ key;
     }
 }

Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java (original)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java Thu Jul  7 18:17:40 2005
@@ -26,6 +26,11 @@
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 
+import javax.jdo.JDOFatalInternalException;
+import javax.jdo.JDONullIdentityException;
+
+import javax.jdo.spi.I18NHelper;
+
 /** This class is the abstract base class for all single field identity
  * classes. A common case of application identity uses exactly one 
  * persistent field in the class to represent identity. In this case, 
@@ -36,6 +41,10 @@
 public abstract class SingleFieldIdentity
     implements Externalizable {
     
+    /** The Internationalization message helper.
+     */
+    protected static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N
+
     /** The class of the target object.
      */
     transient private Class targetClass;
@@ -47,6 +56,10 @@
     /** The hashCode.
      */
     protected int hashCode;
+    
+    /** The key as an Object.
+     */
+    protected Object keyAsObject;
 
     /** Constructor with target class.
      * @param pcClass the class of the target
@@ -64,6 +77,24 @@
     public SingleFieldIdentity () {
     }
 
+    /** Set the given key as the key for this instance. 
+     * Compute the hash code for the instance.
+     */
+    protected void setKeyAsObject(Object key) {
+        assertKeyNotNull(key);
+        keyAsObject = key;
+    }
+
+    /** Assert that the key is not null. Throw a JDONullIdentityException
+     * if the given key is null.
+     */ 
+    protected void assertKeyNotNull(Object key) {
+        if (key == null) {
+            throw new JDONullIdentityException(
+                msg.msg("EXC_SingleFieldIdentityNullParameter")); //NOI18N
+        }
+    }
+    
     /** Return the target class.
      * @return the target class.
      * @since 2.0
@@ -80,6 +111,27 @@
         return targetClassName;
     }
 
+    /** Return the key as an Object. The method is synchronized to avoid
+     * race conditions in multi-threaded environments.
+     * @return the key as an Object.
+     * @since 2.0
+     */
+    public synchronized Object getKeyAsObject() {
+        if (keyAsObject == null) {
+            keyAsObject = createKeyAsObject();
+        }
+        return keyAsObject;
+    }
+    
+    /** Create the key as an Object.
+     * @return the key as an Object;
+     * @since 2.0
+     */
+    protected Object createKeyAsObject() {
+        throw new JDOFatalInternalException
+                (msg.msg("EXC_CreateKeyAsObjectMustNotBeCalled"));
+    }
+    
     /** Check the class and class name and object type. If restored
      * from serialization, class will be null so compare class name.
      * @param obj the other object

Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java (original)
+++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java Thu Jul  7 18:17:40 2005
@@ -25,25 +25,23 @@
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 
+import javax.jdo.JDOUserException;
+
 /** This class is for identity with a single String field.
  * @version 2.0
  */
 public class StringIdentity extends SingleFieldIdentity {
     
-    /** The key.
+    /** The key is stored in the superclass field keyAsObject.
      */
-    private String key;
-
-
+    
     /** Constructor with class and key.
      * @param pcClass the class
      * @param key the key
      */
     public StringIdentity (Class pcClass, String key) {
         super (pcClass);
-        if (key == null)
-            throw new NullPointerException ();
-        this.key = key;
+        setKeyAsObject(key);
         hashCode = hashClassName() ^ key.hashCode();
     }
 
@@ -56,14 +54,14 @@
      * @return the key
      */
     public String getKey () {
-        return key;
+        return (String)keyAsObject;
     }
 
     /** Return the String form of the key.
      * @return the String form of the key
      */
     public String toString () {
-        return key;
+        return (String)keyAsObject;
     }
 
     /** Determine if the other object represents the same object id.
@@ -77,7 +75,7 @@
             return false;
         } else {
             StringIdentity other = (StringIdentity) obj;
-            return key.equals(other.key);
+            return keyAsObject.equals(other.keyAsObject);
         }
     }
 
@@ -86,7 +84,7 @@
      */
     public void writeExternal(ObjectOutput out) throws IOException {
         super.writeExternal (out);
-        out.writeObject(key);
+        out.writeObject(keyAsObject);
     }
 
     /** Read this object. Read the superclass first.
@@ -95,7 +93,6 @@
     public void readExternal(ObjectInput in)
 		throws IOException, ClassNotFoundException {
         super.readExternal (in);
-        key = (String)in.readObject();
-        hashCode = hashClassName() ^ key.hashCode();
+        keyAsObject = (String)in.readObject();
     }
 }

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=209692&r1=209691&r2=209692&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 Thu Jul  7 18:17:40 2005
@@ -21,18 +21,29 @@
 
 package javax.jdo.spi;
 
+import java.lang.reflect.Constructor;
+
+import java.text.DateFormat;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Currency;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.WeakHashMap;
 
+import javax.jdo.JDOException;
 import javax.jdo.JDOFatalInternalException;
 import javax.jdo.JDOFatalUserException;
+import javax.jdo.JDOUserException;
 import javax.jdo.spi.JDOPermission;
 
 /** This class is a helper class for JDO implementations.  It contains methods
@@ -76,8 +87,16 @@
     
     /** The Internationalization message helper.
      */
-    private final static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle");
+    private final static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N
     
+    /** The default DateFormat instance.
+     */
+    static DateFormat dateFormat = DateFormat.getDateTimeInstance();
+
+    /** The DateFormat pattern, set to the default.
+     */
+    static String dateFormatPattern = "MMM d, yyyy hh:mm:ss a";  //NOI18N
+
     /** Creates new JDOImplHelper */
     private JDOImplHelper() {
     }
@@ -267,7 +286,7 @@
             byte[] fieldFlags, Class persistenceCapableSuperclass,
             PersistenceCapable pc) {
         if (pcClass == null) 
-            throw new NullPointerException(msg.msg("ERR_NullClass"));
+            throw new NullPointerException(msg.msg("ERR_NullClass")); //NOI18N
         Meta meta = new Meta (fieldNames, fieldTypes, 
             fieldFlags, persistenceCapableSuperclass, pc);
         registeredClasses.put (pcClass, meta);
@@ -333,7 +352,7 @@
     public void unregisterClass (Class pcClass)
     {
         if (pcClass == null) 
-            throw new NullPointerException(msg.msg("ERR_NullClass"));
+            throw new NullPointerException(msg.msg("ERR_NullClass")); //NOI18N
         SecurityManager sec = System.getSecurityManager();
         if (sec != null) { 
             // throws exception if caller is not authorized
@@ -413,7 +432,7 @@
     public static void registerAuthorizedStateManagerClass (Class smClass) 
         throws SecurityException {
         if (smClass == null) 
-            throw new NullPointerException(msg.msg("ERR_NullClass"));
+            throw new NullPointerException(msg.msg("ERR_NullClass")); //NOI18N
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(JDOPermission.SET_STATE_MANAGER);
@@ -442,7 +461,7 @@
                     Object smClass = it.next();
                     if (!(smClass instanceof Class)) {
                         throw new ClassCastException(
-                            msg.msg("ERR_StateManagerClassCast", 
+                            msg.msg("ERR_StateManagerClassCast", //NOI18N
                                 smClass.getClass().getName()));
                     }
                     registerAuthorizedStateManagerClass((Class)it.next());
@@ -484,9 +503,141 @@
                 return;
             }
         }
-
         // if not already authorized, perform "long" security checking.
         scm.checkPermission(JDOPermission.SET_STATE_MANAGER);
+    }
+
+    /** 
+     * Construct an instance of a key class using a String as input.
+     * This is a helper interface for use with ObjectIdentity.
+     * Classes without a String constructor (such as those in java.lang
+     * and java.util) will use this interface for constructing new instances.
+     * The result might be a singleton or use some other strategy.
+     */
+    public interface StringConstructor {
+        /**
+         * Construct an instance of the class for which this instance
+         * is registered.
+         * @param s the parameter for construction
+         * @return the constructed object
+         */
+        public Object construct(String s);
+    }
+    
+    /** 
+     * Special StringConstructor instances for use with specific
+     * classes that have no public String constructor. The Map is
+     * keyed on class instance and the value is an instance of 
+     * StringConstructor.
+     */
+    static Map stringConstructorMap = new HashMap();
+
+    /**
+     * 
+     * Register special StringConstructor instances. These instances
+     * are for constructing instances from String parameters where there
+     * is no String constructor for them.
+     * @param cls the class to register a StringConstructor for
+     * @param sc the StringConstructor instance
+     * @return the previous StringConstructor registered for this class
+     */
+    public Object registerStringConstructor(Class cls, StringConstructor sc) {
+        return stringConstructorMap.put(cls, sc);
+    }
+
+    /** Register the default special StringConstructor instances.
+     */
+    static {
+        JDOImplHelper helper = getInstance();
+        helper.registerStringConstructor(Currency.class, new StringConstructor() {
+            public Object construct(String s) {
+                try {
+                    return Currency.getInstance(s);
+                } catch (IllegalArgumentException ex) {
+                    throw new javax.jdo.JDOUserException(
+                        msg.msg("EXC_CurrencyStringConstructorIllegalArgument", s), ex); //NOI18N
+                } catch (Exception ex) {
+                    throw new JDOUserException(
+                        msg.msg("EXC_CurrencyStringConstructorException"), ex); //NOI18N
+                }
+            }
+        });
+        helper.registerStringConstructor(Locale.class, new StringConstructor() {
+            public Object construct(String s) {
+                try {
+                    return new Locale(s);
+                } catch (Exception ex) {
+                    throw new JDOUserException(
+                        msg.msg("EXC_LocaleStringConstructorException"), ex); //NOI18N
+                }
+            }
+        });
+        helper.registerStringConstructor(Date.class, new StringConstructor() {
+            public synchronized Object construct(String s) {
+                ParsePosition pp = new ParsePosition(0);
+                Date result = dateFormat.parse(s, pp);
+                if (result == null) {
+                    throw new JDOUserException (
+                        msg.msg("EXC_DateStringConstructor", new Object[] //NOI18N
+                        {s, new Integer(pp.getErrorIndex()), dateFormatPattern}));
+                }
+                return result;
+            }
+        });
+    }
+    
+    /**
+     * Construct an instance of the parameter class, using the keyString
+     * as an argument to the constructor. If the class has a StringConstructor
+     * instance registered, use it. If not, try to find a constructor for
+     * the class with a single String argument. Otherwise, throw a
+     * JDOUserException.
+     * @param className the name of the class
+     * @param keyString the String parameter for the constructor
+     * @return the result of construction
+     */
+    public Object construct(String className, String keyString) {
+        synchronized(stringConstructorMap) {
+            try {
+                Class keyClass = Class.forName(className);
+                StringConstructor stringConstructor = 
+                        (StringConstructor) stringConstructorMap.get(keyClass);
+                if (stringConstructor == null) {
+                    Constructor keyConstructor = 
+                        keyClass.getConstructor(new Class[]{String.class});
+                    return keyConstructor.newInstance(new Object[]{keyString});
+                } else {
+                    return stringConstructor.construct(keyString);
+                }
+            } catch (JDOException ex) {
+                throw ex;
+            } catch (Exception ex) {
+                 /* ClassNotFoundException,
+                    NoSuchMethodException,
+                    InstantiationException,
+                    IllegalAccessException,
+                    InvocationTargetException */
+                throw new JDOUserException(
+                    msg.msg("EXC_ObjectIdentityStringConstruction",  //NOI18N
+                    new Object[] {ex.toString(), className, keyString}), ex);
+            }
+        }
+    }
+
+    /**
+     * Register a DateFormat instance for use with constructing Date 
+     * instances. The default is the default DateFormat instance.
+     * If the new instance implements SimpleDateFormat, get its pattern
+     * for error messages.
+     * @param df the DateFormat instance to use
+     */
+    synchronized void registerDateFormat(DateFormat df) {
+        dateFormat = df;
+        if (df instanceof SimpleDateFormat) {
+            dateFormatPattern = ((SimpleDateFormat)df).toPattern();
+        } else {
+            dateFormatPattern = msg.msg("MSG_unknown"); //NOI18N
+        }
     }
 
     /** This is a helper class to manage metadata per persistence-capable

Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java (original)
+++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java Thu Jul  7 18:17:40 2005
@@ -21,6 +21,8 @@
 
 package javax.jdo.identity;
 
+import javax.jdo.JDONullIdentityException;
+
 import javax.jdo.util.BatchTestRunner;
 
 /**
@@ -95,4 +97,33 @@
         assertFalse ("Not equal ByteIdentity instances compare equal.", sc1.equals(sc3));
         assertFalse ("Not equal ByteIdentity instances compare equal.", sc3.equals(sc1));
     }
+    
+    public void testGetKeyAsObjectPrimitive() {
+        ByteIdentity c1 = new ByteIdentity(Object.class, (byte)1);
+        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Byte((byte)1));
+    }
+
+    public void testGetKeyAsObject() {
+        ByteIdentity c1 = new ByteIdentity(Object.class, new Byte((byte)1));
+        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Byte((byte)1));
+    }
+
+    public void testBadConstructorNullByteParam() {
+        try {
+            ByteIdentity c1 = new ByteIdentity(Object.class, (Byte)null);
+        } catch (JDONullIdentityException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+
+    public void testBadConstructorNullStringParam() {
+        try {
+            ByteIdentity c1 = new ByteIdentity(Object.class, (String)null);
+        } catch (JDONullIdentityException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+
 }

Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java (original)
+++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java Thu Jul  7 18:17:40 2005
@@ -21,6 +21,8 @@
 
 package javax.jdo.identity;
 
+import javax.jdo.JDONullIdentityException;
+
 import javax.jdo.util.BatchTestRunner;
 
 /**
@@ -105,4 +107,32 @@
         assertFalse ("Not equal CharIdentity instances compare equal.", sc1.equals(sc3));
         assertFalse ("Not equal CharIdentity instances compare equal.", sc3.equals(sc1));
     }
+    public void testGetKeyAsObjectPrimitive() {
+        CharIdentity c1 = new CharIdentity(Object.class, '1');
+        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Character('1'));
+    }
+
+    public void testGetKeyAsObject() {
+        CharIdentity c1 = new CharIdentity(Object.class, new Character('1'));
+        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Character('1'));
+    }
+
+    public void testBadConstructorNullCharacterParam() {
+        try {
+            CharIdentity c1 = new CharIdentity(Object.class, (Character)null);
+        } catch (JDONullIdentityException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+
+    public void testBadConstructorNullStringParam() {
+        try {
+            CharIdentity c1 = new CharIdentity(Object.class, (String)null);
+        } catch (JDONullIdentityException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+
 }

Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java (original)
+++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java Thu Jul  7 18:17:40 2005
@@ -21,6 +21,8 @@
 
 package javax.jdo.identity;
 
+import javax.jdo.JDONullIdentityException;
+
 import javax.jdo.util.BatchTestRunner;
 
 /**
@@ -95,4 +97,32 @@
         assertFalse ("Not equal IntIdentity instances compare equal.", sc1.equals(sc3));
         assertFalse ("Not equal IntIdentity instances compare equal.", sc3.equals(sc1));
     }
+    public void testGetKeyAsObjectPrimitive() {
+        IntIdentity c1 = new IntIdentity(Object.class, 1);
+        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Integer(1));
+    }
+
+    public void testGetKeyAsObject() {
+        IntIdentity c1 = new IntIdentity(Object.class, new Integer(1));
+        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Integer(1));
+    }
+
+    public void testBadConstructorNullIntegerParam() {
+        try {
+            IntIdentity c1 = new IntIdentity(Object.class, (Integer)null);
+        } catch (JDONullIdentityException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+
+    public void testBadConstructorNullStringParam() {
+        try {
+            IntIdentity c1 = new IntIdentity(Object.class, (String)null);
+        } catch (JDONullIdentityException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+
 }

Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java (original)
+++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java Thu Jul  7 18:17:40 2005
@@ -21,6 +21,8 @@
 
 package javax.jdo.identity;
 
+import javax.jdo.JDONullIdentityException;
+
 import javax.jdo.util.BatchTestRunner;
 
 /**
@@ -95,4 +97,33 @@
         assertFalse ("Not equal LongIdentity instances compare equal.", sc1.equals(sc3));
         assertFalse ("Not equal LongIdentity instances compare equal.", sc3.equals(sc1));
     }
+    
+    public void testGetKeyAsObjectPrimitive() {
+        LongIdentity c1 = new LongIdentity(Object.class, 1L);
+        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Long(1L));
+    }
+
+    public void testGetKeyAsObject() {
+        LongIdentity c1 = new LongIdentity(Object.class, new Long(1L));
+        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Long(1L));
+    }
+
+    public void testBadConstructorNullShortParam() {
+        try {
+            LongIdentity c1 = new LongIdentity(Object.class, (Long)null);
+        } catch (JDONullIdentityException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+
+    public void testBadConstructorNullStringParam() {
+        try {
+            LongIdentity c1 = new LongIdentity(Object.class, (String)null);
+        } catch (JDONullIdentityException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+
 }

Added: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java?rev=209692&view=auto
==============================================================================
--- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java (added)
+++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java Thu Jul  7 18:17:40 2005
@@ -0,0 +1,369 @@
+/*
+ * 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.
+ */
+
+/*
+ * ObjectIdentityTest.java
+ *
+ */
+
+package javax.jdo.identity;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import java.io.Serializable;
+
+import java.math.BigDecimal;
+import java.util.Currency;
+import java.util.Date;
+import java.util.Locale;
+
+import javax.jdo.JDOUserException;
+import javax.jdo.JDONullIdentityException;
+import javax.jdo.util.BatchTestRunner;
+
+/**
+ *
+ */
+public class ObjectIdentityTest extends SingleFieldIdentityTest {
+    
+    /** Creates a new instance of ObjectIdentityTest */
+    public ObjectIdentityTest() {
+    }
+    
+    /**
+     * @param args the command line arguments
+     */
+    public static void main(String[] args) {
+        BatchTestRunner.run(ObjectIdentityTest.class);
+    }
+    
+    public void testConstructor() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, new IdClass(1));
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, new IdClass(1));
+        ObjectIdentity c3 = new ObjectIdentity(Object.class, new IdClass(2));
+        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
+        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
+    }
+    
+    public void testIntegerConstructor() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Integer(1));
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Integer(1));
+        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Integer(2));
+        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
+        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
+    }
+    
+    public void testLongConstructor() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Long(1));
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Long(1));
+        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Long(2));
+        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
+        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
+    }
+    
+    public void testDateConstructor() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Date(1));
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Date(1));
+        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Date(2));
+        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
+        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
+    }
+    
+    public void testLocaleConstructor() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, Locale.US);
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, Locale.US);
+        ObjectIdentity c3 = new ObjectIdentity(Object.class, Locale.GERMANY);
+        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
+        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
+    }
+    
+    public void testCurrencyConstructor() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, 
+                Currency.getInstance(Locale.US));
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, 
+                Currency.getInstance(Locale.US));
+        ObjectIdentity c3 = new ObjectIdentity(Object.class, 
+                Currency.getInstance(Locale.GERMANY));
+        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
+        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
+    }
+    
+    public void testStringConstructor() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, 
+                "javax.jdo.identity.ObjectIdentityTest$IdClass:1");        
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, 
+                "javax.jdo.identity.ObjectIdentityTest$IdClass:1");        
+        ObjectIdentity c3 = new ObjectIdentity(Object.class, 
+                "javax.jdo.identity.ObjectIdentityTest$IdClass:2");        
+        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
+        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
+    }
+    
+    public void testToStringConstructor() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, new IdClass(1));
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, c1.toString());
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, c2);
+    }
+
+    public void testBadStringConstructorNullClass() {
+        try {
+            ObjectIdentity c1 = new ObjectIdentity(null, "1");
+        } catch (NullPointerException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+    
+    public void testBadStringConstructorNullParam() {
+        try {
+            ObjectIdentity c1 = new ObjectIdentity(Object.class, null);
+        } catch (JDONullIdentityException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+    
+    public void testBadStringConstructorTooShort() {
+        try {
+            ObjectIdentity c1 = new ObjectIdentity(Object.class, "xx");
+        } catch (JDOUserException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+    
+    public void testBadStringConstructorNoDelimiter() {
+        try {
+            ObjectIdentity c1 = new ObjectIdentity(Object.class, "xxxxxxxxx");
+        } catch (JDOUserException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+    
+    public void testBadStringConstructorBadClassName() {
+        try {
+            ObjectIdentity c1 = new ObjectIdentity(Object.class, "xx:yy");
+        } catch (JDOUserException ex) {
+            validateNestedException(ex, ClassNotFoundException.class);
+            return;
+        }
+        fail ("Failed to catch expected ClassNotFoundException.");
+    }
+    
+    public void testBadStringConstructorNoStringConstructor() {
+        try {
+            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
+                    "javax.jdo.identity.ObjectIdentityTest$BadIdClassNoStringConstructor:yy");
+        } catch (JDOUserException ex) {
+            validateNestedException(ex, NoSuchMethodException.class);
+            return;
+        }
+        fail ("Failed to catch expected NoSuchMethodException.");
+    }
+    
+    public void testBadStringConstructorNoPublicStringConstructor() {
+        try {
+            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
+                    "javax.jdo.identity.ObjectIdentityTest$BadIdClassNoPublicStringConstructor:yy");
+        } catch (JDOUserException ex) {
+            validateNestedException(ex, NoSuchMethodException.class);
+            return;
+        }
+        fail ("Failed to catch expected NoSuchMethodException.");
+    }
+    
+    public void testBadStringConstructorIllegalArgument() {
+        try {
+            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
+                    "javax.jdo.identity.ObjectIdentityTest$IdClass:yy");
+        } catch (JDOUserException ex) {
+            validateNestedException(ex, InvocationTargetException.class);
+            return;
+        }
+        fail ("Failed to catch expected InvocationTargetException.");
+    }
+
+    public void testStringDateConstructor() {
+        Object c1 = new ObjectIdentity(Object.class, 
+            "java.util.Date:Jan 01, 1970 00:00:00 AM");
+    }
+
+    public void testBadStringDateConstructor() {
+        try {
+            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
+                "java.util.Date:Jop 1, 1970 00:00:00");
+        } catch (JDOUserException ex) {
+            return;
+        }
+        fail ("Failed to catch expected Exception.");
+    }
+
+    public void testStringLocaleConstructor() {
+        Object c1 = new ObjectIdentity(Object.class, 
+                    "java.util.Locale:en_us");
+    }
+
+    public void testStringCurrencyConstructor() {
+        Object c1 = new ObjectIdentity(Object.class, 
+                    "java.util.Currency:USD");
+    }
+
+    public void testBadStringCurrencyConstructor() {
+        try {
+            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
+                    "java.util.Currency:NowhereInTheWorld");
+        } catch (JDOUserException ex) {
+            validateNestedException(ex, IllegalArgumentException.class);
+            return;
+        }
+        fail ("Failed to catch expected IllegalArgumentException.");
+    }
+
+    public void testSerializedIdClass() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, new IdClass(1));
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, new IdClass(1));
+        ObjectIdentity c3 = new ObjectIdentity(Object.class, new IdClass(2));
+        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
+        Object sc1 = scis[0];
+        Object sc2 = scis[1];
+        Object sc3 = scis[2];
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
+    }
+    
+    public void testSerializedBigDecimal() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, new BigDecimal("123456789.012"));
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, new BigDecimal("123456789.012"));
+        ObjectIdentity c3 = new ObjectIdentity(Object.class, new BigDecimal("123456789.01"));
+        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
+        Object sc1 = scis[0];
+        Object sc2 = scis[1];
+        Object sc3 = scis[2];
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
+    }
+    
+    public void testSerializedCurrency() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, Currency.getInstance(Locale.US));
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, Currency.getInstance(Locale.US));
+        ObjectIdentity c3 = new ObjectIdentity(Object.class, Currency.getInstance(Locale.GERMANY));
+        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
+        Object sc1 = scis[0];
+        Object sc2 = scis[1];
+        Object sc3 = scis[2];
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
+    }
+    
+    public void testSerializedDate() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Date(1));
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Date(1));
+        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Date(2));
+        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
+        Object sc1 = scis[0];
+        Object sc2 = scis[1];
+        Object sc3 = scis[2];
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
+    }
+    
+    public void testSerializedLocale() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Locale("EN_US"));
+        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Locale("en_us"));
+        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Locale("EN_GB"));
+        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
+        Object sc1 = scis[0];
+        Object sc2 = scis[1];
+        Object sc3 = scis[2];
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
+        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
+        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
+    }
+    
+    public void testGetKeyAsObject() {
+        ObjectIdentity c1 = new ObjectIdentity(Object.class, new IdClass(1));
+        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new IdClass(1));
+    }
+
+    private void validateNestedException(JDOUserException ex, Class expected) {
+        Throwable[] nesteds = ex.getNestedExceptions();
+        if (nesteds == null || nesteds.length == 0) {
+            fail ("Nested exception is null or length 0");
+        }
+        Throwable nested = nesteds[0];
+        if (!(expected.isAssignableFrom(nested.getClass()))) {
+            fail ("Wrong nested exception. Expected ClassNotFoundException, got "
+                    + nested.toString());
+        }
+        return;
+    }
+    public static class IdClass implements Serializable {
+        public int value;
+        public IdClass() {value = 0;}
+        public IdClass(int value) {this.value = value;}
+        public IdClass(String str) {this.value = Integer.parseInt(str);}
+        public String toString() {return Integer.toString(value);}
+        public int hashCode() {
+            return value;
+        }
+        public boolean equals (Object obj) {
+            if (this == obj) {
+                return true;
+            } else {
+                IdClass other = (IdClass) obj;
+                return value == other.value;
+            }
+        }
+    }
+    
+    public static class BadIdClassNoStringConstructor {
+    }
+    
+    public static class BadIdClassNoPublicStringConstructor {
+        private BadIdClassNoPublicStringConstructor(String str) {}
+    }
+}

Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java (original)
+++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java Thu Jul  7 18:17:40 2005
@@ -21,6 +21,8 @@
 
 package javax.jdo.identity;
 
+import javax.jdo.JDONullIdentityException;
+
 import javax.jdo.util.BatchTestRunner;
 
 /**
@@ -95,4 +97,32 @@
         assertFalse ("Not equal ShortIdentity instances compare equal.", sc1.equals(sc3));
         assertFalse ("Not equal ShortIdentity instances compare equal.", sc3.equals(sc1));
     }
+    public void testGetKeyAsObjectPrimitive() {
+        ShortIdentity c1 = new ShortIdentity(Object.class, (short)1);
+        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Short((short)1));
+    }
+
+    public void testGetKeyAsObject() {
+        ShortIdentity c1 = new ShortIdentity(Object.class, new Short((short)1));
+        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Short((short)1));
+    }
+
+    public void testBadConstructorNullShortParam() {
+        try {
+            ShortIdentity c1 = new ShortIdentity(Object.class, (Short)null);
+        } catch (JDONullIdentityException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+
+    public void testBadConstructorNullStringParam() {
+        try {
+            ShortIdentity c1 = new ShortIdentity(Object.class, (String)null);
+        } catch (JDONullIdentityException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+
 }

Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
==============================================================================
--- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java (original)
+++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java Thu Jul  7 18:17:40 2005
@@ -21,6 +21,9 @@
 
 package javax.jdo.identity;
 
+import javax.jdo.JDONullIdentityException;
+import javax.jdo.JDOUserException;
+
 import javax.jdo.util.BatchTestRunner;
 
 /**
@@ -70,4 +73,19 @@
         assertFalse ("Not equal StringIdentity instances compare equal.", sc1.equals(sc3));
         assertFalse ("Not equal StringIdentity instances compare equal.", sc3.equals(sc1));
     }
+
+    public void testGetKeyAsObject() {
+        StringIdentity c1 = new StringIdentity(Object.class, "1");
+        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), "1");
+    }
+
+    public void testBadConstructorNullParam() {
+        try {
+            StringIdentity c1 = new StringIdentity(Object.class, null);
+        } catch (JDONullIdentityException ex) {
+            return;
+        }
+        fail ("Failed to catch expected exception.");
+    }
+
 }



Re: svn commit: r209692 - in /incubator/jdo/trunk/api20: src/java/javax/jdo/ src/java/javax/jdo/identity/ src/java/javax/jdo/spi/ test/java/javax/jdo/identity/

Posted by Michael Bouschen <mb...@spree.de>.
Hi Craig,

attached you find my proposal for a fix. I think method 
registerDateFormat should become public.

Regards Michael

> Hi,
>
> It's the date formatter which is set up for US date formats. My bad.
>
> I'll get a fix for this as soon as I can.
>
> Craig
>
> On Jul 8, 2005, at 2:22 AM, Andy Jefferson wrote:
>
>>> I have updated my api20 workspace today and called "maven -o rebuild".
>>> The ObjectIdentityTest prints an error (see below). I'm not sure, why I
>>> do not see the error stacktrace.
>>>
>>
>> You mean the failed test ? 
>> This is the error. Looks like some date parsing needs a fix in 
>> JDOImplHelper.
>>
>> javax.jdo.JDOUserException: Error parsing Date string "Jan 01, 1970 
>> 00:00:00 
>> AM" at position 0 using date format "MMM d, yyyy hh:mm:ss a".
>> at javax.jdo.spi.JDOImplHelper$3.construct(JDOImplHelper.java:580)
>>         at javax.jdo.spi.JDOImplHelper.construct(JDOImplHelper.java:610)
>>         at 
>> javax.jdo.identity.ObjectIdentity.<init>(ObjectIdentity.java:86)
>>         at 
>> javax.jdo.identity.ObjectIdentityTest.testStringDateConstructor(ObjectIdentityTest.java:202)
>>
>>
>> HTH
>> -- 
>> Andy
>> Java Persistent Objects - JPOX
>>
>
> Craig Russell
>
> Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
>
> 408 276-5638 mailto:Craig.Russell@sun.com
>
> P.S. A good JDO? O, Gasp!
>
>


-- 
Michael Bouschen		Tech@Spree Engineering GmbH
mailto:mbo.tech@spree.de	http://www.tech.spree.de/
Tel.:++49/30/235 520-33		Buelowstr. 66			
Fax.:++49/30/2175 2012		D-10783 Berlin			


Re: svn commit: r209692 - in /incubator/jdo/trunk/api20: src/java/javax/jdo/ src/java/javax/jdo/identity/ src/java/javax/jdo/spi/ test/java/javax/jdo/identity/

Posted by Craig Russell <Cr...@Sun.COM>.
Hi,

It's the date formatter which is set up for US date formats. My bad.

I'll get a fix for this as soon as I can.

Craig

On Jul 8, 2005, at 2:22 AM, Andy Jefferson wrote:

>> I have updated my api20 workspace today and called "maven -o  
>> rebuild".
>> The ObjectIdentityTest prints an error (see below). I'm not sure,  
>> why I
>> do not see the error stacktrace.
>>
>
> You mean the failed test ?
> This is the error. Looks like some date parsing needs a fix in  
> JDOImplHelper.
>
> javax.jdo.JDOUserException: Error parsing Date string "Jan 01, 1970  
> 00:00:00
> AM" at position 0 using date format "MMM d, yyyy hh:mm:ss a".
> at javax.jdo.spi.JDOImplHelper$3.construct(JDOImplHelper.java:580)
>         at javax.jdo.spi.JDOImplHelper.construct(JDOImplHelper.java: 
> 610)
>         at javax.jdo.identity.ObjectIdentity.<init> 
> (ObjectIdentity.java:86)
>         at
> javax.jdo.identity.ObjectIdentityTest.testStringDateConstructor 
> (ObjectIdentityTest.java:202)
>
>
> HTH
> -- 
> Andy
> Java Persistent Objects - JPOX
>

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:Craig.Russell@sun.com
P.S. A good JDO? O, Gasp!


Re: svn commit: r209692 - in /incubator/jdo/trunk/api20: src/java/javax/jdo/ src/java/javax/jdo/identity/ src/java/javax/jdo/spi/ test/java/javax/jdo/identity/

Posted by Michael Bouschen <mb...@spree.de>.
Hi Michael,

as Andy pointed out, this is a date parsing error. You find the error 
stack trace in TEST-javax.jdo.identity.ObjectIdentityTest.txt under 
target/test-reports.

The JDOImplHelper parses Date string using a DateFormat instance 
retrieved by calling DateFormat.getDateTimeInstance. The no-arg version 
of getDateTimeInstance uses the default locale which is different for 
Craig and you (Locale.US vs. Locale.GERMANY). The ObjectIdentityTest 
specifies date strings in US format: 'Jan 01, 1970 00:00:00 AM' which 
does not parse with a DateFormat using the German locale.

A possible solution could be using the US locale when creating the 
DateFormat. Replace dateFormat definition on line 94 of JDOImplHelper 
with the following line:
    static DateFormat dateFormat = DateFormat.getDateTimeInstance(
        DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US);
Then all the test cases pass. The downside is that this hard codes the 
US locale in the JDOImplHelper code. Maybe the JDOImplHelper could use 
the US locale as the default, but provide a way to override this. It 
already provides a method registerDateFormat to override the 
dateFormatPattern, but this needs to be in sync with the locale of the 
dateFormat instance.

Regards Michael

>>I have updated my api20 workspace today and called "maven -o rebuild".
>>The ObjectIdentityTest prints an error (see below). I'm not sure, why I
>>do not see the error stacktrace.
>>    
>>
>
>You mean the failed test ? 
>This is the error. Looks like some date parsing needs a fix in JDOImplHelper.
>
>javax.jdo.JDOUserException: Error parsing Date string "Jan 01, 1970 00:00:00 
>AM" at position 0 using date format "MMM d, yyyy hh:mm:ss a".
>at javax.jdo.spi.JDOImplHelper$3.construct(JDOImplHelper.java:580)
>        at javax.jdo.spi.JDOImplHelper.construct(JDOImplHelper.java:610)
>        at javax.jdo.identity.ObjectIdentity.<init>(ObjectIdentity.java:86)
>        at 
>javax.jdo.identity.ObjectIdentityTest.testStringDateConstructor(ObjectIdentityTest.java:202)
>
>
>HTH
>  
>


-- 
Michael Bouschen		Tech@Spree Engineering GmbH
mailto:mbo.tech@spree.de	http://www.tech.spree.de/
Tel.:++49/30/235 520-33		Buelowstr. 66			
Fax.:++49/30/2175 2012		D-10783 Berlin			


Re: svn commit: r209692 - in /incubator/jdo/trunk/api20: src/java/javax/jdo/ src/java/javax/jdo/identity/ src/java/javax/jdo/spi/ test/java/javax/jdo/identity/

Posted by Andy Jefferson <an...@jpox.org>.
> I have updated my api20 workspace today and called "maven -o rebuild".
> The ObjectIdentityTest prints an error (see below). I'm not sure, why I
> do not see the error stacktrace.

You mean the failed test ? 
This is the error. Looks like some date parsing needs a fix in JDOImplHelper.

javax.jdo.JDOUserException: Error parsing Date string "Jan 01, 1970 00:00:00 
AM" at position 0 using date format "MMM d, yyyy hh:mm:ss a".
at javax.jdo.spi.JDOImplHelper$3.construct(JDOImplHelper.java:580)
        at javax.jdo.spi.JDOImplHelper.construct(JDOImplHelper.java:610)
        at javax.jdo.identity.ObjectIdentity.<init>(ObjectIdentity.java:86)
        at 
javax.jdo.identity.ObjectIdentityTest.testStringDateConstructor(ObjectIdentityTest.java:202)


HTH
-- 
Andy
Java Persistent Objects - JPOX

Re: svn commit: r209692 - in /incubator/jdo/trunk/api20: src/java/javax/jdo/ src/java/javax/jdo/identity/ src/java/javax/jdo/spi/ test/java/javax/jdo/identity/

Posted by Michael Watzek <mw...@spree.de>.
Hi Craig,

I have updated my api20 workspace today and called "maven -o rebuild". 
The ObjectIdentityTest prints an error (see below). I'm not sure, why I 
do not see the error stacktrace.

Regards,
Michael

...
test:test:
     [junit] Running javax.jdo.identity.ByteIdentityTest
     [junit] Tests run: 10, Failures: 0, Errors: 0, Time elapsed: 0,094 sec
     [junit] Running javax.jdo.identity.CharIdentityTest
     [junit] Tests run: 11, Failures: 0, Errors: 0, Time elapsed: 0,031 sec
     [junit] Running javax.jdo.identity.IntIdentityTest
     [junit] Tests run: 10, Failures: 0, Errors: 0, Time elapsed: 0,032 sec
     [junit] Running javax.jdo.identity.LongIdentityTest
     [junit] Tests run: 10, Failures: 0, Errors: 0, Time elapsed: 0,047 sec
     [junit] Running javax.jdo.identity.ObjectIdentityTest
     [junit] Tests run: 28, Failures: 0, Errors: 1, Time elapsed: 0,125 sec
     [junit] [ERROR] TEST javax.jdo.identity.ObjectIdentityTest FAILED
     [junit] Running javax.jdo.identity.ShortIdentityTest
     [junit] Tests run: 10, Failures: 0, Errors: 0, Time elapsed: 0,032 sec
     [junit] Running javax.jdo.identity.SingleFieldIdentityTest
     [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0,032 sec
     [junit] Running javax.jdo.identity.StringIdentityTest
     [junit] Tests run: 5, Failures: 0, Errors: 0, Time elapsed: 0,031 sec
     [junit] Running javax.jdo.JDOHelperTest
     [junit] Tests run: 30, Failures: 0, Errors: 0, Time elapsed: 0,093 sec
     [junit] Running javax.jdo.listener.InstanceLifecycleEventTest
     [junit] Tests run: 10, Failures: 0, Errors: 0, Time elapsed: 0,016 sec
     [junit] Running javax.jdo.spi.JDOImplHelperTest
     [junit] Tests run: 8, Failures: 0, Errors: 0, Time elapsed: 0,047 sec

BUILD FAILED
File...... F:\users\brazil\.maven\cache\maven-test-plugin-1.6.2\plugin.jelly
Element... fail
Line...... 181
Column.... 54
There were test failures.
Total time: 10 seconds
Finished at: Fri Jul 08 11:01:47 CEST 2005

> Author: clr
> Date: Thu Jul  7 18:17:40 2005
> New Revision: 209692
> 
> URL: http://svn.apache.org/viewcvs?rev=209692&view=rev
> Log:
> JDO-76 added required methods to SingleFieldIdentity classes; added ObjectIdentity class for non-wrapper identity fields
> 
> Added:
>     incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java
> Modified:
>     incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOImplHelper.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties Thu Jul  7 18:17:40 2005
> @@ -56,9 +56,10 @@
>  has the wrong return type for the getPersistenceManagerFactory(Map props) method.
>  EXC_StringWrongLength: There must be exactly one character in the id in the input String for CharIdentity.
>  EXC_IllegalEventType:The event type is outside the range of valid event types.
> -EXC_ObjectIdentityStringConstruction: The instance could not be constructed from \
> -the parameter String "{0}". \nThe exception thrown was: "{1}". \n\
> -Parsing the class name as "{2}" and key as "{3}".
> +EXC_SingleFieldIdentityNullParameter: The identity must not be null.
> +EXC_ObjectIdentityStringConstruction: The identity instance could not be constructed. \
> +\nThe exception thrown was: "{0}". \
> +\nParsed the class name as "{1}" and key as "{2}".
>  EXC_ObjectIdentityStringConstructionNoDelimiter: Missing delimiter ":".
>  EXC_ObjectIdentityStringConstructionTooShort: Parameter is too short.
>  EXC_ObjectIdentityStringConstructionUsage: The instance could not be constructed \
> @@ -66,3 +67,12 @@
>  \nThe parameter String is of the form "<className>:<keyString>".
>  EXC_CreateKeyAsObjectMustNotBeCalled: The method createKeyAsObject must not be called \
>  because the keyAsObject field must never be null for this class.
> +EXC_CurrencyStringConstructorIllegalArgument: The instance could not be constructed \
> +with the argument "{0}". Try "USD".
> +EXC_CurrencyStringConstructorException: An exception was thrown during construction \
> +of the Currency instance.
> +EXC_LocaleStringConstructorException: An exception was thrown during construction \
> +of the Locale instance.
> +EXC_DateStringConstructor: Error parsing Date string "{0}" at position {1} \
> +using date format "{2}".
> +MSG_unknown: unknown
> 
> Added: incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java?rev=209692&view=auto
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java (added)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java Thu Jul  7 18:17:40 2005
> @@ -0,0 +1,77 @@
> +/*
> + * 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.
> + */
> +
> +/*
> + * JDONullIdentityException.java
> + *
> + */
> +
> +package javax.jdo;
> +
> +/** An instance of this class is thrown when attempting to create an object id
> + *  when the object id constructor parameter is null. This might occur when 
> + *  creating an object id instance from a transient instance where an identity 
> + *  field is null.
> + *
> + * @since 2.0
> + * @version 2.0
> + */
> +public class JDONullIdentityException extends JDOUserException {
> +
> +  /**
> +   * Constructs a new <code>JDONullIdentityException</code> without a detail message.
> +   */
> +  public JDONullIdentityException() {
> +  }
> +
> +  /**
> +   * Constructs a new <code>JDONullIdentityException</code> with the specified detail message.
> +   * @param msg the detail message.
> +   */
> +  public JDONullIdentityException(String msg) {
> +    super(msg);
> +  }
> +
> +  /** Constructs a new <code>JDONullIdentityException</code> with the specified detail message
> +   * and failed object.
> +   * @param msg the detail message.
> +   * @param failed the failed object.
> +   */
> +  public JDONullIdentityException(String msg, Object failed) {
> +    super(msg, failed);
> +  }
> +
> +  /**
> +   * Constructs a new <code>JDONullIdentityException</code> with the specified
> +   * detail message and nested <code>Throwable</code>s.
> +   * @param msg the detail message.
> +   * @param nested the nested <code>Throwable[]</code>.
> +   */
> +  public JDONullIdentityException(String msg, Throwable[] nested) {
> +    super(msg, nested);
> +  }
> +
> +  /**
> +   * Constructs a new <code>JDONullIdentityException</code> with the specified detail message
> +   * and nested <code>Throwable</code>s.
> +   * @param msg the detail message.
> +   * @param nested the nested <code>Throwable</code>.
> +   */
> +  public JDONullIdentityException(String msg, Throwable nested) {
> +    super(msg, nested);
> +  }
> +
> +}
> 
> Added: incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java?rev=209692&view=auto
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java (added)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java Thu Jul  7 18:17:40 2005
> @@ -0,0 +1,67 @@
> +/*
> + * 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.
> + */
> +
> +/*
> + * JDOUserCallbackException.java
> + *
> + */
> +
> +package javax.jdo;
> +
> +/** This class represents exceptions caused by exceptions thrown
> + * during execution of callbacks or listeners.
> + *
> + * @version 2.0
> + */
> +public class JDOUserCallbackException extends JDOUserException {
> +
> +  /**
> +   * Constructs a new <code>JDOUserCallbackException</code> 
> +   * without a detail message.
> +   */
> +  public JDOUserCallbackException() {
> +  }
> +
> +  /**
> +   * Constructs a new <code>JDOUserCallbackException</code> 
> +   * with the specified detail message.
> +   * @param msg the detail message.
> +   */
> +  public JDOUserCallbackException(String msg) {
> +    super(msg);
> +  }
> +
> +  /**
> +   * Constructs a new <code>JDOUserCallbackException</code> with the
> +   * specified detail message and nested <code>Throwable</code>s.
> +   * @param msg the detail message.
> +   * @param nested the nested <code>Throwable[]</code>.
> +   */
> +  public JDOUserCallbackException(String msg, Throwable[] nested) {
> +    super(msg, nested);
> +  }
> +
> +  /**
> +   * Constructs a new <code>JDOUserCallbackException</code> with the
> +   * specified detail message and nested <code>Throwable</code>s.
> +   * @param msg the detail message.
> +   * @param nested the nested <code>Throwable</code>.
> +   */
> +  public JDOUserCallbackException(String msg, Throwable nested) {
> +    super(msg, nested);
> +  }
> +}
> +
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java Thu Jul  7 18:17:40 2005
> @@ -34,14 +34,20 @@
>       */
>      private byte key;
>      
> +    /** Construct this instance with the key value.
> +     */
> +    private void construct(byte key) {
> +        this.key = key;
> +        hashCode = super.hashClassName() ^ key;
> +    }
> +    
>      /** Constructor with class and key.
>       * @param pcClass the target class
>       * @param key the key
>       */
>      public ByteIdentity(Class pcClass, byte key) {
> -        super (pcClass);
> -        this.key = key;
> -        hashCode = super.hashClassName() ^ key;
> +        super(pcClass);
> +        construct(key);
>      }
>      
>      /** Constructor with class and key.
> @@ -49,7 +55,9 @@
>       * @param key the key
>       */
>      public ByteIdentity(Class pcClass, Byte key) {
> -        this (pcClass, key.byteValue());
> +        super(pcClass);
> +        setKeyAsObject(key);
> +        construct(key.byteValue());
>      }
>  
>      /** Constructor with class and key.
> @@ -57,7 +65,9 @@
>       * @param str the key
>       */
>      public ByteIdentity(Class pcClass, String str) {
> -        this (pcClass, Byte.parseByte(str));
> +        super(pcClass);
> +        assertKeyNotNull(str);
> +        construct(Byte.parseByte(str));
>      }
>  
>      /** Constructor only for Externalizable.
> @@ -94,6 +104,14 @@
>          }
>      }
>  
> +    /** Create the key as an Object.
> +     * @return the key as an Object
> +     * @since 2.0
> +     */
> +    protected Object createKeyAsObject() {
> +        return new Byte(key);
> +    }
> +
>      /** Write this object. Write the superclass first.
>       * @param out the output
>       */
> @@ -109,6 +127,5 @@
>  		throws IOException, ClassNotFoundException {
>          super.readExternal (in);
>          key = in.readByte ();
> -        hashCode = super.hashCode() ^ key;
>      }
>  }
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java Thu Jul  7 18:17:40 2005
> @@ -40,14 +40,18 @@
>       */
>      private char key;
>  
> +    private void construct(char key) {
> +        this.key = key;
> +        hashCode = hashClassName() ^ key;
> +    }
> +
>      /** Constructor with class and key.
>       * @param pcClass the target class
>       * @param key the key
>       */
>      public CharIdentity (Class pcClass, char key) {
>          super (pcClass);
> -        this.key = key;
> -        computeHashCode();
> +        construct(key);
>      }
>  
>      /** Constructor with class and key.
> @@ -55,7 +59,9 @@
>       * @param key the key
>       */
>      public CharIdentity (Class pcClass, Character key) {
> -        this (pcClass, key.charValue ());
> +        super (pcClass);
> +        setKeyAsObject(key);
> +        construct(key.charValue());
>      }
>  
>      /** Constructor with class and key. The String must have exactly one
> @@ -65,11 +71,11 @@
>       */
>      public CharIdentity (Class pcClass, String str) {
>          super(pcClass);
> +        assertKeyNotNull(str);
>          if (str.length() != 1) 
>              throw new IllegalArgumentException(
> -                    msg.msg("EXC_StringWrongLength"));
> -        this.key = str.charAt(0);
> -        computeHashCode();
> +                msg.msg("EXC_StringWrongLength")); //NOI18N
> +        construct(str.charAt(0));
>      }
>  
>      /** Constructor only for Externalizable.
> @@ -104,6 +110,14 @@
>              CharIdentity other = (CharIdentity) obj;
>              return key == other.key;
>          }
> +    }
> +
> +    /** Create the key as an Object.
> +     * @return the key as an Object
> +     * @since 2.0
> +     */
> +    protected Object createKeyAsObject() {
> +        return new Character(key);
>      }
>  
>      /** Write this object. Write the superclass first.
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java Thu Jul  7 18:17:40 2005
> @@ -29,16 +29,21 @@
>   * @version 2.0
>   */
>  public class IntIdentity extends SingleFieldIdentity {
> +
>      private int key;
>  
> +    private void construct(int key) {
> +        this.key = key;
> +        hashCode = hashClassName() ^ key;
> +    }
> +
>      /** Constructor with class and key.
>       * @param pcClass the class
>       * @param key the key
>       */
>      public IntIdentity (Class pcClass, int key) {
> -        super (pcClass);
> -        this.key = key;
> -        hashCode = hashClassName() ^ key;
> +        super(pcClass);
> +        construct(key);
>  	}
>  
>      /** Constructor with class and key.
> @@ -46,7 +51,9 @@
>       * @param key the key
>       */
>      public IntIdentity (Class pcClass, Integer key) {
> -        this (pcClass, key.intValue ());
> +        super(pcClass);
> +        setKeyAsObject(key);
> +        construct(key.intValue ());
>      }
>  
>  
> @@ -55,7 +62,9 @@
>       * @param str the key
>       */
>      public IntIdentity (Class pcClass, String str) {
> -        this (pcClass, Integer.parseInt(str));
> +        super(pcClass);
> +        assertKeyNotNull(str);
> +        construct(Integer.parseInt(str));
>      }
>  
>      /** Constructor only for Externalizable.
> @@ -92,6 +101,14 @@
>          }
>      }
>  
> +    /** Create the key as an Object.
> +     * @return the key as an Object
> +     * @since 2.0
> +     */
> +    protected Object createKeyAsObject() {
> +        return new Integer(key);
> +    }
> +
>      /** Write this object. Write the superclass first.
>       * @param out the output
>       */
> @@ -107,6 +124,5 @@
>  		throws IOException, ClassNotFoundException {
>          super.readExternal (in);
>          key = in.readInt();
> -        hashCode = hashClassName() ^ key;
>      }
>  }
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java Thu Jul  7 18:17:40 2005
> @@ -34,14 +34,18 @@
>       */
>      private long key;
>  
> +    private void construct(long key) {
> +        this.key = key;
> +        hashCode = hashClassName() ^ (int)key;
> +    }
> +
>      /** Constructor with class and key.
>       * @param pcClass the class
>       * @param key the key
>       */
>      public LongIdentity (Class pcClass, long key) {
>          super (pcClass);
> -        this.key = key;
> -        hashCode = hashClassName() ^ (int)key;
> +        construct(key);
>      }
>  
>      /** Constructor with class and key.
> @@ -49,7 +53,9 @@
>       * @param key the key
>       */
>      public LongIdentity (Class pcClass, Long key) {
> -        this (pcClass, key.longValue ());
> +        super(pcClass);
> +        setKeyAsObject(key);
> +        construct(key.longValue());
>      }
>  
>      /** Constructor with class and key.
> @@ -57,7 +63,9 @@
>       * @param str the key
>       */
>      public LongIdentity (Class pcClass, String str) {
> -        this (pcClass, Long.parseLong(str));
> +        super(pcClass);
> +        assertKeyNotNull(str);
> +        construct(Long.parseLong(str));
>      }
>  
>      /** Constructor only for Externalizable.
> @@ -94,6 +102,14 @@
>          }
>      }
>  
> +    /** Create the key as an Object.
> +     * @return the key as an Object
> +     * @since 2.0
> +     */
> +    protected Object createKeyAsObject() {
> +        return new Long(key);
> +    }
> +
>      /** Write this object. Write the superclass first.
>       * @param out the output
>       */
> @@ -109,6 +125,6 @@
>  		throws IOException, ClassNotFoundException {
>          super.readExternal (in);
>          key = in.readLong();
> -        hashCode = hashClassName() ^ (int)key;
>      }
> +
>  }
> 
> Added: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java?rev=209692&view=auto
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java (added)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java Thu Jul  7 18:17:40 2005
> @@ -0,0 +1,152 @@
> +/*
> + * 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.
> + */
> +
> +/*
> + * ObjectIdentity.java
> + *
> + */
> + 
> +package javax.jdo.identity;
> +
> +import java.io.IOException;
> +import java.io.ObjectInput;
> +import java.io.ObjectOutput;
> +
> +import java.security.AccessController;
> +import java.security.PrivilegedAction;
> +
> +import javax.jdo.JDOUserException;
> +
> +import javax.jdo.spi.JDOImplHelper;
> +
> +/** This class is for identity with a single Object type field.
> + * @version 2.0
> + */
> +public class ObjectIdentity extends SingleFieldIdentity {
> +    
> +    /** The key is stored in the superclass field keyAsObject.
> +     */
> +    
> +    /** The JDOImplHelper instance used for parsing the String to an Object.
> +     */
> +    private static JDOImplHelper helper = (JDOImplHelper)
> +        AccessController.doPrivileged(
> +            new PrivilegedAction () {
> +                public Object run () {
> +                    return JDOImplHelper.getInstance();
> +                }
> +            }
> +        );
> +    
> +    /** The delimiter for String constructor.
> +     */
> +    public static String STRING_DELIMITER = ":"; //NOI18N
> +    
> +    /** Constructor with class and key.
> +     * @param pcClass the class
> +     * @param param the key
> +     */
> +    public ObjectIdentity (Class pcClass, Object param) {
> +        super (pcClass);
> +        assertKeyNotNull(param);
> +        String paramString = null;
> +        String keyString = null;
> +        String className = null;
> +        if (param instanceof String) {
> +            /* The paramString is of the form "<className>:<keyString>" */
> +            paramString = (String)param;
> +            if (paramString.length() < 3) {
> +                throw new JDOUserException(
> +                    msg.msg("EXC_ObjectIdentityStringConstructionTooShort") + //NOI18N
> +                    msg.msg("EXC_ObjectIdentityStringConstructionUsage", //NOI18N
> +                        paramString));
> +            }
> +            int indexOfDelimiter = paramString.indexOf(STRING_DELIMITER);
> +            if (indexOfDelimiter < 0) {
> +                throw new JDOUserException(
> +                    msg.msg("EXC_ObjectIdentityStringConstructionNoDelimiter") + //NOI18N
> +                    msg.msg("EXC_ObjectIdentityStringConstructionUsage", //NOI18N
> +                        paramString));
> +            }
> +            keyString = paramString.substring(indexOfDelimiter+1);
> +            className = paramString.substring(0, indexOfDelimiter);
> +            keyAsObject = helper.construct(className, keyString);
> +        } else {
> +            keyAsObject = param;
> +        }
> +        hashCode = hashClassName() ^ keyAsObject.hashCode();
> +    }
> +
> +    /** Constructor only for Externalizable.
> +     */
> +    public ObjectIdentity () {
> +    }
> +
> +    /** Return the key.
> +     * @return the key
> +     */
> +    public Object getKey () {
> +        return keyAsObject;
> +    }
> +
> +    /** Return the String form of the object id. The class of the
> +     * object id is written as the first part of the result so that
> +     * the class can be reconstructed later. Then the toString
> +     * of the key instance is appended. During construction, 
> +     * this process is reversed. The class is extracted from 
> +     * the first part of the String, and the String constructor
> +     * of the key is used to construct the key itself.
> +     * @return the String form of the key
> +     */
> +    public String toString () {
> +        return keyAsObject.getClass().getName()
> +                + STRING_DELIMITER
> +                + keyAsObject.toString();
> +    }
> +
> +    /** Determine if the other object represents the same object id.
> +     * @param obj the other object
> +     * @return true if both objects represent the same object id
> +     */
> +    public boolean equals (Object obj) {
> +        if (this == obj) {
> +            return true;
> +        } else if (!super.equals (obj)) {
> +            return false;
> +        } else {
> +            ObjectIdentity other = (ObjectIdentity) obj;
> +            return keyAsObject.equals(other.keyAsObject);
> +        }
> +    }
> +
> +    /** Write this object. Write the superclass first.
> +     * @param out the output
> +     */
> +    public void writeExternal(ObjectOutput out) throws IOException {
> +        super.writeExternal (out);
> +        out.writeObject(keyAsObject);
> +    }
> +
> +    /** Read this object. Read the superclass first.
> +     * @param in the input
> +     */
> +    public void readExternal(ObjectInput in)
> +		throws IOException, ClassNotFoundException {
> +        super.readExternal (in);
> +        keyAsObject = in.readObject();
> +    }
> +    
> +}
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java Thu Jul  7 18:17:40 2005
> @@ -33,15 +33,18 @@
>  {
>  	private short key;
>  
> +    private void construct(short key) {
> +        this.key = key;
> +        hashCode = hashClassName() ^ key;
> +    }
>  
>      /** Constructor with class and key.
>       * @param pcClass the class
>       * @param key the key
>       */
>      public ShortIdentity (Class pcClass, short key) {
> -        super (pcClass);
> -        this.key = key;
> -        hashCode = hashClassName() ^ key;
> +        super(pcClass);
> +        construct(key);
>      }
>  
>      /** Constructor with class and key.
> @@ -49,7 +52,9 @@
>       * @param key the key
>       */
>      public ShortIdentity (Class pcClass, Short key) {
> -        this (pcClass, key.shortValue ());
> +        super(pcClass);
> +        setKeyAsObject(key);
> +        construct(key.shortValue());
>      }
>  
>      /** Constructor with class and key.
> @@ -57,7 +62,9 @@
>       * @param str the key
>       */
>      public ShortIdentity (Class pcClass, String str) {
> -        this (pcClass, Short.parseShort (str));
> +        super(pcClass);
> +        assertKeyNotNull(str);
> +        construct(Short.parseShort (str));
>      }
>  
>      /** Constructor only for Externalizable.
> @@ -94,6 +101,14 @@
>          }
>      }
>  
> +    /** Create the key as an Object.
> +     * @return the key as an Object
> +     * @since 2.0
> +     */
> +    protected Object createKeyAsObject() {
> +        return new Short(key);
> +    }
> +
>      /** Write this object. Write the superclass first.
>       * @param out the output
>       */
> @@ -109,6 +124,5 @@
>  		throws IOException, ClassNotFoundException {
>          super.readExternal (in);
>          key = in.readShort();
> -        hashCode = hashClassName() ^ key;
>      }
>  }
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java Thu Jul  7 18:17:40 2005
> @@ -26,6 +26,11 @@
>  import java.io.ObjectInput;
>  import java.io.ObjectOutput;
>  
> +import javax.jdo.JDOFatalInternalException;
> +import javax.jdo.JDONullIdentityException;
> +
> +import javax.jdo.spi.I18NHelper;
> +
>  /** This class is the abstract base class for all single field identity
>   * classes. A common case of application identity uses exactly one 
>   * persistent field in the class to represent identity. In this case, 
> @@ -36,6 +41,10 @@
>  public abstract class SingleFieldIdentity
>      implements Externalizable {
>      
> +    /** The Internationalization message helper.
> +     */
> +    protected static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N
> +
>      /** The class of the target object.
>       */
>      transient private Class targetClass;
> @@ -47,6 +56,10 @@
>      /** The hashCode.
>       */
>      protected int hashCode;
> +    
> +    /** The key as an Object.
> +     */
> +    protected Object keyAsObject;
>  
>      /** Constructor with target class.
>       * @param pcClass the class of the target
> @@ -64,6 +77,24 @@
>      public SingleFieldIdentity () {
>      }
>  
> +    /** Set the given key as the key for this instance. 
> +     * Compute the hash code for the instance.
> +     */
> +    protected void setKeyAsObject(Object key) {
> +        assertKeyNotNull(key);
> +        keyAsObject = key;
> +    }
> +
> +    /** Assert that the key is not null. Throw a JDONullIdentityException
> +     * if the given key is null.
> +     */ 
> +    protected void assertKeyNotNull(Object key) {
> +        if (key == null) {
> +            throw new JDONullIdentityException(
> +                msg.msg("EXC_SingleFieldIdentityNullParameter")); //NOI18N
> +        }
> +    }
> +    
>      /** Return the target class.
>       * @return the target class.
>       * @since 2.0
> @@ -80,6 +111,27 @@
>          return targetClassName;
>      }
>  
> +    /** Return the key as an Object. The method is synchronized to avoid
> +     * race conditions in multi-threaded environments.
> +     * @return the key as an Object.
> +     * @since 2.0
> +     */
> +    public synchronized Object getKeyAsObject() {
> +        if (keyAsObject == null) {
> +            keyAsObject = createKeyAsObject();
> +        }
> +        return keyAsObject;
> +    }
> +    
> +    /** Create the key as an Object.
> +     * @return the key as an Object;
> +     * @since 2.0
> +     */
> +    protected Object createKeyAsObject() {
> +        throw new JDOFatalInternalException
> +                (msg.msg("EXC_CreateKeyAsObjectMustNotBeCalled"));
> +    }
> +    
>      /** Check the class and class name and object type. If restored
>       * from serialization, class will be null so compare class name.
>       * @param obj the other object
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java Thu Jul  7 18:17:40 2005
> @@ -25,25 +25,23 @@
>  import java.io.ObjectInput;
>  import java.io.ObjectOutput;
>  
> +import javax.jdo.JDOUserException;
> +
>  /** This class is for identity with a single String field.
>   * @version 2.0
>   */
>  public class StringIdentity extends SingleFieldIdentity {
>      
> -    /** The key.
> +    /** The key is stored in the superclass field keyAsObject.
>       */
> -    private String key;
> -
> -
> +    
>      /** Constructor with class and key.
>       * @param pcClass the class
>       * @param key the key
>       */
>      public StringIdentity (Class pcClass, String key) {
>          super (pcClass);
> -        if (key == null)
> -            throw new NullPointerException ();
> -        this.key = key;
> +        setKeyAsObject(key);
>          hashCode = hashClassName() ^ key.hashCode();
>      }
>  
> @@ -56,14 +54,14 @@
>       * @return the key
>       */
>      public String getKey () {
> -        return key;
> +        return (String)keyAsObject;
>      }
>  
>      /** Return the String form of the key.
>       * @return the String form of the key
>       */
>      public String toString () {
> -        return key;
> +        return (String)keyAsObject;
>      }
>  
>      /** Determine if the other object represents the same object id.
> @@ -77,7 +75,7 @@
>              return false;
>          } else {
>              StringIdentity other = (StringIdentity) obj;
> -            return key.equals(other.key);
> +            return keyAsObject.equals(other.keyAsObject);
>          }
>      }
>  
> @@ -86,7 +84,7 @@
>       */
>      public void writeExternal(ObjectOutput out) throws IOException {
>          super.writeExternal (out);
> -        out.writeObject(key);
> +        out.writeObject(keyAsObject);
>      }
>  
>      /** Read this object. Read the superclass first.
> @@ -95,7 +93,6 @@
>      public void readExternal(ObjectInput in)
>  		throws IOException, ClassNotFoundException {
>          super.readExternal (in);
> -        key = (String)in.readObject();
> -        hashCode = hashClassName() ^ key.hashCode();
> +        keyAsObject = (String)in.readObject();
>      }
>  }
> 
> 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=209692&r1=209691&r2=209692&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 Thu Jul  7 18:17:40 2005
> @@ -21,18 +21,29 @@
>  
>  package javax.jdo.spi;
>  
> +import java.lang.reflect.Constructor;
> +
> +import java.text.DateFormat;
> +import java.text.ParsePosition;
> +import java.text.SimpleDateFormat;
> +
>  import java.util.ArrayList;
>  import java.util.Collection;
>  import java.util.Collections;
> +import java.util.Currency;
> +import java.util.Date;
>  import java.util.HashMap;
>  import java.util.HashSet;
>  import java.util.Iterator;
>  import java.util.List;
> +import java.util.Locale;
>  import java.util.Map;
>  import java.util.WeakHashMap;
>  
> +import javax.jdo.JDOException;
>  import javax.jdo.JDOFatalInternalException;
>  import javax.jdo.JDOFatalUserException;
> +import javax.jdo.JDOUserException;
>  import javax.jdo.spi.JDOPermission;
>  
>  /** This class is a helper class for JDO implementations.  It contains methods
> @@ -76,8 +87,16 @@
>      
>      /** The Internationalization message helper.
>       */
> -    private final static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle");
> +    private final static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N
>      
> +    /** The default DateFormat instance.
> +     */
> +    static DateFormat dateFormat = DateFormat.getDateTimeInstance();
> +
> +    /** The DateFormat pattern, set to the default.
> +     */
> +    static String dateFormatPattern = "MMM d, yyyy hh:mm:ss a";  //NOI18N
> +
>      /** Creates new JDOImplHelper */
>      private JDOImplHelper() {
>      }
> @@ -267,7 +286,7 @@
>              byte[] fieldFlags, Class persistenceCapableSuperclass,
>              PersistenceCapable pc) {
>          if (pcClass == null) 
> -            throw new NullPointerException(msg.msg("ERR_NullClass"));
> +            throw new NullPointerException(msg.msg("ERR_NullClass")); //NOI18N
>          Meta meta = new Meta (fieldNames, fieldTypes, 
>              fieldFlags, persistenceCapableSuperclass, pc);
>          registeredClasses.put (pcClass, meta);
> @@ -333,7 +352,7 @@
>      public void unregisterClass (Class pcClass)
>      {
>          if (pcClass == null) 
> -            throw new NullPointerException(msg.msg("ERR_NullClass"));
> +            throw new NullPointerException(msg.msg("ERR_NullClass")); //NOI18N
>          SecurityManager sec = System.getSecurityManager();
>          if (sec != null) { 
>              // throws exception if caller is not authorized
> @@ -413,7 +432,7 @@
>      public static void registerAuthorizedStateManagerClass (Class smClass) 
>          throws SecurityException {
>          if (smClass == null) 
> -            throw new NullPointerException(msg.msg("ERR_NullClass"));
> +            throw new NullPointerException(msg.msg("ERR_NullClass")); //NOI18N
>          SecurityManager sm = System.getSecurityManager();
>          if (sm != null) {
>              sm.checkPermission(JDOPermission.SET_STATE_MANAGER);
> @@ -442,7 +461,7 @@
>                      Object smClass = it.next();
>                      if (!(smClass instanceof Class)) {
>                          throw new ClassCastException(
> -                            msg.msg("ERR_StateManagerClassCast", 
> +                            msg.msg("ERR_StateManagerClassCast", //NOI18N
>                                  smClass.getClass().getName()));
>                      }
>                      registerAuthorizedStateManagerClass((Class)it.next());
> @@ -484,9 +503,141 @@
>                  return;
>              }
>          }
> -
>          // if not already authorized, perform "long" security checking.
>          scm.checkPermission(JDOPermission.SET_STATE_MANAGER);
> +    }
> +
> +    /** 
> +     * Construct an instance of a key class using a String as input.
> +     * This is a helper interface for use with ObjectIdentity.
> +     * Classes without a String constructor (such as those in java.lang
> +     * and java.util) will use this interface for constructing new instances.
> +     * The result might be a singleton or use some other strategy.
> +     */
> +    public interface StringConstructor {
> +        /**
> +         * Construct an instance of the class for which this instance
> +         * is registered.
> +         * @param s the parameter for construction
> +         * @return the constructed object
> +         */
> +        public Object construct(String s);
> +    }
> +    
> +    /** 
> +     * Special StringConstructor instances for use with specific
> +     * classes that have no public String constructor. The Map is
> +     * keyed on class instance and the value is an instance of 
> +     * StringConstructor.
> +     */
> +    static Map stringConstructorMap = new HashMap();
> +
> +    /**
> +     * 
> +     * Register special StringConstructor instances. These instances
> +     * are for constructing instances from String parameters where there
> +     * is no String constructor for them.
> +     * @param cls the class to register a StringConstructor for
> +     * @param sc the StringConstructor instance
> +     * @return the previous StringConstructor registered for this class
> +     */
> +    public Object registerStringConstructor(Class cls, StringConstructor sc) {
> +        return stringConstructorMap.put(cls, sc);
> +    }
> +
> +    /** Register the default special StringConstructor instances.
> +     */
> +    static {
> +        JDOImplHelper helper = getInstance();
> +        helper.registerStringConstructor(Currency.class, new StringConstructor() {
> +            public Object construct(String s) {
> +                try {
> +                    return Currency.getInstance(s);
> +                } catch (IllegalArgumentException ex) {
> +                    throw new javax.jdo.JDOUserException(
> +                        msg.msg("EXC_CurrencyStringConstructorIllegalArgument", s), ex); //NOI18N
> +                } catch (Exception ex) {
> +                    throw new JDOUserException(
> +                        msg.msg("EXC_CurrencyStringConstructorException"), ex); //NOI18N
> +                }
> +            }
> +        });
> +        helper.registerStringConstructor(Locale.class, new StringConstructor() {
> +            public Object construct(String s) {
> +                try {
> +                    return new Locale(s);
> +                } catch (Exception ex) {
> +                    throw new JDOUserException(
> +                        msg.msg("EXC_LocaleStringConstructorException"), ex); //NOI18N
> +                }
> +            }
> +        });
> +        helper.registerStringConstructor(Date.class, new StringConstructor() {
> +            public synchronized Object construct(String s) {
> +                ParsePosition pp = new ParsePosition(0);
> +                Date result = dateFormat.parse(s, pp);
> +                if (result == null) {
> +                    throw new JDOUserException (
> +                        msg.msg("EXC_DateStringConstructor", new Object[] //NOI18N
> +                        {s, new Integer(pp.getErrorIndex()), dateFormatPattern}));
> +                }
> +                return result;
> +            }
> +        });
> +    }
> +    
> +    /**
> +     * Construct an instance of the parameter class, using the keyString
> +     * as an argument to the constructor. If the class has a StringConstructor
> +     * instance registered, use it. If not, try to find a constructor for
> +     * the class with a single String argument. Otherwise, throw a
> +     * JDOUserException.
> +     * @param className the name of the class
> +     * @param keyString the String parameter for the constructor
> +     * @return the result of construction
> +     */
> +    public Object construct(String className, String keyString) {
> +        synchronized(stringConstructorMap) {
> +            try {
> +                Class keyClass = Class.forName(className);
> +                StringConstructor stringConstructor = 
> +                        (StringConstructor) stringConstructorMap.get(keyClass);
> +                if (stringConstructor == null) {
> +                    Constructor keyConstructor = 
> +                        keyClass.getConstructor(new Class[]{String.class});
> +                    return keyConstructor.newInstance(new Object[]{keyString});
> +                } else {
> +                    return stringConstructor.construct(keyString);
> +                }
> +            } catch (JDOException ex) {
> +                throw ex;
> +            } catch (Exception ex) {
> +                 /* ClassNotFoundException,
> +                    NoSuchMethodException,
> +                    InstantiationException,
> +                    IllegalAccessException,
> +                    InvocationTargetException */
> +                throw new JDOUserException(
> +                    msg.msg("EXC_ObjectIdentityStringConstruction",  //NOI18N
> +                    new Object[] {ex.toString(), className, keyString}), ex);
> +            }
> +        }
> +    }
> +
> +    /**
> +     * Register a DateFormat instance for use with constructing Date 
> +     * instances. The default is the default DateFormat instance.
> +     * If the new instance implements SimpleDateFormat, get its pattern
> +     * for error messages.
> +     * @param df the DateFormat instance to use
> +     */
> +    synchronized void registerDateFormat(DateFormat df) {
> +        dateFormat = df;
> +        if (df instanceof SimpleDateFormat) {
> +            dateFormatPattern = ((SimpleDateFormat)df).toPattern();
> +        } else {
> +            dateFormatPattern = msg.msg("MSG_unknown"); //NOI18N
> +        }
>      }
>  
>      /** This is a helper class to manage metadata per persistence-capable
> 
> Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java (original)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -21,6 +21,8 @@
>  
>  package javax.jdo.identity;
>  
> +import javax.jdo.JDONullIdentityException;
> +
>  import javax.jdo.util.BatchTestRunner;
>  
>  /**
> @@ -95,4 +97,33 @@
>          assertFalse ("Not equal ByteIdentity instances compare equal.", sc1.equals(sc3));
>          assertFalse ("Not equal ByteIdentity instances compare equal.", sc3.equals(sc1));
>      }
> +    
> +    public void testGetKeyAsObjectPrimitive() {
> +        ByteIdentity c1 = new ByteIdentity(Object.class, (byte)1);
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Byte((byte)1));
> +    }
> +
> +    public void testGetKeyAsObject() {
> +        ByteIdentity c1 = new ByteIdentity(Object.class, new Byte((byte)1));
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Byte((byte)1));
> +    }
> +
> +    public void testBadConstructorNullByteParam() {
> +        try {
> +            ByteIdentity c1 = new ByteIdentity(Object.class, (Byte)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
> +    public void testBadConstructorNullStringParam() {
> +        try {
> +            ByteIdentity c1 = new ByteIdentity(Object.class, (String)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
>  }
> 
> Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java (original)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -21,6 +21,8 @@
>  
>  package javax.jdo.identity;
>  
> +import javax.jdo.JDONullIdentityException;
> +
>  import javax.jdo.util.BatchTestRunner;
>  
>  /**
> @@ -105,4 +107,32 @@
>          assertFalse ("Not equal CharIdentity instances compare equal.", sc1.equals(sc3));
>          assertFalse ("Not equal CharIdentity instances compare equal.", sc3.equals(sc1));
>      }
> +    public void testGetKeyAsObjectPrimitive() {
> +        CharIdentity c1 = new CharIdentity(Object.class, '1');
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Character('1'));
> +    }
> +
> +    public void testGetKeyAsObject() {
> +        CharIdentity c1 = new CharIdentity(Object.class, new Character('1'));
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Character('1'));
> +    }
> +
> +    public void testBadConstructorNullCharacterParam() {
> +        try {
> +            CharIdentity c1 = new CharIdentity(Object.class, (Character)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
> +    public void testBadConstructorNullStringParam() {
> +        try {
> +            CharIdentity c1 = new CharIdentity(Object.class, (String)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
>  }
> 
> Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java (original)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -21,6 +21,8 @@
>  
>  package javax.jdo.identity;
>  
> +import javax.jdo.JDONullIdentityException;
> +
>  import javax.jdo.util.BatchTestRunner;
>  
>  /**
> @@ -95,4 +97,32 @@
>          assertFalse ("Not equal IntIdentity instances compare equal.", sc1.equals(sc3));
>          assertFalse ("Not equal IntIdentity instances compare equal.", sc3.equals(sc1));
>      }
> +    public void testGetKeyAsObjectPrimitive() {
> +        IntIdentity c1 = new IntIdentity(Object.class, 1);
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Integer(1));
> +    }
> +
> +    public void testGetKeyAsObject() {
> +        IntIdentity c1 = new IntIdentity(Object.class, new Integer(1));
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Integer(1));
> +    }
> +
> +    public void testBadConstructorNullIntegerParam() {
> +        try {
> +            IntIdentity c1 = new IntIdentity(Object.class, (Integer)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
> +    public void testBadConstructorNullStringParam() {
> +        try {
> +            IntIdentity c1 = new IntIdentity(Object.class, (String)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
>  }
> 
> Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java (original)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -21,6 +21,8 @@
>  
>  package javax.jdo.identity;
>  
> +import javax.jdo.JDONullIdentityException;
> +
>  import javax.jdo.util.BatchTestRunner;
>  
>  /**
> @@ -95,4 +97,33 @@
>          assertFalse ("Not equal LongIdentity instances compare equal.", sc1.equals(sc3));
>          assertFalse ("Not equal LongIdentity instances compare equal.", sc3.equals(sc1));
>      }
> +    
> +    public void testGetKeyAsObjectPrimitive() {
> +        LongIdentity c1 = new LongIdentity(Object.class, 1L);
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Long(1L));
> +    }
> +
> +    public void testGetKeyAsObject() {
> +        LongIdentity c1 = new LongIdentity(Object.class, new Long(1L));
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Long(1L));
> +    }
> +
> +    public void testBadConstructorNullShortParam() {
> +        try {
> +            LongIdentity c1 = new LongIdentity(Object.class, (Long)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
> +    public void testBadConstructorNullStringParam() {
> +        try {
> +            LongIdentity c1 = new LongIdentity(Object.class, (String)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
>  }
> 
> Added: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java?rev=209692&view=auto
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java (added)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -0,0 +1,369 @@
> +/*
> + * 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.
> + */
> +
> +/*
> + * ObjectIdentityTest.java
> + *
> + */
> +
> +package javax.jdo.identity;
> +
> +import java.lang.reflect.Constructor;
> +import java.lang.reflect.InvocationTargetException;
> +
> +import java.io.Serializable;
> +
> +import java.math.BigDecimal;
> +import java.util.Currency;
> +import java.util.Date;
> +import java.util.Locale;
> +
> +import javax.jdo.JDOUserException;
> +import javax.jdo.JDONullIdentityException;
> +import javax.jdo.util.BatchTestRunner;
> +
> +/**
> + *
> + */
> +public class ObjectIdentityTest extends SingleFieldIdentityTest {
> +    
> +    /** Creates a new instance of ObjectIdentityTest */
> +    public ObjectIdentityTest() {
> +    }
> +    
> +    /**
> +     * @param args the command line arguments
> +     */
> +    public static void main(String[] args) {
> +        BatchTestRunner.run(ObjectIdentityTest.class);
> +    }
> +    
> +    public void testConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new IdClass(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new IdClass(1));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new IdClass(2));
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testIntegerConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Integer(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Integer(1));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Integer(2));
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testLongConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Long(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Long(1));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Long(2));
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testDateConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Date(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Date(1));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Date(2));
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testLocaleConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, Locale.US);
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, Locale.US);
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, Locale.GERMANY);
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testCurrencyConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                Currency.getInstance(Locale.US));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, 
> +                Currency.getInstance(Locale.US));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, 
> +                Currency.getInstance(Locale.GERMANY));
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testStringConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                "javax.jdo.identity.ObjectIdentityTest$IdClass:1");        
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, 
> +                "javax.jdo.identity.ObjectIdentityTest$IdClass:1");        
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, 
> +                "javax.jdo.identity.ObjectIdentityTest$IdClass:2");        
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testToStringConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new IdClass(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, c1.toString());
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +    }
> +
> +    public void testBadStringConstructorNullClass() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(null, "1");
> +        } catch (NullPointerException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +    
> +    public void testBadStringConstructorNullParam() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +    
> +    public void testBadStringConstructorTooShort() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, "xx");
> +        } catch (JDOUserException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +    
> +    public void testBadStringConstructorNoDelimiter() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, "xxxxxxxxx");
> +        } catch (JDOUserException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +    
> +    public void testBadStringConstructorBadClassName() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, "xx:yy");
> +        } catch (JDOUserException ex) {
> +            validateNestedException(ex, ClassNotFoundException.class);
> +            return;
> +        }
> +        fail ("Failed to catch expected ClassNotFoundException.");
> +    }
> +    
> +    public void testBadStringConstructorNoStringConstructor() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                    "javax.jdo.identity.ObjectIdentityTest$BadIdClassNoStringConstructor:yy");
> +        } catch (JDOUserException ex) {
> +            validateNestedException(ex, NoSuchMethodException.class);
> +            return;
> +        }
> +        fail ("Failed to catch expected NoSuchMethodException.");
> +    }
> +    
> +    public void testBadStringConstructorNoPublicStringConstructor() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                    "javax.jdo.identity.ObjectIdentityTest$BadIdClassNoPublicStringConstructor:yy");
> +        } catch (JDOUserException ex) {
> +            validateNestedException(ex, NoSuchMethodException.class);
> +            return;
> +        }
> +        fail ("Failed to catch expected NoSuchMethodException.");
> +    }
> +    
> +    public void testBadStringConstructorIllegalArgument() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                    "javax.jdo.identity.ObjectIdentityTest$IdClass:yy");
> +        } catch (JDOUserException ex) {
> +            validateNestedException(ex, InvocationTargetException.class);
> +            return;
> +        }
> +        fail ("Failed to catch expected InvocationTargetException.");
> +    }
> +
> +    public void testStringDateConstructor() {
> +        Object c1 = new ObjectIdentity(Object.class, 
> +            "java.util.Date:Jan 01, 1970 00:00:00 AM");
> +    }
> +
> +    public void testBadStringDateConstructor() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                "java.util.Date:Jop 1, 1970 00:00:00");
> +        } catch (JDOUserException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected Exception.");
> +    }
> +
> +    public void testStringLocaleConstructor() {
> +        Object c1 = new ObjectIdentity(Object.class, 
> +                    "java.util.Locale:en_us");
> +    }
> +
> +    public void testStringCurrencyConstructor() {
> +        Object c1 = new ObjectIdentity(Object.class, 
> +                    "java.util.Currency:USD");
> +    }
> +
> +    public void testBadStringCurrencyConstructor() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                    "java.util.Currency:NowhereInTheWorld");
> +        } catch (JDOUserException ex) {
> +            validateNestedException(ex, IllegalArgumentException.class);
> +            return;
> +        }
> +        fail ("Failed to catch expected IllegalArgumentException.");
> +    }
> +
> +    public void testSerializedIdClass() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new IdClass(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new IdClass(1));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new IdClass(2));
> +        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
> +        Object sc1 = scis[0];
> +        Object sc2 = scis[1];
> +        Object sc3 = scis[2];
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
> +    }
> +    
> +    public void testSerializedBigDecimal() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new BigDecimal("123456789.012"));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new BigDecimal("123456789.012"));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new BigDecimal("123456789.01"));
> +        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
> +        Object sc1 = scis[0];
> +        Object sc2 = scis[1];
> +        Object sc3 = scis[2];
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
> +    }
> +    
> +    public void testSerializedCurrency() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, Currency.getInstance(Locale.US));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, Currency.getInstance(Locale.US));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, Currency.getInstance(Locale.GERMANY));
> +        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
> +        Object sc1 = scis[0];
> +        Object sc2 = scis[1];
> +        Object sc3 = scis[2];
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
> +    }
> +    
> +    public void testSerializedDate() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Date(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Date(1));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Date(2));
> +        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
> +        Object sc1 = scis[0];
> +        Object sc2 = scis[1];
> +        Object sc3 = scis[2];
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
> +    }
> +    
> +    public void testSerializedLocale() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Locale("EN_US"));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Locale("en_us"));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Locale("EN_GB"));
> +        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
> +        Object sc1 = scis[0];
> +        Object sc2 = scis[1];
> +        Object sc3 = scis[2];
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
> +    }
> +    
> +    public void testGetKeyAsObject() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new IdClass(1));
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new IdClass(1));
> +    }
> +
> +    private void validateNestedException(JDOUserException ex, Class expected) {
> +        Throwable[] nesteds = ex.getNestedExceptions();
> +        if (nesteds == null || nesteds.length == 0) {
> +            fail ("Nested exception is null or length 0");
> +        }
> +        Throwable nested = nesteds[0];
> +        if (!(expected.isAssignableFrom(nested.getClass()))) {
> +            fail ("Wrong nested exception. Expected ClassNotFoundException, got "
> +                    + nested.toString());
> +        }
> +        return;
> +    }
> +    public static class IdClass implements Serializable {
> +        public int value;
> +        public IdClass() {value = 0;}
> +        public IdClass(int value) {this.value = value;}
> +        public IdClass(String str) {this.value = Integer.parseInt(str);}
> +        public String toString() {return Integer.toString(value);}
> +        public int hashCode() {
> +            return value;
> +        }
> +        public boolean equals (Object obj) {
> +            if (this == obj) {
> +                return true;
> +            } else {
> +                IdClass other = (IdClass) obj;
> +                return value == other.value;
> +            }
> +        }
> +    }
> +    
> +    public static class BadIdClassNoStringConstructor {
> +    }
> +    
> +    public static class BadIdClassNoPublicStringConstructor {
> +        private BadIdClassNoPublicStringConstructor(String str) {}
> +    }
> +}
> 
> Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java (original)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -21,6 +21,8 @@
>  
>  package javax.jdo.identity;
>  
> +import javax.jdo.JDONullIdentityException;
> +
>  import javax.jdo.util.BatchTestRunner;
>  
>  /**
> @@ -95,4 +97,32 @@
>          assertFalse ("Not equal ShortIdentity instances compare equal.", sc1.equals(sc3));
>          assertFalse ("Not equal ShortIdentity instances compare equal.", sc3.equals(sc1));
>      }
> +    public void testGetKeyAsObjectPrimitive() {
> +        ShortIdentity c1 = new ShortIdentity(Object.class, (short)1);
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Short((short)1));
> +    }
> +
> +    public void testGetKeyAsObject() {
> +        ShortIdentity c1 = new ShortIdentity(Object.class, new Short((short)1));
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Short((short)1));
> +    }
> +
> +    public void testBadConstructorNullShortParam() {
> +        try {
> +            ShortIdentity c1 = new ShortIdentity(Object.class, (Short)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
> +    public void testBadConstructorNullStringParam() {
> +        try {
> +            ShortIdentity c1 = new ShortIdentity(Object.class, (String)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
>  }
> 
> Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java (original)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -21,6 +21,9 @@
>  
>  package javax.jdo.identity;
>  
> +import javax.jdo.JDONullIdentityException;
> +import javax.jdo.JDOUserException;
> +
>  import javax.jdo.util.BatchTestRunner;
>  
>  /**
> @@ -70,4 +73,19 @@
>          assertFalse ("Not equal StringIdentity instances compare equal.", sc1.equals(sc3));
>          assertFalse ("Not equal StringIdentity instances compare equal.", sc3.equals(sc1));
>      }
> +
> +    public void testGetKeyAsObject() {
> +        StringIdentity c1 = new StringIdentity(Object.class, "1");
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), "1");
> +    }
> +
> +    public void testBadConstructorNullParam() {
> +        try {
> +            StringIdentity c1 = new StringIdentity(Object.class, null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
>  }
> 


-- 
-------------------------------------------------------------------
Michael Watzek                  Tech@Spree Engineering GmbH
mailto:mwa.tech@spree.de        Buelowstr. 66
Tel.:  ++49/30/235 520 36       10783 Berlin - Germany
Fax.:  ++49/30/217 520 12       http://www.spree.de/
-------------------------------------------------------------------

Re: svn commit: r209692 - in /incubator/jdo/trunk/api20: src/java/javax/jdo/ src/java/javax/jdo/identity/ src/java/javax/jdo/spi/ test/java/javax/jdo/identity/

Posted by Michael Watzek <mw...@spree.de>.
Hi Craig,

I have updated my api20 workspace today and called "maven -o rebuild". 
The ObjectIdentityTest prints an error (see below). I'm not sure, why I 
do not see the error stacktrace.

Regards,
Michael

...
test:test:
     [junit] Running javax.jdo.identity.ByteIdentityTest
     [junit] Tests run: 10, Failures: 0, Errors: 0, Time elapsed: 0,094 sec
     [junit] Running javax.jdo.identity.CharIdentityTest
     [junit] Tests run: 11, Failures: 0, Errors: 0, Time elapsed: 0,031 sec
     [junit] Running javax.jdo.identity.IntIdentityTest
     [junit] Tests run: 10, Failures: 0, Errors: 0, Time elapsed: 0,032 sec
     [junit] Running javax.jdo.identity.LongIdentityTest
     [junit] Tests run: 10, Failures: 0, Errors: 0, Time elapsed: 0,047 sec
     [junit] Running javax.jdo.identity.ObjectIdentityTest
     [junit] Tests run: 28, Failures: 0, Errors: 1, Time elapsed: 0,125 sec
     [junit] [ERROR] TEST javax.jdo.identity.ObjectIdentityTest FAILED
     [junit] Running javax.jdo.identity.ShortIdentityTest
     [junit] Tests run: 10, Failures: 0, Errors: 0, Time elapsed: 0,032 sec
     [junit] Running javax.jdo.identity.SingleFieldIdentityTest
     [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0,032 sec
     [junit] Running javax.jdo.identity.StringIdentityTest
     [junit] Tests run: 5, Failures: 0, Errors: 0, Time elapsed: 0,031 sec
     [junit] Running javax.jdo.JDOHelperTest
     [junit] Tests run: 30, Failures: 0, Errors: 0, Time elapsed: 0,093 sec
     [junit] Running javax.jdo.listener.InstanceLifecycleEventTest
     [junit] Tests run: 10, Failures: 0, Errors: 0, Time elapsed: 0,016 sec
     [junit] Running javax.jdo.spi.JDOImplHelperTest
     [junit] Tests run: 8, Failures: 0, Errors: 0, Time elapsed: 0,047 sec

BUILD FAILED
File...... F:\users\brazil\.maven\cache\maven-test-plugin-1.6.2\plugin.jelly
Element... fail
Line...... 181
Column.... 54
There were test failures.
Total time: 10 seconds
Finished at: Fri Jul 08 11:01:47 CEST 2005

> Author: clr
> Date: Thu Jul  7 18:17:40 2005
> New Revision: 209692
> 
> URL: http://svn.apache.org/viewcvs?rev=209692&view=rev
> Log:
> JDO-76 added required methods to SingleFieldIdentity classes; added ObjectIdentity class for non-wrapper identity fields
> 
> Added:
>     incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java
> Modified:
>     incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java
>     incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOImplHelper.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java
>     incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/Bundle.properties Thu Jul  7 18:17:40 2005
> @@ -56,9 +56,10 @@
>  has the wrong return type for the getPersistenceManagerFactory(Map props) method.
>  EXC_StringWrongLength: There must be exactly one character in the id in the input String for CharIdentity.
>  EXC_IllegalEventType:The event type is outside the range of valid event types.
> -EXC_ObjectIdentityStringConstruction: The instance could not be constructed from \
> -the parameter String "{0}". \nThe exception thrown was: "{1}". \n\
> -Parsing the class name as "{2}" and key as "{3}".
> +EXC_SingleFieldIdentityNullParameter: The identity must not be null.
> +EXC_ObjectIdentityStringConstruction: The identity instance could not be constructed. \
> +\nThe exception thrown was: "{0}". \
> +\nParsed the class name as "{1}" and key as "{2}".
>  EXC_ObjectIdentityStringConstructionNoDelimiter: Missing delimiter ":".
>  EXC_ObjectIdentityStringConstructionTooShort: Parameter is too short.
>  EXC_ObjectIdentityStringConstructionUsage: The instance could not be constructed \
> @@ -66,3 +67,12 @@
>  \nThe parameter String is of the form "<className>:<keyString>".
>  EXC_CreateKeyAsObjectMustNotBeCalled: The method createKeyAsObject must not be called \
>  because the keyAsObject field must never be null for this class.
> +EXC_CurrencyStringConstructorIllegalArgument: The instance could not be constructed \
> +with the argument "{0}". Try "USD".
> +EXC_CurrencyStringConstructorException: An exception was thrown during construction \
> +of the Currency instance.
> +EXC_LocaleStringConstructorException: An exception was thrown during construction \
> +of the Locale instance.
> +EXC_DateStringConstructor: Error parsing Date string "{0}" at position {1} \
> +using date format "{2}".
> +MSG_unknown: unknown
> 
> Added: incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java?rev=209692&view=auto
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java (added)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/JDONullIdentityException.java Thu Jul  7 18:17:40 2005
> @@ -0,0 +1,77 @@
> +/*
> + * 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.
> + */
> +
> +/*
> + * JDONullIdentityException.java
> + *
> + */
> +
> +package javax.jdo;
> +
> +/** An instance of this class is thrown when attempting to create an object id
> + *  when the object id constructor parameter is null. This might occur when 
> + *  creating an object id instance from a transient instance where an identity 
> + *  field is null.
> + *
> + * @since 2.0
> + * @version 2.0
> + */
> +public class JDONullIdentityException extends JDOUserException {
> +
> +  /**
> +   * Constructs a new <code>JDONullIdentityException</code> without a detail message.
> +   */
> +  public JDONullIdentityException() {
> +  }
> +
> +  /**
> +   * Constructs a new <code>JDONullIdentityException</code> with the specified detail message.
> +   * @param msg the detail message.
> +   */
> +  public JDONullIdentityException(String msg) {
> +    super(msg);
> +  }
> +
> +  /** Constructs a new <code>JDONullIdentityException</code> with the specified detail message
> +   * and failed object.
> +   * @param msg the detail message.
> +   * @param failed the failed object.
> +   */
> +  public JDONullIdentityException(String msg, Object failed) {
> +    super(msg, failed);
> +  }
> +
> +  /**
> +   * Constructs a new <code>JDONullIdentityException</code> with the specified
> +   * detail message and nested <code>Throwable</code>s.
> +   * @param msg the detail message.
> +   * @param nested the nested <code>Throwable[]</code>.
> +   */
> +  public JDONullIdentityException(String msg, Throwable[] nested) {
> +    super(msg, nested);
> +  }
> +
> +  /**
> +   * Constructs a new <code>JDONullIdentityException</code> with the specified detail message
> +   * and nested <code>Throwable</code>s.
> +   * @param msg the detail message.
> +   * @param nested the nested <code>Throwable</code>.
> +   */
> +  public JDONullIdentityException(String msg, Throwable nested) {
> +    super(msg, nested);
> +  }
> +
> +}
> 
> Added: incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java?rev=209692&view=auto
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java (added)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/JDOUserCallbackException.java Thu Jul  7 18:17:40 2005
> @@ -0,0 +1,67 @@
> +/*
> + * 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.
> + */
> +
> +/*
> + * JDOUserCallbackException.java
> + *
> + */
> +
> +package javax.jdo;
> +
> +/** This class represents exceptions caused by exceptions thrown
> + * during execution of callbacks or listeners.
> + *
> + * @version 2.0
> + */
> +public class JDOUserCallbackException extends JDOUserException {
> +
> +  /**
> +   * Constructs a new <code>JDOUserCallbackException</code> 
> +   * without a detail message.
> +   */
> +  public JDOUserCallbackException() {
> +  }
> +
> +  /**
> +   * Constructs a new <code>JDOUserCallbackException</code> 
> +   * with the specified detail message.
> +   * @param msg the detail message.
> +   */
> +  public JDOUserCallbackException(String msg) {
> +    super(msg);
> +  }
> +
> +  /**
> +   * Constructs a new <code>JDOUserCallbackException</code> with the
> +   * specified detail message and nested <code>Throwable</code>s.
> +   * @param msg the detail message.
> +   * @param nested the nested <code>Throwable[]</code>.
> +   */
> +  public JDOUserCallbackException(String msg, Throwable[] nested) {
> +    super(msg, nested);
> +  }
> +
> +  /**
> +   * Constructs a new <code>JDOUserCallbackException</code> with the
> +   * specified detail message and nested <code>Throwable</code>s.
> +   * @param msg the detail message.
> +   * @param nested the nested <code>Throwable</code>.
> +   */
> +  public JDOUserCallbackException(String msg, Throwable nested) {
> +    super(msg, nested);
> +  }
> +}
> +
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ByteIdentity.java Thu Jul  7 18:17:40 2005
> @@ -34,14 +34,20 @@
>       */
>      private byte key;
>      
> +    /** Construct this instance with the key value.
> +     */
> +    private void construct(byte key) {
> +        this.key = key;
> +        hashCode = super.hashClassName() ^ key;
> +    }
> +    
>      /** Constructor with class and key.
>       * @param pcClass the target class
>       * @param key the key
>       */
>      public ByteIdentity(Class pcClass, byte key) {
> -        super (pcClass);
> -        this.key = key;
> -        hashCode = super.hashClassName() ^ key;
> +        super(pcClass);
> +        construct(key);
>      }
>      
>      /** Constructor with class and key.
> @@ -49,7 +55,9 @@
>       * @param key the key
>       */
>      public ByteIdentity(Class pcClass, Byte key) {
> -        this (pcClass, key.byteValue());
> +        super(pcClass);
> +        setKeyAsObject(key);
> +        construct(key.byteValue());
>      }
>  
>      /** Constructor with class and key.
> @@ -57,7 +65,9 @@
>       * @param str the key
>       */
>      public ByteIdentity(Class pcClass, String str) {
> -        this (pcClass, Byte.parseByte(str));
> +        super(pcClass);
> +        assertKeyNotNull(str);
> +        construct(Byte.parseByte(str));
>      }
>  
>      /** Constructor only for Externalizable.
> @@ -94,6 +104,14 @@
>          }
>      }
>  
> +    /** Create the key as an Object.
> +     * @return the key as an Object
> +     * @since 2.0
> +     */
> +    protected Object createKeyAsObject() {
> +        return new Byte(key);
> +    }
> +
>      /** Write this object. Write the superclass first.
>       * @param out the output
>       */
> @@ -109,6 +127,5 @@
>  		throws IOException, ClassNotFoundException {
>          super.readExternal (in);
>          key = in.readByte ();
> -        hashCode = super.hashCode() ^ key;
>      }
>  }
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/CharIdentity.java Thu Jul  7 18:17:40 2005
> @@ -40,14 +40,18 @@
>       */
>      private char key;
>  
> +    private void construct(char key) {
> +        this.key = key;
> +        hashCode = hashClassName() ^ key;
> +    }
> +
>      /** Constructor with class and key.
>       * @param pcClass the target class
>       * @param key the key
>       */
>      public CharIdentity (Class pcClass, char key) {
>          super (pcClass);
> -        this.key = key;
> -        computeHashCode();
> +        construct(key);
>      }
>  
>      /** Constructor with class and key.
> @@ -55,7 +59,9 @@
>       * @param key the key
>       */
>      public CharIdentity (Class pcClass, Character key) {
> -        this (pcClass, key.charValue ());
> +        super (pcClass);
> +        setKeyAsObject(key);
> +        construct(key.charValue());
>      }
>  
>      /** Constructor with class and key. The String must have exactly one
> @@ -65,11 +71,11 @@
>       */
>      public CharIdentity (Class pcClass, String str) {
>          super(pcClass);
> +        assertKeyNotNull(str);
>          if (str.length() != 1) 
>              throw new IllegalArgumentException(
> -                    msg.msg("EXC_StringWrongLength"));
> -        this.key = str.charAt(0);
> -        computeHashCode();
> +                msg.msg("EXC_StringWrongLength")); //NOI18N
> +        construct(str.charAt(0));
>      }
>  
>      /** Constructor only for Externalizable.
> @@ -104,6 +110,14 @@
>              CharIdentity other = (CharIdentity) obj;
>              return key == other.key;
>          }
> +    }
> +
> +    /** Create the key as an Object.
> +     * @return the key as an Object
> +     * @since 2.0
> +     */
> +    protected Object createKeyAsObject() {
> +        return new Character(key);
>      }
>  
>      /** Write this object. Write the superclass first.
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/IntIdentity.java Thu Jul  7 18:17:40 2005
> @@ -29,16 +29,21 @@
>   * @version 2.0
>   */
>  public class IntIdentity extends SingleFieldIdentity {
> +
>      private int key;
>  
> +    private void construct(int key) {
> +        this.key = key;
> +        hashCode = hashClassName() ^ key;
> +    }
> +
>      /** Constructor with class and key.
>       * @param pcClass the class
>       * @param key the key
>       */
>      public IntIdentity (Class pcClass, int key) {
> -        super (pcClass);
> -        this.key = key;
> -        hashCode = hashClassName() ^ key;
> +        super(pcClass);
> +        construct(key);
>  	}
>  
>      /** Constructor with class and key.
> @@ -46,7 +51,9 @@
>       * @param key the key
>       */
>      public IntIdentity (Class pcClass, Integer key) {
> -        this (pcClass, key.intValue ());
> +        super(pcClass);
> +        setKeyAsObject(key);
> +        construct(key.intValue ());
>      }
>  
>  
> @@ -55,7 +62,9 @@
>       * @param str the key
>       */
>      public IntIdentity (Class pcClass, String str) {
> -        this (pcClass, Integer.parseInt(str));
> +        super(pcClass);
> +        assertKeyNotNull(str);
> +        construct(Integer.parseInt(str));
>      }
>  
>      /** Constructor only for Externalizable.
> @@ -92,6 +101,14 @@
>          }
>      }
>  
> +    /** Create the key as an Object.
> +     * @return the key as an Object
> +     * @since 2.0
> +     */
> +    protected Object createKeyAsObject() {
> +        return new Integer(key);
> +    }
> +
>      /** Write this object. Write the superclass first.
>       * @param out the output
>       */
> @@ -107,6 +124,5 @@
>  		throws IOException, ClassNotFoundException {
>          super.readExternal (in);
>          key = in.readInt();
> -        hashCode = hashClassName() ^ key;
>      }
>  }
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/LongIdentity.java Thu Jul  7 18:17:40 2005
> @@ -34,14 +34,18 @@
>       */
>      private long key;
>  
> +    private void construct(long key) {
> +        this.key = key;
> +        hashCode = hashClassName() ^ (int)key;
> +    }
> +
>      /** Constructor with class and key.
>       * @param pcClass the class
>       * @param key the key
>       */
>      public LongIdentity (Class pcClass, long key) {
>          super (pcClass);
> -        this.key = key;
> -        hashCode = hashClassName() ^ (int)key;
> +        construct(key);
>      }
>  
>      /** Constructor with class and key.
> @@ -49,7 +53,9 @@
>       * @param key the key
>       */
>      public LongIdentity (Class pcClass, Long key) {
> -        this (pcClass, key.longValue ());
> +        super(pcClass);
> +        setKeyAsObject(key);
> +        construct(key.longValue());
>      }
>  
>      /** Constructor with class and key.
> @@ -57,7 +63,9 @@
>       * @param str the key
>       */
>      public LongIdentity (Class pcClass, String str) {
> -        this (pcClass, Long.parseLong(str));
> +        super(pcClass);
> +        assertKeyNotNull(str);
> +        construct(Long.parseLong(str));
>      }
>  
>      /** Constructor only for Externalizable.
> @@ -94,6 +102,14 @@
>          }
>      }
>  
> +    /** Create the key as an Object.
> +     * @return the key as an Object
> +     * @since 2.0
> +     */
> +    protected Object createKeyAsObject() {
> +        return new Long(key);
> +    }
> +
>      /** Write this object. Write the superclass first.
>       * @param out the output
>       */
> @@ -109,6 +125,6 @@
>  		throws IOException, ClassNotFoundException {
>          super.readExternal (in);
>          key = in.readLong();
> -        hashCode = hashClassName() ^ (int)key;
>      }
> +
>  }
> 
> Added: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java?rev=209692&view=auto
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java (added)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ObjectIdentity.java Thu Jul  7 18:17:40 2005
> @@ -0,0 +1,152 @@
> +/*
> + * 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.
> + */
> +
> +/*
> + * ObjectIdentity.java
> + *
> + */
> + 
> +package javax.jdo.identity;
> +
> +import java.io.IOException;
> +import java.io.ObjectInput;
> +import java.io.ObjectOutput;
> +
> +import java.security.AccessController;
> +import java.security.PrivilegedAction;
> +
> +import javax.jdo.JDOUserException;
> +
> +import javax.jdo.spi.JDOImplHelper;
> +
> +/** This class is for identity with a single Object type field.
> + * @version 2.0
> + */
> +public class ObjectIdentity extends SingleFieldIdentity {
> +    
> +    /** The key is stored in the superclass field keyAsObject.
> +     */
> +    
> +    /** The JDOImplHelper instance used for parsing the String to an Object.
> +     */
> +    private static JDOImplHelper helper = (JDOImplHelper)
> +        AccessController.doPrivileged(
> +            new PrivilegedAction () {
> +                public Object run () {
> +                    return JDOImplHelper.getInstance();
> +                }
> +            }
> +        );
> +    
> +    /** The delimiter for String constructor.
> +     */
> +    public static String STRING_DELIMITER = ":"; //NOI18N
> +    
> +    /** Constructor with class and key.
> +     * @param pcClass the class
> +     * @param param the key
> +     */
> +    public ObjectIdentity (Class pcClass, Object param) {
> +        super (pcClass);
> +        assertKeyNotNull(param);
> +        String paramString = null;
> +        String keyString = null;
> +        String className = null;
> +        if (param instanceof String) {
> +            /* The paramString is of the form "<className>:<keyString>" */
> +            paramString = (String)param;
> +            if (paramString.length() < 3) {
> +                throw new JDOUserException(
> +                    msg.msg("EXC_ObjectIdentityStringConstructionTooShort") + //NOI18N
> +                    msg.msg("EXC_ObjectIdentityStringConstructionUsage", //NOI18N
> +                        paramString));
> +            }
> +            int indexOfDelimiter = paramString.indexOf(STRING_DELIMITER);
> +            if (indexOfDelimiter < 0) {
> +                throw new JDOUserException(
> +                    msg.msg("EXC_ObjectIdentityStringConstructionNoDelimiter") + //NOI18N
> +                    msg.msg("EXC_ObjectIdentityStringConstructionUsage", //NOI18N
> +                        paramString));
> +            }
> +            keyString = paramString.substring(indexOfDelimiter+1);
> +            className = paramString.substring(0, indexOfDelimiter);
> +            keyAsObject = helper.construct(className, keyString);
> +        } else {
> +            keyAsObject = param;
> +        }
> +        hashCode = hashClassName() ^ keyAsObject.hashCode();
> +    }
> +
> +    /** Constructor only for Externalizable.
> +     */
> +    public ObjectIdentity () {
> +    }
> +
> +    /** Return the key.
> +     * @return the key
> +     */
> +    public Object getKey () {
> +        return keyAsObject;
> +    }
> +
> +    /** Return the String form of the object id. The class of the
> +     * object id is written as the first part of the result so that
> +     * the class can be reconstructed later. Then the toString
> +     * of the key instance is appended. During construction, 
> +     * this process is reversed. The class is extracted from 
> +     * the first part of the String, and the String constructor
> +     * of the key is used to construct the key itself.
> +     * @return the String form of the key
> +     */
> +    public String toString () {
> +        return keyAsObject.getClass().getName()
> +                + STRING_DELIMITER
> +                + keyAsObject.toString();
> +    }
> +
> +    /** Determine if the other object represents the same object id.
> +     * @param obj the other object
> +     * @return true if both objects represent the same object id
> +     */
> +    public boolean equals (Object obj) {
> +        if (this == obj) {
> +            return true;
> +        } else if (!super.equals (obj)) {
> +            return false;
> +        } else {
> +            ObjectIdentity other = (ObjectIdentity) obj;
> +            return keyAsObject.equals(other.keyAsObject);
> +        }
> +    }
> +
> +    /** Write this object. Write the superclass first.
> +     * @param out the output
> +     */
> +    public void writeExternal(ObjectOutput out) throws IOException {
> +        super.writeExternal (out);
> +        out.writeObject(keyAsObject);
> +    }
> +
> +    /** Read this object. Read the superclass first.
> +     * @param in the input
> +     */
> +    public void readExternal(ObjectInput in)
> +		throws IOException, ClassNotFoundException {
> +        super.readExternal (in);
> +        keyAsObject = in.readObject();
> +    }
> +    
> +}
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/ShortIdentity.java Thu Jul  7 18:17:40 2005
> @@ -33,15 +33,18 @@
>  {
>  	private short key;
>  
> +    private void construct(short key) {
> +        this.key = key;
> +        hashCode = hashClassName() ^ key;
> +    }
>  
>      /** Constructor with class and key.
>       * @param pcClass the class
>       * @param key the key
>       */
>      public ShortIdentity (Class pcClass, short key) {
> -        super (pcClass);
> -        this.key = key;
> -        hashCode = hashClassName() ^ key;
> +        super(pcClass);
> +        construct(key);
>      }
>  
>      /** Constructor with class and key.
> @@ -49,7 +52,9 @@
>       * @param key the key
>       */
>      public ShortIdentity (Class pcClass, Short key) {
> -        this (pcClass, key.shortValue ());
> +        super(pcClass);
> +        setKeyAsObject(key);
> +        construct(key.shortValue());
>      }
>  
>      /** Constructor with class and key.
> @@ -57,7 +62,9 @@
>       * @param str the key
>       */
>      public ShortIdentity (Class pcClass, String str) {
> -        this (pcClass, Short.parseShort (str));
> +        super(pcClass);
> +        assertKeyNotNull(str);
> +        construct(Short.parseShort (str));
>      }
>  
>      /** Constructor only for Externalizable.
> @@ -94,6 +101,14 @@
>          }
>      }
>  
> +    /** Create the key as an Object.
> +     * @return the key as an Object
> +     * @since 2.0
> +     */
> +    protected Object createKeyAsObject() {
> +        return new Short(key);
> +    }
> +
>      /** Write this object. Write the superclass first.
>       * @param out the output
>       */
> @@ -109,6 +124,5 @@
>  		throws IOException, ClassNotFoundException {
>          super.readExternal (in);
>          key = in.readShort();
> -        hashCode = hashClassName() ^ key;
>      }
>  }
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/SingleFieldIdentity.java Thu Jul  7 18:17:40 2005
> @@ -26,6 +26,11 @@
>  import java.io.ObjectInput;
>  import java.io.ObjectOutput;
>  
> +import javax.jdo.JDOFatalInternalException;
> +import javax.jdo.JDONullIdentityException;
> +
> +import javax.jdo.spi.I18NHelper;
> +
>  /** This class is the abstract base class for all single field identity
>   * classes. A common case of application identity uses exactly one 
>   * persistent field in the class to represent identity. In this case, 
> @@ -36,6 +41,10 @@
>  public abstract class SingleFieldIdentity
>      implements Externalizable {
>      
> +    /** The Internationalization message helper.
> +     */
> +    protected static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N
> +
>      /** The class of the target object.
>       */
>      transient private Class targetClass;
> @@ -47,6 +56,10 @@
>      /** The hashCode.
>       */
>      protected int hashCode;
> +    
> +    /** The key as an Object.
> +     */
> +    protected Object keyAsObject;
>  
>      /** Constructor with target class.
>       * @param pcClass the class of the target
> @@ -64,6 +77,24 @@
>      public SingleFieldIdentity () {
>      }
>  
> +    /** Set the given key as the key for this instance. 
> +     * Compute the hash code for the instance.
> +     */
> +    protected void setKeyAsObject(Object key) {
> +        assertKeyNotNull(key);
> +        keyAsObject = key;
> +    }
> +
> +    /** Assert that the key is not null. Throw a JDONullIdentityException
> +     * if the given key is null.
> +     */ 
> +    protected void assertKeyNotNull(Object key) {
> +        if (key == null) {
> +            throw new JDONullIdentityException(
> +                msg.msg("EXC_SingleFieldIdentityNullParameter")); //NOI18N
> +        }
> +    }
> +    
>      /** Return the target class.
>       * @return the target class.
>       * @since 2.0
> @@ -80,6 +111,27 @@
>          return targetClassName;
>      }
>  
> +    /** Return the key as an Object. The method is synchronized to avoid
> +     * race conditions in multi-threaded environments.
> +     * @return the key as an Object.
> +     * @since 2.0
> +     */
> +    public synchronized Object getKeyAsObject() {
> +        if (keyAsObject == null) {
> +            keyAsObject = createKeyAsObject();
> +        }
> +        return keyAsObject;
> +    }
> +    
> +    /** Create the key as an Object.
> +     * @return the key as an Object;
> +     * @since 2.0
> +     */
> +    protected Object createKeyAsObject() {
> +        throw new JDOFatalInternalException
> +                (msg.msg("EXC_CreateKeyAsObjectMustNotBeCalled"));
> +    }
> +    
>      /** Check the class and class name and object type. If restored
>       * from serialization, class will be null so compare class name.
>       * @param obj the other object
> 
> Modified: incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java (original)
> +++ incubator/jdo/trunk/api20/src/java/javax/jdo/identity/StringIdentity.java Thu Jul  7 18:17:40 2005
> @@ -25,25 +25,23 @@
>  import java.io.ObjectInput;
>  import java.io.ObjectOutput;
>  
> +import javax.jdo.JDOUserException;
> +
>  /** This class is for identity with a single String field.
>   * @version 2.0
>   */
>  public class StringIdentity extends SingleFieldIdentity {
>      
> -    /** The key.
> +    /** The key is stored in the superclass field keyAsObject.
>       */
> -    private String key;
> -
> -
> +    
>      /** Constructor with class and key.
>       * @param pcClass the class
>       * @param key the key
>       */
>      public StringIdentity (Class pcClass, String key) {
>          super (pcClass);
> -        if (key == null)
> -            throw new NullPointerException ();
> -        this.key = key;
> +        setKeyAsObject(key);
>          hashCode = hashClassName() ^ key.hashCode();
>      }
>  
> @@ -56,14 +54,14 @@
>       * @return the key
>       */
>      public String getKey () {
> -        return key;
> +        return (String)keyAsObject;
>      }
>  
>      /** Return the String form of the key.
>       * @return the String form of the key
>       */
>      public String toString () {
> -        return key;
> +        return (String)keyAsObject;
>      }
>  
>      /** Determine if the other object represents the same object id.
> @@ -77,7 +75,7 @@
>              return false;
>          } else {
>              StringIdentity other = (StringIdentity) obj;
> -            return key.equals(other.key);
> +            return keyAsObject.equals(other.keyAsObject);
>          }
>      }
>  
> @@ -86,7 +84,7 @@
>       */
>      public void writeExternal(ObjectOutput out) throws IOException {
>          super.writeExternal (out);
> -        out.writeObject(key);
> +        out.writeObject(keyAsObject);
>      }
>  
>      /** Read this object. Read the superclass first.
> @@ -95,7 +93,6 @@
>      public void readExternal(ObjectInput in)
>  		throws IOException, ClassNotFoundException {
>          super.readExternal (in);
> -        key = (String)in.readObject();
> -        hashCode = hashClassName() ^ key.hashCode();
> +        keyAsObject = (String)in.readObject();
>      }
>  }
> 
> 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=209692&r1=209691&r2=209692&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 Thu Jul  7 18:17:40 2005
> @@ -21,18 +21,29 @@
>  
>  package javax.jdo.spi;
>  
> +import java.lang.reflect.Constructor;
> +
> +import java.text.DateFormat;
> +import java.text.ParsePosition;
> +import java.text.SimpleDateFormat;
> +
>  import java.util.ArrayList;
>  import java.util.Collection;
>  import java.util.Collections;
> +import java.util.Currency;
> +import java.util.Date;
>  import java.util.HashMap;
>  import java.util.HashSet;
>  import java.util.Iterator;
>  import java.util.List;
> +import java.util.Locale;
>  import java.util.Map;
>  import java.util.WeakHashMap;
>  
> +import javax.jdo.JDOException;
>  import javax.jdo.JDOFatalInternalException;
>  import javax.jdo.JDOFatalUserException;
> +import javax.jdo.JDOUserException;
>  import javax.jdo.spi.JDOPermission;
>  
>  /** This class is a helper class for JDO implementations.  It contains methods
> @@ -76,8 +87,16 @@
>      
>      /** The Internationalization message helper.
>       */
> -    private final static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle");
> +    private final static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N
>      
> +    /** The default DateFormat instance.
> +     */
> +    static DateFormat dateFormat = DateFormat.getDateTimeInstance();
> +
> +    /** The DateFormat pattern, set to the default.
> +     */
> +    static String dateFormatPattern = "MMM d, yyyy hh:mm:ss a";  //NOI18N
> +
>      /** Creates new JDOImplHelper */
>      private JDOImplHelper() {
>      }
> @@ -267,7 +286,7 @@
>              byte[] fieldFlags, Class persistenceCapableSuperclass,
>              PersistenceCapable pc) {
>          if (pcClass == null) 
> -            throw new NullPointerException(msg.msg("ERR_NullClass"));
> +            throw new NullPointerException(msg.msg("ERR_NullClass")); //NOI18N
>          Meta meta = new Meta (fieldNames, fieldTypes, 
>              fieldFlags, persistenceCapableSuperclass, pc);
>          registeredClasses.put (pcClass, meta);
> @@ -333,7 +352,7 @@
>      public void unregisterClass (Class pcClass)
>      {
>          if (pcClass == null) 
> -            throw new NullPointerException(msg.msg("ERR_NullClass"));
> +            throw new NullPointerException(msg.msg("ERR_NullClass")); //NOI18N
>          SecurityManager sec = System.getSecurityManager();
>          if (sec != null) { 
>              // throws exception if caller is not authorized
> @@ -413,7 +432,7 @@
>      public static void registerAuthorizedStateManagerClass (Class smClass) 
>          throws SecurityException {
>          if (smClass == null) 
> -            throw new NullPointerException(msg.msg("ERR_NullClass"));
> +            throw new NullPointerException(msg.msg("ERR_NullClass")); //NOI18N
>          SecurityManager sm = System.getSecurityManager();
>          if (sm != null) {
>              sm.checkPermission(JDOPermission.SET_STATE_MANAGER);
> @@ -442,7 +461,7 @@
>                      Object smClass = it.next();
>                      if (!(smClass instanceof Class)) {
>                          throw new ClassCastException(
> -                            msg.msg("ERR_StateManagerClassCast", 
> +                            msg.msg("ERR_StateManagerClassCast", //NOI18N
>                                  smClass.getClass().getName()));
>                      }
>                      registerAuthorizedStateManagerClass((Class)it.next());
> @@ -484,9 +503,141 @@
>                  return;
>              }
>          }
> -
>          // if not already authorized, perform "long" security checking.
>          scm.checkPermission(JDOPermission.SET_STATE_MANAGER);
> +    }
> +
> +    /** 
> +     * Construct an instance of a key class using a String as input.
> +     * This is a helper interface for use with ObjectIdentity.
> +     * Classes without a String constructor (such as those in java.lang
> +     * and java.util) will use this interface for constructing new instances.
> +     * The result might be a singleton or use some other strategy.
> +     */
> +    public interface StringConstructor {
> +        /**
> +         * Construct an instance of the class for which this instance
> +         * is registered.
> +         * @param s the parameter for construction
> +         * @return the constructed object
> +         */
> +        public Object construct(String s);
> +    }
> +    
> +    /** 
> +     * Special StringConstructor instances for use with specific
> +     * classes that have no public String constructor. The Map is
> +     * keyed on class instance and the value is an instance of 
> +     * StringConstructor.
> +     */
> +    static Map stringConstructorMap = new HashMap();
> +
> +    /**
> +     * 
> +     * Register special StringConstructor instances. These instances
> +     * are for constructing instances from String parameters where there
> +     * is no String constructor for them.
> +     * @param cls the class to register a StringConstructor for
> +     * @param sc the StringConstructor instance
> +     * @return the previous StringConstructor registered for this class
> +     */
> +    public Object registerStringConstructor(Class cls, StringConstructor sc) {
> +        return stringConstructorMap.put(cls, sc);
> +    }
> +
> +    /** Register the default special StringConstructor instances.
> +     */
> +    static {
> +        JDOImplHelper helper = getInstance();
> +        helper.registerStringConstructor(Currency.class, new StringConstructor() {
> +            public Object construct(String s) {
> +                try {
> +                    return Currency.getInstance(s);
> +                } catch (IllegalArgumentException ex) {
> +                    throw new javax.jdo.JDOUserException(
> +                        msg.msg("EXC_CurrencyStringConstructorIllegalArgument", s), ex); //NOI18N
> +                } catch (Exception ex) {
> +                    throw new JDOUserException(
> +                        msg.msg("EXC_CurrencyStringConstructorException"), ex); //NOI18N
> +                }
> +            }
> +        });
> +        helper.registerStringConstructor(Locale.class, new StringConstructor() {
> +            public Object construct(String s) {
> +                try {
> +                    return new Locale(s);
> +                } catch (Exception ex) {
> +                    throw new JDOUserException(
> +                        msg.msg("EXC_LocaleStringConstructorException"), ex); //NOI18N
> +                }
> +            }
> +        });
> +        helper.registerStringConstructor(Date.class, new StringConstructor() {
> +            public synchronized Object construct(String s) {
> +                ParsePosition pp = new ParsePosition(0);
> +                Date result = dateFormat.parse(s, pp);
> +                if (result == null) {
> +                    throw new JDOUserException (
> +                        msg.msg("EXC_DateStringConstructor", new Object[] //NOI18N
> +                        {s, new Integer(pp.getErrorIndex()), dateFormatPattern}));
> +                }
> +                return result;
> +            }
> +        });
> +    }
> +    
> +    /**
> +     * Construct an instance of the parameter class, using the keyString
> +     * as an argument to the constructor. If the class has a StringConstructor
> +     * instance registered, use it. If not, try to find a constructor for
> +     * the class with a single String argument. Otherwise, throw a
> +     * JDOUserException.
> +     * @param className the name of the class
> +     * @param keyString the String parameter for the constructor
> +     * @return the result of construction
> +     */
> +    public Object construct(String className, String keyString) {
> +        synchronized(stringConstructorMap) {
> +            try {
> +                Class keyClass = Class.forName(className);
> +                StringConstructor stringConstructor = 
> +                        (StringConstructor) stringConstructorMap.get(keyClass);
> +                if (stringConstructor == null) {
> +                    Constructor keyConstructor = 
> +                        keyClass.getConstructor(new Class[]{String.class});
> +                    return keyConstructor.newInstance(new Object[]{keyString});
> +                } else {
> +                    return stringConstructor.construct(keyString);
> +                }
> +            } catch (JDOException ex) {
> +                throw ex;
> +            } catch (Exception ex) {
> +                 /* ClassNotFoundException,
> +                    NoSuchMethodException,
> +                    InstantiationException,
> +                    IllegalAccessException,
> +                    InvocationTargetException */
> +                throw new JDOUserException(
> +                    msg.msg("EXC_ObjectIdentityStringConstruction",  //NOI18N
> +                    new Object[] {ex.toString(), className, keyString}), ex);
> +            }
> +        }
> +    }
> +
> +    /**
> +     * Register a DateFormat instance for use with constructing Date 
> +     * instances. The default is the default DateFormat instance.
> +     * If the new instance implements SimpleDateFormat, get its pattern
> +     * for error messages.
> +     * @param df the DateFormat instance to use
> +     */
> +    synchronized void registerDateFormat(DateFormat df) {
> +        dateFormat = df;
> +        if (df instanceof SimpleDateFormat) {
> +            dateFormatPattern = ((SimpleDateFormat)df).toPattern();
> +        } else {
> +            dateFormatPattern = msg.msg("MSG_unknown"); //NOI18N
> +        }
>      }
>  
>      /** This is a helper class to manage metadata per persistence-capable
> 
> Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java (original)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ByteIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -21,6 +21,8 @@
>  
>  package javax.jdo.identity;
>  
> +import javax.jdo.JDONullIdentityException;
> +
>  import javax.jdo.util.BatchTestRunner;
>  
>  /**
> @@ -95,4 +97,33 @@
>          assertFalse ("Not equal ByteIdentity instances compare equal.", sc1.equals(sc3));
>          assertFalse ("Not equal ByteIdentity instances compare equal.", sc3.equals(sc1));
>      }
> +    
> +    public void testGetKeyAsObjectPrimitive() {
> +        ByteIdentity c1 = new ByteIdentity(Object.class, (byte)1);
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Byte((byte)1));
> +    }
> +
> +    public void testGetKeyAsObject() {
> +        ByteIdentity c1 = new ByteIdentity(Object.class, new Byte((byte)1));
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Byte((byte)1));
> +    }
> +
> +    public void testBadConstructorNullByteParam() {
> +        try {
> +            ByteIdentity c1 = new ByteIdentity(Object.class, (Byte)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
> +    public void testBadConstructorNullStringParam() {
> +        try {
> +            ByteIdentity c1 = new ByteIdentity(Object.class, (String)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
>  }
> 
> Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java (original)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/CharIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -21,6 +21,8 @@
>  
>  package javax.jdo.identity;
>  
> +import javax.jdo.JDONullIdentityException;
> +
>  import javax.jdo.util.BatchTestRunner;
>  
>  /**
> @@ -105,4 +107,32 @@
>          assertFalse ("Not equal CharIdentity instances compare equal.", sc1.equals(sc3));
>          assertFalse ("Not equal CharIdentity instances compare equal.", sc3.equals(sc1));
>      }
> +    public void testGetKeyAsObjectPrimitive() {
> +        CharIdentity c1 = new CharIdentity(Object.class, '1');
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Character('1'));
> +    }
> +
> +    public void testGetKeyAsObject() {
> +        CharIdentity c1 = new CharIdentity(Object.class, new Character('1'));
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Character('1'));
> +    }
> +
> +    public void testBadConstructorNullCharacterParam() {
> +        try {
> +            CharIdentity c1 = new CharIdentity(Object.class, (Character)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
> +    public void testBadConstructorNullStringParam() {
> +        try {
> +            CharIdentity c1 = new CharIdentity(Object.class, (String)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
>  }
> 
> Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java (original)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/IntIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -21,6 +21,8 @@
>  
>  package javax.jdo.identity;
>  
> +import javax.jdo.JDONullIdentityException;
> +
>  import javax.jdo.util.BatchTestRunner;
>  
>  /**
> @@ -95,4 +97,32 @@
>          assertFalse ("Not equal IntIdentity instances compare equal.", sc1.equals(sc3));
>          assertFalse ("Not equal IntIdentity instances compare equal.", sc3.equals(sc1));
>      }
> +    public void testGetKeyAsObjectPrimitive() {
> +        IntIdentity c1 = new IntIdentity(Object.class, 1);
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Integer(1));
> +    }
> +
> +    public void testGetKeyAsObject() {
> +        IntIdentity c1 = new IntIdentity(Object.class, new Integer(1));
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Integer(1));
> +    }
> +
> +    public void testBadConstructorNullIntegerParam() {
> +        try {
> +            IntIdentity c1 = new IntIdentity(Object.class, (Integer)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
> +    public void testBadConstructorNullStringParam() {
> +        try {
> +            IntIdentity c1 = new IntIdentity(Object.class, (String)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
>  }
> 
> Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java (original)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/LongIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -21,6 +21,8 @@
>  
>  package javax.jdo.identity;
>  
> +import javax.jdo.JDONullIdentityException;
> +
>  import javax.jdo.util.BatchTestRunner;
>  
>  /**
> @@ -95,4 +97,33 @@
>          assertFalse ("Not equal LongIdentity instances compare equal.", sc1.equals(sc3));
>          assertFalse ("Not equal LongIdentity instances compare equal.", sc3.equals(sc1));
>      }
> +    
> +    public void testGetKeyAsObjectPrimitive() {
> +        LongIdentity c1 = new LongIdentity(Object.class, 1L);
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Long(1L));
> +    }
> +
> +    public void testGetKeyAsObject() {
> +        LongIdentity c1 = new LongIdentity(Object.class, new Long(1L));
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Long(1L));
> +    }
> +
> +    public void testBadConstructorNullShortParam() {
> +        try {
> +            LongIdentity c1 = new LongIdentity(Object.class, (Long)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
> +    public void testBadConstructorNullStringParam() {
> +        try {
> +            LongIdentity c1 = new LongIdentity(Object.class, (String)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
>  }
> 
> Added: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java?rev=209692&view=auto
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java (added)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ObjectIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -0,0 +1,369 @@
> +/*
> + * 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.
> + */
> +
> +/*
> + * ObjectIdentityTest.java
> + *
> + */
> +
> +package javax.jdo.identity;
> +
> +import java.lang.reflect.Constructor;
> +import java.lang.reflect.InvocationTargetException;
> +
> +import java.io.Serializable;
> +
> +import java.math.BigDecimal;
> +import java.util.Currency;
> +import java.util.Date;
> +import java.util.Locale;
> +
> +import javax.jdo.JDOUserException;
> +import javax.jdo.JDONullIdentityException;
> +import javax.jdo.util.BatchTestRunner;
> +
> +/**
> + *
> + */
> +public class ObjectIdentityTest extends SingleFieldIdentityTest {
> +    
> +    /** Creates a new instance of ObjectIdentityTest */
> +    public ObjectIdentityTest() {
> +    }
> +    
> +    /**
> +     * @param args the command line arguments
> +     */
> +    public static void main(String[] args) {
> +        BatchTestRunner.run(ObjectIdentityTest.class);
> +    }
> +    
> +    public void testConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new IdClass(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new IdClass(1));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new IdClass(2));
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testIntegerConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Integer(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Integer(1));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Integer(2));
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testLongConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Long(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Long(1));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Long(2));
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testDateConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Date(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Date(1));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Date(2));
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testLocaleConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, Locale.US);
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, Locale.US);
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, Locale.GERMANY);
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testCurrencyConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                Currency.getInstance(Locale.US));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, 
> +                Currency.getInstance(Locale.US));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, 
> +                Currency.getInstance(Locale.GERMANY));
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testStringConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                "javax.jdo.identity.ObjectIdentityTest$IdClass:1");        
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, 
> +                "javax.jdo.identity.ObjectIdentityTest$IdClass:1");        
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, 
> +                "javax.jdo.identity.ObjectIdentityTest$IdClass:2");        
> +        assertEquals("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal", c1.equals(c3));
> +    }
> +    
> +    public void testToStringConstructor() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new IdClass(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, c1.toString());
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, c2);
> +    }
> +
> +    public void testBadStringConstructorNullClass() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(null, "1");
> +        } catch (NullPointerException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +    
> +    public void testBadStringConstructorNullParam() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +    
> +    public void testBadStringConstructorTooShort() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, "xx");
> +        } catch (JDOUserException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +    
> +    public void testBadStringConstructorNoDelimiter() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, "xxxxxxxxx");
> +        } catch (JDOUserException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +    
> +    public void testBadStringConstructorBadClassName() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, "xx:yy");
> +        } catch (JDOUserException ex) {
> +            validateNestedException(ex, ClassNotFoundException.class);
> +            return;
> +        }
> +        fail ("Failed to catch expected ClassNotFoundException.");
> +    }
> +    
> +    public void testBadStringConstructorNoStringConstructor() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                    "javax.jdo.identity.ObjectIdentityTest$BadIdClassNoStringConstructor:yy");
> +        } catch (JDOUserException ex) {
> +            validateNestedException(ex, NoSuchMethodException.class);
> +            return;
> +        }
> +        fail ("Failed to catch expected NoSuchMethodException.");
> +    }
> +    
> +    public void testBadStringConstructorNoPublicStringConstructor() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                    "javax.jdo.identity.ObjectIdentityTest$BadIdClassNoPublicStringConstructor:yy");
> +        } catch (JDOUserException ex) {
> +            validateNestedException(ex, NoSuchMethodException.class);
> +            return;
> +        }
> +        fail ("Failed to catch expected NoSuchMethodException.");
> +    }
> +    
> +    public void testBadStringConstructorIllegalArgument() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                    "javax.jdo.identity.ObjectIdentityTest$IdClass:yy");
> +        } catch (JDOUserException ex) {
> +            validateNestedException(ex, InvocationTargetException.class);
> +            return;
> +        }
> +        fail ("Failed to catch expected InvocationTargetException.");
> +    }
> +
> +    public void testStringDateConstructor() {
> +        Object c1 = new ObjectIdentity(Object.class, 
> +            "java.util.Date:Jan 01, 1970 00:00:00 AM");
> +    }
> +
> +    public void testBadStringDateConstructor() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                "java.util.Date:Jop 1, 1970 00:00:00");
> +        } catch (JDOUserException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected Exception.");
> +    }
> +
> +    public void testStringLocaleConstructor() {
> +        Object c1 = new ObjectIdentity(Object.class, 
> +                    "java.util.Locale:en_us");
> +    }
> +
> +    public void testStringCurrencyConstructor() {
> +        Object c1 = new ObjectIdentity(Object.class, 
> +                    "java.util.Currency:USD");
> +    }
> +
> +    public void testBadStringCurrencyConstructor() {
> +        try {
> +            ObjectIdentity c1 = new ObjectIdentity(Object.class, 
> +                    "java.util.Currency:NowhereInTheWorld");
> +        } catch (JDOUserException ex) {
> +            validateNestedException(ex, IllegalArgumentException.class);
> +            return;
> +        }
> +        fail ("Failed to catch expected IllegalArgumentException.");
> +    }
> +
> +    public void testSerializedIdClass() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new IdClass(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new IdClass(1));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new IdClass(2));
> +        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
> +        Object sc1 = scis[0];
> +        Object sc2 = scis[1];
> +        Object sc3 = scis[2];
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
> +    }
> +    
> +    public void testSerializedBigDecimal() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new BigDecimal("123456789.012"));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new BigDecimal("123456789.012"));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new BigDecimal("123456789.01"));
> +        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
> +        Object sc1 = scis[0];
> +        Object sc2 = scis[1];
> +        Object sc3 = scis[2];
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
> +    }
> +    
> +    public void testSerializedCurrency() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, Currency.getInstance(Locale.US));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, Currency.getInstance(Locale.US));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, Currency.getInstance(Locale.GERMANY));
> +        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
> +        Object sc1 = scis[0];
> +        Object sc2 = scis[1];
> +        Object sc3 = scis[2];
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
> +    }
> +    
> +    public void testSerializedDate() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Date(1));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Date(1));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Date(2));
> +        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
> +        Object sc1 = scis[0];
> +        Object sc2 = scis[1];
> +        Object sc3 = scis[2];
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
> +    }
> +    
> +    public void testSerializedLocale() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new Locale("EN_US"));
> +        ObjectIdentity c2 = new ObjectIdentity(Object.class, new Locale("en_us"));
> +        ObjectIdentity c3 = new ObjectIdentity(Object.class, new Locale("EN_GB"));
> +        Object[] scis = writeReadSerialized(new Object[] {c1, c2, c3});
> +        Object sc1 = scis[0];
> +        Object sc2 = scis[1];
> +        Object sc3 = scis[2];
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c1, sc1);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", c2, sc2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc1, c2);
> +        assertEquals ("Equal ObjectIdentity instances compare not equal.", sc2, c1);
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", c1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(c3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc1.equals(sc3));
> +        assertFalse ("Not equal ObjectIdentity instances compare equal.", sc3.equals(sc1));
> +    }
> +    
> +    public void testGetKeyAsObject() {
> +        ObjectIdentity c1 = new ObjectIdentity(Object.class, new IdClass(1));
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new IdClass(1));
> +    }
> +
> +    private void validateNestedException(JDOUserException ex, Class expected) {
> +        Throwable[] nesteds = ex.getNestedExceptions();
> +        if (nesteds == null || nesteds.length == 0) {
> +            fail ("Nested exception is null or length 0");
> +        }
> +        Throwable nested = nesteds[0];
> +        if (!(expected.isAssignableFrom(nested.getClass()))) {
> +            fail ("Wrong nested exception. Expected ClassNotFoundException, got "
> +                    + nested.toString());
> +        }
> +        return;
> +    }
> +    public static class IdClass implements Serializable {
> +        public int value;
> +        public IdClass() {value = 0;}
> +        public IdClass(int value) {this.value = value;}
> +        public IdClass(String str) {this.value = Integer.parseInt(str);}
> +        public String toString() {return Integer.toString(value);}
> +        public int hashCode() {
> +            return value;
> +        }
> +        public boolean equals (Object obj) {
> +            if (this == obj) {
> +                return true;
> +            } else {
> +                IdClass other = (IdClass) obj;
> +                return value == other.value;
> +            }
> +        }
> +    }
> +    
> +    public static class BadIdClassNoStringConstructor {
> +    }
> +    
> +    public static class BadIdClassNoPublicStringConstructor {
> +        private BadIdClassNoPublicStringConstructor(String str) {}
> +    }
> +}
> 
> Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java (original)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/ShortIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -21,6 +21,8 @@
>  
>  package javax.jdo.identity;
>  
> +import javax.jdo.JDONullIdentityException;
> +
>  import javax.jdo.util.BatchTestRunner;
>  
>  /**
> @@ -95,4 +97,32 @@
>          assertFalse ("Not equal ShortIdentity instances compare equal.", sc1.equals(sc3));
>          assertFalse ("Not equal ShortIdentity instances compare equal.", sc3.equals(sc1));
>      }
> +    public void testGetKeyAsObjectPrimitive() {
> +        ShortIdentity c1 = new ShortIdentity(Object.class, (short)1);
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Short((short)1));
> +    }
> +
> +    public void testGetKeyAsObject() {
> +        ShortIdentity c1 = new ShortIdentity(Object.class, new Short((short)1));
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Short((short)1));
> +    }
> +
> +    public void testBadConstructorNullShortParam() {
> +        try {
> +            ShortIdentity c1 = new ShortIdentity(Object.class, (Short)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
> +    public void testBadConstructorNullStringParam() {
> +        try {
> +            ShortIdentity c1 = new ShortIdentity(Object.class, (String)null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
>  }
> 
> Modified: incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java
> URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java?rev=209692&r1=209691&r2=209692&view=diff
> ==============================================================================
> --- incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java (original)
> +++ incubator/jdo/trunk/api20/test/java/javax/jdo/identity/StringIdentityTest.java Thu Jul  7 18:17:40 2005
> @@ -21,6 +21,9 @@
>  
>  package javax.jdo.identity;
>  
> +import javax.jdo.JDONullIdentityException;
> +import javax.jdo.JDOUserException;
> +
>  import javax.jdo.util.BatchTestRunner;
>  
>  /**
> @@ -70,4 +73,19 @@
>          assertFalse ("Not equal StringIdentity instances compare equal.", sc1.equals(sc3));
>          assertFalse ("Not equal StringIdentity instances compare equal.", sc3.equals(sc1));
>      }
> +
> +    public void testGetKeyAsObject() {
> +        StringIdentity c1 = new StringIdentity(Object.class, "1");
> +        assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), "1");
> +    }
> +
> +    public void testBadConstructorNullParam() {
> +        try {
> +            StringIdentity c1 = new StringIdentity(Object.class, null);
> +        } catch (JDONullIdentityException ex) {
> +            return;
> +        }
> +        fail ("Failed to catch expected exception.");
> +    }
> +
>  }
> 


-- 
-------------------------------------------------------------------
Michael Watzek                  Tech@Spree Engineering GmbH
mailto:mwa.tech@spree.de        Buelowstr. 66
Tel.:  ++49/30/235 520 36       10783 Berlin - Germany
Fax.:  ++49/30/217 520 12       http://www.spree.de/
-------------------------------------------------------------------