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.*; 21 22 import com.versant.core.common.BindingSupportImpl; 23 import com.versant.core.common.PersistenceContext; 24 25 28 public final class SCOVector extends Vector implements VersantManagedSCOCollection, VersantAdvancedSCO { 29 30 private transient PersistenceCapable owner; 31 private final transient VersantFieldMetaData fmd; 32 private transient VersantStateManager stateManager; 33 private final transient boolean isMaster; 34 private final transient boolean isMany; 35 private final transient int inverseFieldNo; 36 private transient Object [] originalData; 37 private transient boolean beenReset; 38 39 public SCOVector(PersistenceCapable owner, VersantStateManager stateManager, 40 VersantFieldMetaData fmd, Object [] originalData) { 41 this.owner = owner; 42 this.fmd = fmd; 43 this.isMaster = fmd.isManaged() && fmd.isMaster(); 44 this.isMany = fmd.isManaged() && fmd.isManyToMany(); 45 this.stateManager = stateManager; 46 this.inverseFieldNo = fmd.getInverseFieldNo(); 47 this.originalData = originalData; 48 int n = originalData == null ? 0 : originalData.length; 49 if (n > 0) ensureCapacity(n); 50 if (!owner.jdoIsNew()) { 51 for (int i = 0; i < n; i++) { 52 Object o = originalData[i]; 53 super.add(o); 54 } 55 } else if (isMaster) { 56 for (int i = 0; i < n; i++) { 57 Object o = originalData[i]; 58 super.add(o); 59 SCOInverseUtil.addMasterOnDetail(o, owner, inverseFieldNo); 60 } 61 } else if (isMany) { 62 for (int i = 0; i < n; i++) { 63 Object o = originalData[i]; 64 super.add(o); 65 SCOInverseUtil.addToOtherSideOfManyToMany(o, inverseFieldNo, owner); 66 } 67 } else { 68 for (int i = 0; i < n; i++) { 69 Object o = originalData[i]; 70 super.add(o); 71 } 72 } 73 } 74 75 public synchronized void setSize(int newSize) { 76 if (newSize > elementCount) { 77 throw BindingSupportImpl.getInstance().nullElement("setSize called with " + newSize + " > " + elementCount + " and " + 78 "null elements are not allowed: " + fmd.getQName()); 79 } 80 if (isMaster) { 81 for (int i = newSize; i < elementCount; i++) { 82 SCOInverseUtil.removeMasterOnDetail(elementData[i], owner, inverseFieldNo); 83 } 84 super.setSize(newSize); 85 makeDirty(); 86 } else if (isMany) { 87 for (int i = newSize; i < elementCount; i++) { 88 SCOInverseUtil.removeFromOtherSideOfManyToMany(elementData[i], inverseFieldNo, owner); 89 } 90 super.setSize(newSize); 91 makeDirty(); 92 } else { 93 super.setSize(newSize); 94 makeDirty(); 95 } 96 97 } 98 99 public synchronized void setElementAt(Object obj, int index) { 100 if (isMaster) { 101 if (index >= elementCount) { 102 throw BindingSupportImpl.getInstance().arrayIndexOutOfBounds(index + " >= " + 103 elementCount); 104 } 105 if (elementData[index] != null) { 106 SCOInverseUtil.removeMasterOnDetail(elementData[index], owner, inverseFieldNo); 107 } 108 SCOInverseUtil.addMasterOnDetail(obj, owner, inverseFieldNo); 109 super.setElementAt(obj, index); 110 makeDirty(); 111 } else if (isMany) { 112 if (index >= elementCount) { 113 throw BindingSupportImpl.getInstance().arrayIndexOutOfBounds(index + " >= " + 114 elementCount); 115 } 116 if (elementData[index] != null) { 117 SCOInverseUtil.removeFromOtherSideOfManyToMany(elementData[index], inverseFieldNo, owner); 118 } 119 SCOInverseUtil.addToOtherSideOfManyToMany(obj, inverseFieldNo, owner); 120 super.setElementAt(obj, index); 121 makeDirty(); 122 } else { 123 super.setElementAt(obj, index); 124 makeDirty(); 125 } 126 127 } 128 129 public synchronized void removeElementAt(int index) { 130 131 if (isMaster) { 132 if (index >= elementCount) { 133 throw BindingSupportImpl.getInstance().arrayIndexOutOfBounds(index + " >= " + 134 elementCount); 135 } else if (index < 0) { 136 throw BindingSupportImpl.getInstance().arrayIndexOutOfBounds(index); 137 } 138 SCOInverseUtil.removeMasterOnDetail(elementData[index], owner, inverseFieldNo); 139 } else if (isMany) { 140 if (index >= elementCount) { 141 throw BindingSupportImpl.getInstance().arrayIndexOutOfBounds(index + " >= " + 142 elementCount); 143 } else if (index < 0) { 144 throw BindingSupportImpl.getInstance().arrayIndexOutOfBounds(index); 145 } 146 SCOInverseUtil.removeFromOtherSideOfManyToMany(elementData[index], inverseFieldNo, owner); 147 } 148 super.removeElementAt(index); 149 150 makeDirty(); 151 } 152 153 public synchronized void insertElementAt(Object obj, int index) { 154 if (isMaster) { 155 super.insertElementAt(obj, index); 156 SCOInverseUtil.addMasterOnDetail(obj, owner, inverseFieldNo); 157 makeDirty(); 158 } else if (isMany) { 159 super.insertElementAt(obj, index); 160 SCOInverseUtil.addToOtherSideOfManyToMany(obj, inverseFieldNo, owner); 161 makeDirty(); 162 } else { 163 makeDirty(); 164 super.insertElementAt(obj, index); 165 } 166 } 167 168 public synchronized void addElement(Object obj) { 169 if (isMaster) { 170 super.addElement(obj); 171 makeDirty(); 172 SCOInverseUtil.addMasterOnDetail(obj, owner, inverseFieldNo); 173 } else if (isMany) { 174 super.addElement(obj); 175 makeDirty(); 176 SCOInverseUtil.addToOtherSideOfManyToMany(obj, inverseFieldNo, owner); 177 } else { 178 super.addElement(obj); 179 makeDirty(); 180 } 181 } 182 183 public synchronized void removeAllElements() { 184 185 modCount++; 186 for (int i = 0; i < elementCount; i++) { 188 if (isMaster) { 189 SCOInverseUtil.removeMasterOnDetail(elementData[i], owner, inverseFieldNo); 190 } else if (isMany) { 191 SCOInverseUtil.removeFromOtherSideOfManyToMany(elementData[i], inverseFieldNo, owner); 192 } 193 elementData[i] = null; 194 } 195 196 elementCount = 0; 197 makeDirty(); 198 } 199 200 public synchronized Object set(int index, Object element) { 201 if (isMaster) { 202 Object obj = super.set(index, element); 203 if (obj != null) { 204 SCOInverseUtil.removeMasterOnDetail(obj, owner, inverseFieldNo); 205 } 206 SCOInverseUtil.addMasterOnDetail(element, owner, inverseFieldNo); 207 makeDirty(); 208 return obj; 209 } else if (isMany) { 210 Object obj = super.set(index, element); 211 if (obj != null) { 212 SCOInverseUtil.removeFromOtherSideOfManyToMany(obj, inverseFieldNo, owner); 213 } 214 SCOInverseUtil.addToOtherSideOfManyToMany(element, inverseFieldNo, owner); 215 makeDirty(); 216 return obj; 217 } else { 218 Object obj = super.set(index, element); 219 makeDirty(); 220 return obj; 221 } 222 } 223 224 public synchronized boolean add(Object o) { 225 if (isMaster) { 226 super.add(o); 227 makeDirty(); 228 SCOInverseUtil.addMasterOnDetail(o, owner, inverseFieldNo); 229 return true; 230 } else if (isMany) { 231 super.add(o); 232 makeDirty(); 233 SCOInverseUtil.addToOtherSideOfManyToMany(o, inverseFieldNo, owner); 234 return true; 235 } else { 236 super.add(o); 237 makeDirty(); 238 return true; 239 } 240 } 241 242 public synchronized Object remove(int index) { 243 Object obj = super.remove(index); 244 if (isMaster) { 245 SCOInverseUtil.removeMasterOnDetail(obj, owner, inverseFieldNo); 246 } else if (isMany) { 247 SCOInverseUtil.removeFromOtherSideOfManyToMany(obj, inverseFieldNo, owner); 248 } 249 makeDirty(); 250 return obj; 251 } 252 253 public synchronized boolean addAll(Collection c) { 254 if (isMaster) { 255 boolean added = false; 256 ensureCapacity(elementCount + c.size()); 257 for (Iterator iter = c.iterator(); iter.hasNext();) { 258 Object o = iter.next(); 259 if (o == null) { 260 } else { 261 added = super.add(o); 262 SCOInverseUtil.addMasterOnDetail(o, owner, inverseFieldNo); 263 } 264 } 265 if (added) { 266 makeDirty(); 267 } 268 return added; 269 } else if (isMany) { 270 boolean added = false; 271 ensureCapacity(elementCount + c.size()); 272 for (Iterator iter = c.iterator(); iter.hasNext();) { 273 Object o = iter.next(); 274 if (o == null) { 275 } else { 276 added = super.add(o); 277 SCOInverseUtil.addToOtherSideOfManyToMany(o, inverseFieldNo, owner); 278 } 279 } 280 if (added) { 281 makeDirty(); 282 } 283 return added; 284 } else if (super.addAll(c)) { 285 makeDirty(); 286 return true; 287 } 288 return false; 289 } 290 291 public synchronized boolean removeAll(Collection c) { 292 boolean modified = false; 293 Iterator e = super.iterator(); 294 Object o = null; 295 while (e.hasNext()) { 296 o = e.next(); 297 if (c.contains(o)) { 298 e.remove(); 299 modified = true; 300 if (isMaster) { 301 SCOInverseUtil.removeMasterOnDetail(o, owner, inverseFieldNo); 302 } else if (isMany) { 303 SCOInverseUtil.removeFromOtherSideOfManyToMany(o, inverseFieldNo, owner); 304 } 305 } 306 } 307 if (modified) makeDirty(); 308 return modified; 309 } 310 311 public synchronized boolean retainAll(Collection c) { 312 boolean modified = false; 313 Iterator e = super.iterator(); 314 Object o = null; 315 while (e.hasNext()) { 316 o = e.next(); 317 if (!c.contains(o)) { 318 e.remove(); 319 modified = true; 320 if (isMaster) { 321 SCOInverseUtil.removeMasterOnDetail(o, owner, inverseFieldNo); 322 } else if (isMany) { 323 SCOInverseUtil.removeFromOtherSideOfManyToMany(o, inverseFieldNo, owner); 324 } 325 } 326 } 327 328 if (modified) { 329 makeDirty(); 330 } 331 return modified; 332 } 333 334 public synchronized boolean addAll(int index, Collection c) { 335 if (isMaster) { 336 boolean added = false; 337 ensureCapacity(elementCount + c.size()); 338 for (Iterator iter = c.iterator(); iter.hasNext();) { 339 Object o = iter.next(); 340 if (o == null) { 341 } else { 342 super.insertElementAt(o, index++); 343 SCOInverseUtil.addMasterOnDetail(o, owner, inverseFieldNo); 344 added = true; 345 } 346 } 347 if (added) { 348 makeDirty(); 349 } 350 return added; 351 } else if (isMany) { 352 boolean added = false; 353 ensureCapacity(elementCount + c.size()); 354 for (Iterator iter = c.iterator(); iter.hasNext();) { 355 Object o = iter.next(); 356 if (o == null) { 357 } else { 358 super.insertElementAt(o, index++); 359 SCOInverseUtil.addToOtherSideOfManyToMany(o, inverseFieldNo, owner); 360 added = true; 361 } 362 } 363 if (added) { 364 makeDirty(); 365 } 366 return added; 367 } else if (super.addAll(index, c)) { 368 makeDirty(); 369 return true; 370 } 371 return false; 372 } 373 374 protected void removeRange(int fromIndex, int toIndex) { 375 if (isMaster) { 376 List removeList = super.subList(fromIndex, toIndex); 377 for (int i = 0; i < removeList.size(); i++) { 378 SCOInverseUtil.removeMasterOnDetail(get(i), owner, inverseFieldNo); 379 } 380 } else if (isMany) { 381 List removeList = super.subList(fromIndex, toIndex); 382 for (int i = 0; i < removeList.size(); i++) { 383 SCOInverseUtil.removeFromOtherSideOfManyToMany(get(i), inverseFieldNo, owner); 384 } 385 } 386 387 super.removeRange(fromIndex, toIndex); 388 makeDirty(); 389 } 390 391 public ListIterator listIterator() { 392 return new SCOListIterator(super.listIterator(), stateManager, owner, fmd.getManagedFieldNo()); 393 } 394 395 public ListIterator listIterator(int index) { 396 return new SCOListIterator(super.listIterator(index), stateManager, owner, fmd.getManagedFieldNo()); 397 } 398 399 public Iterator iterator() { 400 return new SCOIterator(super.iterator(), stateManager, owner, fmd.getManagedFieldNo()); 401 } 402 403 public CollectionDiff getCollectionDiff(PersistenceContext pm) { 404 Object [] data = toArray(); 405 if (fmd.isOrdered()) { 406 return CollectionDiffUtil.getOrderedCollectionDiff(fmd, pm, 407 data, data.length, (owner.jdoIsNew() && !beenReset) ? null : originalData); 408 } else { 409 return CollectionDiffUtil.getUnorderedCollectionDiff(fmd, pm, 410 data, data.length, (owner.jdoIsNew() && !beenReset) ? null : originalData); 411 } 412 } 413 414 public Object getOwner() { 415 return owner; 416 } 417 418 public void makeTransient() { 419 owner = null; 420 stateManager = null; 421 } 422 423 public void makeDirty() { 424 if (stateManager != null) { 425 stateManager.makeDirty(owner, fmd.getManagedFieldNo()); 426 } 427 } 428 429 public void reset() { 430 beenReset = true; 431 originalData = toArray(); 432 } 433 434 public void manyToManyAdd(Object o) { 435 super.add(o); 436 makeDirty(); 437 } 438 439 public void manyToManyRemove(Object o) { 440 if (super.removeElement(o)) { 441 makeDirty(); 442 } 443 } 444 445 448 public boolean isOrdered() { 449 return fmd.isOrdered(); 450 } 451 452 457 public CollectionData fillCollectionData(CollectionData collectionData) { 458 int size = size(); 459 collectionData.valueCount = size; 460 Object [] newData; 461 Object [] values = collectionData.values; 462 if (values == null || values.length < size) { 463 newData = new Object [size]; 464 } else { 465 newData = values; 466 } 467 for (int i = 0; i < size; i++) { 468 newData[i] = get(i); 469 } 470 collectionData.values = newData; 471 return collectionData; 472 } 473 } 474 | Popular Tags |