Program: 67762
Project: 67762
Buggy source:
/** 
 * INTERNAL: <p> This calculates changes in two passes, first on registered objects, second it discovers unregistered new objects on only those objects that changed, and calculates their changes. This also assigns sequence numbers to new objects.
 */
public UnitOfWorkChangeSet calculateChanges(Map registeredObjects,UnitOfWorkChangeSet changeSet,boolean assignSequences){
  getEventManager().preCalculateUnitOfWorkChangeSet();
  if (assignSequences && hasNewObjects()) {
    assignSequenceNumbers(this.newObjectsCloneToOriginal);
  }
  Iterator objects=registeredObjects.keySet().iterator();
  Map changedObjects=new IdentityHashMap();
  Map visitedNodes=new IdentityHashMap();
  while (objects.hasNext()) {
    Object object=objects.next();
    ClassDescriptor descriptor=getDescriptor(object);
    boolean isNew=isObjectNew(object);
    if (isNew || descriptor.getObjectChangePolicy().shouldCompareExistingObjectForChange(object,this,descriptor)) {
      ObjectChangeSet changes=null;
      if (isNew) {
        changes=descriptor.getObjectChangePolicy().calculateChangesForNewObject(object,changeSet,this,descriptor,true);
      }
 else {
        changes=descriptor.getObjectChangePolicy().calculateChangesForExistingObject(object,changeSet,this,descriptor,true);
      }
      if (changes != null) {
        changeSet.addObjectChangeSet(changes,this,true);
        changedObjects.put(object,object);
        if (changes.hasChanges() && !changes.hasForcedChangesFromCascadeLocking()) {
          if (descriptor.hasCascadeLockingPolicies()) {
            for (Enumeration policies=descriptor.getCascadeLockingPolicies().elements(); policies.hasMoreElements(); ) {
              ((CascadeLockingPolicy)policies.nextElement()).lockNotifyParent(object,changeSet,this);
            }
          }
 else           if (descriptor.usesOptimisticLocking() && descriptor.getOptimisticLockingPolicy().isCascaded()) {
            changes.setHasForcedChangesFromCascadeLocking(true);
          }
        }
      }
 else {
        visitedNodes.put(object,object);
      }
    }
 else {
      visitedNodes.put(object,object);
    }
  }
  if (this.project.hasMappingsPostCalculateChangesOnDeleted()) {
    if (hasDeletedObjects()) {
      for (Iterator deletedObjects=getDeletedObjects().keySet().iterator(); deletedObjects.hasNext(); ) {
        Object deletedObject=deletedObjects.next();
        ClassDescriptor descriptor=getDescriptor(deletedObject);
        if (descriptor.hasMappingsPostCalculateChanges()) {
          int size=descriptor.getMappingsPostCalculateChangesOnDeleted().size();
          for (int i=0; i < size; i++) {
            DatabaseMapping mapping=descriptor.getMappingsPostCalculateChangesOnDeleted().get(i);
            mapping.postCalculateChangesOnDeleted(deletedObject,changeSet,this);
          }
        }
      }
    }
  }
  if (this.shouldDiscoverNewObjects) {
    Map newObjects=new IdentityHashMap();
    Map existingObjects=new IdentityHashMap(2);
    discoverUnregisteredNewObjects(changedObjects,newObjects,existingObjects,visitedNodes);
    setUnregisteredExistingObjects(existingObjects);
    setUnregisteredNewObjects(newObjects);
    if (assignSequences) {
      assignSequenceNumbers(newObjects);
    }
    for (Iterator newObjectsEnum=newObjects.values().iterator(); newObjectsEnum.hasNext(); ) {
      Object object=newObjectsEnum.next();
      ClassDescriptor descriptor=getDescriptor(object);
      ObjectChangeSet changes=descriptor.getObjectChangePolicy().calculateChangesForNewObject(object,changeSet,this,descriptor,true);
      changeSet.addObjectChangeSet(changes,this,true);
    }
  }
  this.eventManager.postCalculateUnitOfWorkChangeSet(changeSet);
  return changeSet;
}

Fixed version (ground truth):
/** 
 * INTERNAL: <p> This calculates changes in two passes, first on registered objects, second it discovers unregistered new objects on only those objects that changed, and calculates their changes. This also assigns sequence numbers to new objects.
 */
public UnitOfWorkChangeSet calculateChanges(Map registeredObjects,UnitOfWorkChangeSet changeSet,boolean assignSequences){
  getEventManager().preCalculateUnitOfWorkChangeSet();
  if (assignSequences && hasNewObjects()) {
    assignSequenceNumbers(this.newObjectsCloneToOriginal);
  }
  Iterator objects=registeredObjects.keySet().iterator();
  Map changedObjects=new IdentityHashMap();
  Map visitedNodes=new IdentityHashMap();
  while (objects.hasNext()) {
    Object object=objects.next();
    ClassDescriptor descriptor=getDescriptor(object);
    boolean isNew=isObjectNew(object);
    if (isNew || descriptor.getObjectChangePolicy().shouldCompareExistingObjectForChange(object,this,descriptor)) {
      ObjectChangeSet changes=null;
      if (isNew) {
        changes=descriptor.getObjectChangePolicy().calculateChangesForNewObject(object,changeSet,this,descriptor,true);
      }
 else {
        changes=descriptor.getObjectChangePolicy().calculateChangesForExistingObject(object,changeSet,this,descriptor,true);
      }
      if (changes != null) {
        changeSet.addObjectChangeSet(changes,this,true);
        changedObjects.put(object,object);
        if (changes.hasChanges() && !changes.hasForcedChangesFromCascadeLocking()) {
          if (descriptor.hasCascadeLockingPolicies()) {
            for (Enumeration policies=descriptor.getCascadeLockingPolicies().elements(); policies.hasMoreElements(); ) {
              ((CascadeLockingPolicy)policies.nextElement()).lockNotifyParent(object,changeSet,this);
            }
          }
 else           if (descriptor.usesOptimisticLocking() && descriptor.getOptimisticLockingPolicy().isCascaded()) {
            changes.setHasForcedChangesFromCascadeLocking(true);
          }
        }
      }
 else {
        visitedNodes.put(object,object);
      }
    }
 else {
      visitedNodes.put(object,object);
    }
  }
  if (this.project.hasMappingsPostCalculateChangesOnDeleted()) {
    if (hasDeletedObjects()) {
      for (Iterator deletedObjects=getDeletedObjects().keySet().iterator(); deletedObjects.hasNext(); ) {
        Object deletedObject=deletedObjects.next();
        ClassDescriptor descriptor=getDescriptor(deletedObject);
        if (descriptor.hasMappingsPostCalculateChanges()) {
          int size=descriptor.getMappingsPostCalculateChangesOnDeleted().size();
          for (int i=0; i < size; i++) {
            DatabaseMapping mapping=descriptor.getMappingsPostCalculateChangesOnDeleted().get(i);
            mapping.postCalculateChangesOnDeleted(deletedObject,changeSet,this);
          }
        }
      }
    }
  }
  if (this.shouldDiscoverNewObjects) {
    Map newObjects=new IdentityHashMap();
    Map existingObjects=new IdentityHashMap(2);
    discoverUnregisteredNewObjects(changedObjects,newObjects,existingObjects,visitedNodes);
    setUnregisteredExistingObjects(existingObjects);
    setUnregisteredNewObjects(newObjects);
    if (assignSequences) {
      assignSequenceNumbers(newObjects);
    }
    for (Iterator newObjectsEnum=newObjects.values().iterator(); newObjectsEnum.hasNext(); ) {
      Object object=newObjectsEnum.next();
      ClassDescriptor descriptor=getDescriptor(object);
      ObjectChangeSet changes=descriptor.getObjectChangePolicy().calculateChangesForNewObject(object,changeSet,this,descriptor,true);
      changeSet.addObjectChangeSet(changes,this,true);
    }
  }
  if (this.hasPrivateOwnedObjects()) {
    Map visitedObjects=new IdentityHashMap();
    for (    Set privateOwnedObjects : getPrivateOwnedObjects().values()) {
      for (      Object objectToRemove : privateOwnedObjects) {
        performRemovePrivateOwnedObjectFromChangeSet(objectToRemove,visitedObjects);
      }
    }
  }
  this.eventManager.postCalculateUnitOfWorkChangeSet(changeSet);
  return changeSet;
}