1 2 12 package com.versant.core.common; 13 14 import com.versant.core.metadata.ClassMetaData; 15 import com.versant.core.metadata.FieldMetaData; 16 import com.versant.core.metadata.MDStatics; 17 import com.versant.core.metadata.ModelMetaData; 18 import com.versant.core.util.FastParser; 19 import com.versant.core.util.OIDObjectInput; 20 import com.versant.core.util.OIDObjectOutput; 21 22 import java.io.*; 23 import java.math.BigDecimal ; 24 import java.math.BigInteger ; 25 import java.util.Date ; 26 import java.util.Locale ; 27 28 35 public abstract class GenericOID implements OID, Externalizable 36 37 { 38 39 protected ClassMetaData cmd; 40 protected boolean resolved; 41 protected Object [] pk; 42 43 public GenericOID() { 44 } 45 46 public GenericOID(ClassMetaData cmd, boolean resolved) { 47 if (cmd == null) { 48 throw BindingSupportImpl.getInstance().internal("The supplied cmd is null"); 49 } 50 this.cmd = cmd; 51 this.resolved = resolved; 52 pk = new Object [cmd.pkFields == null ? 1 : cmd.pkFields.length]; 53 } 54 55 58 public Object [] getPk() { 59 return pk; 60 } 61 62 70 public boolean isResolved() { 71 return resolved; 72 } 73 74 81 public void resolve(State state) { 82 if (!resolved) { 83 cmd = state.getClassMetaData(); 84 resolved = true; 85 } 86 } 87 88 public int getClassIndex() { 89 return cmd.index; 90 } 91 92 public ClassMetaData getClassMetaData() { 93 if (!resolved) { 94 throw BindingSupportImpl.getInstance().internal( 95 "Called 'getClassMetaData()' on unresolved oid"); 96 } 97 return cmd; 98 } 99 100 public ClassMetaData getAvailableClassMetaData() { 101 return cmd; 102 } 103 104 public ClassMetaData getBaseClassMetaData() { 105 return cmd.top; 106 } 107 108 public int getIdentityType() { 109 return cmd.top.identityType; 110 } 111 112 public void copyKeyFields(Object [] data) { 113 for (int i = 0; i < pk.length; i++) pk[i] = data[i]; 114 } 115 116 119 public OID copy() { 120 GenericOID copy = newInstance(); 121 copy.resolved = resolved; 122 copy.cmd = cmd; 123 copy.pk = pk; 124 return copy; 125 } 126 127 protected abstract GenericOID newInstance(); 128 129 public void fillFromPK(Object pk) { 130 FieldMetaData[] pkFields = cmd.pkFields; 131 Object [] pkValues = new Object [pkFields.length]; 132 for (int i = 0; i < pkFields.length; i++) { 133 try { 134 pkValues[i] = pk.getClass().getField(pkFields[i].getPkFieldName()).get(pk); 135 } catch (Exception e) { 136 throw BindingSupportImpl.getInstance().internal(e.getMessage(), e); 137 } 138 } 139 copyKeyFields(pkValues); 140 } 141 142 public OID fillFromIDObject(Object id) { 143 pk = new Object [cmd.pkFields.length]; 144 if (cmd.objectIdClass == null) { 145 if (cmd.pkFields.length != 1) { 146 throw BindingSupportImpl.getInstance().invalidOperation( 147 "Classes with application can only have a single pk " + 148 "field if a ApplicationId class is not specified"); 149 } 150 pk[0] = id; 151 } else { 152 FieldMetaData[] pkFields = cmd.pkFields; 153 Object [] pkValues = pk; 154 for (int i = 0; i < pkFields.length; i++) { 155 try { 156 pkValues[i] = pk.getClass().getField(pkFields[i].getPkFieldName()).get(pk); 157 } catch (Exception e) { 158 throw BindingSupportImpl.getInstance().internal(e.getMessage(), e); 159 } 160 } 161 } 162 return this; 163 } 164 165 170 public void fillFromIDString(String s, int i) { 171 try { 172 switch (cmd.datastoreIdentityTypeCode) { 176 case MDStatics.INTW: 177 case MDStatics.INT: 178 pk[0] = new Integer (FastParser.parseInt(s, i)); 179 break; 180 case MDStatics.SHORTW: 181 case MDStatics.SHORT: 182 pk[0] = new Short ((short)FastParser.parseInt(s, i)); 183 break; 184 case MDStatics.STRING: 185 pk[0] = s.substring(i); 186 break; 187 case MDStatics.BOOLEANW: 188 case MDStatics.BOOLEAN: 189 pk[0] = new Boolean (s.substring(i)); 190 break; 191 case MDStatics.BYTEW: 192 case MDStatics.BYTE: 193 pk[0] = new Byte ((byte)FastParser.parseInt(s, i)); 194 break; 195 case MDStatics.BIGDECIMAL: 196 pk[0] = new BigDecimal (s.substring(i)); 197 break; 198 case MDStatics.BIGINTEGER: 199 pk[0] = new BigInteger (s.substring(i)); 200 break; 201 case MDStatics.DOUBLEW: 202 case MDStatics.DOUBLE: 203 pk[0] = new Double (s.substring(i)); 204 break; 205 case MDStatics.FLOATW: 206 case MDStatics.FLOAT: 207 pk[0] = new Float (s.substring(i)); 208 break; 209 case MDStatics.LONGW: 210 case MDStatics.LONG: 211 pk[0] = new Long (FastParser.parseLong(s, i)); 212 break; 213 default: 214 throw BindingSupportImpl.getInstance().internal( 215 "Unable to create id from the string '" + s + 216 "' type code " + cmd.datastoreIdentityTypeCode); 217 } 218 } catch (Exception e) { 219 throw BindingSupportImpl.getInstance().invalidOperation("invalid OID String: '" + s + "'", e); 220 } 221 } 222 223 public int hashCode() { 224 if (pk == null) return super.hashCode(); 225 int hc = pk[0].hashCode() + cmd.top.index; 226 for (int i = 1; i < pk.length; i++) hc = hc * 17 + pk[i].hashCode(); 227 return hc; 228 } 229 230 public boolean equals(Object obj) { 231 if (obj == null) return false; 232 if (obj instanceof GenericOID) { 233 GenericOID o = (GenericOID)obj; 234 if (o.cmd.top != cmd.top) return false; 235 for (int i = pk.length - 1; i >= 0; i--) { 236 if (pk[i] == null) { 237 if (o.pk[i] != null) return false; 238 } else if (!pk[i].equals(o.pk[i])) { 239 return false; 240 } 241 } 242 return true; 243 } else { 244 return obj.equals(this); 245 } 246 } 247 248 public String toString() { 249 if (!resolved) { 250 throw BindingSupportImpl.getInstance().internal( 251 "This oid is not resolved to its actual type"); 252 } 253 return toStringImp(); 254 } 255 256 259 public String toStringImp() { 260 if (pk == null) return "null pk"; 261 StringBuffer s = new StringBuffer (); 262 s.append(cmd.classId); 263 s.append(MDStatics.OID_STRING_SEPERATOR); 264 int len = pk.length; 265 s.append(pk[0]); 266 for (int i = 1; i < len; i++) { 267 s.append(MDStatics.OID_STRING_SEPERATOR); 268 s.append(pk[i]); 269 } 270 return s.toString(); 271 } 272 273 public abstract String toSString(); 274 275 279 public String toPkString() { 280 if (pk == null) return "null pk"; 281 StringBuffer s = new StringBuffer (); 282 int len = pk.length; 283 s.append(pk[0]); 284 for (int i = 1; i < len; i++) { 285 s.append(','); 286 s.append(' '); 287 s.append(pk[i]); 288 } 289 return s.toString(); 290 } 291 292 public int compareTo(Object o) { 293 OID oo = (OID)o; 294 int diff = cmd.top.index - oo.getBaseClassMetaData().index; 295 if (diff != 0) return diff; 296 if (oo.isNew()) { 297 return +1; } else { 299 GenericOID oid = (GenericOID)oo; 300 for (int i = 0; i < pk.length; i++) { 301 Object a = pk[i]; 302 Object b = oid.pk[i]; 303 if (a instanceof Comparable ) { 304 diff = ((Comparable )a).compareTo(b); 305 } else { 306 diff = a.toString().compareTo(b.toString()); 308 } 309 if (diff != 0) return diff; 310 } 311 return 0; 312 } 313 } 314 315 319 public long getLongPrimaryKey() { 320 return ((Number )pk[0]).longValue(); 321 } 322 323 327 public void setLongPrimaryKey(long pki) { 328 switch (cmd.datastoreIdentityTypeCode) { 329 case MDStatics.INTW: 330 case MDStatics.INT: 331 pk[0] = new Integer ((int)pki); 332 break; 333 case MDStatics.SHORTW: 334 case MDStatics.SHORT: 335 pk[0] = new Short ((short)pki); 336 break; 337 case MDStatics.BYTEW: 338 case MDStatics.BYTE: 339 pk[0] = new Byte ((byte)pki); 340 break; 341 case MDStatics.LONGW: 342 case MDStatics.LONG: 343 pk[0] = new Long (pki); 344 break; 345 default: 346 throw BindingSupportImpl.getInstance().internal( 347 "Unhandled java type code " + cmd.datastoreIdentityTypeCode); 348 } 349 } 350 351 public void populateObjectIdClassInstance(Object o) { 352 ClassMetaData cmd = getAvailableClassMetaData(); 353 if (cmd.identityType != MDStatics.IDENTITY_TYPE_APPLICATION) { 354 throw BindingSupportImpl.getInstance().internal("not an app identity class: " + 355 cmd.qname); 356 } 357 FieldMetaData[] a = cmd.pkFields; 358 for (int i = 0; i < a.length; i++) { 359 try { 360 a[i].getObjectidClassField().set(o, pk[i]); 361 } catch (Exception e) { 362 throw BindingSupportImpl.getInstance().internal(e.toString(), e); 363 } 364 } 365 } 366 367 public boolean isNew() { 368 return false; 369 } 370 371 public OID getMappedOID() { 372 return this; 373 } 374 375 public OID getRealOID() { 376 return this; 377 } 378 379 public OID getAvailableOID() { 380 return this; 381 } 382 383 public int getAvailableClassId() { 384 return getAvailableClassMetaData().classId; 385 } 386 387 public void setCmd(ClassMetaData cmd) { 388 this.cmd = cmd; 389 } 390 391 public void writeExternal(OIDObjectOutput os) throws IOException { 392 writeExternalImp(os); 393 } 394 395 public void writeExternal(ObjectOutput os) throws IOException { 396 os.writeShort(getClassIndex()); 397 os.writeBoolean(resolved); 398 writeExternalImp(os); 399 } 400 401 private void writeExternalImp(ObjectOutput os) throws IOException { 402 if (cmd.pkFields == null) { 403 writeObjectByTypeCode(pk[0], cmd.datastoreIdentityTypeCode, os); 404 } else { 405 int n = cmd.pkFields.length; 406 for (int i = 0; i < n; i++) { 407 writeObjectByTypeCode(pk[i], cmd.pkFields[i].typeCode, os); 408 } 409 } 410 } 411 412 public void readExternal(OIDObjectInput is) throws ClassNotFoundException , 413 IOException { 414 readExternalImp(is); 415 } 416 417 public void readExternal(ObjectInput is) throws ClassNotFoundException , 418 IOException { 419 cmd = ModelMetaData.getThreadMetaData().classes[is.readShort()]; 420 resolved = is.readBoolean(); 421 readExternalImp(is); 422 } 423 424 private void readExternalImp(ObjectInput is) throws IOException { 425 if (cmd.pkFields == null) { 428 pk = new Object []{readObjectByTypeCode(cmd.datastoreIdentityTypeCode, is)}; 429 } else { 430 int n = cmd.pkFields.length; 431 pk = new Object [n]; 432 for (int i = 0; i < n; i++) { 433 pk[i] = readObjectByTypeCode(cmd.pkFields[i].typeCode, is); 434 } 435 } 436 } 437 438 private void writeObjectByTypeCode(Object value, int typeCode, ObjectOutput os) 439 throws IOException { 440 if (value != null) { 441 os.writeBoolean(false); 443 switch (typeCode) { 444 case MDStatics.INTW: 445 case MDStatics.INT: 446 os.writeInt(((Integer )value).intValue()); 447 break; 448 case MDStatics.CHARW: 449 case MDStatics.CHAR: 450 os.writeInt(((Character )value).charValue()); 451 break; 452 case MDStatics.SHORTW: 453 case MDStatics.SHORT: 454 os.writeShort(((Short )value).intValue()); 455 break; 456 case MDStatics.STRING: 457 os.writeUTF((String )value); 458 break; 459 case MDStatics.BOOLEANW: 460 case MDStatics.BOOLEAN: 461 os.writeBoolean(((Boolean )value).booleanValue()); 462 break; 463 case MDStatics.BYTEW: 464 case MDStatics.BYTE: 465 os.writeByte(((Byte )value).byteValue()); 466 break; 467 case MDStatics.DOUBLEW: 468 case MDStatics.DOUBLE: 469 os.writeDouble(((Double )value).doubleValue()); 470 break; 471 case MDStatics.FLOATW: 472 case MDStatics.FLOAT: 473 os.writeFloat(((Float )value).floatValue()); 474 break; 475 case MDStatics.LONGW: 476 case MDStatics.LONG: 477 os.writeLong(((Long )value).longValue()); 478 break; 479 case MDStatics.LOCALE: 480 final Locale l = (Locale )value; 481 os.writeUTF(l.getLanguage()); 482 os.writeUTF(l.getCountry()); 483 os.writeUTF(l.getVariant()); 484 break; 485 case MDStatics.BIGDECIMAL: 486 os.writeUTF(value.toString()); 487 break; 488 case MDStatics.BIGINTEGER: 489 os.writeUTF(value.toString()); 490 break; 491 case MDStatics.DATE: 492 os.writeLong(((Date )value).getTime()); 493 break; 494 default: 495 throw BindingSupportImpl.getInstance().internal( 496 "Unable to write type code " + typeCode); 497 } 498 } else { 499 os.writeBoolean(true); 501 } 502 } 503 504 private Object readObjectByTypeCode(int typeCode, ObjectInput is) 505 throws IOException { 506 if (is.readBoolean()) { 507 return null; 508 } else { 509 switch (typeCode) { 510 case MDStatics.INTW: 511 case MDStatics.INT: 512 return new Integer (is.readInt()); 513 case MDStatics.CHARW: 514 case MDStatics.CHAR: 515 return new Character (is.readChar()); 516 case MDStatics.SHORTW: 517 case MDStatics.SHORT: 518 return new Short (is.readShort()); 519 case MDStatics.STRING: 520 return is.readUTF(); 521 case MDStatics.BOOLEANW: 522 case MDStatics.BOOLEAN: 523 return new Boolean (is.readBoolean()); 524 case MDStatics.BYTEW: 525 case MDStatics.BYTE: 526 return new Byte (is.readByte()); 527 case MDStatics.DOUBLEW: 528 case MDStatics.DOUBLE: 529 return new Double (is.readDouble()); 530 case MDStatics.FLOATW: 531 case MDStatics.FLOAT: 532 return new Float (is.readFloat()); 533 case MDStatics.LONGW: 534 case MDStatics.LONG: 535 return new Long (is.readLong()); 536 case MDStatics.LOCALE: 537 return new Locale (is.readUTF(), is.readUTF(), 538 is.readUTF()); 539 case MDStatics.BIGDECIMAL: 540 return new BigDecimal (is.readUTF()); 541 case MDStatics.BIGINTEGER: 542 return new BigInteger (is.readUTF()); 543 case MDStatics.DATE: 544 return new Date (is.readLong()); 545 default: 546 throw BindingSupportImpl.getInstance().internal( 547 "Unable to read java type code " + typeCode); 548 } 549 } 550 } 551 552 } 553 | Popular Tags |