| Hi, This is still a work in progress, pending inclusion of the JDONullIdentityFIeldException. But the ObjectIdentity class is mostly done. Craig |
Index: test/java/javax/jdo/identity/StringIdentityTest.java
===================================================================
--- test/java/javax/jdo/identity/StringIdentityTest.java (revision
209512)
+++ test/java/javax/jdo/identity/StringIdentityTest.java (working copy)
@@ -70,4 +70,10 @@
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");
+ }
+
}
Index: test/java/javax/jdo/identity/ObjectIdentityTest.java
===================================================================
--- test/java/javax/jdo/identity/ObjectIdentityTest.java (revision 0)
+++ test/java/javax/jdo/identity/ObjectIdentityTest.java (revision 0)
@@ -0,0 +1,384 @@
+/*
+ * 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.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 (NullPointerException 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;
+ try {
+ c1 = new ObjectIdentity(Object.class,
+ "java.util.Date:Jan 01, 1970 00:00:00 AM");
+ } catch (JDOUserException ex) {
+ fail ("Unexpected Exception " + ex);
+ }
+ }
+
+ 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;
+ try {
+ c1 = new ObjectIdentity(Object.class,
+ "java.util.Locale:en_us");
+ } catch (JDOUserException ex) {
+ fail ("Unexpected Exception " + ex);
+ }
+ }
+
+ public void testStringCurrencyConstructor() {
+ Object c1;
+ try {
+ c1 = new ObjectIdentity(Object.class,
+ "java.util.Currency:USD");
+ } catch (JDOUserException ex) {
+ fail ("Unexpected Exception " + ex);
+ }
+ }
+
+ 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) {}
+ }
+}
Index: test/java/javax/jdo/identity/IntIdentityTest.java
===================================================================
--- test/java/javax/jdo/identity/IntIdentityTest.java (revision 209512)
+++ test/java/javax/jdo/identity/IntIdentityTest.java (working copy)
@@ -95,4 +95,14 @@
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));
+ }
+
}
Index: test/java/javax/jdo/identity/CharIdentityTest.java
===================================================================
--- test/java/javax/jdo/identity/CharIdentityTest.java (revision 209512)
+++ test/java/javax/jdo/identity/CharIdentityTest.java (working copy)
@@ -105,4 +105,14 @@
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'));
+ }
+
}
Index: test/java/javax/jdo/identity/ShortIdentityTest.java
===================================================================
--- test/java/javax/jdo/identity/ShortIdentityTest.java (revision 209512)
+++ test/java/javax/jdo/identity/ShortIdentityTest.java (working copy)
@@ -95,4 +95,14 @@
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));
+ }
+
}
Index: test/java/javax/jdo/identity/LongIdentityTest.java
===================================================================
--- test/java/javax/jdo/identity/LongIdentityTest.java (revision 209512)
+++ test/java/javax/jdo/identity/LongIdentityTest.java (working copy)
@@ -95,4 +95,15 @@
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));
+ }
+
}
Index: test/java/javax/jdo/identity/ByteIdentityTest.java
===================================================================
--- test/java/javax/jdo/identity/ByteIdentityTest.java (revision 209512)
+++ test/java/javax/jdo/identity/ByteIdentityTest.java (working copy)
@@ -95,4 +95,15 @@
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));
+ }
+
}
Index: src/java/javax/jdo/identity/SingleFieldIdentity.java
===================================================================
--- src/java/javax/jdo/identity/SingleFieldIdentity.java (revision
209512)
+++ src/java/javax/jdo/identity/SingleFieldIdentity.java (working copy)
@@ -26,6 +26,10 @@
import java.io.ObjectInput;
import java.io.ObjectOutput;
+import javax.jdo.JDOFatalInternalException;
+
+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 +40,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 +55,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
@@ -80,6 +92,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
Index: src/java/javax/jdo/identity/StringIdentity.java
===================================================================
--- src/java/javax/jdo/identity/StringIdentity.java (revision 209512)
+++ src/java/javax/jdo/identity/StringIdentity.java (working copy)
@@ -30,11 +30,9 @@
*/
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
@@ -43,8 +41,8 @@
super (pcClass);
if (key == null)
throw new NullPointerException ();
- this.key = key;
- hashCode = hashClassName() ^ key.hashCode();
+ this.keyAsObject = key;
+ hashCode = hashClassName() ^ keyAsObject.hashCode();
}
/** Constructor only for Externalizable.
@@ -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();
}
}
Index: src/java/javax/jdo/identity/ObjectIdentity.java
===================================================================
--- src/java/javax/jdo/identity/ObjectIdentity.java (revision 0)
+++ src/java/javax/jdo/identity/ObjectIdentity.java (revision 0)
@@ -0,0 +1,172 @@
+/*
+ * 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.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import java.util.Currency;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.jdo.JDOException;
+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.
+ */
+ JDOImplHelper helper = JDOImplHelper.getInstance();
+
+ /** The delimiter for String constructor.
+ */
+ public String STRING_DELIMITER = ":";
+
+ /** Constructor with class and key.
+ * @param pcClass the class
+ * @param param the key
+ */
+ public ObjectIdentity (Class pcClass, Object param) {
+ super (pcClass);
+ String paramString = null;
+ String keyString = null;
+ String className = null;
+ if (param == null | pcClass == null)
+ throw new NullPointerException ();
+ 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);
+ try {
+ Class keyClass = Class.forName(className);
+ keyAsObject = helper.construct(keyClass, keyString);
+ if (keyAsObject == null) {
+ Constructor keyConstructor = keyClass.getConstructor(new
Class[]{String.class});
+ keyAsObject = keyConstructor.newInstance(new
Object[]{keyString});
+ }
+ } catch (JDOUserException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ /* ClassNotFoundException,
+ NoSuchMethodException,
+ InstantiationException,
+ IllegalAccessException,
+ InvocationTargetException */
+ throw new JDOUserException(
+ msg.msg("EXC_ObjectIdentityStringConstruction",
//NOI18N
+ new Object[]
+ {paramString, ex.toString(), className, keyString}),
ex);
+ }
+ } 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();
+// hashCode = hashClassName() ^ keyAsObject.hashCode();
+ }
+
+}
Index: src/java/javax/jdo/identity/IntIdentity.java
===================================================================
--- src/java/javax/jdo/identity/IntIdentity.java (revision 209512)
+++ src/java/javax/jdo/identity/IntIdentity.java (working copy)
@@ -47,6 +47,7 @@
*/
public IntIdentity (Class pcClass, Integer key) {
this (pcClass, key.intValue ());
+ keyAsObject = key;
}
@@ -92,6 +93,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 +116,5 @@
throws IOException, ClassNotFoundException {
super.readExternal (in);
key = in.readInt();
- hashCode = hashClassName() ^ key;
}
}
Index: src/java/javax/jdo/identity/CharIdentity.java
===================================================================
--- src/java/javax/jdo/identity/CharIdentity.java (revision 209512)
+++ src/java/javax/jdo/identity/CharIdentity.java (working copy)
@@ -56,6 +56,7 @@
*/
public CharIdentity (Class pcClass, Character key) {
this (pcClass, key.charValue ());
+ keyAsObject = key;
}
/** Constructor with class and key. The String must have exactly one
@@ -106,6 +107,14 @@
}
}
+ /** 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.
* @param out the output
*/
Index: src/java/javax/jdo/identity/ShortIdentity.java
===================================================================
--- src/java/javax/jdo/identity/ShortIdentity.java (revision 209512)
+++ src/java/javax/jdo/identity/ShortIdentity.java (working copy)
@@ -50,6 +50,7 @@
*/
public ShortIdentity (Class pcClass, Short key) {
this (pcClass, key.shortValue ());
+ keyAsObject = key;
}
/** Constructor with class and key.
@@ -94,6 +95,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 +118,5 @@
throws IOException, ClassNotFoundException {
super.readExternal (in);
key = in.readShort();
- hashCode = hashClassName() ^ key;
}
}
Index: src/java/javax/jdo/identity/LongIdentity.java
===================================================================
--- src/java/javax/jdo/identity/LongIdentity.java (revision 209512)
+++ src/java/javax/jdo/identity/LongIdentity.java (working copy)
@@ -50,6 +50,7 @@
*/
public LongIdentity (Class pcClass, Long key) {
this (pcClass, key.longValue ());
+ keyAsObject = key;
}
/** Constructor with class and key.
@@ -94,6 +95,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 +118,6 @@
throws IOException, ClassNotFoundException {
super.readExternal (in);
key = in.readLong();
- hashCode = hashClassName() ^ (int)key;
}
+
}
Index: src/java/javax/jdo/identity/ByteIdentity.java
===================================================================
--- src/java/javax/jdo/identity/ByteIdentity.java (revision 209512)
+++ src/java/javax/jdo/identity/ByteIdentity.java (working copy)
@@ -50,6 +50,7 @@
*/
public ByteIdentity(Class pcClass, Byte key) {
this (pcClass, key.byteValue());
+ keyAsObject = key;
}
/** Constructor with class and key.
@@ -94,6 +95,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 +118,5 @@
throws IOException, ClassNotFoundException {
super.readExternal (in);
key = in.readByte ();
- hashCode = super.hashCode() ^ key;
}
}
Index: src/java/javax/jdo/spi/JDOImplHelper.java
===================================================================
--- src/java/javax/jdo/spi/JDOImplHelper.java (revision 209536)
+++ src/java/javax/jdo/spi/JDOImplHelper.java (working copy)
@@ -21,18 +21,26 @@
package javax.jdo.spi;
+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.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
@@ -267,7 +275,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);
@@ -413,7 +421,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 +450,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());
@@ -489,6 +497,106 @@
scm.checkPermission(JDOPermission.SET_STATE_MANAGER);
}
+ /** 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
+
+ /** Register a DateFormat instance for use with constructing Date
+ * instances. The default is the default DateFormat instance.
+ * If the new instance implements SimpleDateFormat, set the pattern
+ * for error messages.
+ */
+ synchronized void registerDateFormat(DateFormat df) {
+ dateFormat = df;
+ if (df instanceof SimpleDateFormat) {
+ dateFormatPattern = ((SimpleDateFormat)df).toPattern();
+ }
+ }
+
+ /**
+ * 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.
+ */
+ public interface StringConstructor {
+ 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.
+ */
+ 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;
+ }
+ });
+ }
+
+ public Object construct(Class cls, String s) {
+ synchronized(stringConstructorMap) {
+ StringConstructor sc = (StringConstructor)
stringConstructorMap.get(cls);
+ if (sc == null) {
+ // no special treatment for this class
+ return null;
+ } else {
+ return sc.construct(s);
+ }
+ }
+ }
+
/** This is a helper class to manage metadata per persistence-capable
* class. The information is used at runtime to provide field names and
* field types to the JDO Model.
Index: src/java/javax/jdo/Bundle.properties
===================================================================
--- src/java/javax/jdo/Bundle.properties (revision 209514)
+++ src/java/javax/jdo/Bundle.properties (working copy)
@@ -66,3 +66,11 @@
\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}".
\ No newline at end of file
Craig Russell Architect, Sun Java Enterprise System http://java.sun.com/products/jdo 408 276-5638 mailto:[EMAIL PROTECTED] P.S. A good JDO? O, Gasp! |
smime.p7s
Description: S/MIME cryptographic signature
