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<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 = ":"; //NOI18N
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              /* The paramString is of the form "<className>:<keyString>" */
72              paramString = (String)param;
73              if (paramString.length() < 3) {
74                  throw new JDOUserException(
75                      msg.msg("EXC_ObjectIdentityStringConstructionTooShort") + //NOI18N
76                      msg.msg("EXC_ObjectIdentityStringConstructionUsage", //NOI18N
77                          paramString));
78              }
79              int indexOfDelimiter = paramString.indexOf(STRING_DELIMITER);
80              if (indexOfDelimiter < 0) {
81                  throw new JDOUserException(
82                      msg.msg("EXC_ObjectIdentityStringConstructionNoDelimiter") + //NOI18N
83                      msg.msg("EXC_ObjectIdentityStringConstructionUsage", //NOI18N
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 }