001: /*
002: * <copyright>
003: *
004: * Copyright 2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.util;
028:
029: import java.util.*;
030:
031: /**
032: * A "double buffered" List implementation, optimized for
033: * cases where the contents rarely change.
034: * This implementation acts superficially like a normal list
035: * except that it actually is implemented by always creating
036: * a new private copy of the list on each modification.
037: * This allows iteration and such to never have to worry about
038: * comodification exceptions. The downside is that
039: * it is relatively expensive to modify the contents.
040: * @note If consistency between calls to accessors is required,
041: * use #iterator() or #getUnmodifiableList() instead of the local
042: * methods. You may also synchronize on the instance for consecutive
043: * access safety, but then you are getting fewer of the benefits of
044: * this class without avoiding any of the costs.
045: * @note This implementation has near-zero read impact, versus best-base
046: * ArrayList, but can have a very high mutate impact (10-100 times),
047: * particularly for large arrays. Large arrays or many mutates would
048: * be better served by a different implementation.
049: **/
050:
051: public class RarelyModifiedList implements List, java.io.Serializable {
052: /** current backing list **/
053: private List back;
054:
055: public RarelyModifiedList() {
056: back = Collections.EMPTY_LIST;
057: }
058:
059: public RarelyModifiedList(Collection c) {
060: back = Collections.unmodifiableList(new ArrayList(c));
061: }
062:
063: public RarelyModifiedList(int l) {
064: // no reason to actually pay attention to this
065: back = Collections.EMPTY_LIST;
066: }
067:
068: /** make a mutable copy of the backing list.
069: * @note callers must synchronize on this.
070: **/
071: protected final List copy() {
072: // must be externally synchronized
073: return new ArrayList(back);
074: }
075:
076: /** make a mutable copy of the backing list with extra space for adds.
077: * @note callers must synchronize on this.
078: **/
079: protected final List copy(int extra) {
080: // must be externally synchronized
081: List l = new ArrayList(back.size() + extra);
082: l.addAll(back);
083: return l;
084: }
085:
086: /** make the backing list an unmodifiable version of the passed
087: * list.
088: * @note callers must synchronize on this.
089: */
090: protected final List freeze(List l) {
091: // must be externally synchronized
092: back = Collections.unmodifiableList(l);
093: return back;
094: }
095:
096: /** returns an immutable list which is guaranteed not to result
097: * in ComodificationExceptions or inconsistencies when traversing.
098: **/
099: public synchronized final List getUnmodifiableList() {
100: return back;
101: }
102:
103: public synchronized void add(int index, Object element) {
104: List l = copy(1);
105: l.add(index, element);
106: freeze(l);
107: }
108:
109: public synchronized boolean add(Object o) {
110: List l = copy(1);
111: boolean b = l.add(o);
112: freeze(l);
113: return b;
114: }
115:
116: public synchronized boolean addAll(Collection c) {
117: List l = copy(c.size());
118: boolean b = l.addAll(c);
119: freeze(l);
120: return b;
121: }
122:
123: public synchronized boolean addAll(int i, Collection c) {
124: List l = copy(c.size());
125: boolean b = l.addAll(i, c);
126: freeze(l);
127: return b;
128: }
129:
130: public synchronized void clear() {
131: back = Collections.EMPTY_LIST;
132: }
133:
134: public synchronized boolean contains(Object o) {
135: return back.contains(o);
136: }
137:
138: public synchronized boolean containsAll(Collection c) {
139: return back.containsAll(c);
140: }
141:
142: public synchronized boolean equals(Object o) {
143: return back.equals(o);
144: }
145:
146: public synchronized Object get(int i) {
147: return back.get(i);
148: }
149:
150: public synchronized int hashCode() {
151: return back.hashCode();
152: }
153:
154: public synchronized int indexOf(Object o) {
155: return back.indexOf(o);
156: }
157:
158: public synchronized boolean isEmpty() {
159: return back.isEmpty();
160: }
161:
162: public synchronized Iterator iterator() {
163: return back.iterator();
164: }
165:
166: public synchronized int lastIndexOf(Object o) {
167: return back.lastIndexOf(o);
168: }
169:
170: public synchronized ListIterator listIterator() {
171: return back.listIterator();
172: }
173:
174: public synchronized ListIterator listIterator(int i) {
175: return back.listIterator(i);
176: }
177:
178: public synchronized Object remove(int i) {
179: List l = copy();
180: Object o = l.remove(i);
181: freeze(l);
182: return o;
183: }
184:
185: public synchronized boolean remove(Object ob) {
186: List l = copy();
187: boolean b = l.remove(ob);
188: freeze(l);
189: return b;
190: }
191:
192: public synchronized boolean removeAll(Collection c) {
193: List l = copy();
194: boolean b = l.removeAll(c);
195: freeze(l);
196: return b;
197: }
198:
199: public synchronized boolean retainAll(Collection c) {
200: List l = copy();
201: boolean b = l.retainAll(c);
202: freeze(l);
203: return b;
204: }
205:
206: public synchronized Object set(int i, Object el) {
207: List l = copy();
208: Object o = l.set(i, el);
209: freeze(l);
210: return o;
211: }
212:
213: public synchronized int size() {
214: return back.size();
215: }
216:
217: public synchronized List subList(int x, int y) {
218: return back.subList(x, y);
219: }
220:
221: public synchronized Object[] toArray() {
222: return back.toArray();
223: }
224:
225: public synchronized Object[] toArray(Object[] a) {
226: return back.toArray(a);
227: }
228: }
|