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 }