1 21 package oracle.toplink.essentials.internal.queryframework; 23 24 import java.util.List ; 25 import java.util.Vector ; 26 import java.util.Hashtable ; 27 import java.util.Collections ; 28 import java.util.Enumeration ; 29 import java.util.IdentityHashMap ; 30 import java.util.ListIterator ; 31 import oracle.toplink.essentials.exceptions.QueryException; 32 import oracle.toplink.essentials.internal.helper.IdentityHashtable; 33 import oracle.toplink.essentials.internal.sessions.MergeManager; 34 import oracle.toplink.essentials.internal.sessions.ObjectChangeSet; 35 import oracle.toplink.essentials.internal.sessions.UnitOfWorkChangeSet; 36 import oracle.toplink.essentials.internal.sessions.CollectionChangeRecord; 37 import oracle.toplink.essentials.internal.sessions.AbstractSession; 38 import oracle.toplink.essentials.descriptors.ClassDescriptor; 39 40 51 public class OrderedListContainerPolicy extends ListContainerPolicy { 52 56 public OrderedListContainerPolicy() { 57 super(); 58 } 59 60 64 public OrderedListContainerPolicy(Class containerClass) { 65 super(containerClass); 66 } 67 68 72 public OrderedListContainerPolicy(String containerClassName) { 73 super(containerClassName); 74 } 75 76 81 protected void addIntoAtIndex(Integer index, Object object, Object container, AbstractSession session) { 82 if (hasElementDescriptor()) { 83 object = getElementDescriptor().getObjectBuilder().wrapObject(object, session); 84 } 85 86 try { 87 if (index == null || (index.intValue() > sizeFor(container))) { 88 ((List )container).add(object); 92 } else { 93 ((List )container).add(index.intValue(), object); 94 } 95 } catch (ClassCastException ex1) { 96 throw QueryException.cannotAddElement(object, container, ex1); 97 } catch (IllegalArgumentException ex2) { 98 throw QueryException.cannotAddElement(object, container, ex2); 99 } catch (UnsupportedOperationException ex3) { 100 throw QueryException.cannotAddElement(object, container, ex3); 101 } 102 } 103 104 110 public void compareCollectionsForChange(Object oldList, Object newList, CollectionChangeRecord changeRecord, AbstractSession session, ClassDescriptor referenceDescriptor) { 111 Vector orderedObjectsToAdd = new Vector (); 112 Hashtable indicesToRemove = new Hashtable (); 113 Hashtable oldListIndexValue = new Hashtable (); 114 IdentityHashMap oldListValueIndex = new IdentityHashMap (); 115 IdentityHashMap objectsToAdd = new IdentityHashMap (); 116 IdentityHashtable newListValueIndex = new IdentityHashtable(); 117 118 if (oldList != null) { 120 ListIterator iterator = iteratorFor(oldList); 121 122 while (iterator.hasNext()) { 123 Integer index = new Integer (iterator.nextIndex()); 124 Object value = iterator.next(); 125 oldListValueIndex.put(value, index); 126 oldListIndexValue.put(index, value); 127 indicesToRemove.put(index, index); 128 } 129 } 130 131 if (newList != null) { 133 ListIterator iterator = iteratorFor(newList); 135 while (iterator.hasNext()) { 136 newListValueIndex.put(iterator.next(), new Integer (iterator.previousIndex())); 137 } 138 139 int index = 0; 141 int offset = 0; 142 iterator = iteratorFor(newList); 143 while (iterator.hasNext()) { 144 index = iterator.nextIndex(); 145 Object currentObject = iterator.next(); 146 147 if (currentObject != null) { 149 if (oldListValueIndex.containsKey(currentObject)) { 150 int oldIndex = ((Integer ) oldListValueIndex.get(currentObject)).intValue(); 151 oldListValueIndex.remove(currentObject); 152 153 if (index == oldIndex) { 154 indicesToRemove.remove(new Integer (oldIndex)); 155 offset = 0; } else if (index == (oldIndex + offset)) { 157 indicesToRemove.remove(new Integer (oldIndex)); 159 } else { 160 int movedObjects = 0; 162 int deletedObjects = 0; 163 boolean moved = true; 164 165 if (oldIndex < index) { 166 ++offset; 167 } else { 168 for (int i = oldIndex - 1; i >= index; i--) { 169 Object oldObject = oldListIndexValue.get(new Integer (i)); 170 if (newListValueIndex.containsKey(oldObject)) { 171 ++movedObjects; 172 } else { 173 ++deletedObjects; 174 } 175 } 176 177 if (index == ((oldIndex + offset) - deletedObjects)) { 178 offset = offset - deletedObjects; 180 moved = false; 181 } else if (movedObjects > 1) { 182 ++offset; 184 } else { 185 Object oldObject = oldListIndexValue.get(new Integer (index)); 188 189 if (newListValueIndex.containsKey(oldObject)) { 190 if ((((Integer ) newListValueIndex.get(oldObject)).intValue() - index) > 1) { 191 moved = false; --offset; 193 } 194 } 195 } 196 } 197 198 if (moved) { 199 orderedObjectsToAdd.add(currentObject); 201 } else { 202 indicesToRemove.remove(new Integer (oldIndex)); 204 } 205 } 206 } else { 207 ++offset; 208 objectsToAdd.put(currentObject, currentObject); 209 orderedObjectsToAdd.add(currentObject); 210 } 211 } else { 212 offset--; 214 } 215 } 216 } 217 218 Vector orderedIndicesToRemove = new Vector (indicesToRemove.values()); 221 Collections.sort(orderedIndicesToRemove); 222 changeRecord.addAdditionChange(objectsToAdd, (UnitOfWorkChangeSet) changeRecord.getOwner().getUOWChangeSet(), session); 223 changeRecord.addRemoveChange(oldListValueIndex, (UnitOfWorkChangeSet) changeRecord.getOwner().getUOWChangeSet(), session); 224 changeRecord.addOrderedAdditionChange(orderedObjectsToAdd, newListValueIndex, (UnitOfWorkChangeSet) changeRecord.getOwner().getUOWChangeSet(), session); 225 changeRecord.addOrderedRemoveChange(orderedIndicesToRemove, oldListIndexValue, (UnitOfWorkChangeSet) changeRecord.getOwner().getUOWChangeSet(), session); 226 } 227 228 232 public ListIterator iteratorFor(Object container) { 233 return ((List )container).listIterator(); 234 } 235 236 242 public void mergeChanges(CollectionChangeRecord changeRecord, Object valueOfTarget, boolean shouldMergeCascadeParts, MergeManager mergeManager, AbstractSession parentSession) { 243 ObjectChangeSet objectChanges; 244 245 synchronized (valueOfTarget) { 246 Vector removedIndices = changeRecord.getOrderedRemoveObjectIndices(); 248 249 if (removedIndices.isEmpty()) { 250 Enumeration removedObjects = changeRecord.getRemoveObjectList().keys(); 253 254 while (removedObjects.hasMoreElements()) { 255 objectChanges = (ObjectChangeSet) removedObjects.nextElement(); 256 removeFrom(objectChanges.getOldKey(), objectChanges.getTargetVersionOfSourceObject(mergeManager.getSession()), valueOfTarget, parentSession); 257 registerRemoveNewObjectIfRequired(objectChanges, mergeManager); 258 } 259 } else { 260 for (int i = removedIndices.size() - 1; i >= 0; i--) { 261 Integer index = ((Integer ) removedIndices.elementAt(i)).intValue(); 262 objectChanges = (ObjectChangeSet) changeRecord.getOrderedRemoveObject(index);; 263 removeFromAtIndex(index, valueOfTarget); 264 265 if (changeRecord.getRemoveObjectList().containsKey(objectChanges)) { 267 registerRemoveNewObjectIfRequired(objectChanges, mergeManager); 268 } 269 } 270 } 271 272 Enumeration addObjects = changeRecord.getOrderedAddObjects().elements(); 274 while (addObjects.hasMoreElements()) { 275 objectChanges = (ObjectChangeSet) addObjects.nextElement(); 276 boolean objectAdded = changeRecord.getAddObjectList().containsKey(objectChanges); 277 Object object = null; 278 279 if (objectAdded && shouldMergeCascadeParts) { 281 object = mergeCascadeParts(objectChanges, mergeManager, parentSession); 282 } 283 284 if (object == null) { 285 object = objectChanges.getTargetVersionOfSourceObject(mergeManager.getSession()); 287 } 288 289 if (objectAdded && mergeManager.shouldMergeChangesIntoDistributedCache()) { 293 if (! contains(object, valueOfTarget, mergeManager.getSession())) { 296 addIntoAtIndex(changeRecord.getOrderedAddObjectIndex(objectChanges), object, valueOfTarget, mergeManager.getSession()); 297 } 298 } else { 299 addIntoAtIndex(changeRecord.getOrderedAddObjectIndex(objectChanges), object, valueOfTarget, mergeManager.getSession()); 300 } 301 } 302 } 303 } 304 305 308 protected void registerRemoveNewObjectIfRequired(ObjectChangeSet objectChanges, MergeManager mergeManager) { 309 if (! mergeManager.shouldMergeChangesIntoDistributedCache()) { 310 mergeManager.registerRemovedNewObjectIfRequired(objectChanges.getUnitOfWorkClone()); 311 } 312 } 313 314 318 protected void removeFromAtIndex(int index, Object container) { 319 try { 320 ((List ) container).remove(index); 321 } catch (ClassCastException ex1) { 322 throw QueryException.cannotRemoveFromContainer(new Integer (index), container, this); 323 } catch (IllegalArgumentException ex2) { 324 throw QueryException.cannotRemoveFromContainer(new Integer (index), container, this); 325 } catch (UnsupportedOperationException ex3) { 326 throw QueryException.cannotRemoveFromContainer(new Integer (index), container, this); 327 } 328 } 329 } 330 | Popular Tags |