001: /*
002: *
003: * JMoney - A Personal Finance Manager
004: * Copyright (c) 2005 Nigel Westbury <westbury@users.sourceforge.net>
005: *
006: *
007: * This program is free software; you can redistribute it and/or modify
008: * it under the terms of the GNU General Public License as published by
009: * the Free Software Foundation; either version 2 of the License, or
010: * (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
020: *
021: */
022:
023: package net.sf.jmoney.isolation;
024:
025: import java.util.Collection;
026: import java.util.Iterator;
027:
028: import net.sf.jmoney.model2.ExtendableObject;
029: import net.sf.jmoney.model2.IObjectKey;
030:
031: /**
032: * Class imlementing an iterator that wraps a iterator of committed
033: * objects in the datastore,
034: * but adjusting the elements by applying changes made in
035: * the transaction. New elements are added and deleted elements
036: * are removed from the iteration. Furthermore, the elements
037: * returned by the given iterator are adjusted to get the
038: * uncommitted versions.
039: *
040: * @author Nigel Westbury
041: */
042: class DeltaListIterator<E extends ExtendableObject> implements
043: Iterator<E> {
044: TransactionManager transactionManager;
045: boolean processingCommittedObjects = true;
046:
047: /**
048: * This collection contains the uncommitted version
049: * of objects that have been added
050: */
051: Collection<E> addedObjects;
052:
053: /**
054: * The object keys in this collection are the keys for
055: * the committed version of the objects.
056: */
057: Collection<IObjectKey> deletedObjects;
058:
059: Iterator<E> subIterator;
060:
061: /**
062: * Always non-null if processingCommittedObjects = true
063: * Not applicable if processingCommittedObjects = false
064: */
065: E nextObject;
066:
067: /**
068: * Construct an iterator that iterates the given iterator,
069: * but adjusting the elements by adding and removing elements
070: * in the given lists.
071: *
072: * @param committedListIterator
073: * @param addedObjects list of objects that have been added
074: * in the transaction. These objects may be either
075: * objects newly created in the transation or may be
076: * uncommitted versions of objects that exist in the
077: * committed datastore (the latter being possible only
078: * if this iterator is being used for an indexed value
079: * list).
080: * @param deletedObjects list of objects in the committed datastore
081: * that have been deleted in the transaction. All objects
082: * in this list should be also in the set returned by
083: * committedListIterator. This list contains the committed
084: * object keys.
085: */
086: DeltaListIterator(TransactionManager transactionManager,
087: Iterator<E> committedListIterator,
088: Collection<E> addedObjects,
089: Collection<IObjectKey> deletedObjects) {
090: this .transactionManager = transactionManager;
091: subIterator = committedListIterator;
092: this .addedObjects = addedObjects;
093: this .deletedObjects = deletedObjects;
094: setNextObject();
095: }
096:
097: public boolean hasNext() {
098: if (processingCommittedObjects) {
099: return true;
100: } else {
101: return subIterator.hasNext();
102: }
103: }
104:
105: /*
106: * When processing the list of committed objects (the first sub-iteration),
107: * we always leave the sub-iterator positioned at the next object to be
108: * returned. That is, we pass any objects in the set that are marked for
109: * deletion. Doing this enables the hasNext() method to easily return the
110: * correct result. This does mean we must save the next object to be
111: * returned because it will have already been fetched from the sub-iterator.
112: */
113: public E next() {
114: if (processingCommittedObjects) {
115: E objectToReturn = nextObject;
116: setNextObject();
117: return objectToReturn;
118: } else {
119: return subIterator.next();
120: }
121: }
122:
123: public void remove() {
124: throw new RuntimeException("not implemented");
125: }
126:
127: /**
128: * Set nextObject to the first/next object from the committed list that has
129: * not been marked for deletion, or, if there is no more such objects, set
130: * up for returning the newly added objects by setting the flag and setting
131: * the sub-iterator to be an iterator that iterates the newly added objects.
132: */
133: private void setNextObject() {
134: E committedObject;
135: do {
136: if (!subIterator.hasNext()) {
137: processingCommittedObjects = false;
138: subIterator = addedObjects.iterator();
139: return;
140: }
141: committedObject = subIterator.next();
142: } while (deletedObjects
143: .contains(committedObject.getObjectKey()));
144:
145: nextObject = transactionManager
146: .getCopyInTransaction(committedObject);
147: }
148: }
|