1 2 12 package com.versant.core.jdo.sco; 13 14 import com.versant.core.jdo.VersantPersistenceManagerImp; 15 import com.versant.core.jdo.VersantStateManager; 16 import com.versant.core.common.CollectionDiff; 17 import com.versant.core.common.VersantFieldMetaData; 18 19 import javax.jdo.spi.PersistenceCapable; 20 import java.util.ArrayList ; 21 import java.util.Collection ; 22 import java.util.Iterator ; 23 24 import com.versant.core.common.BindingSupportImpl; 25 import com.versant.core.common.PersistenceContext; 26 import com.versant.core.jdo.VersantPersistenceManagerImp; 27 import com.versant.core.jdo.VersantStateManager; 28 29 32 public final class SCOArrayList extends ArrayList implements VersantManagedSCOCollection, VersantAdvancedSCO { 33 34 private transient PersistenceCapable owner; 35 private final transient int managed; 36 private final transient int inverseFieldNo; 37 private final transient VersantFieldMetaData fmd; 38 private transient VersantStateManager stateManager; 39 private transient Object [] originalData; 40 private transient boolean beenReset; 41 42 public SCOArrayList(PersistenceCapable owner, VersantStateManager stateManager, 43 VersantFieldMetaData fmd, Object [] originalData) { 44 this.owner = owner; 45 if (fmd.isManaged()) { 46 if (fmd.isMaster()) { 47 managed = MANAGED_ONE_TO_MANY; 48 } else if (fmd.isManyToMany()) { 49 managed = MANAGED_MANY_TO_MANY; 50 } else { 51 managed = MANAGED_NONE; 52 } 53 } else { 54 managed = MANAGED_NONE; 55 } 56 this.inverseFieldNo = fmd.getInverseFieldNo(); 57 this.stateManager = stateManager; 58 this.fmd = fmd; 59 this.originalData = originalData; 60 int n = originalData == null ? 0 : originalData.length; 61 if (n > 0) ensureCapacity(n); 62 if (!owner.jdoIsNew()) { 63 for (int i = 0; i < n; i++) { 64 Object o = originalData[i]; 65 67 super.add( o); 68 } 69 } else { 70 switch (managed) { 71 case MANAGED_ONE_TO_MANY: 72 for (int i = 0; i < n; i++) { 73 Object o = originalData[i]; 74 super.add( o); 76 SCOInverseUtil.addMasterOnDetail(o, owner, inverseFieldNo); 77 } 78 break; 79 case MANAGED_MANY_TO_MANY: 80 for (int i = 0; i < n; i++) { 81 Object o = originalData[i]; 82 super.add( o); 84 SCOInverseUtil.addToOtherSideOfManyToMany(o, inverseFieldNo, owner); 85 } 86 break; 87 default: 88 for (int i = 0; i < n; i++) { 89 Object o = originalData[i]; 90 super.add( o); 92 } 93 } 94 ; 95 } 96 } 97 98 private RuntimeException createNPE() { 99 return BindingSupportImpl.getInstance().nullElement("Null element not allowed: " + fmd.getQName()); 100 } 101 102 public Object set(int index, Object element) { 103 Object result; 105 switch (managed) { 106 case MANAGED_ONE_TO_MANY: 107 result = super.set(index, element); 108 makeDirty(); 109 if (result != null) { 110 SCOInverseUtil.removeMasterOnDetail(result, owner, inverseFieldNo); 111 } 112 SCOInverseUtil.addMasterOnDetail(element, owner, inverseFieldNo); 113 return result; 114 case MANAGED_MANY_TO_MANY: 115 result = super.set(index, element); 116 makeDirty(); 117 if (result != null) { 118 SCOInverseUtil.removeFromOtherSideOfManyToMany(result, inverseFieldNo, owner); 119 } 120 SCOInverseUtil.addToOtherSideOfManyToMany(element, inverseFieldNo, owner); 121 return result; 122 } 123 result = super.set(index, element); 124 makeDirty(); 125 return result; 126 } 127 128 public boolean add(Object o) { 129 switch (managed) { 131 case MANAGED_ONE_TO_MANY: 132 super.add(o); 133 makeDirty(); 134 SCOInverseUtil.addMasterOnDetail(o, owner, inverseFieldNo); 135 return true; 136 case MANAGED_MANY_TO_MANY: 137 super.add(o); 138 makeDirty(); 139 SCOInverseUtil.addToOtherSideOfManyToMany(o, inverseFieldNo, owner); 140 return true; 141 } 142 super.add(o); 143 makeDirty(); 144 return true; 145 } 146 147 public void add(int index, Object element) { 148 switch (managed) { 150 case MANAGED_ONE_TO_MANY: 151 super.add(index, element); 152 makeDirty(); 153 SCOInverseUtil.addMasterOnDetail(element, owner, inverseFieldNo); 154 return; 155 case MANAGED_MANY_TO_MANY: 156 super.add(index, element); 157 makeDirty(); 158 SCOInverseUtil.addToOtherSideOfManyToMany(element, inverseFieldNo, owner); 159 return; 160 } 161 super.add(index, element); 162 makeDirty(); 163 } 164 165 public Object remove(int index) { 166 Object result = super.remove(index); 167 if (result == null) return null; makeDirty(); 169 switch (managed) { 170 case MANAGED_ONE_TO_MANY: 171 SCOInverseUtil.removeMasterOnDetail(result, owner, inverseFieldNo); 172 break; 173 case MANAGED_MANY_TO_MANY: 174 SCOInverseUtil.removeFromOtherSideOfManyToMany(result, inverseFieldNo, owner); 175 break; 176 } 177 return result; 178 } 179 180 public boolean remove(Object o) { 181 int i = indexOf(o); 186 if (i < 0) return false; 187 remove(i); 188 return true; 189 } 190 191 public boolean addAll(Collection c) { 192 Iterator i; 193 Object o; 194 switch (managed) { 195 case MANAGED_ONE_TO_MANY: 196 i = c.iterator(); 197 if (!i.hasNext()) return false; 198 ensureCapacity(c.size() + size()); 199 o = null; 200 for (; ;) { 201 o = i.next(); 202 super.add(o); 206 SCOInverseUtil.addMasterOnDetail(o, owner, inverseFieldNo); 207 if (!i.hasNext()) break; 209 } 210 makeDirty(); 211 return true; 212 case MANAGED_MANY_TO_MANY: 213 i = c.iterator(); 214 if (!i.hasNext()) return false; 215 ensureCapacity(c.size() + size()); 216 o = null; 217 for (; ;) { 218 o = i.next(); 219 super.add(o); 223 SCOInverseUtil.addToOtherSideOfManyToMany(o, inverseFieldNo, owner); 224 if (!i.hasNext()) break; 226 } 227 makeDirty(); 228 return true; 229 } 230 ; 231 if (super.addAll(c)) { 232 makeDirty(); 233 return true; 234 } 235 return false; 236 } 237 238 public void clear() { 239 int n; 240 switch (managed) { 241 case MANAGED_ONE_TO_MANY: 242 n = size(); 243 for (int i = 0; i < n; i++) { 244 SCOInverseUtil.removeMasterOnDetail(get(i), owner, inverseFieldNo); 245 } 246 break; 247 case MANAGED_MANY_TO_MANY: 248 n = size(); 249 for (int i = 0; i < n; i++) { 250 SCOInverseUtil.removeFromOtherSideOfManyToMany(get(i), inverseFieldNo, owner); 251 } 252 break; 253 } 254 super.clear(); 255 makeDirty(); 256 } 257 258 public boolean addAll(int index, Collection c) { 259 boolean result; 260 int colSize; 261 switch (managed) { 262 case MANAGED_ONE_TO_MANY: 263 result = false; 264 colSize = c.size(); 265 ensureCapacity(size() + colSize); 266 for (Iterator iter = c.iterator(); iter.hasNext();) { 267 Object o = iter.next(); 268 super.add(index++, o); 272 SCOInverseUtil.addMasterOnDetail(o, owner, inverseFieldNo); 273 result = true; 274 } 276 if (result) makeDirty(); 277 return result; 278 case MANAGED_MANY_TO_MANY: 279 result = false; 280 colSize = c.size(); 281 ensureCapacity(size() + colSize); 282 for (Iterator iter = c.iterator(); iter.hasNext();) { 283 Object o = iter.next(); 284 super.add(index++, o); 288 SCOInverseUtil.addToOtherSideOfManyToMany(o, inverseFieldNo, owner); 289 result = true; 290 } 292 if (result) makeDirty(); 293 return result; 294 } 295 ; 296 result = super.addAll(index, c); 297 if (result) makeDirty(); 298 return result; 299 } 300 301 protected void removeRange(int fromIndex, int toIndex) { 302 switch (managed) { 303 case MANAGED_ONE_TO_MANY: 304 for (int i = fromIndex; i < toIndex; i++) { 305 SCOInverseUtil.removeMasterOnDetail(get(i), owner, inverseFieldNo); 306 } 307 break; 308 case MANAGED_MANY_TO_MANY: 309 for (int i = fromIndex; i < toIndex; i++) { 310 SCOInverseUtil.removeFromOtherSideOfManyToMany(get(i), inverseFieldNo, owner); 311 } 312 break; 313 } 314 super.removeRange(fromIndex, toIndex); 315 makeDirty(); 316 } 317 318 public boolean removeAll(Collection c) { 319 boolean modified; 320 Iterator e; 321 switch (managed) { 322 case MANAGED_ONE_TO_MANY: 323 modified = false; 324 e = super.iterator(); 325 while (e.hasNext()) { 326 Object o = e.next(); 327 if (c.contains(o)) { 328 e.remove(); 329 SCOInverseUtil.removeMasterOnDetail(o, owner, inverseFieldNo); 330 modified = true; 331 } 332 } 333 if (modified) makeDirty(); 334 return modified; 335 case MANAGED_MANY_TO_MANY: 336 modified = false; 337 e = super.iterator(); 338 while (e.hasNext()) { 339 Object o = e.next(); 340 if (c.contains(o)) { 341 e.remove(); 342 SCOInverseUtil.removeFromOtherSideOfManyToMany(o, inverseFieldNo, owner); 343 modified = true; 344 } 345 } 346 if (modified) makeDirty(); 347 return modified; 348 } 349 if (super.removeAll(c)) { 350 makeDirty(); 351 return true; 352 } 353 return false; 354 } 355 356 public boolean retainAll(Collection c) { 357 boolean modified = false; 358 Iterator e = super.iterator(); 359 while (e.hasNext()) { 360 Object o = e.next(); 361 if (!c.contains(o)) { 362 e.remove(); 363 modified = true; 364 switch (managed) { 365 case MANAGED_ONE_TO_MANY: 366 SCOInverseUtil.removeMasterOnDetail(o, owner, inverseFieldNo); 367 break; 368 case MANAGED_MANY_TO_MANY: 369 SCOInverseUtil.removeFromOtherSideOfManyToMany(o, inverseFieldNo, owner); 370 break; 371 } 372 } 373 } 374 if (modified) makeDirty(); 375 return modified; 376 } 377 378 public CollectionDiff getCollectionDiff(PersistenceContext pm) { 379 Object [] data = toArray(); 380 if (fmd.isOrdered()) { 381 return CollectionDiffUtil.getOrderedCollectionDiff(fmd, pm, 382 data, data.length, (owner.jdoIsNew() && !beenReset) ? null : originalData); 383 } else { 384 return CollectionDiffUtil.getUnorderedCollectionDiff(fmd, pm, 385 data, data.length, (owner.jdoIsNew() && !beenReset) ? null : originalData); 386 } 387 } 388 389 public Object getOwner() { 390 return owner; 391 } 392 393 public void makeTransient() { 394 owner = null; 395 stateManager = null; 396 } 397 398 public void makeDirty() { 399 if (stateManager != null) { 400 stateManager.makeDirty(owner, fmd.getManagedFieldNo()); 401 } 402 } 403 404 public void reset() { 405 beenReset = true; 406 originalData = toArray(); 407 } 408 409 public void manyToManyAdd(Object o) { 410 super.add(o); 411 makeDirty(); 412 } 413 414 public void manyToManyRemove(Object o) { 415 int i = indexOf(o); 420 if (i < 0) return; 421 super.remove(i); 422 makeDirty(); 423 } 424 425 428 public boolean isOrdered() { 429 return fmd.isOrdered(); 430 } 431 432 437 public CollectionData fillCollectionData(CollectionData collectionData) { 438 int size = size(); 439 collectionData.valueCount = size; 440 Object [] newData; 441 Object [] values = collectionData.values; 442 if (values == null || values.length < size) { 443 newData = new Object [size]; 444 } else { 445 newData = values; 446 } 447 for (int i = 0; i < size; i++) { 448 newData[i] = get(i); 449 } 450 collectionData.values = newData; 451 return collectionData; 452 } 453 } 454 | Popular Tags |