*/
public void compareCollectionsForChange(Object oldList, Object newList, CollectionChangeRecord changeRecord, AbstractSession session, ClassDescriptor referenceDescriptor) {
Vector orderedObjectsToAdd = new Vector();
Hashtable indicesToRemove = new Hashtable();
Hashtable oldListIndexValue = new Hashtable();
IdentityHashMap oldListValueIndex = new IdentityHashMap();
IdentityHashMap objectsToAdd = new IdentityHashMap();
IdentityHashtable newListValueIndex = new IdentityHashtable();
// Step 1 - Go through the old list.
if (oldList != null) {
ListIterator iterator = iteratorFor(oldList);
while (iterator.hasNext()) {
Integer index = new Integer(iterator.nextIndex());
Object value = iterator.next();
oldListValueIndex.put(value, index);
oldListIndexValue.put(index, value);
indicesToRemove.put(index, index);
}
}
// Step 2 - Go though the new list.
if (newList != null) {
// Step i - Gather the list info.
ListIterator iterator = iteratorFor(newList);
while (iterator.hasNext()) {
newListValueIndex.put(iterator.next(), new Integer(iterator.previousIndex()));
}
// Step ii - Go through the new list again.
int index = 0;
int offset = 0;
iterator = iteratorFor(newList);
while (iterator.hasNext()) {
index = iterator.nextIndex();
Object currentObject = iterator.next();
// If value is null then nothing can be done with it.
if (currentObject != null) {
if (oldListValueIndex.containsKey(currentObject)) {
int oldIndex = ((Integer) oldListValueIndex.get(currentObject)).intValue();
oldListValueIndex.remove(currentObject);
if (index == oldIndex) {
indicesToRemove.remove(new Integer(oldIndex));
offset = 0; // Reset the offset, assume we're back on track.
} else if (index == (oldIndex + offset)) {
// We're in the right spot according to the offset.
indicesToRemove.remove(new Integer(oldIndex));
} else {
// Time to be clever and figure out why we're not in the right spot!
int movedObjects = 0;
int deletedObjects = 0;
boolean moved = true;
if (oldIndex < index) {
++offset;
} else {
for (int i = oldIndex - 1; i >= index; i--) {
Object oldObject = oldListIndexValue.get(new Integer(i));
if (newListValueIndex.containsKey(oldObject)) {
++movedObjects;
} else {
++deletedObjects;
}
}
if (index == ((oldIndex + offset) - deletedObjects)) {
// We fell into place because of deleted objects.
offset = offset - deletedObjects;
moved = false;
} else if (movedObjects > 1) {
// Assume we moved down, bumping everyone by one.
++offset;
} else {
// Assume we moved down unless the object that was
// here before is directly beside us.
Object oldObject = oldListIndexValue.get(new Integer(index));
if (newListValueIndex.containsKey(oldObject)) {
if ((((Integer) newListValueIndex.get(oldObject)).intValue() - index) > 1) {
moved = false; // Assume the old object moved up.
--offset;
}
}
}
}
if (moved) {
// Add ourselves to the ordered add list.
orderedObjectsToAdd.add(currentObject);
} else {
// Take us off the removed list.
indicesToRemove.remove(new Integer(oldIndex));
}
}
} else {
++offset;
objectsToAdd.put(currentObject, currentObject);
orderedObjectsToAdd.add(currentObject);
}
} else {
// If we find nulls we need decrease our offset.
offset--;