1 /**********************************************************************
2 Copyright (c) 2002 Kelly Grizzle (TJDO) and others. All rights reserved.
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14
15
16 Contributors:
17 2003 Erik Bengtson - Refactored OID
18 2003 Andy Jefferson - fixed OID(String)
19 2003 Andy Jefferson - coding standards
20 2004 Andy Jefferson - fixes to allow full use of long or String OIDs
21 2005 Erik Bengtson - removed oidType
22 2007 Brett Porter - changed hashcode algorithm to avoid collisions (see CORE-3297)
23 ...
24 **********************************************************************/
25 package org.jpox.store;
26
27 import org.jpox.ClassNameConstants;
28 import org.jpox.util.Localiser;
29
30 /**
31 * An object identifier. OIDs are normally used as object identifiers for
32 * persistent objects that use datastore identity. They're also used for
33 * view objects, which actually use non-datastore identity. The behaviour of
34 * this class is governed by JDO spec 5.4.3.
35 *
36 * @version $Revision: 1.17 $
37 */
38 public class OID
39 implements java.io.Serializable
40 {
41 private transient static final Localiser LOCALISER = Localiser.getInstance( "org.jpox.store.Localisation" );
42
43 /**
44 * Separator to use between fields.
45 */
46 private transient static final String oidSeparator = "[OID]";
47
48 // JDO spec 5.4.3 - serializable fields required to be public.
49
50 /**
51 * The identity.
52 */
53 public final Object oid;
54
55 /**
56 * The PersistenceCapable class name
57 */
58 public final String pcClass;
59
60 /**
61 * pre-created toString to improve performance *
62 */
63 public final String toString;
64
65 /**
66 * pre-created hasCode to improve performance *
67 */
68 public final int hashCode;
69
70 /**
71 * Creates an OID with the no value.
72 * Required by the JDO spec
73 */
74 public OID()
75 {
76 oid = null;
77 pcClass = null;
78 toString = null;
79 hashCode = -1;
80 }
81
82 /**
83 * Create a string datastore identity
84 *
85 * @param pcClass The PersistenceCapable class that this represents
86 * @param object The value
87 */
88 public OID( String pcClass, Object object )
89 {
90 this.pcClass = pcClass;
91 this.oid = object;
92
93 StringBuffer s = new StringBuffer();
94 s.append( this.oid.toString() );
95 s.append( oidSeparator );
96 s.append( this.pcClass );
97 toString = s.toString();
98 hashCode = this.oid.hashCode() * 39 + pcClass.hashCode();
99 }
100
101 /**
102 * Constructs an OID from its string representation that is
103 * consistent with the output of toString().
104 *
105 * @param str the string representation of an OID.
106 * @throws IllegalArgumentException if the given string representation is not valid.
107 * @see #toString
108 */
109 public OID( String str )
110 throws IllegalArgumentException
111 {
112 if ( str.length() < 2 )
113 {
114 throw new IllegalArgumentException( LOCALISER.msg( "OID.InvalidValue", str ) );
115 }
116
117 int start = 0;
118 int end = str.indexOf( oidSeparator, start );
119 String oidStr = str.substring( start, end );
120 Object oidValue = null;
121 try
122 {
123 // Use Long if possible, else String
124 oidValue = new Long( oidStr );
125 }
126 catch ( NumberFormatException nfe )
127 {
128 oidValue = oidStr;
129 }
130 oid = oidValue;
131
132 start = end + oidSeparator.length();
133 this.pcClass = str.substring( start, str.length() );
134
135 toString = str;
136 hashCode = this.oid.hashCode() * 39 + pcClass.hashCode();
137 }
138
139 /**
140 * Returns copy of the requested oid to be accessed by the user.
141 *
142 * @return Copy of the OID.
143 */
144 public Object getNewObjectIdCopy()
145 {
146 return new OID( this.pcClass, this.oid );
147 }
148
149 /**
150 * Provides the OID in a form that can be used by the database as a key.
151 *
152 * @return The key value
153 */
154 public Object keyValue()
155 {
156 return oid;
157 }
158
159 /**
160 * Equality operator.
161 *
162 * @param obj Object to compare against
163 * @return Whether they are equal
164 */
165 public boolean equals( Object obj )
166 {
167 if ( obj == null )
168 {
169 return false;
170 }
171 if ( obj == this )
172 {
173 return true;
174 }
175 if ( !( obj.getClass().getName().equals( ClassNameConstants.OID ) ) )
176 {
177 return false;
178 }
179 if ( hashCode() != obj.hashCode() )
180 {
181 return false;
182 }
183 return true;
184 }
185
186 /**
187 * Accessor for the hashcode
188 *
189 * @return Hashcode for this object
190 */
191 public int hashCode()
192 {
193 return hashCode;
194 }
195
196 /**
197 * Returns the string representation of the OID.
198 * Will be a string such as "1[OID]org.jpox.samples.MyClass"
199 * where
200 * <UL>
201 * <LI>1 is the identity "id"</LI>
202 * <LI>class name is the name of the PersistenceCapable class that it represents</LI>
203 * </UL>
204 *
205 * @return the string representation of the OID.
206 */
207 public String toString()
208 {
209 return toString;
210 }
211
212 /**
213 * Accessor for the PC class name
214 *
215 * @return the PC Class
216 */
217 public String getPcClass()
218 {
219 return pcClass;
220 }
221 }