0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package java.util;
0019:
0020: import java.io.IOException;
0021: import java.io.ObjectOutputStream;
0022: import java.io.Serializable;
0023: import java.lang.reflect.Array;
0024:
0025: import org.apache.harmony.luni.internal.nls.Messages;
0026:
0027: /**
0028: * Collections contains static methods which operate on Collection classes.
0029: *
0030: * @since 1.2
0031: */
0032: public class Collections {
0033:
0034: private static final class CopiesList<E> extends AbstractList<E>
0035: implements Serializable {
0036: private static final long serialVersionUID = 2739099268398711800L;
0037:
0038: private final int n;
0039:
0040: private final E element;
0041:
0042: CopiesList(int length, E object) {
0043: if (length < 0) {
0044: throw new IllegalArgumentException();
0045: }
0046: n = length;
0047: element = object;
0048: }
0049:
0050: @Override
0051: public boolean contains(Object object) {
0052: return element == null ? object == null : element
0053: .equals(object);
0054: }
0055:
0056: @Override
0057: public int size() {
0058: return n;
0059: }
0060:
0061: @Override
0062: public E get(int location) {
0063: if (0 <= location && location < n) {
0064: return element;
0065: }
0066: throw new IndexOutOfBoundsException();
0067: }
0068: }
0069:
0070: @SuppressWarnings("unchecked")
0071: private static final class EmptyList extends AbstractList implements
0072: Serializable {
0073: private static final long serialVersionUID = 8842843931221139166L;
0074:
0075: @Override
0076: public boolean contains(Object object) {
0077: return false;
0078: }
0079:
0080: @Override
0081: public int size() {
0082: return 0;
0083: }
0084:
0085: @Override
0086: public Object get(int location) {
0087: throw new IndexOutOfBoundsException();
0088: }
0089:
0090: private Object readResolve() {
0091: return Collections.EMPTY_LIST;
0092: }
0093: }
0094:
0095: @SuppressWarnings("unchecked")
0096: private static final class EmptySet extends AbstractSet implements
0097: Serializable {
0098: private static final long serialVersionUID = 1582296315990362920L;
0099:
0100: @Override
0101: public boolean contains(Object object) {
0102: return false;
0103: }
0104:
0105: @Override
0106: public int size() {
0107: return 0;
0108: }
0109:
0110: @Override
0111: public Iterator iterator() {
0112: return new Iterator() {
0113: public boolean hasNext() {
0114: return false;
0115: }
0116:
0117: public Object next() {
0118: throw new NoSuchElementException();
0119: }
0120:
0121: public void remove() {
0122: throw new UnsupportedOperationException();
0123: }
0124: };
0125: }
0126:
0127: private Object readResolve() {
0128: return Collections.EMPTY_SET;
0129: }
0130: }
0131:
0132: @SuppressWarnings("unchecked")
0133: private static final class EmptyMap extends AbstractMap implements
0134: Serializable {
0135: private static final long serialVersionUID = 6428348081105594320L;
0136:
0137: @Override
0138: public boolean containsKey(Object key) {
0139: return false;
0140: }
0141:
0142: @Override
0143: public boolean containsValue(Object value) {
0144: return false;
0145: }
0146:
0147: @Override
0148: public Set entrySet() {
0149: return EMPTY_SET;
0150: }
0151:
0152: @Override
0153: public Object get(Object key) {
0154: return null;
0155: }
0156:
0157: @Override
0158: public Set keySet() {
0159: return EMPTY_SET;
0160: }
0161:
0162: @Override
0163: public Collection values() {
0164: return EMPTY_LIST;
0165: }
0166:
0167: private Object readResolve() {
0168: return Collections.EMPTY_MAP;
0169: }
0170: }
0171:
0172: /**
0173: * An immutable, serializable, empty <code>List</code>.
0174: *
0175: * @see Collections#emptyList()
0176: */
0177: @SuppressWarnings("unchecked")
0178: public static final List EMPTY_LIST = new EmptyList();
0179:
0180: /**
0181: * An immutable, serializable, empty <code>Set</code>.
0182: *
0183: * @see Collections#emptySet()
0184: */
0185: @SuppressWarnings("unchecked")
0186: public static final Set EMPTY_SET = new EmptySet();
0187:
0188: /**
0189: * An immutable, serializable, empty <code>Map</code>.
0190: *
0191: * @see Collections#emptyMap()
0192: */
0193: @SuppressWarnings("unchecked")
0194: public static final Map EMPTY_MAP = new EmptyMap();
0195:
0196: private static final class ReverseComparator<T> implements
0197: Comparator<T>, Serializable {
0198: private static final long serialVersionUID = 7207038068494060240L;
0199:
0200: @SuppressWarnings("unchecked")
0201: public int compare(T o1, T o2) {
0202: Comparable<T> c2 = (Comparable<T>) o2;
0203: return c2.compareTo(o1);
0204: }
0205: }
0206:
0207: private static final class ReverseComparatorWithComparator<T>
0208: implements Comparator<T>, Serializable {
0209: private static final long serialVersionUID = 4374092139857L;
0210:
0211: private final Comparator<T> comparator;
0212:
0213: ReverseComparatorWithComparator(Comparator<T> comparator) {
0214: super ();
0215: this .comparator = comparator;
0216: }
0217:
0218: public int compare(T o1, T o2) {
0219: return comparator.compare(o2, o1);
0220: }
0221: }
0222:
0223: private static final class SingletonSet<E> extends AbstractSet<E>
0224: implements Serializable {
0225: private static final long serialVersionUID = 3193687207550431679L;
0226:
0227: final E element;
0228:
0229: SingletonSet(E object) {
0230: element = object;
0231: }
0232:
0233: @Override
0234: public boolean contains(Object object) {
0235: return element == null ? object == null : element
0236: .equals(object);
0237: }
0238:
0239: @Override
0240: public int size() {
0241: return 1;
0242: }
0243:
0244: @Override
0245: public Iterator<E> iterator() {
0246: return new Iterator<E>() {
0247: boolean hasNext = true;
0248:
0249: public boolean hasNext() {
0250: return hasNext;
0251: }
0252:
0253: public E next() {
0254: if (hasNext) {
0255: hasNext = false;
0256: return element;
0257: }
0258: throw new NoSuchElementException();
0259: }
0260:
0261: public void remove() {
0262: throw new UnsupportedOperationException();
0263: }
0264: };
0265: }
0266: }
0267:
0268: private static final class SingletonList<E> extends AbstractList<E>
0269: implements Serializable {
0270: private static final long serialVersionUID = 3093736618740652951L;
0271:
0272: final E element;
0273:
0274: SingletonList(E object) {
0275: element = object;
0276: }
0277:
0278: @Override
0279: public boolean contains(Object object) {
0280: return element == null ? object == null : element
0281: .equals(object);
0282: }
0283:
0284: @Override
0285: public E get(int location) {
0286: if (location == 0) {
0287: return element;
0288: }
0289: throw new IndexOutOfBoundsException();
0290: }
0291:
0292: @Override
0293: public int size() {
0294: return 1;
0295: }
0296: }
0297:
0298: private static final class SingletonMap<K, V> extends
0299: AbstractMap<K, V> implements Serializable {
0300: private static final long serialVersionUID = -6979724477215052911L;
0301:
0302: final K k;
0303:
0304: final V v;
0305:
0306: SingletonMap(K key, V value) {
0307: k = key;
0308: v = value;
0309: }
0310:
0311: @Override
0312: public boolean containsKey(Object key) {
0313: return k == null ? key == null : k.equals(key);
0314: }
0315:
0316: @Override
0317: public boolean containsValue(Object value) {
0318: return v == null ? value == null : v.equals(value);
0319: }
0320:
0321: @Override
0322: public V get(Object key) {
0323: if (containsKey(key)) {
0324: return v;
0325: }
0326: return null;
0327: }
0328:
0329: @Override
0330: public int size() {
0331: return 1;
0332: }
0333:
0334: @Override
0335: public Set<Map.Entry<K, V>> entrySet() {
0336: return new AbstractSet<Map.Entry<K, V>>() {
0337: @Override
0338: public boolean contains(Object object) {
0339: if (object instanceof Map.Entry) {
0340: Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
0341: return containsKey(entry.getKey())
0342: && containsValue(entry.getValue());
0343: }
0344: return false;
0345: }
0346:
0347: @Override
0348: public int size() {
0349: return 1;
0350: }
0351:
0352: @Override
0353: public Iterator<Map.Entry<K, V>> iterator() {
0354: return new Iterator<Map.Entry<K, V>>() {
0355: boolean hasNext = true;
0356:
0357: public boolean hasNext() {
0358: return hasNext;
0359: }
0360:
0361: public Map.Entry<K, V> next() {
0362: if (hasNext) {
0363: hasNext = false;
0364: return new Map.Entry<K, V>() {
0365: @Override
0366: public boolean equals(Object object) {
0367: return contains(object);
0368: }
0369:
0370: public K getKey() {
0371: return k;
0372: }
0373:
0374: public V getValue() {
0375: return v;
0376: }
0377:
0378: @Override
0379: public int hashCode() {
0380: return (k == null ? 0 : k
0381: .hashCode())
0382: ^ (v == null ? 0 : v
0383: .hashCode());
0384: }
0385:
0386: public V setValue(V value) {
0387: throw new UnsupportedOperationException();
0388: }
0389: };
0390: }
0391: throw new NoSuchElementException();
0392: }
0393:
0394: public void remove() {
0395: throw new UnsupportedOperationException();
0396: }
0397: };
0398: }
0399: };
0400: }
0401: }
0402:
0403: static class SynchronizedCollection<E> implements Collection<E>,
0404: Serializable {
0405: private static final long serialVersionUID = 3053995032091335093L;
0406:
0407: final Collection<E> c;
0408:
0409: final Object mutex;
0410:
0411: SynchronizedCollection(Collection<E> collection) {
0412: c = collection;
0413: mutex = this ;
0414: }
0415:
0416: SynchronizedCollection(Collection<E> collection, Object mutex) {
0417: c = collection;
0418: this .mutex = mutex;
0419: }
0420:
0421: public boolean add(E object) {
0422: synchronized (mutex) {
0423: return c.add(object);
0424: }
0425: }
0426:
0427: public boolean addAll(Collection<? extends E> collection) {
0428: synchronized (mutex) {
0429: return c.addAll(collection);
0430: }
0431: }
0432:
0433: public void clear() {
0434: synchronized (mutex) {
0435: c.clear();
0436: }
0437: }
0438:
0439: public boolean contains(Object object) {
0440: synchronized (mutex) {
0441: return c.contains(object);
0442: }
0443: }
0444:
0445: public boolean containsAll(Collection<?> collection) {
0446: synchronized (mutex) {
0447: return c.containsAll(collection);
0448: }
0449: }
0450:
0451: public boolean isEmpty() {
0452: synchronized (mutex) {
0453: return c.isEmpty();
0454: }
0455: }
0456:
0457: public Iterator<E> iterator() {
0458: synchronized (mutex) {
0459: return c.iterator();
0460: }
0461: }
0462:
0463: public boolean remove(Object object) {
0464: synchronized (mutex) {
0465: return c.remove(object);
0466: }
0467: }
0468:
0469: public boolean removeAll(Collection<?> collection) {
0470: synchronized (mutex) {
0471: return c.removeAll(collection);
0472: }
0473: }
0474:
0475: public boolean retainAll(Collection<?> collection) {
0476: synchronized (mutex) {
0477: return c.retainAll(collection);
0478: }
0479: }
0480:
0481: public int size() {
0482: synchronized (mutex) {
0483: return c.size();
0484: }
0485: }
0486:
0487: public java.lang.Object[] toArray() {
0488: synchronized (mutex) {
0489: return c.toArray();
0490: }
0491: }
0492:
0493: @Override
0494: public String toString() {
0495: synchronized (mutex) {
0496: return c.toString();
0497: }
0498: }
0499:
0500: public <T> T[] toArray(T[] array) {
0501: synchronized (mutex) {
0502: return c.toArray(array);
0503: }
0504: }
0505:
0506: private void writeObject(ObjectOutputStream stream)
0507: throws IOException {
0508: synchronized (mutex) {
0509: stream.defaultWriteObject();
0510: }
0511: }
0512: }
0513:
0514: static class SynchronizedRandomAccessList<E> extends
0515: SynchronizedList<E> implements RandomAccess {
0516: private static final long serialVersionUID = 1530674583602358482L;
0517:
0518: SynchronizedRandomAccessList(List<E> l) {
0519: super (l);
0520: }
0521:
0522: SynchronizedRandomAccessList(List<E> l, Object mutex) {
0523: super (l, mutex);
0524: }
0525:
0526: @Override
0527: public List<E> subList(int start, int end) {
0528: synchronized (mutex) {
0529: return new SynchronizedRandomAccessList<E>(list
0530: .subList(start, end), mutex);
0531: }
0532: }
0533:
0534: /**
0535: * Replaces this SynchronizedRandomAccessList with a SynchronizedList so
0536: * that JREs before 1.4 can deserialize this object without any
0537: * problems. This is necessary since RandomAccess API was introduced
0538: * only in 1.4.
0539: * <p>
0540: *
0541: * @return SynchronizedList
0542: *
0543: * @see SynchronizedList#readResolve()
0544: */
0545: private Object writeReplace() {
0546: return new SynchronizedList<E>(list);
0547: }
0548: }
0549:
0550: static class SynchronizedList<E> extends SynchronizedCollection<E>
0551: implements List<E> {
0552: private static final long serialVersionUID = -7754090372962971524L;
0553:
0554: final List<E> list;
0555:
0556: SynchronizedList(List<E> l) {
0557: super (l);
0558: list = l;
0559: }
0560:
0561: SynchronizedList(List<E> l, Object mutex) {
0562: super (l, mutex);
0563: list = l;
0564: }
0565:
0566: public void add(int location, E object) {
0567: synchronized (mutex) {
0568: list.add(location, object);
0569: }
0570: }
0571:
0572: public boolean addAll(int location,
0573: Collection<? extends E> collection) {
0574: synchronized (mutex) {
0575: return list.addAll(location, collection);
0576: }
0577: }
0578:
0579: @Override
0580: public boolean equals(Object object) {
0581: synchronized (mutex) {
0582: return list.equals(object);
0583: }
0584: }
0585:
0586: public E get(int location) {
0587: synchronized (mutex) {
0588: return list.get(location);
0589: }
0590: }
0591:
0592: @Override
0593: public int hashCode() {
0594: synchronized (mutex) {
0595: return list.hashCode();
0596: }
0597: }
0598:
0599: public int indexOf(Object object) {
0600: final int size;
0601: final Object[] array;
0602: synchronized (mutex) {
0603: size = list.size();
0604: array = new Object[size];
0605: list.toArray(array);
0606: }
0607: if (null != object)
0608: for (int i = 0; i < size; i++) {
0609: if (object.equals(array[i])) {
0610: return i;
0611: }
0612: }
0613: else {
0614: for (int i = 0; i < size; i++) {
0615: if (null == array[i]) {
0616: return i;
0617: }
0618: }
0619: }
0620: return -1;
0621: }
0622:
0623: public int lastIndexOf(Object object) {
0624: final int size;
0625: final Object[] array;
0626: synchronized (mutex) {
0627: size = list.size();
0628: array = new Object[size];
0629: list.toArray(array);
0630: }
0631: if (null != object)
0632: for (int i = size - 1; i >= 0; i--) {
0633: if (object.equals(array[i])) {
0634: return i;
0635: }
0636: }
0637: else {
0638: for (int i = size - 1; i >= 0; i--) {
0639: if (null == array[i]) {
0640: return i;
0641: }
0642: }
0643: }
0644: return -1;
0645: }
0646:
0647: public ListIterator<E> listIterator() {
0648: synchronized (mutex) {
0649: return list.listIterator();
0650: }
0651: }
0652:
0653: public ListIterator<E> listIterator(int location) {
0654: synchronized (mutex) {
0655: return list.listIterator(location);
0656: }
0657: }
0658:
0659: public E remove(int location) {
0660: synchronized (mutex) {
0661: return list.remove(location);
0662: }
0663: }
0664:
0665: public E set(int location, E object) {
0666: synchronized (mutex) {
0667: return list.set(location, object);
0668: }
0669: }
0670:
0671: public List<E> subList(int start, int end) {
0672: synchronized (mutex) {
0673: return new SynchronizedList<E>(
0674: list.subList(start, end), mutex);
0675: }
0676: }
0677:
0678: private void writeObject(ObjectOutputStream stream)
0679: throws IOException {
0680: synchronized (mutex) {
0681: stream.defaultWriteObject();
0682: }
0683: }
0684:
0685: /**
0686: * Resolves SynchronizedList instances to SynchronizedRandomAccessList
0687: * instances if the underlying list is a Random Access list.
0688: * <p>
0689: * This is necessary since SynchronizedRandomAccessList instances are
0690: * replaced with SynchronizedList instances during serialization for
0691: * compliance with JREs before 1.4.
0692: * <p>
0693: *
0694: * @return a SynchronizedList instance if the underlying list implements
0695: * RandomAccess interface, or this same object if not.
0696: *
0697: * @see SynchronizedRandomAccessList#writeReplace()
0698: */
0699: private Object readResolve() {
0700: if (list instanceof RandomAccess) {
0701: return new SynchronizedRandomAccessList<E>(list, mutex);
0702: }
0703: return this ;
0704: }
0705: }
0706:
0707: static class SynchronizedMap<K, V> implements Map<K, V>,
0708: Serializable {
0709: private static final long serialVersionUID = 1978198479659022715L;
0710:
0711: private final Map<K, V> m;
0712:
0713: final Object mutex;
0714:
0715: SynchronizedMap(Map<K, V> map) {
0716: m = map;
0717: mutex = this ;
0718: }
0719:
0720: SynchronizedMap(Map<K, V> map, Object mutex) {
0721: m = map;
0722: this .mutex = mutex;
0723: }
0724:
0725: public void clear() {
0726: synchronized (mutex) {
0727: m.clear();
0728: }
0729: }
0730:
0731: public boolean containsKey(Object key) {
0732: synchronized (mutex) {
0733: return m.containsKey(key);
0734: }
0735: }
0736:
0737: public boolean containsValue(Object value) {
0738: synchronized (mutex) {
0739: return m.containsValue(value);
0740: }
0741: }
0742:
0743: public Set<Map.Entry<K, V>> entrySet() {
0744: synchronized (mutex) {
0745: return new SynchronizedSet<Map.Entry<K, V>>(m
0746: .entrySet(), mutex);
0747: }
0748: }
0749:
0750: @Override
0751: public boolean equals(Object object) {
0752: synchronized (mutex) {
0753: return m.equals(object);
0754: }
0755: }
0756:
0757: public V get(Object key) {
0758: synchronized (mutex) {
0759: return m.get(key);
0760: }
0761: }
0762:
0763: @Override
0764: public int hashCode() {
0765: synchronized (mutex) {
0766: return m.hashCode();
0767: }
0768: }
0769:
0770: public boolean isEmpty() {
0771: synchronized (mutex) {
0772: return m.isEmpty();
0773: }
0774: }
0775:
0776: public Set<K> keySet() {
0777: synchronized (mutex) {
0778: return new SynchronizedSet<K>(m.keySet(), mutex);
0779: }
0780: }
0781:
0782: public V put(K key, V value) {
0783: synchronized (mutex) {
0784: return m.put(key, value);
0785: }
0786: }
0787:
0788: public void putAll(Map<? extends K, ? extends V> map) {
0789: synchronized (mutex) {
0790: m.putAll(map);
0791: }
0792: }
0793:
0794: public V remove(Object key) {
0795: synchronized (mutex) {
0796: return m.remove(key);
0797: }
0798: }
0799:
0800: public int size() {
0801: synchronized (mutex) {
0802: return m.size();
0803: }
0804: }
0805:
0806: public Collection<V> values() {
0807: synchronized (mutex) {
0808: return new SynchronizedCollection<V>(m.values(), mutex);
0809: }
0810: }
0811:
0812: @Override
0813: public String toString() {
0814: synchronized (mutex) {
0815: return m.toString();
0816: }
0817: }
0818:
0819: private void writeObject(ObjectOutputStream stream)
0820: throws IOException {
0821: synchronized (mutex) {
0822: stream.defaultWriteObject();
0823: }
0824: }
0825: }
0826:
0827: static class SynchronizedSet<E> extends SynchronizedCollection<E>
0828: implements Set<E> {
0829: private static final long serialVersionUID = 487447009682186044L;
0830:
0831: SynchronizedSet(Set<E> set) {
0832: super (set);
0833: }
0834:
0835: SynchronizedSet(Set<E> set, Object mutex) {
0836: super (set, mutex);
0837: }
0838:
0839: @Override
0840: public boolean equals(Object object) {
0841: synchronized (mutex) {
0842: return c.equals(object);
0843: }
0844: }
0845:
0846: @Override
0847: public int hashCode() {
0848: synchronized (mutex) {
0849: return c.hashCode();
0850: }
0851: }
0852:
0853: private void writeObject(ObjectOutputStream stream)
0854: throws IOException {
0855: synchronized (mutex) {
0856: stream.defaultWriteObject();
0857: }
0858: }
0859: }
0860:
0861: static class SynchronizedSortedMap<K, V> extends
0862: SynchronizedMap<K, V> implements SortedMap<K, V> {
0863: private static final long serialVersionUID = -8798146769416483793L;
0864:
0865: private final SortedMap<K, V> sm;
0866:
0867: SynchronizedSortedMap(SortedMap<K, V> map) {
0868: super (map);
0869: sm = map;
0870: }
0871:
0872: SynchronizedSortedMap(SortedMap<K, V> map, Object mutex) {
0873: super (map, mutex);
0874: sm = map;
0875: }
0876:
0877: public Comparator<? super K> comparator() {
0878: synchronized (mutex) {
0879: return sm.comparator();
0880: }
0881: }
0882:
0883: public K firstKey() {
0884: synchronized (mutex) {
0885: return sm.firstKey();
0886: }
0887: }
0888:
0889: public SortedMap<K, V> headMap(K endKey) {
0890: synchronized (mutex) {
0891: return new SynchronizedSortedMap<K, V>(sm
0892: .headMap(endKey), mutex);
0893: }
0894: }
0895:
0896: public K lastKey() {
0897: synchronized (mutex) {
0898: return sm.lastKey();
0899: }
0900: }
0901:
0902: public SortedMap<K, V> subMap(K startKey, K endKey) {
0903: synchronized (mutex) {
0904: return new SynchronizedSortedMap<K, V>(sm.subMap(
0905: startKey, endKey), mutex);
0906: }
0907: }
0908:
0909: public SortedMap<K, V> tailMap(K startKey) {
0910: synchronized (mutex) {
0911: return new SynchronizedSortedMap<K, V>(sm
0912: .tailMap(startKey), mutex);
0913: }
0914: }
0915:
0916: private void writeObject(ObjectOutputStream stream)
0917: throws IOException {
0918: synchronized (mutex) {
0919: stream.defaultWriteObject();
0920: }
0921: }
0922: }
0923:
0924: static class SynchronizedSortedSet<E> extends SynchronizedSet<E>
0925: implements SortedSet<E> {
0926: private static final long serialVersionUID = 8695801310862127406L;
0927:
0928: private final SortedSet<E> ss;
0929:
0930: SynchronizedSortedSet(SortedSet<E> set) {
0931: super (set);
0932: ss = set;
0933: }
0934:
0935: SynchronizedSortedSet(SortedSet<E> set, Object mutex) {
0936: super (set, mutex);
0937: ss = set;
0938: }
0939:
0940: public Comparator<? super E> comparator() {
0941: synchronized (mutex) {
0942: return ss.comparator();
0943: }
0944: }
0945:
0946: public E first() {
0947: synchronized (mutex) {
0948: return ss.first();
0949: }
0950: }
0951:
0952: public SortedSet<E> headSet(E end) {
0953: synchronized (mutex) {
0954: return new SynchronizedSortedSet<E>(ss.headSet(end),
0955: mutex);
0956: }
0957: }
0958:
0959: public E last() {
0960: synchronized (mutex) {
0961: return ss.last();
0962: }
0963: }
0964:
0965: public SortedSet<E> subSet(E start, E end) {
0966: synchronized (mutex) {
0967: return new SynchronizedSortedSet<E>(ss.subSet(start,
0968: end), mutex);
0969: }
0970: }
0971:
0972: public SortedSet<E> tailSet(E start) {
0973: synchronized (mutex) {
0974: return new SynchronizedSortedSet<E>(ss.tailSet(start),
0975: mutex);
0976: }
0977: }
0978:
0979: private void writeObject(ObjectOutputStream stream)
0980: throws IOException {
0981: synchronized (mutex) {
0982: stream.defaultWriteObject();
0983: }
0984: }
0985: }
0986:
0987: private static class UnmodifiableCollection<E> implements
0988: Collection<E>, Serializable {
0989: private static final long serialVersionUID = 1820017752578914078L;
0990:
0991: final Collection<E> c;
0992:
0993: UnmodifiableCollection(Collection<E> collection) {
0994: c = collection;
0995: }
0996:
0997: public boolean add(E object) {
0998: throw new UnsupportedOperationException();
0999: }
1000:
1001: public boolean addAll(Collection<? extends E> collection) {
1002: throw new UnsupportedOperationException();
1003: }
1004:
1005: public void clear() {
1006: throw new UnsupportedOperationException();
1007: }
1008:
1009: public boolean contains(Object object) {
1010: return c.contains(object);
1011: }
1012:
1013: public boolean containsAll(Collection<?> collection) {
1014: return c.containsAll(collection);
1015: }
1016:
1017: public boolean isEmpty() {
1018: return c.isEmpty();
1019: }
1020:
1021: public Iterator<E> iterator() {
1022: return new Iterator<E>() {
1023: Iterator<E> iterator = c.iterator();
1024:
1025: public boolean hasNext() {
1026: return iterator.hasNext();
1027: }
1028:
1029: public E next() {
1030: return iterator.next();
1031: }
1032:
1033: public void remove() {
1034: throw new UnsupportedOperationException();
1035: }
1036: };
1037: }
1038:
1039: public boolean remove(Object object) {
1040: throw new UnsupportedOperationException();
1041: }
1042:
1043: public boolean removeAll(Collection<?> collection) {
1044: throw new UnsupportedOperationException();
1045: }
1046:
1047: public boolean retainAll(Collection<?> collection) {
1048: throw new UnsupportedOperationException();
1049: }
1050:
1051: public int size() {
1052: return c.size();
1053: }
1054:
1055: public Object[] toArray() {
1056: return c.toArray();
1057: }
1058:
1059: public <T> T[] toArray(T[] array) {
1060: return c.toArray(array);
1061: }
1062:
1063: @Override
1064: public String toString() {
1065: return c.toString();
1066: }
1067: }
1068:
1069: private static class UnmodifiableRandomAccessList<E> extends
1070: UnmodifiableList<E> implements RandomAccess {
1071: private static final long serialVersionUID = -2542308836966382001L;
1072:
1073: UnmodifiableRandomAccessList(List<E> l) {
1074: super (l);
1075: }
1076:
1077: @Override
1078: public List<E> subList(int start, int end) {
1079: return new UnmodifiableRandomAccessList<E>(list.subList(
1080: start, end));
1081: }
1082:
1083: /**
1084: * Replaces this UnmodifiableRandomAccessList with an UnmodifiableList
1085: * so that JREs before 1.4 can deserialize this object without any
1086: * problems. This is necessary since RandomAccess API was introduced
1087: * only in 1.4.
1088: * <p>
1089: *
1090: * @return UnmodifiableList
1091: *
1092: * @see UnmodifiableList#readResolve()
1093: */
1094: private Object writeReplace() {
1095: return new UnmodifiableList<E>(list);
1096: }
1097: }
1098:
1099: private static class UnmodifiableList<E> extends
1100: UnmodifiableCollection<E> implements List<E> {
1101: private static final long serialVersionUID = -283967356065247728L;
1102:
1103: final List<E> list;
1104:
1105: UnmodifiableList(List<E> l) {
1106: super (l);
1107: list = l;
1108: }
1109:
1110: public void add(int location, E object) {
1111: throw new UnsupportedOperationException();
1112: }
1113:
1114: public boolean addAll(int location,
1115: Collection<? extends E> collection) {
1116: throw new UnsupportedOperationException();
1117: }
1118:
1119: @Override
1120: public boolean equals(Object object) {
1121: return list.equals(object);
1122: }
1123:
1124: public E get(int location) {
1125: return list.get(location);
1126: }
1127:
1128: @Override
1129: public int hashCode() {
1130: return list.hashCode();
1131: }
1132:
1133: public int indexOf(Object object) {
1134: return list.indexOf(object);
1135: }
1136:
1137: public int lastIndexOf(Object object) {
1138: return list.lastIndexOf(object);
1139: }
1140:
1141: public ListIterator<E> listIterator() {
1142: return listIterator(0);
1143: }
1144:
1145: public ListIterator<E> listIterator(final int location) {
1146: return new ListIterator<E>() {
1147: ListIterator<E> iterator = list.listIterator(location);
1148:
1149: public void add(E object) {
1150: throw new UnsupportedOperationException();
1151: }
1152:
1153: public boolean hasNext() {
1154: return iterator.hasNext();
1155: }
1156:
1157: public boolean hasPrevious() {
1158: return iterator.hasPrevious();
1159: }
1160:
1161: public E next() {
1162: return iterator.next();
1163: }
1164:
1165: public int nextIndex() {
1166: return iterator.nextIndex();
1167: }
1168:
1169: public E previous() {
1170: return iterator.previous();
1171: }
1172:
1173: public int previousIndex() {
1174: return iterator.previousIndex();
1175: }
1176:
1177: public void remove() {
1178: throw new UnsupportedOperationException();
1179: }
1180:
1181: public void set(E object) {
1182: throw new UnsupportedOperationException();
1183: }
1184: };
1185: }
1186:
1187: public E remove(int location) {
1188: throw new UnsupportedOperationException();
1189: }
1190:
1191: public E set(int location, E object) {
1192: throw new UnsupportedOperationException();
1193: }
1194:
1195: public List<E> subList(int start, int end) {
1196: return new UnmodifiableList<E>(list.subList(start, end));
1197: }
1198:
1199: /**
1200: * Resolves UnmodifiableList instances to UnmodifiableRandomAccessList
1201: * instances if the underlying list is a Random Access list.
1202: * <p>
1203: * This is necessary since UnmodifiableRandomAccessList instances are
1204: * replaced with UnmodifiableList instances during serialization for
1205: * compliance with JREs before 1.4.
1206: * <p>
1207: *
1208: * @return an UnmodifiableList instance if the underlying list
1209: * implements RandomAccess interface, or this same object if
1210: * not.
1211: *
1212: * @see UnmodifiableRandomAccessList#writeReplace()
1213: */
1214: private Object readResolve() {
1215: if (list instanceof RandomAccess) {
1216: return new UnmodifiableRandomAccessList<E>(list);
1217: }
1218: return this ;
1219: }
1220: }
1221:
1222: private static class UnmodifiableMap<K, V> implements Map<K, V>,
1223: Serializable {
1224: private static final long serialVersionUID = -1034234728574286014L;
1225:
1226: private final Map<K, V> m;
1227:
1228: private static class UnmodifiableEntrySet<K, V> extends
1229: UnmodifiableSet<Map.Entry<K, V>> {
1230: private static final long serialVersionUID = 7854390611657943733L;
1231:
1232: private static class UnmodifiableMapEntry<K, V> implements
1233: Map.Entry<K, V> {
1234: Map.Entry<K, V> mapEntry;
1235:
1236: UnmodifiableMapEntry(Map.Entry<K, V> entry) {
1237: mapEntry = entry;
1238: }
1239:
1240: @Override
1241: public boolean equals(Object object) {
1242: return mapEntry.equals(object);
1243: }
1244:
1245: public K getKey() {
1246: return mapEntry.getKey();
1247: }
1248:
1249: public V getValue() {
1250: return mapEntry.getValue();
1251: }
1252:
1253: @Override
1254: public int hashCode() {
1255: return mapEntry.hashCode();
1256: }
1257:
1258: public V setValue(V object) {
1259: throw new UnsupportedOperationException();
1260: }
1261:
1262: @Override
1263: public String toString() {
1264: return mapEntry.toString();
1265: }
1266: }
1267:
1268: UnmodifiableEntrySet(Set<Map.Entry<K, V>> set) {
1269: super (set);
1270: }
1271:
1272: @Override
1273: public Iterator<Map.Entry<K, V>> iterator() {
1274: return new Iterator<Map.Entry<K, V>>() {
1275: Iterator<Map.Entry<K, V>> iterator = c.iterator();
1276:
1277: public boolean hasNext() {
1278: return iterator.hasNext();
1279: }
1280:
1281: public Map.Entry<K, V> next() {
1282: return new UnmodifiableMapEntry<K, V>(iterator
1283: .next());
1284: }
1285:
1286: public void remove() {
1287: throw new UnsupportedOperationException();
1288: }
1289: };
1290: }
1291:
1292: @Override
1293: public Object[] toArray() {
1294: int length = c.size();
1295: Object[] result = new Object[length];
1296: Iterator<?> it = iterator();
1297: for (int i = length; --i >= 0;) {
1298: result[i] = it.next();
1299: }
1300: return result;
1301: }
1302:
1303: @Override
1304: @SuppressWarnings("unchecked")
1305: public <T> T[] toArray(T[] contents) {
1306: int size = c.size(), index = 0;
1307: Iterator<Map.Entry<K, V>> it = iterator();
1308: if (size > contents.length) {
1309: Class<?> ct = contents.getClass()
1310: .getComponentType();
1311: contents = (T[]) Array.newInstance(ct, size);
1312: }
1313: while (index < size) {
1314: contents[index++] = (T) it.next();
1315: }
1316: if (index < contents.length) {
1317: contents[index] = null;
1318: }
1319: return contents;
1320: }
1321: }
1322:
1323: UnmodifiableMap(Map<K, V> map) {
1324: m = map;
1325: }
1326:
1327: public void clear() {
1328: throw new UnsupportedOperationException();
1329: }
1330:
1331: public boolean containsKey(Object key) {
1332: return m.containsKey(key);
1333: }
1334:
1335: public boolean containsValue(Object value) {
1336: return m.containsValue(value);
1337: }
1338:
1339: public Set<Map.Entry<K, V>> entrySet() {
1340: return new UnmodifiableEntrySet<K, V>(m.entrySet());
1341: }
1342:
1343: @Override
1344: public boolean equals(Object object) {
1345: return m.equals(object);
1346: }
1347:
1348: public V get(Object key) {
1349: return m.get(key);
1350: }
1351:
1352: @Override
1353: public int hashCode() {
1354: return m.hashCode();
1355: }
1356:
1357: public boolean isEmpty() {
1358: return m.isEmpty();
1359: }
1360:
1361: public Set<K> keySet() {
1362: return new UnmodifiableSet<K>(m.keySet());
1363: }
1364:
1365: public V put(K key, V value) {
1366: throw new UnsupportedOperationException();
1367: }
1368:
1369: public void putAll(Map<? extends K, ? extends V> map) {
1370: throw new UnsupportedOperationException();
1371: }
1372:
1373: public V remove(Object key) {
1374: throw new UnsupportedOperationException();
1375: }
1376:
1377: public int size() {
1378: return m.size();
1379: }
1380:
1381: public Collection<V> values() {
1382: return new UnmodifiableCollection<V>(m.values());
1383: }
1384:
1385: @Override
1386: public String toString() {
1387: return m.toString();
1388: }
1389: }
1390:
1391: private static class UnmodifiableSet<E> extends
1392: UnmodifiableCollection<E> implements Set<E> {
1393: private static final long serialVersionUID = -9215047833775013803L;
1394:
1395: UnmodifiableSet(Set<E> set) {
1396: super (set);
1397: }
1398:
1399: @Override
1400: public boolean equals(Object object) {
1401: return c.equals(object);
1402: }
1403:
1404: @Override
1405: public int hashCode() {
1406: return c.hashCode();
1407: }
1408: }
1409:
1410: private static class UnmodifiableSortedMap<K, V> extends
1411: UnmodifiableMap<K, V> implements SortedMap<K, V> {
1412: private static final long serialVersionUID = -8806743815996713206L;
1413:
1414: private final SortedMap<K, V> sm;
1415:
1416: UnmodifiableSortedMap(SortedMap<K, V> map) {
1417: super (map);
1418: sm = map;
1419: }
1420:
1421: public Comparator<? super K> comparator() {
1422: return sm.comparator();
1423: }
1424:
1425: public K firstKey() {
1426: return sm.firstKey();
1427: }
1428:
1429: public SortedMap<K, V> headMap(K before) {
1430: return new UnmodifiableSortedMap<K, V>(sm.headMap(before));
1431: }
1432:
1433: public K lastKey() {
1434: return sm.lastKey();
1435: }
1436:
1437: public SortedMap<K, V> subMap(K start, K end) {
1438: return new UnmodifiableSortedMap<K, V>(sm
1439: .subMap(start, end));
1440: }
1441:
1442: public SortedMap<K, V> tailMap(K after) {
1443: return new UnmodifiableSortedMap<K, V>(sm.tailMap(after));
1444: }
1445: }
1446:
1447: private static class UnmodifiableSortedSet<E> extends
1448: UnmodifiableSet<E> implements SortedSet<E> {
1449: private static final long serialVersionUID = -4929149591599911165L;
1450:
1451: private final SortedSet<E> ss;
1452:
1453: UnmodifiableSortedSet(SortedSet<E> set) {
1454: super (set);
1455: ss = set;
1456: }
1457:
1458: public Comparator<? super E> comparator() {
1459: return ss.comparator();
1460: }
1461:
1462: public E first() {
1463: return ss.first();
1464: }
1465:
1466: public SortedSet<E> headSet(E before) {
1467: return new UnmodifiableSortedSet<E>(ss.headSet(before));
1468: }
1469:
1470: public E last() {
1471: return ss.last();
1472: }
1473:
1474: public SortedSet<E> subSet(E start, E end) {
1475: return new UnmodifiableSortedSet<E>(ss.subSet(start, end));
1476: }
1477:
1478: public SortedSet<E> tailSet(E after) {
1479: return new UnmodifiableSortedSet<E>(ss.tailSet(after));
1480: }
1481: }
1482:
1483: private Collections() {
1484: /* empty */
1485: }
1486:
1487: /**
1488: * Performs a binary search for the specified element in the specified
1489: * sorted List.
1490: *
1491: * @param list
1492: * the sorted List to search
1493: * @param object
1494: * the element to find
1495: * @return the non-negative index of the element, or a negative index which
1496: * is the -index - 1 where the element would be inserted
1497: *
1498: * @throws ClassCastException
1499: * when an element in the List or the search element does not
1500: * implement Comparable, or cannot be compared to each other
1501: */
1502: @SuppressWarnings("unchecked")
1503: public static <T> int binarySearch(
1504: List<? extends Comparable<? super T>> list, T object) {
1505: if (list == null) {
1506: throw new NullPointerException();
1507: }
1508: if (list.isEmpty()) {
1509: return -1;
1510: }
1511:
1512: if (!(list instanceof RandomAccess)) {
1513: ListIterator<? extends Comparable<? super T>> it = list
1514: .listIterator();
1515: while (it.hasNext()) {
1516: int result;
1517: if ((result = -it.next().compareTo(object)) <= 0) {
1518: if (result == 0) {
1519: return it.previousIndex();
1520: }
1521: return -it.previousIndex() - 1;
1522: }
1523: }
1524: return -list.size() - 1;
1525: }
1526:
1527: int low = 0, mid = list.size(), high = mid - 1, result = -1;
1528: while (low <= high) {
1529: mid = (low + high) >> 1;
1530: if ((result = -list.get(mid).compareTo(object)) > 0) {
1531: low = mid + 1;
1532: } else if (result == 0) {
1533: return mid;
1534: } else {
1535: high = mid - 1;
1536: }
1537: }
1538: return -mid - (result < 0 ? 1 : 2);
1539: }
1540:
1541: /**
1542: * Performs a binary search for the specified element in the specified
1543: * sorted List using the specified Comparator.
1544: *
1545: * @param <T> The element type
1546: *
1547: * @param list
1548: * the sorted List to search
1549: * @param object
1550: * the element to find
1551: * @param comparator
1552: * the Comparator. If the comparator is <code>null</code> then
1553: * the search uses the objects' natural ordering.
1554: * @return the non-negative index of the element, or a negative index which
1555: * is the -index - 1 where the element would be inserted
1556: *
1557: * @throws ClassCastException
1558: * when an element in the list and the searched element cannot
1559: * be compared to each other using the Comparator
1560: */
1561: @SuppressWarnings("unchecked")
1562: public static <T> int binarySearch(List<? extends T> list,
1563: T object, Comparator<? super T> comparator) {
1564: if (comparator == null) {
1565: return Collections.binarySearch(
1566: (List<? extends Comparable<? super T>>) list,
1567: object);
1568: }
1569: if (!(list instanceof RandomAccess)) {
1570: ListIterator<? extends T> it = list.listIterator();
1571: while (it.hasNext()) {
1572: int result;
1573: if ((result = -comparator.compare(it.next(), object)) <= 0) {
1574: if (result == 0) {
1575: return it.previousIndex();
1576: }
1577: return -it.previousIndex() - 1;
1578: }
1579: }
1580: return -list.size() - 1;
1581: }
1582:
1583: int low = 0, mid = list.size(), high = mid - 1, result = -1;
1584: while (low <= high) {
1585: mid = (low + high) >> 1;
1586: if ((result = -comparator.compare(list.get(mid), object)) > 0) {
1587: low = mid + 1;
1588: } else if (result == 0) {
1589: return mid;
1590: } else {
1591: high = mid - 1;
1592: }
1593: }
1594: return -mid - (result < 0 ? 1 : 2);
1595: }
1596:
1597: /**
1598: * Copies the elements from the source list to the destination list.
1599: *
1600: * @param destination
1601: * @param source
1602: *
1603: * @throws IndexOutOfBoundsException
1604: * when the destination List is smaller than the source List
1605: * @throws UnsupportedOperationException
1606: * when replacing an element in the destination list is not
1607: * supported
1608: */
1609: public static <T> void copy(List<? super T> destination,
1610: List<? extends T> source) {
1611: if (destination.size() < source.size()) {
1612: throw new ArrayIndexOutOfBoundsException();
1613: }
1614: Iterator<? extends T> srcIt = source.iterator();
1615: ListIterator<? super T> destIt = destination.listIterator();
1616: while (srcIt.hasNext()) {
1617: try {
1618: destIt.next();
1619: } catch (NoSuchElementException e) {
1620: throw new ArrayIndexOutOfBoundsException();
1621: }
1622: destIt.set(srcIt.next());
1623: }
1624: }
1625:
1626: /**
1627: * Answers an Enumeration on the specified Collection.
1628: *
1629: * @param collection
1630: * the Collection to enumerate
1631: * @return an Enumeration
1632: */
1633: public static <T> Enumeration<T> enumeration(
1634: Collection<T> collection) {
1635: final Collection<T> c = collection;
1636: return new Enumeration<T>() {
1637: Iterator<T> it = c.iterator();
1638:
1639: public boolean hasMoreElements() {
1640: return it.hasNext();
1641: }
1642:
1643: public T nextElement() {
1644: return it.next();
1645: }
1646: };
1647: }
1648:
1649: /**
1650: * Fills the specified List with the specified element.
1651: *
1652: * @param list
1653: * the List to fill
1654: * @param object
1655: * the fill element
1656: *
1657: * @throws UnsupportedOperationException
1658: * when replacing an element in the List is not supported
1659: */
1660: public static <T> void fill(List<? super T> list, T object) {
1661: ListIterator<? super T> it = list.listIterator();
1662: while (it.hasNext()) {
1663: it.next();
1664: it.set(object);
1665: }
1666: }
1667:
1668: /**
1669: * Searches the specified Collection for the maximum element.
1670: *
1671: * @param collection
1672: * the Collection to search
1673: * @return the maximum element in the Collection
1674: *
1675: * @throws ClassCastException
1676: * when an element in the Collection does not implement
1677: * Comparable or elements cannot be compared to each other
1678: */
1679: public static <T extends Object & Comparable<? super T>> T max(
1680: Collection<? extends T> collection) {
1681: Iterator<? extends T> it = collection.iterator();
1682: T max = it.next();
1683: while (it.hasNext()) {
1684: T next = it.next();
1685: if (max.compareTo(next) < 0) {
1686: max = next;
1687: }
1688: }
1689: return max;
1690: }
1691:
1692: /**
1693: * Searches the specified Collection for the maximum element using the
1694: * specified Comparator.
1695: *
1696: * @param collection
1697: * the Collection to search
1698: * @param comparator
1699: * the Comparator
1700: * @return the maximum element in the Collection
1701: *
1702: * @throws ClassCastException
1703: * when elements in the Collection cannot be compared to each
1704: * other using the Comparator
1705: */
1706: public static <T> T max(Collection<? extends T> collection,
1707: Comparator<? super T> comparator) {
1708: Iterator<? extends T> it = collection.iterator();
1709: T max = it.next();
1710: while (it.hasNext()) {
1711: T next = it.next();
1712: if (comparator.compare(max, next) < 0) {
1713: max = next;
1714: }
1715: }
1716: return max;
1717: }
1718:
1719: /**
1720: * Searches the specified Collection for the minimum element.
1721: *
1722: * @param collection
1723: * the Collection to search
1724: * @return the minimum element in the Collection
1725: *
1726: * @throws ClassCastException
1727: * when an element in the Collection does not implement
1728: * Comparable or elements cannot be compared to each other
1729: */
1730: public static <T extends Object & Comparable<? super T>> T min(
1731: Collection<? extends T> collection) {
1732: Iterator<? extends T> it = collection.iterator();
1733: T min = it.next();
1734: while (it.hasNext()) {
1735: T next = it.next();
1736: if (min.compareTo(next) > 0) {
1737: min = next;
1738: }
1739: }
1740: return min;
1741: }
1742:
1743: /**
1744: * Searches the specified Collection for the minimum element using the
1745: * specified Comparator.
1746: *
1747: * @param collection
1748: * the Collection to search
1749: * @param comparator
1750: * the Comparator
1751: * @return the minimum element in the Collection
1752: *
1753: * @throws ClassCastException
1754: * when elements in the Collection cannot be compared to each
1755: * other using the Comparator
1756: */
1757: public static <T> T min(Collection<? extends T> collection,
1758: Comparator<? super T> comparator) {
1759: Iterator<? extends T> it = collection.iterator();
1760: T min = it.next();
1761: while (it.hasNext()) {
1762: T next = it.next();
1763: if (comparator.compare(min, next) > 0) {
1764: min = next;
1765: }
1766: }
1767: return min;
1768: }
1769:
1770: /**
1771: * Answers a List containing the specified number of the specified element.
1772: * The list cannot be modified.
1773: *
1774: * @param length
1775: * the size of the returned List
1776: * @param object
1777: * the element
1778: * @return a List containing <code>length</code> copies of the element
1779: *
1780: * @throws IllegalArgumentException
1781: * when <code>length < 0</code>
1782: */
1783: public static <T> List<T> nCopies(final int length, T object) {
1784: return new CopiesList<T>(length, object);
1785: }
1786:
1787: /**
1788: * Returns the supplied <code>List</code> with the order of its contained
1789: * elements reversed.
1790: *
1791: * @param list
1792: * the List to reverse
1793: *
1794: * @throws UnsupportedOperationException
1795: * when replacing an element in the List is not supported
1796: */
1797: @SuppressWarnings("unchecked")
1798: public static void reverse(List<?> list) {
1799: int size = list.size();
1800: ListIterator<Object> front = (ListIterator<Object>) list
1801: .listIterator();
1802: ListIterator<Object> back = (ListIterator<Object>) list
1803: .listIterator(size);
1804: for (int i = 0; i < size / 2; i++) {
1805: Object frontNext = front.next();
1806: Object backPrev = back.previous();
1807: front.set(backPrev);
1808: back.set(frontNext);
1809: }
1810: }
1811:
1812: /**
1813: * <p>
1814: * A Comparator which reverses the natural order of the elements. The
1815: * <code>Comparator</code> that's returned is {@link Serializable}.
1816: * </p>
1817: *
1818: * @return A <code>Comparator</code> instance.
1819: *
1820: * @see Comparator
1821: * @see Comparable
1822: * @see Serializable
1823: */
1824: public static <T> Comparator<T> reverseOrder() {
1825: return new ReverseComparator<T>();
1826: }
1827:
1828: /**
1829: * <p>
1830: * Returns a {@link Comparator} that reverses the order of the
1831: * <code>Comparator</code> passed. If the <code>Comparator</code> passed
1832: * is <code>null</code>, then this method is equivalent to
1833: * {@link #reverseOrder()}.
1834: * </p>
1835: *
1836: * <p>
1837: * The <code>Comparator</code> that's returned is {@link Serializable} if
1838: * the <code>Comparator</code> passed is serializable or <code>null</code>.
1839: * </p>
1840: *
1841: * @param c
1842: * The <code>Comparator</code> to reverse or <code>null</code>.
1843: * @return A <code>Comparator</code> instance.
1844: * @see Comparator
1845: * @since 1.5
1846: */
1847: public static <T> Comparator<T> reverseOrder(Comparator<T> c) {
1848: if (c == null) {
1849: return reverseOrder();
1850: }
1851: return new ReverseComparatorWithComparator<T>(c);
1852: }
1853:
1854: /**
1855: * Moves every element of the List to a random new position in the list.
1856: *
1857: * @param list
1858: * the List to shuffle
1859: *
1860: * @throws UnsupportedOperationException
1861: * when replacing an element in the List is not supported
1862: */
1863: public static void shuffle(List<?> list) {
1864: shuffle(list, new Random());
1865: }
1866:
1867: /**
1868: * Moves every element of the List to a random new position in the list
1869: * using the specified random number generator.
1870: *
1871: * @param list
1872: * the List to shuffle
1873: * @param random
1874: * the random number generator
1875: *
1876: * @throws UnsupportedOperationException
1877: * when replacing an element in the List is not supported
1878: */
1879: @SuppressWarnings("unchecked")
1880: public static void shuffle(List<?> list, Random random) {
1881: if (!(list instanceof RandomAccess)) {
1882: Object[] array = list.toArray();
1883: for (int i = array.length - 1; i > 0; i--) {
1884: int index = random.nextInt(i + 1);
1885: if (index < 0) {
1886: index = -index;
1887: }
1888: Object temp = array[i];
1889: array[i] = array[index];
1890: array[index] = temp;
1891: }
1892:
1893: int i = 0;
1894: ListIterator<Object> it = (ListIterator<Object>) list
1895: .listIterator();
1896: while (it.hasNext()) {
1897: it.next();
1898: it.set(array[i++]);
1899: }
1900: } else {
1901: List<Object> rawList = (List<Object>) list;
1902: for (int i = rawList.size() - 1; i > 0; i--) {
1903: int index = random.nextInt(i + 1);
1904: if (index < 0) {
1905: index = -index;
1906: }
1907: rawList.set(index, rawList.set(i, rawList.get(index)));
1908: }
1909: }
1910: }
1911:
1912: /**
1913: * Answers a Set containing the specified element. The set cannot be
1914: * modified.
1915: *
1916: * @param object
1917: * the element
1918: * @return a Set containing the element
1919: */
1920: public static <E> Set<E> singleton(E object) {
1921: return new SingletonSet<E>(object);
1922: }
1923:
1924: /**
1925: * Answers a List containing the specified element. The list cannot be
1926: * modified.
1927: *
1928: * @param object
1929: * the element
1930: * @return a List containing the element
1931: */
1932: public static <E> List<E> singletonList(E object) {
1933: return new SingletonList<E>(object);
1934: }
1935:
1936: /**
1937: * Answers a Map containing the specified key and value. The map cannot be
1938: * modified.
1939: *
1940: * @param key
1941: * the key
1942: * @param value
1943: * the value
1944: * @return a Map containing the key and value
1945: */
1946: public static <K, V> Map<K, V> singletonMap(K key, V value) {
1947: return new SingletonMap<K, V>(key, value);
1948: }
1949:
1950: /**
1951: * Sorts the specified List in ascending order.
1952: *
1953: * @param list
1954: * the List to be sorted
1955: *
1956: * @throws ClassCastException
1957: * when an element in the List does not implement Comparable or
1958: * elements cannot be compared to each other
1959: */
1960: @SuppressWarnings("unchecked")
1961: public static <T extends Comparable<? super T>> void sort(
1962: List<T> list) {
1963: Object[] array = list.toArray();
1964: Arrays.sort(array);
1965: int i = 0;
1966: ListIterator<T> it = list.listIterator();
1967: while (it.hasNext()) {
1968: it.next();
1969: it.set((T) array[i++]);
1970: }
1971: }
1972:
1973: /**
1974: * Sorts the specified List using the specified Comparator.
1975: *
1976: * @param list
1977: * the List to be sorted
1978: * @param comparator
1979: * the Comparator
1980: *
1981: * @throws ClassCastException
1982: * when elements in the List cannot be compared to each other
1983: * using the Comparator
1984: */
1985: @SuppressWarnings("unchecked")
1986: public static <T> void sort(List<T> list,
1987: Comparator<? super T> comparator) {
1988: T[] array = list.toArray((T[]) new Object[list.size()]);
1989: Arrays.sort(array, comparator);
1990: int i = 0;
1991: ListIterator<T> it = list.listIterator();
1992: while (it.hasNext()) {
1993: it.next();
1994: it.set(array[i++]);
1995: }
1996: }
1997:
1998: /**
1999: * Swaps the elements of List <code>list</code> at indices
2000: * <code>index1</code> and <code>index2</code>
2001: *
2002: * @param list
2003: * the List to manipulate on
2004: * @param index1
2005: * int position of the first element to swap with the element in
2006: * index2
2007: * @param index2
2008: * int position of the other element
2009: *
2010: * @throws IndexOutOfBoundsException
2011: * if index1 or index2 is out of range of this list
2012: */
2013: @SuppressWarnings("unchecked")
2014: public static void swap(List<?> list, int index1, int index2) {
2015: if (list == null) {
2016: throw new NullPointerException();
2017: }
2018: if (index1 == index2) {
2019: return;
2020: }
2021: List<Object> rawList = (List<Object>) list;
2022: rawList.set(index2, rawList.set(index1, rawList.get(index2)));
2023: }
2024:
2025: /**
2026: * Replaces all occurrences of Object <code>obj</code> in
2027: * <code>list</code> with <code>newObj</code>. If the <code>obj</code>
2028: * is <code>null</code>, then all occurrences of <code>null</code> is
2029: * replaced with <code>newObj</code>.
2030: *
2031: * @param list
2032: * the List to modify
2033: * @param obj
2034: * the Object to find and replace occurrences of.
2035: * @param obj2
2036: * the Object to replace all occurrences of <code>obj</code> in
2037: * <code>list</code>
2038: * @return true, if at least one occurrence of <code>obj</code> has been
2039: * found in <code>list</code>
2040: *
2041: * @throws UnsupportedOperationException
2042: * if the list does not support setting elements
2043: */
2044: public static <T> boolean replaceAll(List<T> list, T obj, T obj2) {
2045: int index;
2046: boolean found = false;
2047:
2048: while ((index = list.indexOf(obj)) > -1) {
2049: found = true;
2050: list.set(index, obj2);
2051: }
2052: return found;
2053: }
2054:
2055: /**
2056: * Rotates the elements in List <code>list</code> by the distance
2057: * <code>dist</code>
2058: * <p>
2059: * e.g. for a given list with elements [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
2060: * calling rotate(list, 3) or rotate(list, -7) would modify the list to look
2061: * like this: [8, 9, 0, 1, 2, 3, 4, 5, 6, 7]
2062: *
2063: * @param lst
2064: * @param dist
2065: * It can be any integer: 0, positive, negative, larger than the
2066: * list size
2067: */
2068: @SuppressWarnings("unchecked")
2069: public static void rotate(List<?> lst, int dist) {
2070: List<Object> list = (List<Object>) lst;
2071: int size = list.size();
2072:
2073: // Can't sensibly rotate an empty collection
2074: if (size == 0) {
2075: return;
2076: }
2077:
2078: // normalize the distance
2079: int normdist;
2080: if (dist > 0) {
2081: normdist = dist % size;
2082: } else {
2083: normdist = size - ((dist % size) * (-1));
2084: }
2085:
2086: if (normdist == 0 || normdist == size) {
2087: return;
2088: }
2089:
2090: if (list instanceof RandomAccess) {
2091: // make sure each element gets juggled
2092: // with the element in the position it is supposed to go to
2093: Object temp = list.get(0);
2094: int index = 0, beginIndex = 0;
2095: for (int i = 0; i < size; i++) {
2096: index = (index + normdist) % size;
2097: temp = list.set(index, temp);
2098: if (index == beginIndex) {
2099: index = ++beginIndex;
2100: temp = list.get(beginIndex);
2101: }
2102: }
2103: } else {
2104: int divideIndex = (size - normdist) % size;
2105: List<Object> sublist1 = list.subList(0, divideIndex);
2106: List<Object> sublist2 = list.subList(divideIndex, size);
2107: reverse(sublist1);
2108: reverse(sublist2);
2109: reverse(list);
2110: }
2111: }
2112:
2113: /**
2114: * Searches the <code>list</code> for <code>sublist</code> and answers
2115: * the beginning index of the first occurrence.
2116: * <p>
2117: * -1 is returned if the <code>sublist</code> does not exist in
2118: * <code>list</code>
2119: *
2120: * @param list
2121: * the List to search <code>sublist</code> in
2122: * @param sublist
2123: * the List to search in <code>list</code>
2124: * @return the beginning index of the first occurrence of
2125: * <code>sublist</code> in <code>list</code>, or -1
2126: */
2127: public static int indexOfSubList(List<?> list, List<?> sublist) {
2128: int size = list.size();
2129: int sublistSize = sublist.size();
2130:
2131: if (sublistSize > size) {
2132: return -1;
2133: }
2134:
2135: if (sublistSize == 0) {
2136: return 0;
2137: }
2138:
2139: // find the first element of sublist in the list to get a head start
2140: Object firstObj = sublist.get(0);
2141: int index = list.indexOf(firstObj);
2142: if (index == -1) {
2143: return -1;
2144: }
2145:
2146: while (index < size && (size - index >= sublistSize)) {
2147: ListIterator<?> listIt = list.listIterator(index);
2148:
2149: if ((firstObj == null) ? listIt.next() == null : firstObj
2150: .equals(listIt.next())) {
2151:
2152: // iterate through the elements in sublist to see
2153: // if they are included in the same order in the list
2154: ListIterator<?> sublistIt = sublist.listIterator(1);
2155: boolean difFound = false;
2156: while (sublistIt.hasNext()) {
2157: Object element = sublistIt.next();
2158: if (!listIt.hasNext()) {
2159: return -1;
2160: }
2161: if ((element == null) ? listIt.next() != null
2162: : !element.equals(listIt.next())) {
2163: difFound = true;
2164: break;
2165: }
2166: }
2167: // All elements of sublist are found in main list
2168: // starting from index.
2169: if (!difFound) {
2170: return index;
2171: }
2172: }
2173: // This was not the sequence we were looking for,
2174: // continue search for the firstObj in main list
2175: // at the position after index.
2176: index++;
2177: }
2178: return -1;
2179: }
2180:
2181: /**
2182: * Searches the <code>list</code> for <code>sublist</code> and answers
2183: * the beginning index of the last occurrence.
2184: * <p>
2185: * -1 is returned if the <code>sublist</code> does not exist in
2186: * <code>list</code>
2187: *
2188: * @param list
2189: * the List to search <code>sublist</code> in
2190: * @param sublist
2191: * the List to search in <code>list</code>
2192: * @return the beginning index of the last occurrence of
2193: * <code>sublist</code> in <code>list</code>, or -1
2194: */
2195: public static int lastIndexOfSubList(List<?> list, List<?> sublist) {
2196: int sublistSize = sublist.size();
2197: int size = list.size();
2198:
2199: if (sublistSize > size) {
2200: return -1;
2201: }
2202:
2203: if (sublistSize == 0) {
2204: return size;
2205: }
2206:
2207: // find the last element of sublist in the list to get a head start
2208: Object lastObj = sublist.get(sublistSize - 1);
2209: int index = list.lastIndexOf(lastObj);
2210:
2211: while ((index > -1) && (index + 1 >= sublistSize)) {
2212: ListIterator<?> listIt = list.listIterator(index + 1);
2213:
2214: if ((lastObj == null) ? listIt.previous() == null : lastObj
2215: .equals(listIt.previous())) {
2216: // iterate through the elements in sublist to see
2217: // if they are included in the same order in the list
2218: ListIterator<?> sublistIt = sublist
2219: .listIterator(sublistSize - 1);
2220: boolean difFound = false;
2221: while (sublistIt.hasPrevious()) {
2222: Object element = sublistIt.previous();
2223: if (!listIt.hasPrevious()) {
2224: return -1;
2225: }
2226: if ((element == null) ? listIt.previous() != null
2227: : !element.equals(listIt.previous())) {
2228: difFound = true;
2229: break;
2230: }
2231: }
2232: // All elements of sublist are found in main list
2233: // starting from listIt.nextIndex().
2234: if (!difFound) {
2235: return listIt.nextIndex();
2236: }
2237: }
2238: // This was not the sequence we were looking for,
2239: // continue search for the lastObj in main list
2240: // at the position before index.
2241: index--;
2242: }
2243: return -1;
2244: }
2245:
2246: /**
2247: * Answers an ArrayList with all the elements in the
2248: * <code>enumeration</code>. The elements in the returned ArrayList are
2249: * in the same order as in the <code>enumeration</code>.
2250: *
2251: * @param enumeration
2252: * Enumeration
2253: * @return and ArrayList
2254: */
2255: public static <T> ArrayList<T> list(Enumeration<T> enumeration) {
2256: ArrayList<T> list = new ArrayList<T>();
2257: while (enumeration.hasMoreElements()) {
2258: list.add(enumeration.nextElement());
2259: }
2260: return list;
2261: }
2262:
2263: /**
2264: * Answers a wrapper on the specified Collection which synchronizes all
2265: * access to the Collection.
2266: *
2267: * @param collection
2268: * the Collection
2269: * @return a synchronized Collection
2270: */
2271: public static <T> Collection<T> synchronizedCollection(
2272: Collection<T> collection) {
2273: if (collection == null) {
2274: throw new NullPointerException();
2275: }
2276: return new SynchronizedCollection<T>(collection);
2277: }
2278:
2279: /**
2280: * Answers a wrapper on the specified List which synchronizes all access to
2281: * the List.
2282: *
2283: * @param list
2284: * the List
2285: * @return a synchronized List
2286: */
2287: public static <T> List<T> synchronizedList(List<T> list) {
2288: if (list == null) {
2289: throw new NullPointerException();
2290: }
2291: if (list instanceof RandomAccess) {
2292: return new SynchronizedRandomAccessList<T>(list);
2293: }
2294: return new SynchronizedList<T>(list);
2295: }
2296:
2297: /**
2298: * Answers a wrapper on the specified Map which synchronizes all access to
2299: * the Map.
2300: *
2301: * @param map
2302: * the Map
2303: * @return a synchronized Map
2304: */
2305: public static <K, V> Map<K, V> synchronizedMap(Map<K, V> map) {
2306: if (map == null) {
2307: throw new NullPointerException();
2308: }
2309: return new SynchronizedMap<K, V>(map);
2310: }
2311:
2312: /**
2313: * Answers a wrapper on the specified Set which synchronizes all access to
2314: * the Set.
2315: *
2316: * @param set
2317: * the Set
2318: * @return a synchronized Set
2319: */
2320: public static <E> Set<E> synchronizedSet(Set<E> set) {
2321: if (set == null) {
2322: throw new NullPointerException();
2323: }
2324: return new SynchronizedSet<E>(set);
2325: }
2326:
2327: /**
2328: * Answers a wrapper on the specified SortedMap which synchronizes all
2329: * access to the SortedMap.
2330: *
2331: * @param map
2332: * the SortedMap
2333: * @return a synchronized SortedMap
2334: */
2335: public static <K, V> SortedMap<K, V> synchronizedSortedMap(
2336: SortedMap<K, V> map) {
2337: if (map == null) {
2338: throw new NullPointerException();
2339: }
2340: return new SynchronizedSortedMap<K, V>(map);
2341: }
2342:
2343: /**
2344: * Answers a wrapper on the specified SortedSet which synchronizes all
2345: * access to the SortedSet.
2346: *
2347: * @param set
2348: * the SortedSet
2349: * @return a synchronized SortedSet
2350: */
2351: public static <E> SortedSet<E> synchronizedSortedSet(
2352: SortedSet<E> set) {
2353: if (set == null) {
2354: throw new NullPointerException();
2355: }
2356: return new SynchronizedSortedSet<E>(set);
2357: }
2358:
2359: /**
2360: * Answers a wrapper on the specified Collection which throws an
2361: * <code>UnsupportedOperationException</code> whenever an attempt is made
2362: * to modify the Collection.
2363: *
2364: * @param collection
2365: * the Collection
2366: * @return an unmodifiable Collection
2367: */
2368: @SuppressWarnings("unchecked")
2369: public static <E> Collection<E> unmodifiableCollection(
2370: Collection<? extends E> collection) {
2371: if (collection == null) {
2372: throw new NullPointerException();
2373: }
2374: return new UnmodifiableCollection<E>((Collection<E>) collection);
2375: }
2376:
2377: /**
2378: * Answers a wrapper on the specified List which throws an
2379: * <code>UnsupportedOperationException</code> whenever an attempt is made
2380: * to modify the List.
2381: *
2382: * @param list
2383: * the List
2384: * @return an unmodifiable List
2385: */
2386: @SuppressWarnings("unchecked")
2387: public static <E> List<E> unmodifiableList(List<? extends E> list) {
2388: if (list == null) {
2389: throw new NullPointerException();
2390: }
2391: if (list instanceof RandomAccess) {
2392: return new UnmodifiableRandomAccessList<E>((List<E>) list);
2393: }
2394: return new UnmodifiableList<E>((List<E>) list);
2395: }
2396:
2397: /**
2398: * Answers a wrapper on the specified Map which throws an
2399: * <code>UnsupportedOperationException</code> whenever an attempt is made
2400: * to modify the Map.
2401: *
2402: * @param map
2403: * the Map
2404: * @return a unmodifiable Map
2405: */
2406: @SuppressWarnings("unchecked")
2407: public static <K, V> Map<K, V> unmodifiableMap(
2408: Map<? extends K, ? extends V> map) {
2409: if (map == null) {
2410: throw new NullPointerException();
2411: }
2412: return new UnmodifiableMap<K, V>((Map<K, V>) map);
2413: }
2414:
2415: /**
2416: * Answers a wrapper on the specified Set which throws an
2417: * <code>UnsupportedOperationException</code> whenever an attempt is made
2418: * to modify the Set.
2419: *
2420: * @param set
2421: * the Set
2422: * @return a unmodifiable Set
2423: */
2424: @SuppressWarnings("unchecked")
2425: public static <E> Set<E> unmodifiableSet(Set<? extends E> set) {
2426: if (set == null) {
2427: throw new NullPointerException();
2428: }
2429: return new UnmodifiableSet<E>((Set<E>) set);
2430: }
2431:
2432: /**
2433: * Answers a wrapper on the specified SortedMap which throws an
2434: * <code>UnsupportedOperationException</code> whenever an attempt is made
2435: * to modify the SortedMap.
2436: *
2437: * @param map
2438: * the SortedMap
2439: * @return a unmodifiable SortedMap
2440: */
2441: @SuppressWarnings("unchecked")
2442: public static <K, V> SortedMap<K, V> unmodifiableSortedMap(
2443: SortedMap<K, ? extends V> map) {
2444: if (map == null) {
2445: throw new NullPointerException();
2446: }
2447: return new UnmodifiableSortedMap<K, V>((SortedMap<K, V>) map);
2448: }
2449:
2450: /**
2451: * Answers a wrapper on the specified SortedSet which throws an
2452: * <code>UnsupportedOperationException</code> whenever an attempt is made
2453: * to modify the SortedSet.
2454: *
2455: * @param set
2456: * the SortedSet
2457: * @return a unmodifiable SortedSet
2458: */
2459: public static <E> SortedSet<E> unmodifiableSortedSet(
2460: SortedSet<E> set) {
2461: if (set == null) {
2462: throw new NullPointerException();
2463: }
2464: return new UnmodifiableSortedSet<E>(set);
2465: }
2466:
2467: /**
2468: * <p>
2469: * Returns the number of elements in the <code>Collection</code> that
2470: * match the <code>Object</code> passed. If the <code>Object</code> is
2471: * <code>null</code>, then the number of <code>null</code> elements is
2472: * returned.
2473: * </p>
2474: *
2475: * @param c
2476: * The <code>Collection</code> to search.
2477: * @param o
2478: * The <code>Object</code> to search for.
2479: * @return The number of matching elements.
2480: * @throws NullPointerException
2481: * if the <code>Collection</code> parameter is
2482: * <code>null</code>.
2483: *
2484: * @since 1.5
2485: */
2486: public static int frequency(Collection<?> c, Object o) {
2487: if (c == null) {
2488: throw new NullPointerException();
2489: }
2490: if (c.isEmpty()) {
2491: return 0;
2492: }
2493: int result = 0;
2494: Iterator<?> itr = c.iterator();
2495: while (itr.hasNext()) {
2496: Object e = itr.next();
2497: if (o == null ? e == null : o.equals(e)) {
2498: result++;
2499: }
2500: }
2501: return result;
2502: }
2503:
2504: /**
2505: * Returns a type-safe empty, immutable {@link List}.
2506: *
2507: * @return An empty {@link List}.
2508: * @since 1.5
2509: * @see #EMPTY_LIST
2510: */
2511: @SuppressWarnings("unchecked")
2512: public static final <T> List<T> emptyList() {
2513: return EMPTY_LIST;
2514: }
2515:
2516: /**
2517: * Returns a type-safe empty, immutable {@link Set}.
2518: *
2519: * @return An empty {@link Set}.
2520: * @since 1.5
2521: * @see #EMPTY_SET
2522: */
2523: @SuppressWarnings("unchecked")
2524: public static final <T> Set<T> emptySet() {
2525: return EMPTY_SET;
2526: }
2527:
2528: /**
2529: * Returns a type-safe empty, immutable {@link Map}.
2530: *
2531: * @return An empty {@link Map}.
2532: * @since 1.5
2533: * @see #EMPTY_MAP
2534: */
2535: @SuppressWarnings("unchecked")
2536: public static final <K, V> Map<K, V> emptyMap() {
2537: return EMPTY_MAP;
2538: }
2539:
2540: /**
2541: * Returns a dynamically typesafe view of the specified collection.
2542: *
2543: * @param c
2544: * the collection
2545: * @param type
2546: * the type of the elements is permitted to insert
2547: *
2548: * @return a typesafe collection
2549: */
2550: public static <E> Collection<E> checkedCollection(Collection<E> c,
2551: Class<E> type) {
2552: return new CheckedCollection<E>(c, type);
2553: }
2554:
2555: /**
2556: * Returns a dynamically typesafe view of the specified map.
2557: *
2558: * @param m
2559: * the map
2560: * @param keyType
2561: * the type of keys permitted to be inserted
2562: * @param valueType
2563: * the type of values permitted to be inserted
2564: *
2565: * @return a typesafe map
2566: */
2567: public static <K, V> Map<K, V> checkedMap(Map<K, V> m,
2568: Class<K> keyType, Class<V> valueType) {
2569: return new CheckedMap<K, V>(m, keyType, valueType);
2570: }
2571:
2572: /**
2573: * Returns a dynamically typesafe view of the specified list.
2574: *
2575: * @param list
2576: * the list
2577: * @param type
2578: * the type of the elements is permitted to insert
2579: *
2580: * @return a typesafe list
2581: */
2582: public static <E> List<E> checkedList(List<E> list, Class<E> type) {
2583: if (list instanceof RandomAccess) {
2584: return new CheckedRandomAccessList<E>(list, type);
2585: }
2586: return new CheckedList<E>(list, type);
2587: }
2588:
2589: /**
2590: * Returns a dynamically typesafe view of the specified set.
2591: *
2592: * @param s
2593: * the set
2594: * @param type
2595: * the type of the elements is permitted to insert
2596: *
2597: * @return a typesafe set
2598: */
2599: public static <E> Set<E> checkedSet(Set<E> s, Class<E> type) {
2600: return new CheckedSet<E>(s, type);
2601: }
2602:
2603: /**
2604: * Returns a dynamically typesafe view of the specified sorted map.
2605: *
2606: * @param m
2607: * the sorted map
2608: * @param keyType
2609: * the type of keys permitted to be inserted
2610: * @param valueType
2611: * the type of values permitted to be inserted
2612: *
2613: * @return a typesafe sorted map
2614: */
2615: public static <K, V> SortedMap<K, V> checkedSortedMap(
2616: SortedMap<K, V> m, Class<K> keyType, Class<V> valueType) {
2617: return new CheckedSortedMap<K, V>(m, keyType, valueType);
2618: }
2619:
2620: /**
2621: * Returns a dynamically typesafe view of the specified sorted set.
2622: *
2623: * @param s
2624: * the sorted set
2625: * @param type
2626: * the type of the elements is permitted to insert
2627: *
2628: * @return a typesafe sorted set
2629: */
2630: public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s,
2631: Class<E> type) {
2632: return new CheckedSortedSet<E>(s, type);
2633: }
2634:
2635: /**
2636: * Adds all the specified elements to the specified collection
2637: *
2638: * @param c
2639: * the collection the elements are to be inserted into
2640: * @param a
2641: * the elements to insert
2642: *
2643: * @return true if the collection changed during insertion
2644: *
2645: * @throws UnsupportedOperationException
2646: * when the method is not supported
2647: * @throws NullPointerException
2648: * when c or elements is null, or elements contains one or more
2649: * null elements and c doesn't support null elements
2650: */
2651: public static <T> boolean addAll(Collection<? super T> c, T... a) {
2652: boolean modified = false;
2653: for (int i = 0; i < a.length; i++) {
2654: modified |= c.add(a[i]);
2655: }
2656: return modified;
2657: }
2658:
2659: /**
2660: * Returns true if the collections have no elements in common
2661: *
2662: * @param c1
2663: * the first collection
2664: * @param c2
2665: * the second collection
2666: *
2667: * @return true if the collections have no elements in common
2668: *
2669: * @throws NullPointerException
2670: * if one of the collections is null
2671: */
2672: public static boolean disjoint(Collection<?> c1, Collection<?> c2) {
2673: if ((c1 instanceof Set) && !(c2 instanceof Set)
2674: || (c2.size()) > c1.size()) {
2675: Collection<?> tmp = c1;
2676: c1 = c2;
2677: c2 = tmp;
2678: }
2679: Iterator<?> it = c1.iterator();
2680: while (it.hasNext()) {
2681: if (c2.contains(it.next())) {
2682: return false;
2683: }
2684: }
2685: return true;
2686: }
2687:
2688: /**
2689: * Checks if specified object is instance of specified class. Used for a
2690: * dynamically typesafe view of the collections.
2691: *
2692: * @param obj -
2693: * object is to be checked
2694: * @param type -
2695: * class of object that should be
2696: * @return specified object
2697: */
2698: static <E> E checkType(E obj, Class<E> type) {
2699: if (!type.isInstance(obj)) {
2700: // luni.05=Attempt to insert {0} element into collection with
2701: // element type {1}
2702: throw new ClassCastException(Messages.getString(
2703: "luni.05", obj.getClass(), type)); //$NON-NLS-1$
2704: }
2705: return obj;
2706: }
2707:
2708: /**
2709: * Class represents a dynamically typesafe view of the specified collection.
2710: */
2711: private static class CheckedCollection<E> implements Collection<E>,
2712: Serializable {
2713:
2714: private static final long serialVersionUID = 1578914078182001775L;
2715:
2716: Collection<E> c;
2717:
2718: Class<E> type;
2719:
2720: /**
2721: * Constructs a dynamically typesafe view of the specified collection.
2722: *
2723: * @param c -
2724: * the collection for which an unmodifiable view is to be
2725: * constructed.
2726: */
2727: public CheckedCollection(Collection<E> c, Class<E> type) {
2728: if (c == null || type == null) {
2729: throw new NullPointerException();
2730: }
2731: this .c = c;
2732: this .type = type;
2733: }
2734:
2735: /**
2736: * @see java.util.Collection#size()
2737: */
2738: public int size() {
2739: return c.size();
2740: }
2741:
2742: /**
2743: * @see java.util.Collection#isEmpty()
2744: */
2745: public boolean isEmpty() {
2746: return c.isEmpty();
2747: }
2748:
2749: /**
2750: * @see java.util.Collection#contains(Object)
2751: */
2752: public boolean contains(Object obj) {
2753: return c.contains(obj);
2754: }
2755:
2756: /**
2757: * @see java.util.Collection#iterator()
2758: */
2759: public Iterator<E> iterator() {
2760: Iterator<E> i = c.iterator();
2761: if (i instanceof ListIterator) {
2762: i = new CheckedListIterator<E>((ListIterator<E>) i,
2763: type);
2764: }
2765: return i;
2766: }
2767:
2768: /**
2769: * @see java.util.Collection#toArray()
2770: */
2771: public Object[] toArray() {
2772: return c.toArray();
2773: }
2774:
2775: /**
2776: * @see java.util.Collection#toArray(Object[])
2777: */
2778: public <T> T[] toArray(T[] arr) {
2779: return c.toArray(arr);
2780: }
2781:
2782: /**
2783: * @see java.util.Collection#add(Object)
2784: */
2785: public boolean add(E obj) {
2786: return c.add(checkType(obj, type));
2787: }
2788:
2789: /**
2790: * @see java.util.Collection#remove(Object)
2791: */
2792: public boolean remove(Object obj) {
2793: return c.remove(obj);
2794: }
2795:
2796: /**
2797: * @see java.util.Collection#containsAll(Collection)
2798: */
2799: public boolean containsAll(Collection<?> c1) {
2800: return c.containsAll(c1);
2801: }
2802:
2803: /**
2804: * @see java.util.Collection#addAll(Collection)
2805: */
2806: @SuppressWarnings("unchecked")
2807: public boolean addAll(Collection<? extends E> c1) {
2808: int size = c1.size();
2809: if (size == 0) {
2810: return false;
2811: }
2812: E[] arr = (E[]) new Object[size];
2813: Iterator<? extends E> it = c1.iterator();
2814: for (int i = 0; i < size; i++) {
2815: arr[i] = checkType(it.next(), type);
2816: }
2817: boolean added = false;
2818: for (int i = 0; i < size; i++) {
2819: added |= c.add(arr[i]);
2820: }
2821: return added;
2822: }
2823:
2824: /**
2825: * @see java.util.Collection#removeAll(Collection)
2826: */
2827: public boolean removeAll(Collection<?> c1) {
2828: return c.removeAll(c1);
2829: }
2830:
2831: /**
2832: * @see java.util.Collection#retainAll(Collection)
2833: */
2834: public boolean retainAll(Collection<?> c1) {
2835: return c.retainAll(c1);
2836: }
2837:
2838: /**
2839: * @see java.util.Collection#clear()
2840: */
2841: public void clear() {
2842: c.clear();
2843: }
2844:
2845: /**
2846: * @see java.lang.Object#toString()
2847: */
2848: @Override
2849: public String toString() {
2850: return c.toString();
2851: }
2852: }
2853:
2854: /**
2855: * Class represents a dynamically typesafe view of the specified
2856: * ListIterator.
2857: */
2858: private static class CheckedListIterator<E> implements
2859: ListIterator<E> {
2860:
2861: private ListIterator<E> i;
2862:
2863: private Class<E> type;
2864:
2865: /**
2866: * Constructs a dynamically typesafe view of the specified ListIterator.
2867: *
2868: * @param i -
2869: * the listIterator for which a dynamically typesafe view to
2870: * be constructed.
2871: */
2872: public CheckedListIterator(ListIterator<E> i, Class<E> type) {
2873: this .i = i;
2874: this .type = type;
2875: }
2876:
2877: /**
2878: * @see java.util.Iterator#hasNext()
2879: */
2880: public boolean hasNext() {
2881: return i.hasNext();
2882: }
2883:
2884: /**
2885: * @see java.util.Iterator#next()
2886: */
2887: public E next() {
2888: return i.next();
2889: }
2890:
2891: /**
2892: * @see java.util.Iterator#remove()
2893: */
2894: public void remove() {
2895: i.remove();
2896: }
2897:
2898: /**
2899: * @see java.util.ListIterator#hasPrevious()
2900: */
2901: public boolean hasPrevious() {
2902: return i.hasPrevious();
2903: }
2904:
2905: /**
2906: * @see java.util.ListIterator#previous()
2907: */
2908: public E previous() {
2909: return i.previous();
2910: }
2911:
2912: /**
2913: * @see java.util.ListIterator#nextIndex()
2914: */
2915: public int nextIndex() {
2916: return i.nextIndex();
2917: }
2918:
2919: /**
2920: * @see java.util.ListIterator#previousIndex()
2921: */
2922: public int previousIndex() {
2923: return i.previousIndex();
2924: }
2925:
2926: /**
2927: * @see java.util.ListIterator#set(Object)
2928: */
2929: public void set(E obj) {
2930: i.set(checkType(obj, type));
2931: }
2932:
2933: /**
2934: * @see java.util.ListIterator#add(Object)
2935: */
2936: public void add(E obj) {
2937: i.add(checkType(obj, type));
2938: }
2939: }
2940:
2941: /**
2942: * Class represents a dynamically typesafe view of the specified list.
2943: */
2944: private static class CheckedList<E> extends CheckedCollection<E>
2945: implements List<E> {
2946:
2947: private static final long serialVersionUID = 65247728283967356L;
2948:
2949: List<E> l;
2950:
2951: /**
2952: * Constructs a dynamically typesafe view of the specified list.
2953: *
2954: * @param l -
2955: * the list for which a dynamically typesafe view is to be
2956: * constructed.
2957: */
2958: public CheckedList(List<E> l, Class<E> type) {
2959: super (l, type);
2960: this .l = l;
2961: }
2962:
2963: /**
2964: * @see java.util.List#addAll(int, Collection)
2965: */
2966: @SuppressWarnings("unchecked")
2967: public boolean addAll(int index, Collection<? extends E> c1) {
2968: int size = c1.size();
2969: if (size == 0) {
2970: return false;
2971: }
2972: E[] arr = (E[]) new Object[size];
2973: Iterator<? extends E> it = c1.iterator();
2974: for (int i = 0; i < size; i++) {
2975: arr[i] = checkType(it.next(), type);
2976: }
2977: return l.addAll(index, Arrays.asList(arr));
2978: }
2979:
2980: /**
2981: * @see java.util.List#get(int)
2982: */
2983: public E get(int index) {
2984: return l.get(index);
2985: }
2986:
2987: /**
2988: * @see java.util.List#set(int, Object)
2989: */
2990: public E set(int index, E obj) {
2991: return l.set(index, checkType(obj, type));
2992: }
2993:
2994: /**
2995: * @see java.util.List#add(int, Object)
2996: */
2997: public void add(int index, E obj) {
2998: l.add(index, checkType(obj, type));
2999: }
3000:
3001: /**
3002: * @see java.util.List#remove(int)
3003: */
3004: public E remove(int index) {
3005: return l.remove(index);
3006: }
3007:
3008: /**
3009: * @see java.util.List#indexOf(Object)
3010: */
3011: public int indexOf(Object obj) {
3012: return l.indexOf(obj);
3013: }
3014:
3015: /**
3016: * @see java.util.List#lastIndexOf(Object)
3017: */
3018: public int lastIndexOf(Object obj) {
3019: return l.lastIndexOf(obj);
3020: }
3021:
3022: /**
3023: * @see java.util.List#listIterator()
3024: */
3025: public ListIterator<E> listIterator() {
3026: return new CheckedListIterator<E>(l.listIterator(), type);
3027: }
3028:
3029: /**
3030: * @see java.util.List#listIterator(int)
3031: */
3032: public ListIterator<E> listIterator(int index) {
3033: return new CheckedListIterator<E>(l.listIterator(index),
3034: type);
3035: }
3036:
3037: /**
3038: * @see java.util.List#subList(int, int)
3039: */
3040: public List<E> subList(int fromIndex, int toIndex) {
3041: return checkedList(l.subList(fromIndex, toIndex), type);
3042: }
3043:
3044: /**
3045: * @see java.util.List#equals(Object)
3046: */
3047: @Override
3048: public boolean equals(Object obj) {
3049: return l.equals(obj);
3050: }
3051:
3052: /**
3053: * @see java.util.List#hashCode()
3054: */
3055: @Override
3056: public int hashCode() {
3057: return l.hashCode();
3058: }
3059: }
3060:
3061: /**
3062: * Class represents a dynamically typesafe view of the specified
3063: * randomAccessList.
3064: */
3065: private static class CheckedRandomAccessList<E> extends
3066: CheckedList<E> implements RandomAccess {
3067:
3068: private static final long serialVersionUID = 1638200125423088369L;
3069:
3070: /**
3071: * Constructs a dynamically typesafe view of the specified
3072: * randomAccessList.
3073: *
3074: * @param l -
3075: * the randomAccessList for which a dynamically typesafe view
3076: * is to be constructed.
3077: */
3078: public CheckedRandomAccessList(List<E> l, Class<E> type) {
3079: super (l, type);
3080: }
3081: }
3082:
3083: /**
3084: * Class represents a dynamically typesafe view of the specified set.
3085: */
3086: private static class CheckedSet<E> extends CheckedCollection<E>
3087: implements Set<E> {
3088:
3089: private static final long serialVersionUID = 4694047833775013803L;
3090:
3091: /**
3092: * Constructs a dynamically typesafe view of the specified set.
3093: *
3094: * @param s -
3095: * the set for which a dynamically typesafe view is to be
3096: * constructed.
3097: */
3098: public CheckedSet(Set<E> s, Class<E> type) {
3099: super (s, type);
3100: }
3101:
3102: /**
3103: * @see java.util.Set#equals(Object)
3104: */
3105: @Override
3106: public boolean equals(Object obj) {
3107: return c.equals(obj);
3108: }
3109:
3110: /**
3111: * @see java.util.Set#hashCode()
3112: */
3113: @Override
3114: public int hashCode() {
3115: return c.hashCode();
3116: }
3117:
3118: }
3119:
3120: /**
3121: * Class represents a dynamically typesafe view of the specified map.
3122: */
3123: private static class CheckedMap<K, V> implements Map<K, V>,
3124: Serializable {
3125:
3126: private static final long serialVersionUID = 5742860141034234728L;
3127:
3128: Map<K, V> m;
3129:
3130: Class<K> keyType;
3131:
3132: Class<V> valueType;
3133:
3134: /**
3135: * Constructs a dynamically typesafe view of the specified map.
3136: *
3137: * @param m -
3138: * the map for which a dynamically typesafe view is to be
3139: * constructed.
3140: */
3141: private CheckedMap(Map<K, V> m, Class<K> keyType,
3142: Class<V> valueType) {
3143: if (m == null || keyType == null || valueType == null) {
3144: throw new NullPointerException();
3145: }
3146: this .m = m;
3147: this .keyType = keyType;
3148: this .valueType = valueType;
3149: }
3150:
3151: /**
3152: * @see java.util.Map#size()
3153: */
3154: public int size() {
3155: return m.size();
3156: }
3157:
3158: /**
3159: * @see java.util.Map#isEmpty()
3160: */
3161: public boolean isEmpty() {
3162: return m.isEmpty();
3163: }
3164:
3165: /**
3166: * @see java.util.Map#containsKey(Object)
3167: */
3168: public boolean containsKey(Object key) {
3169: return m.containsKey(key);
3170: }
3171:
3172: /**
3173: * @see java.util.Map#containsValue(Object)
3174: */
3175: public boolean containsValue(Object value) {
3176: return m.containsValue(value);
3177: }
3178:
3179: /**
3180: * @see java.util.Map#get(Object)
3181: */
3182: public V get(Object key) {
3183: return m.get(key);
3184: }
3185:
3186: /**
3187: * @see java.util.Map#put(Object, Object)
3188: */
3189: public V put(K key, V value) {
3190: return m.put(checkType(key, keyType), checkType(value,
3191: valueType));
3192: }
3193:
3194: /**
3195: * @see java.util.Map#remove(Object)
3196: */
3197: public V remove(Object key) {
3198: return m.remove(key);
3199: }
3200:
3201: /**
3202: * @see java.util.Map#putAll(Map)
3203: */
3204: @SuppressWarnings("unchecked")
3205: public void putAll(Map<? extends K, ? extends V> map) {
3206: int size = map.size();
3207: if (size == 0) {
3208: return;
3209: }
3210: Map.Entry<? extends K, ? extends V>[] entries = new Map.Entry[size];
3211: Iterator<? extends Map.Entry<? extends K, ? extends V>> it = map
3212: .entrySet().iterator();
3213: for (int i = 0; i < size; i++) {
3214: Map.Entry<? extends K, ? extends V> e = it.next();
3215: checkType(e.getKey(), keyType);
3216: checkType(e.getValue(), valueType);
3217: entries[i] = e;
3218: }
3219: for (int i = 0; i < size; i++) {
3220: m.put(entries[i].getKey(), entries[i].getValue());
3221: }
3222: }
3223:
3224: /**
3225: * @see java.util.Map#clear()
3226: */
3227: public void clear() {
3228: m.clear();
3229: }
3230:
3231: /**
3232: * @see java.util.Map#keySet()
3233: */
3234: public Set<K> keySet() {
3235: return m.keySet();
3236: }
3237:
3238: /**
3239: * @see java.util.Map#values()
3240: */
3241: public Collection<V> values() {
3242: return m.values();
3243: }
3244:
3245: /**
3246: * @see java.util.Map#entrySet()
3247: */
3248: public Set<Map.Entry<K, V>> entrySet() {
3249: return new CheckedEntrySet<K, V>(m.entrySet(), valueType);
3250: }
3251:
3252: /**
3253: * @see java.util.Map#equals(Object)
3254: */
3255: @Override
3256: public boolean equals(Object obj) {
3257: return m.equals(obj);
3258: }
3259:
3260: /**
3261: * @see java.util.Map#hashCode()
3262: */
3263: @Override
3264: public int hashCode() {
3265: return m.hashCode();
3266: }
3267:
3268: /**
3269: * @see java.lang.Object#toString()
3270: */
3271: @Override
3272: public String toString() {
3273: return m.toString();
3274: }
3275:
3276: /**
3277: * Class represents a dynamically typesafe view of the specified map
3278: * entry.
3279: */
3280: private static class CheckedEntry<K, V> implements
3281: Map.Entry<K, V> {
3282:
3283: Map.Entry<K, V> e;
3284:
3285: Class<V> valueType;
3286:
3287: /**
3288: * Constructs a dynamically typesafe view of the specified map
3289: * entry.
3290: *
3291: * @param e
3292: * the map entry for which a dynamically typesafe view is
3293: * to be constructed.
3294: * @param valueType
3295: * the type of the value
3296: */
3297: public CheckedEntry(Map.Entry<K, V> e, Class<V> valueType) {
3298: if (e == null) {
3299: throw new NullPointerException();
3300: }
3301: this .e = e;
3302: this .valueType = valueType;
3303: }
3304:
3305: /**
3306: * @see java.util.Map.Entry#getKey()
3307: */
3308: public K getKey() {
3309: return e.getKey();
3310: }
3311:
3312: /**
3313: * @see java.util.Map.Entry#getValue()
3314: */
3315: public V getValue() {
3316: return e.getValue();
3317: }
3318:
3319: /**
3320: * @see java.util.Map.Entry#setValue(Object)
3321: */
3322: public V setValue(V obj) {
3323: return e.setValue(checkType(obj, valueType));
3324: }
3325:
3326: /**
3327: * @see java.util.Map.Entry#equals(Object)
3328: */
3329: @Override
3330: public boolean equals(Object obj) {
3331: return e.equals(obj);
3332: }
3333:
3334: /**
3335: * @see java.util.Map.Entry#hashCode()
3336: */
3337: @Override
3338: public int hashCode() {
3339: return e.hashCode();
3340: }
3341: }
3342:
3343: /**
3344: * Class represents a dynamically typesafe view of the specified entry
3345: * set.
3346: */
3347: private static class CheckedEntrySet<K, V> implements
3348: Set<Map.Entry<K, V>> {
3349:
3350: Set<Map.Entry<K, V>> s;
3351:
3352: Class<V> valueType;
3353:
3354: /**
3355: * Constructs a dynamically typesafe view of the specified entry
3356: * set.
3357: *
3358: * @param s -
3359: * the entry set for which a dynamically typesafe view is
3360: * to be constructed.
3361: */
3362: public CheckedEntrySet(Set<Map.Entry<K, V>> s,
3363: Class<V> valueType) {
3364: this .s = s;
3365: this .valueType = valueType;
3366: }
3367:
3368: /**
3369: * @see java.util.Set#iterator()
3370: */
3371: public Iterator<Map.Entry<K, V>> iterator() {
3372: return new CheckedEntryIterator<K, V>(s.iterator(),
3373: valueType);
3374: }
3375:
3376: /**
3377: * @see java.util.Set#toArray()
3378: */
3379: public Object[] toArray() {
3380: int this Size = size();
3381: Object[] array = new Object[this Size];
3382: Iterator<?> it = iterator();
3383: for (int i = 0; i < this Size; i++) {
3384: array[i] = it.next();
3385: }
3386: return array;
3387: }
3388:
3389: /**
3390: * @see java.util.Set#toArray(Object[])
3391: */
3392: @SuppressWarnings("unchecked")
3393: public <T> T[] toArray(T[] array) {
3394: int this Size = size();
3395: if (array.length < this Size) {
3396: Class<?> ct = array.getClass().getComponentType();
3397: array = (T[]) Array.newInstance(ct, this Size);
3398: }
3399: Iterator<?> it = iterator();
3400: for (int i = 0; i < this Size; i++) {
3401: array[i] = (T) it.next();
3402: }
3403: if (this Size < array.length) {
3404: array[this Size] = null;
3405: }
3406: return array;
3407: }
3408:
3409: /**
3410: * @see java.util.Set#retainAll(Collection)
3411: */
3412: public boolean retainAll(Collection<?> c) {
3413: return s.retainAll(c);
3414: }
3415:
3416: /**
3417: * @see java.util.Set#removeAll(Collection)
3418: */
3419: public boolean removeAll(Collection<?> c) {
3420: return s.removeAll(c);
3421: }
3422:
3423: /**
3424: * @see java.util.Set#containsAll(Collection)
3425: */
3426: public boolean containsAll(Collection<?> c) {
3427: return s.containsAll(c);
3428: }
3429:
3430: /**
3431: * @see java.util.Set#addAll(Collection)
3432: */
3433: public boolean addAll(
3434: Collection<? extends Map.Entry<K, V>> c) {
3435: throw new UnsupportedOperationException();
3436: }
3437:
3438: /**
3439: * @see java.util.Set#remove(Object)
3440: */
3441: public boolean remove(Object o) {
3442: return s.remove(o);
3443: }
3444:
3445: /**
3446: * @see java.util.Set#contains(Object)
3447: */
3448: public boolean contains(Object o) {
3449: return s.contains(o);
3450: }
3451:
3452: /**
3453: * @see java.util.Set#add(Object)
3454: */
3455: public boolean add(Map.Entry<K, V> o) {
3456: throw new UnsupportedOperationException();
3457: }
3458:
3459: /**
3460: * @see java.util.Set#isEmpty()
3461: */
3462: public boolean isEmpty() {
3463: return s.isEmpty();
3464: }
3465:
3466: /**
3467: * @see java.util.Set#clear()
3468: */
3469: public void clear() {
3470: s.clear();
3471: }
3472:
3473: /**
3474: * @see java.util.Set#size()
3475: */
3476: public int size() {
3477: return s.size();
3478: }
3479:
3480: /**
3481: * @see java.util.Set#hashCode()
3482: */
3483: @Override
3484: public int hashCode() {
3485: return s.hashCode();
3486: }
3487:
3488: /**
3489: * @see java.util.Set#equals(Object)
3490: */
3491: @Override
3492: public boolean equals(Object object) {
3493: return s.equals(object);
3494: }
3495:
3496: /**
3497: * Class represents a dynamically typesafe view of the specified
3498: * entry iterator.
3499: */
3500: private static class CheckedEntryIterator<K, V> implements
3501: Iterator<Map.Entry<K, V>> {
3502:
3503: Iterator<Map.Entry<K, V>> i;
3504:
3505: Class<V> valueType;
3506:
3507: /**
3508: * Constructs a dynamically typesafe view of the specified entry
3509: * iterator.
3510: *
3511: * @param i -
3512: * the entry iterator for which a dynamically
3513: * typesafe view is to be constructed.
3514: */
3515: public CheckedEntryIterator(
3516: Iterator<Map.Entry<K, V>> i, Class<V> valueType) {
3517: this .i = i;
3518: this .valueType = valueType;
3519: }
3520:
3521: /**
3522: * @see java.util.Iterator#hasNext()
3523: */
3524: public boolean hasNext() {
3525: return i.hasNext();
3526: }
3527:
3528: /**
3529: * @see java.util.Iterator#remove()
3530: */
3531: public void remove() {
3532: i.remove();
3533: }
3534:
3535: /**
3536: * @see java.util.Iterator#next()
3537: */
3538: public Map.Entry<K, V> next() {
3539: return new CheckedEntry<K, V>(i.next(), valueType);
3540: }
3541: }
3542:
3543: }
3544:
3545: }
3546:
3547: /**
3548: * Class represents a dynamically typesafe view of the specified sortedSet.
3549: */
3550: private static class CheckedSortedSet<E> extends CheckedSet<E>
3551: implements SortedSet<E> {
3552:
3553: private static final long serialVersionUID = 1599911165492914959L;
3554:
3555: private SortedSet<E> ss;
3556:
3557: /**
3558: * Constructs a dynamically typesafe view of the specified sortedSet.
3559: *
3560: * @param s -
3561: * the sortedSet for which a dynamically typesafe view is to
3562: * be constructed.
3563: */
3564: public CheckedSortedSet(SortedSet<E> s, Class<E> type) {
3565: super (s, type);
3566: this .ss = s;
3567: }
3568:
3569: /**
3570: * @see java.util.SortedSet#comparator()
3571: */
3572: public Comparator<? super E> comparator() {
3573: return ss.comparator();
3574: }
3575:
3576: /**
3577: * @see java.util.SortedSet#subSet(Object, Object)
3578: */
3579: public SortedSet<E> subSet(E fromElement, E toElement) {
3580: return new CheckedSortedSet<E>(ss.subSet(fromElement,
3581: toElement), type);
3582: }
3583:
3584: /**
3585: * @see java.util.SortedSet#headSet(Object)
3586: */
3587: public SortedSet<E> headSet(E toElement) {
3588: return new CheckedSortedSet<E>(ss.headSet(toElement), type);
3589: }
3590:
3591: /**
3592: * @see java.util.SortedSet#tailSet(Object)
3593: */
3594: public SortedSet<E> tailSet(E fromElement) {
3595: return new CheckedSortedSet<E>(ss.tailSet(fromElement),
3596: type);
3597: }
3598:
3599: /**
3600: * @see java.util.SortedSet#first()
3601: */
3602: public E first() {
3603: return ss.first();
3604: }
3605:
3606: /**
3607: * @see java.util.SortedSet#last()
3608: */
3609: public E last() {
3610: return ss.last();
3611: }
3612: }
3613:
3614: /**
3615: * Class represents a dynamically typesafe view of the specified sortedMap.
3616: */
3617: private static class CheckedSortedMap<K, V> extends
3618: CheckedMap<K, V> implements SortedMap<K, V> {
3619:
3620: private static final long serialVersionUID = 1599671320688067438L;
3621:
3622: SortedMap<K, V> sm;
3623:
3624: /**
3625: * Constructs a dynamically typesafe view of the specified sortedMap.
3626: *
3627: * @param m -
3628: * the sortedMap for which a dynamically typesafe view is to
3629: * be constructed.
3630: */
3631: CheckedSortedMap(SortedMap<K, V> m, Class<K> keyType,
3632: Class<V> valueType) {
3633: super (m, keyType, valueType);
3634: this .sm = m;
3635: }
3636:
3637: /**
3638: * @see java.util.SortedMap#comparator()
3639: */
3640: public Comparator<? super K> comparator() {
3641: return sm.comparator();
3642: }
3643:
3644: /**
3645: * @see java.util.SortedMap#subMap(Object, Object)
3646: */
3647: public SortedMap<K, V> subMap(K fromKey, K toKey) {
3648: return new CheckedSortedMap<K, V>(
3649: sm.subMap(fromKey, toKey), keyType, valueType);
3650: }
3651:
3652: /**
3653: * @see java.util.SortedMap#headMap(Object)
3654: */
3655: public SortedMap<K, V> headMap(K toKey) {
3656: return new CheckedSortedMap<K, V>(sm.headMap(toKey),
3657: keyType, valueType);
3658: }
3659:
3660: /**
3661: * @see java.util.SortedMap#tailMap(Object)
3662: */
3663: public SortedMap<K, V> tailMap(K fromKey) {
3664: return new CheckedSortedMap<K, V>(sm.tailMap(fromKey),
3665: keyType, valueType);
3666: }
3667:
3668: /**
3669: * @see java.util.SortedMap#firstKey()
3670: */
3671: public K firstKey() {
3672: return sm.firstKey();
3673: }
3674:
3675: /**
3676: * @see java.util.SortedMap#lastKey()
3677: */
3678: public K lastKey() {
3679: return sm.lastKey();
3680: }
3681: }
3682: }
|