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 @SuppressWarnings("unchecked")
154 public int compareTo(Object o) {
155 if (o instanceof ObjectIdentity) {
156 ObjectIdentity other = (ObjectIdentity)o;
157 int result = super.compare(other);
158 if (result == 0) {
159 if (other.keyAsObject instanceof Comparable &&
160 keyAsObject instanceof Comparable) {
161 return ((Comparable)keyAsObject).compareTo(
162 (Comparable)other.keyAsObject);
163 }
164 else
165 {
166 throw new ClassCastException("The key class (" +
167 keyAsObject.getClass().getName() +
168 ") does not implement Comparable");
169 }
170 } else {
171 return result;
172 }
173 }
174 else if (o == null) {
175 throw new ClassCastException("object is null");
176 }
177 throw new ClassCastException(this.getClass().getName() +
178 " != " + o.getClass().getName());
179 }
180
181 /** Write this object. Write the superclass first.
182 * @param out the output
183 */
184 @Override
185 public void writeExternal(ObjectOutput out) throws IOException {
186 super.writeExternal (out);
187 out.writeObject(keyAsObject);
188 }
189
190 /** Read this object. Read the superclass first.
191 * @param in the input
192 */
193 @Override
194 public void readExternal(ObjectInput in)
195 throws IOException, ClassNotFoundException {
196 super.readExternal (in);
197 keyAsObject = in.readObject();
198 }
199
200 }