View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software 
12   * distributed under the License is distributed on an "AS IS" BASIS, 
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
14   * See the License for the specific language governing permissions and 
15   * limitations under the License.
16   */
17  
18  /*
19   * ObjectIdentity.java
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 () {
49                  public Object run () {
50                      return JDOImplHelper.getInstance();
51                  }
52              }
53          );
54      
55      /*** The delimiter for String constructor.
56       */
57      private static final String STRING_DELIMITER = ":"; //NOI18N
58      
59      /*** Constructor with class and key.
60       * @param pcClass the class
61       * @param param the key
62       */
63      public ObjectIdentity (Class pcClass, Object param) {
64          super (pcClass);
65          assertKeyNotNull(param);
66          String paramString = null;
67          String keyString = null;
68          String className = null;
69          if (param instanceof String) {
70              /* The paramString is of the form "<className>:<keyString>" */
71              paramString = (String)param;
72              if (paramString.length() < 3) {
73                  throw new JDOUserException(
74                      msg.msg("EXC_ObjectIdentityStringConstructionTooShort") + //NOI18N
75                      msg.msg("EXC_ObjectIdentityStringConstructionUsage", //NOI18N
76                          paramString));
77              }
78              int indexOfDelimiter = paramString.indexOf(STRING_DELIMITER);
79              if (indexOfDelimiter < 0) {
80                  throw new JDOUserException(
81                      msg.msg("EXC_ObjectIdentityStringConstructionNoDelimiter") + //NOI18N
82                      msg.msg("EXC_ObjectIdentityStringConstructionUsage", //NOI18N
83                          paramString));
84              }
85              keyString = paramString.substring(indexOfDelimiter+1);
86              className = paramString.substring(0, indexOfDelimiter);
87              keyAsObject = helper.construct(className, keyString);
88          } else {
89              keyAsObject = param;
90          }
91          hashCode = hashClassName() ^ keyAsObject.hashCode();
92      }
93  
94      /*** Constructor only for Externalizable.
95       */
96      public ObjectIdentity () {
97      }
98  
99      /*** Return the key.
100      * @return the key
101      */
102     public Object getKey () {
103         return keyAsObject;
104     }
105 
106     /*** Return the String form of the object id. The class of the
107      * object id is written as the first part of the result so that
108      * the class can be reconstructed later. Then the toString
109      * of the key instance is appended. During construction, 
110      * this process is reversed. The class is extracted from 
111      * the first part of the String, and the String constructor
112      * of the key is used to construct the key itself.
113      * @return the String form of the key
114      */
115     public String toString () {
116         return keyAsObject.getClass().getName()
117                 + STRING_DELIMITER
118                 + keyAsObject.toString();
119     }
120 
121     /*** Determine if the other object represents the same object id.
122      * @param obj the other object
123      * @return true if both objects represent the same object id
124      */
125     public boolean equals (Object obj) {
126         if (this == obj) {
127             return true;
128         } else if (!super.equals (obj)) {
129             return false;
130         } else {
131             ObjectIdentity other = (ObjectIdentity) obj;
132             return keyAsObject.equals(other.keyAsObject);
133         }
134     }
135 
136     /*** Determine the ordering of identity objects.
137      * @param o Other identity
138      * @return The relative ordering between the objects
139      * @since 2.2
140      */
141     public int compareTo(Object o) {
142         if (o instanceof ObjectIdentity) {
143         	ObjectIdentity other = (ObjectIdentity)o;
144             int result = super.compare(other);
145             if (result == 0) {
146                 if (other.keyAsObject instanceof Comparable && 
147                         keyAsObject instanceof Comparable) {
148                     return ((Comparable)keyAsObject).compareTo(
149                             (Comparable)other.keyAsObject);
150                 }
151                 else
152                 {
153                     throw new ClassCastException("The key class (" + 
154                             keyAsObject.getClass().getName() + 
155                             ") does not implement Comparable");
156                 }
157             } else {
158                 return result;
159             }
160         }
161         else if (o == null) {
162             throw new ClassCastException("object is null");
163         }
164         throw new ClassCastException(this.getClass().getName() + 
165                 " != " + o.getClass().getName());
166     }
167 
168     /*** Write this object. Write the superclass first.
169      * @param out the output
170      */
171     public void writeExternal(ObjectOutput out) throws IOException {
172         super.writeExternal (out);
173         out.writeObject(keyAsObject);
174     }
175 
176     /*** Read this object. Read the superclass first.
177      * @param in the input
178      */
179     public void readExternal(ObjectInput in)
180 		throws IOException, ClassNotFoundException {
181         super.readExternal (in);
182         keyAsObject = in.readObject();
183     }
184     
185 }