1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package javax.jdo.identity;
24
25 import java.io.IOException;
26 import java.io.ObjectInput;
27 import java.io.ObjectOutput;
28
29 import java.security.AccessController;
30 import java.security.PrivilegedAction;
31
32 import javax.jdo.JDOUserException;
33
34 import javax.jdo.spi.JDOImplHelper;
35
36 /** This class is for identity with a single Object type field.
37 * @version 2.0
38 */
39 public class ObjectIdentity extends SingleFieldIdentity {
40
41 /** The key is stored in the superclass field keyAsObject.
42 */
43
44 /** The JDOImplHelper instance used for parsing the String to an Object.
45 */
46 private static JDOImplHelper helper = (JDOImplHelper)
47 AccessController.doPrivileged(
48 new PrivilegedAction<JDOImplHelper> () {
49 public JDOImplHelper run () {
50 return JDOImplHelper.getInstance();
51 }
52 }
53 );
54
55 /** The delimiter for String constructor.
56 */
57 private static final String STRING_DELIMITER = ":";
58
59 /** Constructor with class and key.
60 * @param pcClass the class
61 * @param param the key
62 */
63 @SuppressWarnings("static-access")
64 public ObjectIdentity (Class pcClass, Object param) {
65 super (pcClass);
66 assertKeyNotNull(param);
67 String paramString = null;
68 String keyString = null;
69 String className = null;
70 if (param instanceof String) {
71
72 paramString = (String)param;
73 if (paramString.length() < 3) {
74 throw new JDOUserException(
75 msg.msg("EXC_ObjectIdentityStringConstructionTooShort") +
76 msg.msg("EXC_ObjectIdentityStringConstructionUsage",
77 paramString));
78 }
79 int indexOfDelimiter = paramString.indexOf(STRING_DELIMITER);
80 if (indexOfDelimiter < 0) {
81 throw new JDOUserException(
82 msg.msg("EXC_ObjectIdentityStringConstructionNoDelimiter") +
83 msg.msg("EXC_ObjectIdentityStringConstructionUsage",
84 paramString));
85 }
86 keyString = paramString.substring(indexOfDelimiter+1);
87 className = paramString.substring(0, indexOfDelimiter);
88 keyAsObject = helper.construct(className, keyString);
89 } else {
90 keyAsObject = param;
91 }
92 hashCode = hashClassName() ^ keyAsObject.hashCode();
93 }
94
95 /** Constructor only for Externalizable.
96 */
97 public ObjectIdentity () {
98 }
99
100 /** Return the key.
101 * @return the key
102 */
103 public Object getKey () {
104 return keyAsObject;
105 }
106
107 /** Return the String form of the object id. The class of the
108 * object id is written as the first part of the result so that
109 * the class can be reconstructed later. Then the toString
110 * of the key instance is appended. During construction,
111 * this process is reversed. The class is extracted from
112 * the first part of the String, and the String constructor
113 * of the key is used to construct the key itself.
114 * @return the String form of the key
115 */
116 @Override
117 public String toString () {
118 return keyAsObject.getClass().getName()
119 + STRING_DELIMITER
120 + keyAsObject.toString();
121 }
122
123 /** Determine if the other object represents the same object id.
124 * @param obj the other object
125 * @return true if both objects represent the same object id
126 */
127 @Override
128 public boolean equals (Object obj) {
129 if (this == obj) {
130 return true;
131 } else if (!super.equals (obj)) {
132 return false;
133 } else {
134 ObjectIdentity other = (ObjectIdentity) obj;
135 return keyAsObject.equals(other.keyAsObject);
136 }
137 }
138
139 /** Provide the hash code for this instance. The hash code is the
140 * hash code of the contained key.
141 * @return the hash code
142 */
143 @Override
144 public int hashCode() {
145 return keyAsObject.hashCode();
146 }
147
148 /** Determine the ordering of identity objects.
149 * @param o Other identity
150 * @return The relative ordering between the objects
151 * @since 2.2
152 */
153 public int compareTo(Object o) {
154 if (o instanceof ObjectIdentity) {
155 ObjectIdentity other = (ObjectIdentity)o;
156 int result = super.compare(other);
157 if (result == 0) {
158 if (other.keyAsObject instanceof Comparable &&
159 keyAsObject instanceof Comparable) {
160 return ((Comparable)keyAsObject).compareTo(
161 (Comparable)other.keyAsObject);
162 }
163 else
164 {
165 throw new ClassCastException("The key class (" +
166 keyAsObject.getClass().getName() +
167 ") does not implement Comparable");
168 }
169 } else {
170 return result;
171 }
172 }
173 else if (o == null) {
174 throw new ClassCastException("object is null");
175 }
176 throw new ClassCastException(this.getClass().getName() +
177 " != " + o.getClass().getName());
178 }
179
180 /** Write this object. Write the superclass first.
181 * @param out the output
182 */
183 @Override
184 public void writeExternal(ObjectOutput out) throws IOException {
185 super.writeExternal (out);
186 out.writeObject(keyAsObject);
187 }
188
189 /** Read this object. Read the superclass first.
190 * @param in the input
191 */
192 @Override
193 public void readExternal(ObjectInput in)
194 throws IOException, ClassNotFoundException {
195 super.readExternal (in);
196 keyAsObject = in.readObject();
197 }
198
199 }