Program: 66928
Project: 66928
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){
  if (this.eventManager != null) {
    this.eventManager.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 (hasDeletedObjects() && !isNestedUnitOfWork()) {
    Object obj1;
    for (Iterator iterator1=((IdentityHashMap)((IdentityHashMap)deletedObjects).clone()).keySet().iterator(); iterator1.hasNext(); getDescriptor(obj1).getObjectBuilder().recordPrivateOwnedRemovals(obj1,this,true))     obj1=iterator1.next();
  }
  if (deletedPrivateOwnedObjects != null && !isNestedUnitOfWork()) {
    for (Iterator iterator2=deletedPrivateOwnedObjects.entrySet().iterator(); iterator2.hasNext(); ) {
      java.util.Map.Entry entry=(java.util.Map.Entry)iterator2.next();
      DatabaseMapping databasemapping=(DatabaseMapping)entry.getKey();
      Iterator iterator6=((List)entry.getValue()).iterator();
      while (iterator6.hasNext()) {
        Object obj4=iterator6.next();
        databasemapping.getReferenceDescriptor().getObjectBuilder().recordPrivateOwnedRemovals(obj4,this,false);
      }
    }
    deletedPrivateOwnedObjects.clear();
  }
  if (this.project.hasMappingsPostCalculateChangesOnDeleted()) {
    if (hasDeletedObjects()) {
      for (Iterator deletedObjects=getDeletedObjects().keySet().iterator(); deletedObjects.hasNext(); ) {
        Object deletedObject=deletedObjects.next();
        ClassDescriptor descriptor=getDescriptor(deletedObject);
        if (descriptor.hasMappingsPostCalculateChangesOnDeleted()) {
          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.privateOwnedObjects.clear();
  }
  if (this.eventManager != null) {
    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){
  if (this.eventManager != null) {
    this.eventManager.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);
    updateDerivedIds(object,descriptor);
    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 (hasDeletedObjects() && !isNestedUnitOfWork()) {
    Object obj1;
    for (Iterator iterator1=((IdentityHashMap)((IdentityHashMap)deletedObjects).clone()).keySet().iterator(); iterator1.hasNext(); getDescriptor(obj1).getObjectBuilder().recordPrivateOwnedRemovals(obj1,this,true))     obj1=iterator1.next();
  }
  if (deletedPrivateOwnedObjects != null && !isNestedUnitOfWork()) {
    for (Iterator iterator2=deletedPrivateOwnedObjects.entrySet().iterator(); iterator2.hasNext(); ) {
      java.util.Map.Entry entry=(java.util.Map.Entry)iterator2.next();
      DatabaseMapping databasemapping=(DatabaseMapping)entry.getKey();
      Iterator iterator6=((List)entry.getValue()).iterator();
      while (iterator6.hasNext()) {
        Object obj4=iterator6.next();
        databasemapping.getReferenceDescriptor().getObjectBuilder().recordPrivateOwnedRemovals(obj4,this,false);
      }
    }
    deletedPrivateOwnedObjects.clear();
  }
  if (this.project.hasMappingsPostCalculateChangesOnDeleted()) {
    if (hasDeletedObjects()) {
      for (Iterator deletedObjects=getDeletedObjects().keySet().iterator(); deletedObjects.hasNext(); ) {
        Object deletedObject=deletedObjects.next();
        ClassDescriptor descriptor=getDescriptor(deletedObject);
        if (descriptor.hasMappingsPostCalculateChangesOnDeleted()) {
          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.privateOwnedObjects.clear();
  }
  if (this.eventManager != null) {
    this.eventManager.postCalculateUnitOfWorkChangeSet(changeSet);
  }
  return changeSet;
}