1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.common.collection;
25
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.ListIterator;
31 import java.util.NoSuchElementException;
32 import net.jcip.annotations.Immutable;
33 import org.modeshape.common.util.CheckArg;
34
35
36
37
38
39
40
41
42 @Immutable
43 public class ImmutableAppendedList<T> implements List<T> {
44
45 private final List<T> parent;
46 private final T element;
47 private final int size;
48 private transient int hc;
49
50
51
52
53
54
55
56
57
58 public ImmutableAppendedList( List<T> parent,
59 T element ) {
60 CheckArg.isNotNull(parent, "parent");
61 this.parent = parent;
62 this.element = element;
63 this.size = parent.size() + 1;
64 }
65
66
67
68
69
70
71 public boolean contains( Object o ) {
72 return element == o || (element != null && element.equals(o)) || parent.contains(o);
73 }
74
75
76
77
78
79
80 public boolean containsAll( Collection<?> c ) {
81 Iterator<?> e = c.iterator();
82 while (e.hasNext()) {
83 if (!contains(e.next())) return false;
84 }
85 return true;
86 }
87
88
89
90
91
92
93 public T get( int index ) {
94 if (index == (size - 1)) return element;
95 return parent.get(index);
96 }
97
98
99
100
101
102
103 public int indexOf( Object o ) {
104 int index = parent.indexOf(o);
105 if (index == -1) {
106 return (element == o || (element != null && element.equals(o))) ? (size - 1) : -1;
107 }
108 return -1;
109 }
110
111
112
113
114
115
116 public boolean isEmpty() {
117 return false;
118 }
119
120
121
122
123
124
125 @SuppressWarnings( "synthetic-access" )
126 public Iterator<T> iterator() {
127 final Iterator<T> parentIterator = parent.iterator();
128 return new Iterator<T>() {
129 boolean finished = false;
130
131 public boolean hasNext() {
132 return parentIterator.hasNext() || !finished;
133 }
134
135 public T next() {
136 if (parentIterator.hasNext()) return parentIterator.next();
137 if (finished) throw new NoSuchElementException();
138 finished = true;
139 return element;
140 }
141
142 public void remove() {
143 throw new UnsupportedOperationException();
144 }
145 };
146 }
147
148
149
150
151
152
153 public int lastIndexOf( Object o ) {
154 if (element == o || (element != null && element.equals(o))) return size - 1;
155 return parent.lastIndexOf(o);
156 }
157
158
159
160
161
162
163 public ListIterator<T> listIterator() {
164 return listIterator(0);
165 }
166
167
168
169
170
171
172 @SuppressWarnings( "synthetic-access" )
173 public ListIterator<T> listIterator( final int index ) {
174 return new ListIterator<T>() {
175 int cursor = index;
176
177 public boolean hasNext() {
178 return cursor < size;
179 }
180
181 public T next() {
182 try {
183 T next = get(cursor);
184 cursor++;
185 return next;
186 } catch (IndexOutOfBoundsException e) {
187 throw new NoSuchElementException();
188 }
189 }
190
191 public boolean hasPrevious() {
192 return cursor != 0;
193 }
194
195 public int nextIndex() {
196 return cursor;
197 }
198
199 public T previous() {
200 try {
201 int i = cursor - 1;
202 T previous = get(i);
203 cursor = i;
204 return previous;
205 } catch (IndexOutOfBoundsException e) {
206 throw new NoSuchElementException();
207 }
208 }
209
210 public int previousIndex() {
211 return cursor - 1;
212 }
213
214 public void set( T o ) {
215 throw new UnsupportedOperationException();
216 }
217
218 public void remove() {
219 throw new UnsupportedOperationException();
220 }
221
222 public void add( T o ) {
223 throw new UnsupportedOperationException();
224 }
225
226 };
227 }
228
229
230
231
232
233
234 public int size() {
235 return size;
236 }
237
238
239
240
241
242
243 public List<T> subList( int fromIndex,
244 int toIndex ) {
245 if (fromIndex == 0 && toIndex == size) {
246
247 return this;
248 }
249 if (toIndex == size || fromIndex == (size - 1)) {
250
251 return Collections.singletonList(element);
252 }
253 if (toIndex < size) {
254
255 return parent.subList(fromIndex, toIndex);
256 }
257
258
259 List<T> sublist = parent.subList(fromIndex, toIndex - 1);
260
261 return new ImmutableAppendedList<T>(sublist, element);
262 }
263
264
265
266
267
268
269 public Object[] toArray() {
270 Object[] result = new Object[size];
271 int i = 0;
272 for (T e : parent) {
273 result[i++] = e;
274 }
275 result[i] = element;
276 return result;
277 }
278
279
280
281
282
283
284 @SuppressWarnings( "unchecked" )
285 public <X> X[] toArray( X[] a ) {
286 if (a.length < size) a = (X[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
287 a = parent.toArray(a);
288 a[size - 1] = (X)element;
289 return a;
290 }
291
292
293
294
295
296
297 @Override
298 public int hashCode() {
299 if (hc == 0) {
300 int hashCode = 1;
301 for (T element : this) {
302 hashCode = 31 * hashCode + (element == null ? 0 : element.hashCode());
303 }
304 hc = hashCode;
305 }
306 return hc;
307 }
308
309
310
311
312
313
314 @Override
315 public boolean equals( Object obj ) {
316 if (obj == this) return true;
317 if (obj instanceof List) {
318 List<?> that = (List<?>)obj;
319 if (this.size() != that.size()) return false;
320 Iterator<?> thisIter = this.iterator();
321 Iterator<?> thatIter = that.iterator();
322 while (thisIter.hasNext()) {
323 Object thisValue = thisIter.next();
324 Object thatValue = thatIter.next();
325 if (thisValue == null) {
326 if (thatValue != null) return false;
327
328 } else {
329 if (!thisValue.equals(thatValue)) return false;
330 }
331 }
332 return true;
333 }
334 return super.equals(obj);
335 }
336
337
338
339
340
341
342 @Override
343 public String toString() {
344 StringBuffer buf = new StringBuffer();
345 buf.append("[");
346
347 Iterator<T> i = iterator();
348 boolean hasNext = i.hasNext();
349 while (hasNext) {
350 T o = i.next();
351 buf.append(o == this ? "(this Collection)" : String.valueOf(o));
352 hasNext = i.hasNext();
353 if (hasNext) buf.append(", ");
354 }
355
356 buf.append("]");
357 return buf.toString();
358 }
359
360
361
362
363
364
365
366
367
368
369 public void add( int index,
370 T element ) {
371 throw new UnsupportedOperationException();
372 }
373
374
375
376
377
378
379 public boolean add( T o ) {
380 throw new UnsupportedOperationException();
381 }
382
383
384
385
386
387
388 public boolean addAll( Collection<? extends T> c ) {
389 throw new UnsupportedOperationException();
390 }
391
392
393
394
395
396
397 public boolean addAll( int index,
398 Collection<? extends T> c ) {
399 throw new UnsupportedOperationException();
400 }
401
402
403
404
405
406
407 public void clear() {
408 throw new UnsupportedOperationException();
409 }
410
411
412
413
414
415
416 public boolean remove( Object o ) {
417 throw new UnsupportedOperationException();
418 }
419
420
421
422
423
424
425 public T remove( int index ) {
426 throw new UnsupportedOperationException();
427 }
428
429
430
431
432
433
434 public boolean removeAll( Collection<?> c ) {
435 throw new UnsupportedOperationException();
436 }
437
438
439
440
441
442
443 public boolean retainAll( Collection<?> c ) {
444 throw new UnsupportedOperationException();
445 }
446
447
448
449
450
451
452 public T set( int index,
453 T element ) {
454 throw new UnsupportedOperationException();
455 }
456
457 }