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   * SingleFieldIdentity.java
20   *
21   */
22   
23  package javax.jdo.identity;
24  
25  import java.io.Externalizable;
26  import java.io.IOException;
27  import java.io.ObjectInput;
28  import java.io.ObjectOutput;
29  
30  import javax.jdo.JDOFatalInternalException;
31  import javax.jdo.JDONullIdentityException;
32  
33  import javax.jdo.spi.I18NHelper;
34  
35  /** This class is the abstract base class for all single field identity
36   * classes. A common case of application identity uses exactly one 
37   * persistent field in the class to represent identity. In this case, 
38   * the application can use a standard JDO class instead of creating 
39   * a new user-defined class for the purpose.
40   * @version 2.0
41   */
42  public abstract class SingleFieldIdentity
43      implements Externalizable, Comparable {
44      
45      /** The Internationalization message helper.
46       */
47      protected static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N
48  
49      /** The class of the target object.
50       */
51      transient private Class targetClass;
52      
53      /** The name of the class of the target object.
54       */
55      private String targetClassName;
56  
57      /** The hashCode.
58       */
59      protected int hashCode;
60      
61      /** The key as an Object.
62       */
63      protected Object keyAsObject;
64  
65      /** Constructor with target class.
66       * @param pcClass the class of the target
67       * @since 2.0
68       */
69      protected SingleFieldIdentity(Class pcClass) {
70          if (pcClass == null)
71              throw new NullPointerException();
72          targetClass = pcClass;
73          targetClassName = pcClass.getName();
74      }
75  
76      /** Constructor only for Externalizable.
77       * @since 2.0
78       */
79      public SingleFieldIdentity () {
80      }
81  
82      /** Set the given key as the key for this instance. 
83       * Compute the hash code for the instance.
84       * @since 2.0
85       */
86      protected void setKeyAsObject(Object key) {
87          assertKeyNotNull(key);
88          keyAsObject = key;
89      }
90  
91      /** Assert that the key is not null. Throw a JDONullIdentityException
92       * if the given key is null.
93       * @since 2.0
94       */ 
95      protected void assertKeyNotNull(Object key) {
96          if (key == null) {
97              throw new JDONullIdentityException(
98                  msg.msg("EXC_SingleFieldIdentityNullParameter")); //NOI18N
99          }
100     }
101     
102     /** Return the target class.
103      * @return the target class.
104      * @since 2.0
105      */
106     public Class getTargetClass() {
107         return targetClass;
108     }
109 
110     /** Return the target class name.
111      * @return the target class name.
112      * @since 2.0
113      */
114     public String getTargetClassName() {
115         return targetClassName;
116     }
117 
118     /** Return the key as an Object. The method is synchronized to avoid
119      * race conditions in multi-threaded environments.
120      * @return the key as an Object.
121      * @since 2.0
122      */
123     public synchronized Object getKeyAsObject() {
124         if (keyAsObject == null) {
125             keyAsObject = createKeyAsObject();
126         }
127         return keyAsObject;
128     }
129     
130     /** Create the key as an Object.
131      * @return the key as an Object;
132      * @since 2.0
133      */
134     protected Object createKeyAsObject() {
135         throw new JDOFatalInternalException
136                 (msg.msg("EXC_CreateKeyAsObjectMustNotBeCalled"));
137     }
138     
139     /** Check the class and class name and object type. If restored
140      * from serialization, class will be null so compare class name.
141      * @param obj the other object
142      * @return true if the class or class name is the same
143      */
144     public boolean equals(Object obj) {
145         if (this == obj) {
146             return true;
147         } else if (obj == null || this.getClass() != obj.getClass()) {
148             return false;
149         } else {
150             SingleFieldIdentity other = (SingleFieldIdentity) obj;
151             if (targetClass != null && targetClass == other.targetClass)
152                 return true;
153             return targetClassName.equals (other.targetClassName);
154         }
155     }
156 
157     /** Return the hash code of the class name.
158      * @return the hash code of the class name
159      * @since 2.0
160      */
161     protected int hashClassName() {
162         return targetClassName.hashCode();
163     }
164     
165     /** Return the cached hash code.
166      * @return the cached hash code.
167      */
168     public int hashCode() {
169         return hashCode;
170     }
171     
172     /** Write to the output stream.
173      * @param out the stream
174      */
175     public void writeExternal(ObjectOutput out) throws IOException {
176         out.writeObject(targetClassName);
177         out.writeInt(hashCode);
178     }
179 
180     /** Read from the input stream.
181      * Creates a new instance with the target class name set
182      */
183     public void readExternal(ObjectInput in)
184             throws IOException, ClassNotFoundException {
185         targetClass = null;
186         targetClassName = (String)in.readObject();
187         hashCode = in.readInt();
188     }
189 
190     /** Determine the ordering of identity objects. Only the class name
191      *  is compared. This method is only used by subclasses.
192      * @param o Other identity
193      * @return The relative ordering between the objects
194      * @since 2.2
195      */
196     protected int compare(SingleFieldIdentity o) {
197             return targetClassName.compareTo(o.targetClassName);
198         }
199  
200 }