View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections.primitives;
18  
19  import java.util.ConcurrentModificationException;
20  import java.util.NoSuchElementException;
21  
22  /**
23   * Abstract base class for {@link BooleanList}s backed by random access
24   * structures like arrays.
25   * <p />
26   * Read-only subclasses must override {@link #get} and {@link #size}.
27   * Mutable subclasses should also override {@link #set}.  Variably-sized
28   * subclasses should also override {@link #add(boolean)} and {@link #removeElementAt}.
29   * All other methods have at least some base implementation derived from
30   * these.  Subclasses may choose to override these methods to provide a
31   * more efficient implementation.
32   * 
33   * @since Commons Primitives 1.2
34   * @version $Revision: 480460 $
35   */
36  public abstract class RandomAccessBooleanList extends
37          AbstractBooleanCollection implements BooleanList {
38  
39      // constructors
40      //-------------------------------------------------------------------------
41  
42      /** Constructs an empty list. */
43      protected RandomAccessBooleanList() { 
44      }    
45  
46      // fully abstract methods
47      //-------------------------------------------------------------------------
48      
49      public abstract boolean get(int index);
50      public abstract int size();
51  
52      // unsupported in base
53      //-------------------------------------------------------------------------
54      
55      /** 
56       * Unsupported in this implementation. 
57       * @throws UnsupportedOperationException since this method is not supported
58       */
59      public boolean removeElementAt(int index) {
60          throw new UnsupportedOperationException();
61      }
62      
63      /** 
64       * Unsupported in this implementation. 
65       * @throws UnsupportedOperationException since this method is not supported
66       */
67      public boolean set(int index, boolean element) {
68          throw new UnsupportedOperationException();
69      }
70          
71      /** 
72       * Unsupported in this implementation. 
73       * @throws UnsupportedOperationException since this method is not supported
74       */
75      public void add(int index, boolean element) {
76          throw new UnsupportedOperationException();
77      }
78  
79      //-------------------------------------------------------------------------
80  
81      // javadocs here are inherited
82      
83      public boolean add(boolean element) {
84          add(size(),element);
85          return true;
86      }
87  
88      public boolean addAll(int index, BooleanCollection collection) {
89          boolean modified = false;
90          for(BooleanIterator iter = collection.iterator(); iter.hasNext(); ) {
91              add(index++,iter.next());
92              modified = true;
93          }
94          return modified;
95      }
96  
97      public int indexOf(boolean element) {
98          int i = 0;
99          for(BooleanIterator iter = iterator(); iter.hasNext(); ) {
100             if(iter.next() == element) { 
101                 return i;
102             } else {
103                 i++;
104             }
105         }
106         return -1;
107     }
108 
109     public int lastIndexOf(boolean element) {
110         for(BooleanListIterator iter = listIterator(size()); iter.hasPrevious(); ) {
111             if(iter.previous() == element) {
112                 return iter.nextIndex();
113             }
114         }
115         return -1;
116     }
117 
118     public BooleanIterator iterator() {
119         return listIterator();
120     }
121 
122     public BooleanListIterator listIterator() {
123         return listIterator(0);
124     }
125 
126     public BooleanListIterator listIterator(int index) {
127         return new RandomAccessBooleanListIterator(this,index);
128     }
129 
130     public BooleanList subList(int fromIndex, int toIndex) {
131         return new RandomAccessBooleanSubList(this,fromIndex,toIndex);
132     }
133 
134     public boolean equals(Object that) {
135         if(this == that) { 
136             return true; 
137         } else if(that instanceof BooleanList) {
138             BooleanList thatList = (BooleanList)that;
139             if(size() != thatList.size()) {
140                 return false;
141             }
142             for(BooleanIterator thatIter = thatList.iterator(),
143                     thisIter = iterator(); thisIter.hasNext();) {
144                 if(thisIter.next() != thatIter.next()) { 
145                     return false; 
146                 }
147             }
148             return true;
149         } else {
150             return false;
151         }        
152     }
153 
154     public int hashCode() {
155         int hash = 1;
156         for(BooleanIterator iter = iterator(); iter.hasNext(); ) {
157             hash = 31*hash + (iter.next() ? 1231 : 1237);
158         }
159         return hash;
160     }
161     
162     public String toString() {
163         StringBuffer buf = new StringBuffer();
164         buf.append("[");
165         for(BooleanIterator iter = iterator(); iter.hasNext();) {
166             buf.append(iter.next());
167             if(iter.hasNext()) {
168                 buf.append(", ");
169             }
170         }
171         buf.append("]");
172         return buf.toString();
173     }
174     
175     // protected utilities
176     //-------------------------------------------------------------------------
177     
178     /** Get my count of structural modifications. */
179     protected int getModCount() {
180         return _modCount;
181     }
182 
183     /** Increment my count of structural modifications. */
184     protected void incrModCount() {
185         _modCount++;
186     }
187 
188     // attributes
189     //-------------------------------------------------------------------------
190     
191     private int _modCount = 0;
192 
193     // inner classes
194     //-------------------------------------------------------------------------
195     
196     private static class ComodChecker {
197         ComodChecker(RandomAccessBooleanList source) {
198             _source = source;  
199             resyncModCount();             
200         }
201         
202         protected RandomAccessBooleanList getList() {
203             return _source;
204         }
205         
206         protected void assertNotComodified() throws ConcurrentModificationException {
207             if(_expectedModCount != getList().getModCount()) {
208                 throw new ConcurrentModificationException();
209             }
210         }
211             
212         protected void resyncModCount() {
213             _expectedModCount = getList().getModCount();
214         }
215         
216         private RandomAccessBooleanList _source = null;
217         private int _expectedModCount = -1;
218     }
219     
220     protected static class RandomAccessBooleanListIterator
221             extends ComodChecker implements BooleanListIterator {
222         RandomAccessBooleanListIterator(RandomAccessBooleanList list, int index) {
223             super(list);
224             if(index < 0 || index > getList().size()) {
225                 throw new IndexOutOfBoundsException("Index " + index +
226                         " not in [0," + getList().size() + ")");
227             } else {
228                 _nextIndex = index;
229                 resyncModCount();
230             }
231         }
232             
233         public boolean hasNext() {
234             assertNotComodified();
235             return _nextIndex < getList().size();
236         }
237         
238         public boolean hasPrevious() {
239             assertNotComodified();
240             return _nextIndex > 0;
241         }
242         
243         public int nextIndex() {
244             assertNotComodified();
245             return _nextIndex;
246         }
247         
248         public int previousIndex() {
249             assertNotComodified();
250             return _nextIndex - 1;
251         }
252         
253         public boolean next() {
254             assertNotComodified();
255             if(!hasNext()) {
256                 throw new NoSuchElementException();
257             } else {
258                 boolean val = getList().get(_nextIndex);
259                 _lastReturnedIndex = _nextIndex;
260                 _nextIndex++;
261                 return val;
262             }
263         }
264         
265         public boolean previous() {
266             assertNotComodified();
267             if(!hasPrevious()) {
268                 throw new NoSuchElementException();
269             } else {
270                 boolean val = getList().get(_nextIndex-1);
271                 _lastReturnedIndex = _nextIndex-1;
272                 _nextIndex--;
273                 return val;
274             }
275         }
276         
277         public void add(boolean value) {
278             assertNotComodified();
279             getList().add(_nextIndex,value);
280             _nextIndex++;
281             _lastReturnedIndex = -1;
282             resyncModCount();
283         }
284     
285         public void remove() {
286             assertNotComodified();
287             if (_lastReturnedIndex == -1) {
288                 throw new IllegalStateException();
289             }
290             if (_lastReturnedIndex == _nextIndex) {
291                 // remove() following previous()
292                 getList().removeElementAt(_lastReturnedIndex);
293             } else {
294                 // remove() following next()
295                 getList().removeElementAt(_lastReturnedIndex);
296                 _nextIndex--;
297             }
298             _lastReturnedIndex = -1;
299             resyncModCount();
300         }
301         
302         public void set(boolean value) {
303             assertNotComodified();
304             if(-1 == _lastReturnedIndex) {
305                 throw new IllegalStateException();
306             } else {
307                 getList().set(_lastReturnedIndex,value);
308                 resyncModCount();
309             }
310         }
311         
312         private int _nextIndex = 0;
313         private int _lastReturnedIndex = -1;        
314     }   
315 
316     protected static class RandomAccessBooleanSubList
317             extends RandomAccessBooleanList implements BooleanList {
318         RandomAccessBooleanSubList(RandomAccessBooleanList list,
319                                    int fromIndex, int toIndex) {
320             if(fromIndex < 0 || toIndex > list.size()) {
321                 throw new IndexOutOfBoundsException();
322             } else if(fromIndex > toIndex) {
323                 throw new IllegalArgumentException();                
324             } else {
325                 _list = list;
326                 _offset = fromIndex;
327                 _limit = toIndex - fromIndex;
328                 _comod = new ComodChecker(list);
329                 _comod.resyncModCount();
330             }            
331         }
332     
333         public boolean get(int index) {
334             checkRange(index);
335             _comod.assertNotComodified();
336             return _list.get(toUnderlyingIndex(index));
337         }
338     
339         public boolean removeElementAt(int index) {
340             checkRange(index);
341             _comod.assertNotComodified();
342             boolean val = _list.removeElementAt(toUnderlyingIndex(index));
343             _limit--;
344             _comod.resyncModCount();
345             incrModCount();
346             return val;
347         }
348     
349         public boolean set(int index, boolean element) {
350             checkRange(index);
351             _comod.assertNotComodified();
352             boolean val = _list.set(toUnderlyingIndex(index),element);
353             incrModCount();
354             _comod.resyncModCount();
355             return val;
356         }
357     
358         public void add(int index, boolean element) {
359             checkRangeIncludingEndpoint(index);
360             _comod.assertNotComodified();
361              _list.add(toUnderlyingIndex(index),element);
362             _limit++;
363             _comod.resyncModCount();
364             incrModCount();
365         }
366     
367         public int size() {
368             _comod.assertNotComodified();
369             return _limit;
370         }
371     
372         private void checkRange(int index) {
373             if(index < 0 || index >= size()) {
374                 throw new IndexOutOfBoundsException("index " + index
375                         + " not in [0," + size() + ")");
376             }
377         }
378           
379         private void checkRangeIncludingEndpoint(int index) {
380             if(index < 0 || index > size()) {
381                 throw new IndexOutOfBoundsException("index " + index
382                         + " not in [0," + size() + "]");
383             }
384         }
385           
386         private int toUnderlyingIndex(int index) {
387             return (index + _offset);
388         }
389         
390         private int _offset = 0;        
391         private int _limit = 0; 
392         private RandomAccessBooleanList _list = null;
393         private ComodChecker _comod = null;
394     
395     }
396 }
397