1 21 package oracle.toplink.essentials.descriptors; 23 24 import java.math.*; 25 import java.io.*; 26 import java.util.*; 27 import oracle.toplink.essentials.mappings.*; 28 import oracle.toplink.essentials.internal.helper.*; 29 import oracle.toplink.essentials.queryframework.*; 30 import oracle.toplink.essentials.expressions.*; 31 import oracle.toplink.essentials.exceptions.*; 32 import oracle.toplink.essentials.internal.descriptors.OptimisticLockingPolicy; 33 import oracle.toplink.essentials.internal.sessions.ObjectChangeSet; 34 import oracle.toplink.essentials.internal.sessions.AbstractRecord; 35 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl; 36 import oracle.toplink.essentials.internal.sessions.AbstractSession; 37 38 43 public class VersionLockingPolicy implements OptimisticLockingPolicy, Serializable { 44 protected DatabaseField writeLockField; 45 protected int lockValueStored; 46 protected ClassDescriptor descriptor; 47 protected transient Expression cachedExpression; 48 public final static int IN_CACHE = 1; 49 public final static int IN_OBJECT = 2; 50 51 56 public VersionLockingPolicy() { 57 super(); 58 storeInCache(); 59 } 60 61 68 public VersionLockingPolicy(String fieldName) { 69 this(new DatabaseField(fieldName)); 70 } 71 72 78 public VersionLockingPolicy(DatabaseField field) { 79 this(); 80 setWriteLockField(field); 81 } 82 83 88 public void addLockFieldsToUpdateRow(AbstractRecord databaseRow, AbstractSession session) { 89 if (isStoredInCache()) { 90 databaseRow.put(getWriteLockField(), null); 91 } 92 } 93 94 100 public void addLockValuesToTranslationRow(ObjectLevelModifyQuery query) { 101 Object value; 102 if (isStoredInCache()) { 103 value = query.getSession().getIdentityMapAccessor().getWriteLockValue(query.getPrimaryKey(), query.getObject().getClass()); 104 } else { 105 value = lockValueFromObject(query.getObject()); 106 } 107 if (value == null) { 108 if (query.isDeleteObjectQuery()) { 109 throw OptimisticLockException.noVersionNumberWhenDeleting(query.getObject(), query); 110 } else { 111 throw OptimisticLockException.noVersionNumberWhenUpdating(query.getObject(), query); 112 } 113 } 114 query.getTranslationRow().put(getWriteLockField(), value); 115 } 116 117 123 public Expression buildDeleteExpression(DatabaseTable table, Expression mainExpression, AbstractRecord row) { 124 return buildUpdateExpression(table, mainExpression, row, null); 126 } 127 128 133 protected Expression buildExpression() { 134 ExpressionBuilder builder = new ExpressionBuilder(); 135 136 return builder.getField(getWriteLockField()).equal(builder.getParameter(getWriteLockField())); 137 } 138 139 146 public Expression buildUpdateExpression(DatabaseTable table, Expression mainExpression, AbstractRecord row, AbstractRecord row2) { 147 if (cachedExpression == null) { 148 cachedExpression = buildExpression(); 149 } 150 if (getWriteLockField().getTableName().equals(table.getName())) { 151 return mainExpression.and(cachedExpression); 152 } 153 return mainExpression; 154 } 155 156 160 public Object clone() { 161 try { 162 return super.clone(); 163 } catch (CloneNotSupportedException e) { 164 return null; 165 } 166 } 167 168 180 public int compareWriteLockValues(Object value1, Object value2) { 181 BigDecimal bigDecimalValue1, bigDecimalValue2; 182 if(value1 instanceof BigDecimal) { 183 bigDecimalValue1 = (BigDecimal)value1; 184 } else { 185 bigDecimalValue1 = new BigDecimal(((Number )value1).longValue()); 186 } 187 if(value2 instanceof BigDecimal) { 188 bigDecimalValue2 = (BigDecimal)value2; 189 } else { 190 bigDecimalValue2 = new BigDecimal(((Number )value2).longValue()); 191 } 192 return bigDecimalValue1.compareTo(bigDecimalValue2); 193 } 194 195 201 protected Class getDefaultLockingFieldType() { 202 return ClassConstants.BIGDECIMAL; 203 204 } 205 206 211 public Object getBaseValue() { 212 return new BigDecimal(0); 213 } 214 215 218 protected ClassDescriptor getDescriptor() { 219 return descriptor; 220 } 221 222 226 protected Object getInitialWriteValue(AbstractSession session) { 227 return new BigDecimal(1); 228 } 229 230 235 protected Object getNewLockValue(ModifyQuery query) { 236 Class objectClass = query.getDescriptor().getJavaClass(); 237 Number value; 238 Number newWriteLockValue = null; 239 if (isStoredInCache()) { 240 value = (Number )query.getSession().getIdentityMapAccessor().getWriteLockValue(((WriteObjectQuery)query).getPrimaryKey(), objectClass); 241 } else { 242 value = (Number )lockValueFromObject(((ObjectLevelModifyQuery)query).getObject()); 243 } 244 if (value == null) { 245 throw oracle.toplink.essentials.exceptions.OptimisticLockException.noVersionNumberWhenUpdating(((ObjectLevelModifyQuery)query).getObject(), (ObjectLevelModifyQuery)query); 246 } 247 248 newWriteLockValue = incrementWriteLockValue(value); 250 return newWriteLockValue; 251 } 252 253 260 protected Vector getUnmappedFields() { 261 Vector fields = new Vector(1); 262 if (isStoredInCache()) { 263 fields.addElement(getWriteLockField()); 264 } 265 return fields; 266 } 267 268 273 public Object getValueToPutInCache(AbstractRecord row, AbstractSession session) { 274 if (isStoredInCache()) { 275 return row.get(getWriteLockField()); 276 } else { 277 return null; 278 } 279 } 280 281 289 public int getVersionDifference(Object currentValue, Object domainObject, Vector primaryKeys, AbstractSession session) { 290 Number writeLockFieldValue; 291 Number newWriteLockFieldValue = (Number )currentValue; 292 293 if (newWriteLockFieldValue == null) { 295 return 0; } 297 298 if (isStoredInCache()) { 299 writeLockFieldValue = (Number )session.getIdentityMapAccessor().getWriteLockValue(primaryKeys, domainObject.getClass()); 300 } else { 301 writeLockFieldValue = (Number )lockValueFromObject(domainObject); 302 } 303 if (writeLockFieldValue == null) { 304 writeLockFieldValue = new BigDecimal(0); } 306 if (!(writeLockFieldValue instanceof BigDecimal)) { 307 writeLockFieldValue = new BigDecimal(writeLockFieldValue.longValue()); 308 } 309 if (!(newWriteLockFieldValue instanceof BigDecimal)) { 310 newWriteLockFieldValue = new BigDecimal(newWriteLockFieldValue.longValue()); 311 } 312 return ((BigDecimal)newWriteLockFieldValue).subtract((BigDecimal)writeLockFieldValue).intValue(); 313 } 314 315 319 public DatabaseField getWriteLockField() { 320 return writeLockField; 321 } 322 323 327 public String getWriteLockFieldName() { 328 return getWriteLockField().getQualifiedName(); 329 } 330 331 335 public Expression getWriteLockUpdateExpression(ExpressionBuilder builder) { 336 return ExpressionMath.add(builder.getField(writeLockField.getName()), 1); 337 } 338 339 343 public Object getWriteLockValue(Object domainObject, java.util.Vector primaryKey, AbstractSession session) { 344 Number writeLockFieldValue; 345 if (isStoredInCache()) { 346 writeLockFieldValue = (Number )session.getIdentityMapAccessor().getWriteLockValue(primaryKey, domainObject.getClass()); 347 } else { 348 writeLockFieldValue = (Number )lockValueFromObject(domainObject); 349 } 350 return writeLockFieldValue; 351 } 352 353 357 protected Number incrementWriteLockValue(Number numberValue) { 358 BigDecimal writeLockValue; 359 360 if (numberValue instanceof BigDecimal) { 361 writeLockValue = (BigDecimal)numberValue; 362 } else { 363 writeLockValue = new BigDecimal(numberValue.doubleValue()); 364 } 365 366 return writeLockValue.add(new BigDecimal(1)); 367 } 368 369 373 public void initialize(AbstractSession session) { 374 DatabaseMapping mapping = mappingFromLockField(); 375 if (mapping == null) { 376 if (isStoredInObject()) { 377 throw OptimisticLockException.mustHaveMappingWhenStoredInObject(descriptor.getJavaClass()); 378 } else { 379 return; 380 } 381 } 382 if (mapping.isReadOnly()) { 383 throw DescriptorException.mappingCanNotBeReadOnly(mapping); 384 } else { 385 if (isStoredInCache()) { 386 session.getIntegrityChecker().handleError(DescriptorException.mustBeReadOnlyMappingWhenStoredInCache(mapping)); 387 } 388 } 389 } 390 391 395 public void initializeProperties() { 396 DatabaseField dbField = getWriteLockField(); 397 398 descriptor.buildField(dbField); 399 if (dbField.getType() == null) { 400 dbField.setType(getDefaultLockingFieldType()); 402 403 } 404 Enumeration enumtr = this.getUnmappedFields().elements(); 405 while (enumtr.hasMoreElements()) { 406 DatabaseField lockField; 407 lockField = (DatabaseField)enumtr.nextElement(); 408 descriptor.getFields().addElement(lockField); 409 } 410 } 411 412 416 public boolean isChildWriteLockValueGreater(AbstractSession session, java.util.Vector primaryKey, Class original, ObjectChangeSet changeSet) { 417 if (isStoredInCache()) { 418 Number writeLockValue = (Number )changeSet.getWriteLockValue(); 421 Number parentValue = (Number )session.getIdentityMapAccessor().getWriteLockValue(primaryKey, original); 422 if ((parentValue != null) && (!(parentValue instanceof BigDecimal))) { 423 parentValue = new BigDecimal(parentValue.longValue()); 424 } 425 if ((writeLockValue != null) && (!(writeLockValue instanceof BigDecimal))) { 426 writeLockValue = new BigDecimal(writeLockValue.longValue()); 427 } 428 if (writeLockValue != null) { if ((parentValue == null) || (((BigDecimal)parentValue).compareTo((BigDecimal)writeLockValue) == -1)) { 430 return true; 431 } 432 } 433 } 434 return false; 435 } 436 437 441 public boolean isChildWriteLockValueGreater(UnitOfWorkImpl uow, java.util.Vector primaryKey, Class original) { 442 if (isStoredInCache()) { 443 Number writeLockValue = (Number )uow.getIdentityMapAccessor().getWriteLockValue(primaryKey, original); 446 Number parentValue = (Number )uow.getParent().getIdentityMapAccessor().getWriteLockValue(primaryKey, original); 447 if ((parentValue != null) && (!(parentValue instanceof BigDecimal))) { 448 parentValue = new BigDecimal(parentValue.longValue()); 449 } 450 if ((writeLockValue != null) && (!(writeLockValue instanceof BigDecimal))) { 451 writeLockValue = new BigDecimal(writeLockValue.longValue()); 452 } 453 if (writeLockValue != null) { if ((parentValue == null) || (((BigDecimal)parentValue).compareTo((BigDecimal)writeLockValue) == -1)) { 455 return true; 456 } 457 } 458 } 459 return false; 460 } 461 462 467 public boolean isNewerVersion(Object currentValue, Object domainObject, java.util.Vector primaryKey, AbstractSession session) { 468 Number writeLockFieldValue; 469 Number newWriteLockFieldValue = (Number )currentValue; 470 471 if (newWriteLockFieldValue == null) { 473 return true; 474 } 475 476 if (isStoredInCache()) { 477 writeLockFieldValue = (Number )session.getIdentityMapAccessor().getWriteLockValue(primaryKey, domainObject.getClass()); 478 } else { 479 writeLockFieldValue = (Number )lockValueFromObject(domainObject); 480 } 481 if (!(writeLockFieldValue instanceof BigDecimal)) { 482 writeLockFieldValue = new BigDecimal(writeLockFieldValue.longValue()); 483 } 484 if (!(newWriteLockFieldValue instanceof BigDecimal)) { 485 newWriteLockFieldValue = new BigDecimal(newWriteLockFieldValue.longValue()); 486 } 487 if ((writeLockFieldValue != null) && (((BigDecimal)newWriteLockFieldValue).compareTo((BigDecimal)writeLockFieldValue) != 1)) { 488 return false; 489 } 490 return true; 491 } 492 493 498 public boolean isNewerVersion(AbstractRecord databaseRow, Object domainObject, java.util.Vector primaryKey, AbstractSession session) { 499 Number writeLockFieldValue; 500 Number newWriteLockFieldValue = (Number )databaseRow.get(getWriteLockField()); 501 if (isStoredInCache()) { 502 writeLockFieldValue = (Number )session.getIdentityMapAccessor().getWriteLockValue(primaryKey, domainObject.getClass()); 503 } else { 504 writeLockFieldValue = (Number )lockValueFromObject(domainObject); 505 } 506 if (!(writeLockFieldValue instanceof BigDecimal)) { 507 writeLockFieldValue = new BigDecimal(writeLockFieldValue.longValue()); 508 } 509 if (!(newWriteLockFieldValue instanceof BigDecimal)) { 510 newWriteLockFieldValue = new BigDecimal(newWriteLockFieldValue.longValue()); 511 } 512 if ((writeLockFieldValue != null) && (((BigDecimal)newWriteLockFieldValue).compareTo((BigDecimal)writeLockFieldValue) != 1)) { 513 return false; 514 } 515 return true; 516 } 517 518 522 public boolean isStoredInCache() { 523 return lockValueStored == IN_CACHE; 524 } 525 526 530 public boolean isStoredInObject() { 531 return lockValueStored == IN_OBJECT; 532 } 533 534 538 protected Object lockValueFromObject(Object domainObject) { 539 return getDescriptor().getObjectBuilder().getBaseValueForField(getWriteLockField(), domainObject); 540 } 541 542 547 protected DatabaseMapping mappingFromLockField() { 548 return descriptor.getObjectBuilder().getMappingForField(getWriteLockField()); 549 } 550 551 555 public void mergeIntoParentCache(UnitOfWorkImpl uow, Vector primaryKey, Object object) { 556 if (isStoredInCache()) { 557 Object parentValue = uow.getParent().getIdentityMapAccessor().getWriteLockValue(primaryKey, object.getClass()); 558 uow.getIdentityMapAccessor().updateWriteLockValue(primaryKey, object.getClass(), parentValue); 559 } 560 } 561 562 565 public void setDescriptor(ClassDescriptor descriptor) { 566 this.descriptor = descriptor; 567 } 568 569 575 public void setIsStoredInCache(boolean isStoredInCache) { 576 if (isStoredInCache) { 577 storeInCache(); 578 } else { 579 storeInObject(); 580 } 581 } 582 583 588 public void setupWriteFieldsForInsert(ObjectLevelModifyQuery query) { 589 Object lockValue = getInitialWriteValue(query.getSession()); 590 ObjectChangeSet objectChangeSet = query.getObjectChangeSet(); 591 if (objectChangeSet != null) { 592 objectChangeSet.setInitialWriteLockValue(lockValue); 593 } 594 updateWriteLockValueForWrite(query, lockValue); 595 } 596 597 602 protected void updateWriteLockValueForWrite(ObjectLevelModifyQuery query, Object lockValue) { 603 query.getModifyRow().put(getWriteLockField(), lockValue); 604 ObjectChangeSet objectChangeSet = query.getObjectChangeSet(); 605 if (objectChangeSet != null) { 606 objectChangeSet.setWriteLockValue(lockValue); 607 } 608 609 AbstractRecord record = getDescriptor().getObjectBuilder().createRecord(1); 615 record.put(getWriteLockField(), lockValue); 616 getDescriptor().getObjectBuilder().assignReturnRow(query.getObject(), query.getSession(), record); 617 if (query.getSession().isUnitOfWork() && (((UnitOfWorkImpl)query.getSession()).getUnitOfWorkChangeSet() != null)) { 618 if (objectChangeSet == null) { 619 objectChangeSet = (ObjectChangeSet)((UnitOfWorkImpl)query.getSession()).getUnitOfWorkChangeSet().getObjectChangeSetForClone(query.getObject()); 621 } 622 query.getQueryMechanism().updateChangeSet(getDescriptor(), objectChangeSet, record, query.getObject()); 623 } 624 } 625 626 631 public void setWriteLockField(DatabaseField writeLockField) { 632 this.writeLockField = writeLockField; 633 } 634 635 640 public void setWriteLockFieldName(String writeLockFieldName) { 641 setWriteLockField(new DatabaseField(writeLockFieldName)); 642 } 643 644 653 public void storeInCache() { 654 lockValueStored = IN_CACHE; 655 } 656 657 664 public void storeInObject() { 665 lockValueStored = IN_OBJECT; 666 } 667 668 675 public void updateRowAndObjectForUpdate(ObjectLevelModifyQuery query, Object domainObject) { 676 Object lockValue = getNewLockValue(query); 677 if (isStoredInCache()) { 678 query.getSession().getIdentityMapAccessor().updateWriteLockValue(query.getPrimaryKey(), domainObject.getClass(), lockValue); 679 } 680 updateWriteLockValueForWrite(query, lockValue); 681 } 682 683 687 public void writeLockValueIntoRow(ObjectLevelModifyQuery query, Object domainObject) { 688 Object lockValue = getWriteLockValue(domainObject, query.getPrimaryKey(), query.getSession()); 689 query.getModifyRow().put(getWriteLockField(), lockValue); 690 if (isStoredInCache()) { 691 query.getSession().getIdentityMapAccessor().updateWriteLockValue(query.getPrimaryKey(), domainObject.getClass(), lockValue); 692 } 693 } 694 695 699 public void validateDelete(int rowCount, Object object, DeleteObjectQuery query) { 700 if (rowCount <= 0) { 701 throw OptimisticLockException.objectChangedSinceLastReadWhenDeleting(object, query); 702 } 703 } 704 705 709 public void validateUpdate(int rowCount, Object object, WriteObjectQuery owner) { 710 if (rowCount <= 0) { 711 throw OptimisticLockException.objectChangedSinceLastReadWhenUpdating(object, owner); 712 } 713 } 714 715 719 public void prepareFetchGroupForReadQuery(FetchGroup fetchGroup, ObjectLevelReadQuery query) { 720 if (isStoredInObject()) { 722 String verAttributeName = descriptor.getObjectBuilder().getMappingForField(writeLockField).getAttributeName(); 723 fetchGroup.addAttribute(verAttributeName); 724 } else { if (!query.getAdditionalFields().contains(writeLockField)) { 726 query.addAdditionalField(writeLockField); 727 } 728 } 729 } 730 } 731 | Popular Tags |