1 10 11 package com.triactive.jdo.sco; 12 13 import com.triactive.jdo.PersistenceManager; 14 import com.triactive.jdo.SCO; 15 import com.triactive.jdo.StateManager; 16 import com.triactive.jdo.store.Query; 17 import com.triactive.jdo.store.Queryable; 18 import com.triactive.jdo.store.QueryStatement; 19 import com.triactive.jdo.store.SetStore; 20 import java.io.ObjectStreamException ; 21 import java.util.ArrayList ; 22 import java.util.Collection ; 23 import java.util.ConcurrentModificationException ; 24 import java.util.Iterator ; 25 import java.util.Set ; 26 import javax.jdo.JDOFatalInternalException; 27 import javax.jdo.JDOHelper; 28 import org.apache.log4j.Category; 29 30 31 90 91 public class HashSet extends java.util.HashSet implements SCOCollection, Cloneable , Queryable 92 { 93 private static final Category LOG = Category.getInstance(HashSet.class); 94 95 private transient Object owner; 96 private transient PersistenceManager pm; 97 private transient StateManager ownerSM; 98 private transient String fieldName; 99 private transient SetStore setStore; 100 private transient boolean isPersistent; 101 private transient boolean isLoaded; private transient int expectedDSModCount = 0; 103 private transient volatile int modCount = 0; 104 105 106 private void init(Object owner, String fieldName, SetStore setStore) 107 { 108 this.owner = owner; 109 this.pm = (PersistenceManager)JDOHelper.getPersistenceManager(owner); 110 this.ownerSM = pm.findStateManager(owner); 111 this.fieldName = fieldName; 112 this.setStore = setStore; 113 this.isPersistent = JDOHelper.isPersistent(owner); 114 } 115 116 117 128 129 public HashSet(Object owner, String fieldName, SetStore setStore) 130 { 131 init(owner, fieldName, setStore); 132 133 if (!isPersistent) 134 throw new JDOFatalInternalException("Wrong constructor called, owner object is transient"); 135 136 isLoaded = false; 137 } 138 139 140 157 158 public HashSet(Object owner, String fieldName, SetStore setStore, Collection value) 159 { 160 init(owner, fieldName, setStore); 161 162 if (isPersistent) 163 { 164 clearPersistent(); 165 addAllPersistent(value); 166 } 167 else 168 addAllInternal(value); 169 170 setIsLoaded(); 171 } 172 173 174 private void setIsLoaded() 175 { 176 isLoaded = true; 177 expectedDSModCount = pm.dataStoreModifyCount(); 178 } 179 180 181 private boolean upToDate() 182 { 183 if (!isPersistent) 184 return true; 185 else if (!isLoaded) 186 return false; 187 else if (!pm.currentTransaction().isActive()) 188 return true; 189 else 190 { 191 195 return pm.dataStoreModifyCount() == expectedDSModCount; 196 } 197 } 198 199 200 public Object getOwner() 201 { 202 return owner; 203 } 204 205 206 public String getFieldName() 207 { 208 return fieldName; 209 } 210 211 212 public Class getElementType() 213 { 214 return setStore.getElementType(); 215 } 216 217 218 public boolean allowsNulls() 219 { 220 return setStore.allowsNulls(); 221 } 222 223 224 public void makeDirty() 225 { 226 ++modCount; 227 228 233 if (owner != null) 234 JDOHelper.makeDirty(owner, fieldName); 235 } 236 237 238 public void applyUpdates() 239 { 240 245 if (!isPersistent) 246 { 247 setStore.addAll(ownerSM, this); 248 isPersistent = true; 249 expectedDSModCount = pm.dataStoreModifyCount(); 250 251 if (LOG.isDebugEnabled()) 252 LOG.debug(toLogString() + " is now persistent"); 253 } 254 } 255 256 257 public void unsetOwner() 258 { 259 if (owner != null) 260 { 261 owner = null; 262 ownerSM = null; 263 fieldName = null; 264 isPersistent = false; 265 266 if (LOG.isDebugEnabled()) 267 LOG.debug(toLogString() + " is now unowned"); 268 } 269 } 270 271 272 public Class getCandidateClass() 273 { 274 return getElementType(); 275 } 276 277 278 public QueryStatement newQueryStatement(Class candidateClass) 279 { 280 if (!isPersistent) 281 throw new QueryUnownedSCOException(this); 282 283 return setStore.newQueryStatement(ownerSM, candidateClass); 284 } 285 286 287 public Query.ResultObjectFactory newResultObjectFactory(QueryStatement stmt) 288 { 289 if (!isPersistent) 290 throw new QueryUnownedSCOException(this); 291 292 return setStore.newResultObjectFactory(ownerSM, stmt); 293 } 294 295 296 304 305 public Object clone() 306 { 307 Object obj = super.clone(); 308 309 ((HashSet)obj).unsetOwner(); 310 311 return obj; 312 } 313 314 315 private synchronized void load() 316 { 317 if (!upToDate()) 318 { 319 if (LOG.isDebugEnabled()) 320 LOG.debug(toLogString() + " loading from storage"); 321 322 Collection contents = setStore.load(ownerSM); 323 clearInternal(); 324 addAllInternal(contents); 325 setIsLoaded(); 326 } 327 } 328 329 330 private boolean addInternal(Object o) 331 { 332 return super.add(o); 333 } 334 335 336 private boolean addAllInternal(Collection c) 337 { 338 boolean modified = false; 339 Iterator i = c.iterator(); 340 341 while (i.hasNext()) 342 { 343 if (super.add(i.next())) 344 modified = true; 345 } 346 347 return modified; 348 } 349 350 351 private Iterator iteratorInternal() 352 { 353 return super.iterator(); 354 } 355 356 357 private boolean removeInternal(Object o) 358 { 359 return super.remove(o); 360 } 361 362 363 private void clearInternal() 364 { 365 super.clear(); 366 } 367 368 369 private boolean addPersistent(Object o) 370 { 371 if (isPersistent) 372 { 373 addInternal(o); 374 return setStore.add(ownerSM, o); 375 } 376 else 377 return addInternal(o); 378 } 379 380 381 private boolean addAllPersistent(Collection c) 382 { 383 SCOHelper.assertAllValidElements(this, c); 384 385 if (isPersistent) 386 { 387 addAllInternal(c); 388 return setStore.addAll(ownerSM, c); 389 } 390 else 391 return addAllInternal(c); 392 } 393 394 395 private boolean removePersistent(Object o) 396 { 397 if (isPersistent) 398 { 399 removeInternal(o); 400 return setStore.remove(ownerSM, o); 401 } 402 else 403 return removeInternal(o); 404 } 405 406 407 private void clearPersistent() 408 { 409 if (isPersistent) 410 { 411 setStore.clear(ownerSM); 412 setIsLoaded(); 413 } 414 415 clearInternal(); 416 } 417 418 419 public Iterator iterator() 420 { 421 return new HashSetIterator(); 422 } 423 424 425 private class HashSetIterator implements Iterator 426 { 427 private final Iterator iter; 428 private Object last = null; 429 private int expectedModCount = modCount; 430 431 public HashSetIterator() 432 { 433 load(); 434 ArrayList entries = new ArrayList (size()); 435 Iterator i = iteratorInternal(); 436 437 while (i.hasNext()) 438 entries.add(i.next()); 439 440 iter = entries.iterator(); 441 } 442 443 public boolean hasNext() 444 { 445 return iter.hasNext(); 446 } 447 448 public Object next() 449 { 450 if (modCount != expectedModCount) 451 throw new ConcurrentModificationException (); 452 453 return last = iter.next(); 454 } 455 456 public void remove() 457 { 458 if (last == null) 459 throw new IllegalStateException (); 460 if (modCount != expectedModCount) 461 throw new ConcurrentModificationException (); 462 463 makeDirty(); 464 removePersistent(last); 465 last = null; 466 expectedModCount = modCount; 467 } 468 } 469 470 471 public int size() 472 { 473 return upToDate() ? super.size() : setStore.size(ownerSM); 474 } 475 476 477 public boolean isEmpty() 478 { 479 return upToDate() ? super.isEmpty() : setStore.isEmpty(ownerSM); 480 } 481 482 483 public boolean contains(Object o) 484 { 485 if (!SCOHelper.isValidElement(this, o)) 486 return false; 487 488 return upToDate() ? super.contains(o) : setStore.contains(ownerSM, o); 489 } 490 491 492 public boolean add(Object o) 493 { 494 SCOHelper.assertIsValidElement(this, o); 495 496 makeDirty(); 497 return addPersistent(o); 498 } 499 500 501 public boolean remove(Object o) 502 { 503 if (!SCOHelper.isValidElement(this, o)) 504 return false; 505 506 makeDirty(); 507 return removePersistent(o); 508 } 509 510 511 public void clear() 512 { 513 makeDirty(); 514 clearPersistent(); 515 } 516 517 518 public boolean containsAll(Collection c) 519 { 520 load(); 521 return super.containsAll(c); 522 } 523 524 525 public boolean addAll(Collection c) 526 { 527 makeDirty(); 528 return addAllPersistent(c); 529 } 530 531 532 public boolean removeAll(Collection c) 533 { 534 makeDirty(); 535 536 boolean modified = false; 537 Iterator i = c.iterator(); 538 539 while (i.hasNext()) 540 { 541 Object o = i.next(); 542 543 if (SCOHelper.isValidElement(this, o) && removePersistent(o)) 544 modified = true; 545 } 546 547 return modified; 548 } 549 550 551 public boolean retainAll(Collection c) 552 { 553 makeDirty(); 554 555 if (c instanceof SCO) 556 c = new java.util.HashSet (c); 557 558 boolean modified = false; 559 Iterator i = iterator(); 560 561 while (i.hasNext()) 562 { 563 Object o = i.next(); 564 565 if (!c.contains(o)) 566 { 567 if (SCOHelper.isValidElement(this, o) && removePersistent(o)) 568 modified = true; 569 } 570 } 571 572 return modified; 573 } 574 575 576 public Object [] toArray() 577 { 578 load(); 579 return super.toArray(); 580 } 581 582 583 public Object [] toArray(Object a[]) 584 { 585 load(); 586 return super.toArray(a); 587 } 588 589 590 public boolean equals(Object o) 591 { 592 load(); 593 return super.equals(o); 594 } 595 596 597 public int hashCode() 598 { 599 load(); 600 return super.hashCode(); 601 } 602 603 604 public String toString() 605 { 606 load(); 607 return super.toString(); 608 } 609 610 611 private String toLogString() 612 { 613 return SCOHelper.toLogString(this); 614 } 615 616 617 625 626 protected Object writeReplace() throws ObjectStreamException 627 { 628 return new java.util.HashSet (this); 629 } 630 } 631 | Popular Tags |