1 56 57 package org.objectstyle.cayenne.access; 58 59 import java.io.Serializable ; 60 import java.util.Collection ; 61 import java.util.Iterator ; 62 import java.util.LinkedList ; 63 import java.util.List ; 64 import java.util.ListIterator ; 65 66 import org.objectstyle.cayenne.CayenneRuntimeException; 67 import org.objectstyle.cayenne.DataObject; 68 import org.objectstyle.cayenne.PersistenceState; 69 import org.objectstyle.cayenne.query.RelationshipQuery; 70 71 81 public class ToManyList implements List , Serializable { 82 private DataObject source; 83 private String relationship; 84 85 List objectList; 87 88 LinkedList addedToUnresolved; 90 LinkedList removedFromUnresolved; 91 92 97 public ToManyList(DataObject source, String relationship) { 98 if (source == null) { 99 throw new NullPointerException ("'source' can't be null."); 100 } 101 102 if (relationship == null) { 103 throw new NullPointerException ("'relationship' can't be null."); 104 } 105 106 this.source = source; 107 this.relationship = relationship; 108 109 if (isTransientSource()) { 111 objectList = new LinkedList (); 112 } 113 } 114 115 120 public DataObject getSource() { 121 return source; 122 } 123 124 129 public String getRelationship() { 130 return relationship; 131 } 132 133 136 public boolean needsFetch() { 137 return objectList == null; 138 } 139 140 143 public void invalidateObjectList() { 144 setObjectList(null); 145 } 146 147 public void setObjectList(List objectList) { 148 this.objectList = objectList; 149 } 150 151 155 public boolean add(Object o) { 156 return (needsFetch()) ? addLocal(o) : objectList.add(o); 157 } 158 159 public void add(int index, Object element) { 160 resolvedObjectList().add(index, element); 161 } 162 163 public boolean addAll(Collection c) { 164 return resolvedObjectList().addAll(c); 165 } 166 167 public boolean addAll(int index, Collection c) { 168 return resolvedObjectList().addAll(index, c); 169 } 170 171 public void clear() { 172 resolvedObjectList().clear(); 173 } 174 175 public boolean contains(Object o) { 176 return resolvedObjectList().contains(o); 177 } 178 179 public boolean containsAll(Collection c) { 180 return resolvedObjectList().containsAll(c); 181 } 182 183 public boolean equals(Object o) { 184 if (o == null) { 185 return false; 186 } 187 188 if (!(o instanceof ToManyList)) { 189 return false; 190 } 191 192 return resolvedObjectList().equals(((ToManyList) o).resolvedObjectList()); 193 } 194 195 public int hashCode() { 196 return 15 + resolvedObjectList().hashCode(); 197 } 198 199 public Object get(int index) { 200 return resolvedObjectList().get(index); 201 } 202 203 public int indexOf(Object o) { 204 return resolvedObjectList().indexOf(o); 205 } 206 207 public boolean isEmpty() { 208 return resolvedObjectList().isEmpty(); 209 } 210 211 public Iterator iterator() { 212 return resolvedObjectList().iterator(); 213 } 214 215 public int lastIndexOf(Object o) { 216 return resolvedObjectList().lastIndexOf(o); 217 } 218 219 public ListIterator listIterator() { 220 return resolvedObjectList().listIterator(); 221 } 222 223 public ListIterator listIterator(int index) { 224 return resolvedObjectList().listIterator(index); 225 } 226 227 public Object remove(int index) { 228 return resolvedObjectList().remove(index); 229 } 230 231 public boolean remove(Object o) { 232 return (needsFetch()) ? removeLocal(o) : objectList.remove(o); 233 } 234 235 public boolean removeAll(Collection c) { 236 return resolvedObjectList().removeAll(c); 237 } 238 239 public boolean retainAll(Collection c) { 240 return resolvedObjectList().retainAll(c); 241 } 242 243 public Object set(int index, Object element) { 244 return resolvedObjectList().set(index, element); 245 } 246 247 public int size() { 248 return resolvedObjectList().size(); 249 } 250 251 public List subList(int fromIndex, int toIndex) { 252 return resolvedObjectList().subList(fromIndex, toIndex); 253 } 254 255 public Object [] toArray() { 256 return resolvedObjectList().toArray(); 257 } 258 259 public Object [] toArray(Object [] a) { 260 return resolvedObjectList().toArray(a); 261 } 262 263 268 boolean isTransientSource() { 269 int state = source.getPersistenceState(); 270 return state == PersistenceState.NEW || state == PersistenceState.TRANSIENT; 271 } 272 273 boolean isUncommittedSource() { 274 int state = source.getPersistenceState(); 275 return state == PersistenceState.MODIFIED || state == PersistenceState.DELETED; 276 } 277 278 281 List resolvedObjectList() { 282 if (needsFetch()) { 283 284 synchronized (this) { 285 288 if (needsFetch()) { 289 List localList; 290 291 if (isTransientSource()) { 292 localList = new LinkedList (); 293 } 294 else { 295 if (source.getObjectId().isTemporary()) { 296 throw new CayenneRuntimeException( 297 "Can't resolve relationship for temporary id: " 298 + source.getObjectId()); 299 } 300 301 RelationshipQuery query = new RelationshipQuery( 302 source, 303 relationship); 304 305 localList = source.getDataContext().performQuery(query); 306 } 307 308 mergeLocalChanges(localList); 309 this.objectList = localList; 310 } 311 } 312 } 313 314 return objectList; 315 } 316 317 void clearLocalChanges() { 318 addedToUnresolved = null; 319 removedFromUnresolved = null; 320 } 321 322 void mergeLocalChanges(List fetchedList) { 323 324 if (isUncommittedSource()) { 328 329 if (removedFromUnresolved != null) { 330 fetchedList.removeAll(removedFromUnresolved); 331 } 332 333 if (addedToUnresolved != null && !addedToUnresolved.isEmpty()) { 336 Iterator it = addedToUnresolved.iterator(); 337 while (it.hasNext()) { 338 Object next = it.next(); 339 340 if (next instanceof DataObject) { 341 DataObject dataObject = (DataObject) next; 342 if (dataObject.getPersistenceState() 343 == PersistenceState.TRANSIENT) { 344 continue; 345 } 346 } 347 348 if (!fetchedList.contains(next)) { 349 fetchedList.add(next); 350 } 351 } 352 } 353 } 354 355 clearLocalChanges(); 357 } 358 359 boolean addLocal(Object object) { 360 361 if (removedFromUnresolved != null) { 362 removedFromUnresolved.remove(object); 363 } 364 365 if (addedToUnresolved == null) { 366 addedToUnresolved = new LinkedList (); 367 } 368 369 addedToUnresolved.addLast(object); 370 371 return true; 374 } 375 376 boolean removeLocal(Object object) { 377 if (addedToUnresolved != null) { 378 addedToUnresolved.remove(object); 379 } 380 381 if (removedFromUnresolved == null) { 382 removedFromUnresolved = new LinkedList (); 383 } 384 385 removedFromUnresolved.addLast(object); 386 387 return true; 390 } 391 } 392 | Popular Tags |