summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean McDirmid <sean.mcdirmid@gmail.com>2007-01-17 12:58:27 +0000
committerSean McDirmid <sean.mcdirmid@gmail.com>2007-01-17 12:58:27 +0000
commit767bb1b875dbde7aef1994edf445dbc687dbe8eb (patch)
tree07f65ebb3d3010a19f52edbecf8d83ebc206f189 /src
parent4c0d1ef392c1cb0f535b97fae6b5ebfd56be3218 (diff)
downloadscala-767bb1b875dbde7aef1994edf445dbc687dbe8eb.tar.gz
scala-767bb1b875dbde7aef1994edf445dbc687dbe8eb.tar.bz2
scala-767bb1b875dbde7aef1994edf445dbc687dbe8eb.zip
Initial check-in of Java collection library wra...
Initial check-in of Java collection library wrappers (JCL).
Diffstat (limited to 'src')
-rw-r--r--src/library/scala/collection/jcl/ArrayList.scala9
-rw-r--r--src/library/scala/collection/jcl/Buffer.scala137
-rw-r--r--src/library/scala/collection/jcl/BufferIterator.scala19
-rw-r--r--src/library/scala/collection/jcl/BufferWrapper.scala40
-rw-r--r--src/library/scala/collection/jcl/Collection.scala65
-rw-r--r--src/library/scala/collection/jcl/CollectionWrapper.scala25
-rw-r--r--src/library/scala/collection/jcl/ConcreteMapWrapper.scala14
-rw-r--r--src/library/scala/collection/jcl/ConcreteWrapper.scala18
-rw-r--r--src/library/scala/collection/jcl/HashMap.scala8
-rw-r--r--src/library/scala/collection/jcl/HashSet.scala10
-rw-r--r--src/library/scala/collection/jcl/IdentityHashMap.scala9
-rw-r--r--src/library/scala/collection/jcl/IterableWrapper.scala27
-rw-r--r--src/library/scala/collection/jcl/LinkedHashMap.scala8
-rw-r--r--src/library/scala/collection/jcl/LinkedHashSet.scala8
-rw-r--r--src/library/scala/collection/jcl/LinkedList.scala17
-rw-r--r--src/library/scala/collection/jcl/Map.scala85
-rw-r--r--src/library/scala/collection/jcl/MapWrapper.scala44
-rw-r--r--src/library/scala/collection/jcl/MutableIterable.scala70
-rw-r--r--src/library/scala/collection/jcl/MutableIterator.scala80
-rw-r--r--src/library/scala/collection/jcl/MutableSeq.scala66
-rw-r--r--src/library/scala/collection/jcl/SeqIterator.scala41
-rw-r--r--src/library/scala/collection/jcl/Set.scala34
-rw-r--r--src/library/scala/collection/jcl/SetWrapper.scala10
-rw-r--r--src/library/scala/collection/jcl/Sorted.scala43
-rw-r--r--src/library/scala/collection/jcl/SortedMap.scala78
-rw-r--r--src/library/scala/collection/jcl/SortedMapWrapper.scala28
-rw-r--r--src/library/scala/collection/jcl/SortedSet.scala62
-rw-r--r--src/library/scala/collection/jcl/SortedSetWrapper.scala23
-rw-r--r--src/library/scala/collection/jcl/Tests.scala66
-rw-r--r--src/library/scala/collection/jcl/TreeMap.scala8
-rw-r--r--src/library/scala/collection/jcl/TreeSet.scala10
-rw-r--r--src/library/scala/collection/jcl/WeakHashMap.scala11
32 files changed, 1173 insertions, 0 deletions
diff --git a/src/library/scala/collection/jcl/ArrayList.scala b/src/library/scala/collection/jcl/ArrayList.scala
new file mode 100644
index 0000000000..5de213ce2a
--- /dev/null
+++ b/src/library/scala/collection/jcl/ArrayList.scala
@@ -0,0 +1,9 @@
+package scala.collection.jcl;
+
+/** Creates a buffer backed by a Java array list.
+ * @author Sean McDirmid
+ */
+class ArrayList[A](override val underlying : java.util.ArrayList) extends ConcreteWrapper[A] with BufferWrapper[A] {
+ def this() = this(new java.util.ArrayList);
+ override def elements = super[BufferWrapper].elements;
+}
diff --git a/src/library/scala/collection/jcl/Buffer.scala b/src/library/scala/collection/jcl/Buffer.scala
new file mode 100644
index 0000000000..0919e62914
--- /dev/null
+++ b/src/library/scala/collection/jcl/Buffer.scala
@@ -0,0 +1,137 @@
+package scala.collection.jcl;
+
+/** A mutable sequence that supports element insertion and update.
+ *
+ * @author Sean McDirmid
+ */
+trait Buffer[A] extends MutableSeq[A] with Collection[A] with Sorted[Int,A] {
+ final protected type SortedSelf = Buffer[A];
+ override def elements : BufferIterator[Int,A];
+ /** The first index of a buffer is 0. */
+ override def first = 0;
+ /** The last index of a buffer is its size - 1. */
+ override def last = size - 1;
+ /** Indices are compared through subtraction. */
+ final def compare(k0 : Int, k1 : Int) = k0 - k1;
+ /** Removes the element at index "idx" */
+ def remove(idx : Int) = {
+ val i = elements;
+ val ret = i.seek(idx); i.remove; ret;
+ }
+ /** Replaces the element at index "idx" with "a."
+ * @returns the element replaced.
+ */
+ def set(idx : Int, a : A) : A = {
+ val i = elements;
+ val ret = i.seek(idx); i.set(a); ret;
+ }
+ /** Equivalent to set except the replaced element is not returned. */
+ def update(idx : Int, a : A) : Unit = set(idx, a);
+ /** @returns always true. */
+ def add(a : A) : Boolean = {
+ val i = elements;
+ while (i.hasNext) i.next;
+ i.add(a);
+ true;
+ }
+ /** Inserts "a" into this buffer just before the element at index "idx." */
+ def add(idx : Int, a : A) : Unit = {
+ val i = elements; i.seek(idx);
+ i.add(a);
+ }
+ /** Inserts all elements of "that" into this buffer just before the element at index "idx." */
+ def addAll(idx : Int, that : Iterable[A]) : Unit = {
+ val i = elements; i.seek(idx);
+ for (val that <- that) {
+ i.add(that); i.next;
+ }
+ }
+ override def transform(f : A => A) : Boolean = {
+ var changed = false;
+ val i = elements;
+ while (i.hasNext) {
+ val a0 = i.next;
+ val a1 = f(a0);
+ if (a0 != a1) {
+ i.set(a1); changed = true;
+ }
+ }
+ changed;
+ }
+ override def +(a : A) : this.type = super[Collection].+(a);
+ override def -=(a : A) = super[Collection].-=(a);
+ override def isEmpty = super[MutableSeq].isEmpty;
+ override def pfilter(p : A => Boolean) : MutableSeq[A] = super[MutableSeq].pfilter(p);
+ override def rangeImpl(from : Option[Int], until : Option[Int]) : Buffer[A] = new Range(from, until);
+
+ protected class Range(var from : Option[Int], var until : Option[Int]) extends Buffer[A] {
+ if (from == None && until == None) throw new IllegalArgumentException;
+ if (from != None && until != None && !(from.get < until.get)) throw new IllegalArgumentException;
+ override def add(a : A) =
+ if (until == None) Buffer.this.add(a);
+ else {
+ Buffer.this.add(until.get, a);
+ true;
+ }
+ private def translate(idx : Int) = {
+ if (until != None && idx > until.get) throw new IllegalArgumentException;
+ else if (from != None) from.get + idx;
+ else idx;
+ }
+ override def apply(idx : Int) : A = Buffer.this.apply(translate(idx));
+ override def set(idx : Int, a : A) = Buffer.this.set(translate(idx), a);
+ override def add(idx : Int, a : A) = Buffer.this.add(translate(idx), a);
+ override def remove(idx : Int) = Buffer.this.remove(translate(idx));
+ override def size = {
+ if (until != None) {
+ if (from != None) until.get - from.get;
+ else until.get;
+ } else super.size;
+ }
+ def elements : BufferIterator[Int,A] = new RangeIterator;
+ class RangeIterator extends BufferIterator[Int,A] {
+ val underlying = Buffer.this.elements;
+ if (from != None) underlying.seek(from.get);
+ def hasNext = underlying.hasNext &&
+ (until == None || underlying.nextIndex < until.get);
+ def hasPrevious = underlying.hasPrevious &&
+ (from == None || underlying.previousIndex >= from.get);
+ def next = {
+ if (until != None && underlying.nextIndex >= until.get) throw new NoSuchElementException;
+ underlying.next;
+ }
+ def previous = {
+ if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException;
+ underlying.previous;
+ }
+ def add(a : A) = {
+ if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException;
+ if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException;
+ underlying.add(a);
+ if (until != None) until = Some(until.get + 1);
+ }
+ def set(a : A) = {
+ if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException;
+ if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException;
+ underlying.set(a);
+ }
+ def remove = {
+ if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException;
+ if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException;
+ underlying.remove;
+ }
+ def nextIndex = {
+ val ret = underlying.nextIndex;
+ if (until != None && ret >= until.get) throw new NoSuchElementException;
+ if (from != None) ret - from.get;
+ else ret;
+ }
+ def previousIndex = {
+ val ret = underlying.previousIndex;
+ if (from != None && ret < from.get) throw new NoSuchElementException;
+ if (from != None) ret - from.get;
+ else ret;
+ }
+ }
+ }
+}
diff --git a/src/library/scala/collection/jcl/BufferIterator.scala b/src/library/scala/collection/jcl/BufferIterator.scala
new file mode 100644
index 0000000000..be1101df9f
--- /dev/null
+++ b/src/library/scala/collection/jcl/BufferIterator.scala
@@ -0,0 +1,19 @@
+package scala.collection.jcl;
+
+/** An iterator for a buffer that supports element update and insertion.
+ * @author Sean McDirmid
+ */
+trait BufferIterator[K,A] extends SeqIterator[K,A] {
+ /** Sets the element before this iterator's cursor to "a."
+ * Replaces either the last element returned by "next" or,
+ * if previous was called,
+ * the next element that would be return by "previous."
+ */
+ def set(a : A) : Unit;
+
+ /** Inserts "a" after the iterator's cursor.
+ If next was last called, "a" is inserted after the element returned.
+ If previous was last called, "a" is inserted before the element returned.
+ */
+ def add(a : A) : Unit;
+}
diff --git a/src/library/scala/collection/jcl/BufferWrapper.scala b/src/library/scala/collection/jcl/BufferWrapper.scala
new file mode 100644
index 0000000000..2364322d28
--- /dev/null
+++ b/src/library/scala/collection/jcl/BufferWrapper.scala
@@ -0,0 +1,40 @@
+package scala.collection.jcl;
+
+/** Wraps Java lists.
+ * @author Sean McDirmid
+ */
+trait BufferWrapper[A] extends Buffer[A] with CollectionWrapper[A] {
+ protected def underlying : java.util.List;
+ override def elements : BufferIterator[Int,A] = new IteratorWrapper(underlying.listIterator);
+ override def remove(idx : Int) = underlying.remove(idx).asInstanceOf[A];
+ override def add(a : A) = underlying.add(a);
+ override def add(idx : Int, a : A) = underlying.add(idx,a);
+ override def addAll(idx : Int, that : Iterable[A]) = that match {
+ case that : CollectionWrapper[_] => underlying.addAll(idx, that.underlying0); {}
+ case _ => super.addAll(idx, that);
+ }
+ override def indexOf(a : A) = {
+ val result = underlying.indexOf(a);
+ if (result == -1) None;
+ else Some(result);
+ }
+ override def apply(idx : Int) = underlying.get(idx).asInstanceOf[A];
+ override def set(idx : Int, a : A) = underlying.set(idx, a).asInstanceOf[A];
+ override def rangeImpl(from : Option[Int], until : Option[Int]) : Buffer[A] = new Range(from, until);
+ protected class Range(from : Option[Int], until : Option[Int]) extends super.Range(from,until) with BufferWrapper[A] {
+ val underlying = {
+ val fromi = if (from == None) 0 else from.get;
+ val toi = if (until == None) BufferWrapper.this.size else until.get;
+ BufferWrapper.this.underlying.subList(fromi, toi);
+ }
+ override def elements = super[BufferWrapper].elements;
+ }
+ class IteratorWrapper(underlying : java.util.ListIterator) extends super.IteratorWrapper(underlying) with BufferIterator[Int,A] {
+ def add(a : A) = underlying.add(a);
+ def set(a : A) = underlying.set(a);
+ def hasPrevious = underlying.hasPrevious;
+ def previous = underlying.previous.asInstanceOf[A];
+ def previousIndex = underlying.previousIndex;
+ def nextIndex = underlying.nextIndex;
+ }
+}
diff --git a/src/library/scala/collection/jcl/Collection.scala b/src/library/scala/collection/jcl/Collection.scala
new file mode 100644
index 0000000000..2b2589fdfc
--- /dev/null
+++ b/src/library/scala/collection/jcl/Collection.scala
@@ -0,0 +1,65 @@
+package scala.collection.jcl;
+object Collection {
+ val DEFAULT_FILTER : Any => Boolean = x => true;
+}
+
+/** Analogous to a Java collection.
+ **
+ ** @author Sean McDirmid
+ **/
+trait Collection[A] extends MutableIterable[A] {
+ /** Type-safe version of containsAll.
+ **
+ ** @author Sean McDirmid
+ **/
+ def hasAll(i : Iterable[A]) : Boolean = i.forall(elements.has);
+ /** Adds "a" to the collection, return true if "a" is actually added. */
+ def add(a : A ) : Boolean;
+ /** Adds all elements in "i" to the collection, return true if any elements are added. */
+ def addAll(i : Iterable[A]) : Boolean = {
+ var changed = false;
+ i.foreach(t => changed = add(t) || changed);
+ changed;
+ }
+ /** Operator shortcut for addAll. */
+ def ++(that : Iterable[A]) : this.type = {
+ addAll(that); this;
+ }
+
+
+ /** removes "a" from the collection. */
+ def -=(a : A) : Unit = remove(a);
+ /** adds "a" from the collection. */
+ def +=(t : A) : Unit = add(t);
+ /** adds "a" from the collection. Useful for chaining. */
+ def +(t : A) : this.type = { add(t); this; }
+
+ /** Transforms each element of the collection in-place according to "f." Returns true
+ ** if the collection is actually updated.
+ **/
+ def transform(f : A => A) : Boolean;
+ /** Used for non-strict filtered collection that only includes elements of this collection that are true for "p."
+ ** Any elements added to or removed from the resulting
+ ** filter will update this collection. Any changes to this collection
+ ** can update the filtered collection.
+ ** @return a non-strict filter of this collection.
+ **/
+ def pfilter(p : A => Boolean) : MutableIterable[A] = new Filter(p);
+ /** Base implementation of a filtered collection */
+ class Filter(p : A => Boolean) extends Collection[A] {
+ def transform(f : A => A) =
+ Collection.this.transform(a => if (p(a)) f(a) else a);
+ override def add(a : A) = {
+ if (!p(a)) throw new IllegalArgumentException;
+ Collection.this.add(a);
+ }
+ override def has(a : A) = if (!p(a)) false else Collection.this.has(a);
+ override def remove(a : A) = {
+ if (!p(a)) throw new IllegalArgumentException;
+ Collection.this.remove(a);
+ }
+ override def pfilter(p1 : A => Boolean) : MutableIterable[A] =
+ Collection.this.pfilter(a => p(a) && p1(a));
+ def elements = Collection.this.elements.filter(p);
+ }
+}
diff --git a/src/library/scala/collection/jcl/CollectionWrapper.scala b/src/library/scala/collection/jcl/CollectionWrapper.scala
new file mode 100644
index 0000000000..94a439e269
--- /dev/null
+++ b/src/library/scala/collection/jcl/CollectionWrapper.scala
@@ -0,0 +1,25 @@
+package scala.collection.jcl;
+
+/** Used to wrap Java collections in Scala.
+ **
+ ** @author Sean McDirmid
+ **/
+trait CollectionWrapper[A] extends Collection[A] with IterableWrapper[A] {
+ /** Override to specify the collection being accessed through this wrapper.
+ ** Collection operations are then routed through the wrapped Java collection.
+ **/
+ protected def underlying : java.util.Collection;
+ private[jcl] final def underlying0 = underlying;
+ override def has(a : A) = underlying.contains(a);
+ override def elements : MutableIterator[A] = super.elements;
+
+ override def hasAll(that : Iterable[A]) = that match {
+ case that : CollectionWrapper[_] => underlying.containsAll(that.underlying);
+ case _ => super.hasAll(that);
+ }
+ override def add(a : A) = underlying.add(a);
+ override def addAll(that : Iterable[A]) = that match {
+ case that : CollectionWrapper[_] => underlying.addAll(that.underlying);
+ case _ => super.addAll(that);
+ }
+}
diff --git a/src/library/scala/collection/jcl/ConcreteMapWrapper.scala b/src/library/scala/collection/jcl/ConcreteMapWrapper.scala
new file mode 100644
index 0000000000..1f9a16dab4
--- /dev/null
+++ b/src/library/scala/collection/jcl/ConcreteMapWrapper.scala
@@ -0,0 +1,14 @@
+package scala.collection.jcl;
+
+/** A concrete wrapper around a Java map. The identity of the wraper is fixed to the identity of the underlying map.
+ * @author Sean McDirmid
+ */
+abstract class ConcreteMapWrapper[K,E] extends MapWrapper[K,E] {
+ val underlying : java.util.Map;
+ override def toString = underlying.toString;
+ override def hashCode = underlying.hashCode;
+ override def equals(that : Any) = that match {
+ case that : ConcreteMapWrapper[_,_] => underlying == that.underlying;
+ case _ => false;
+ }
+}
diff --git a/src/library/scala/collection/jcl/ConcreteWrapper.scala b/src/library/scala/collection/jcl/ConcreteWrapper.scala
new file mode 100644
index 0000000000..f113ba827e
--- /dev/null
+++ b/src/library/scala/collection/jcl/ConcreteWrapper.scala
@@ -0,0 +1,18 @@
+package scala.collection.jcl;
+
+/* Describes wrappers around concrete underlying collections. The identity
+ * of the wrapper is related strictly to the Java collection being wrapped,
+ * which is structurally determined.
+ *
+ * @author Sean McDirmid
+ */
+abstract class ConcreteWrapper[A] extends CollectionWrapper[A] {
+ val underlying : java.util.Collection;
+ override def elements : MutableIterator[A] = super.elements;
+ override def toString = underlying.toString;
+ override def hashCode = underlying.hashCode;
+ override def equals(that : Any) = that match {
+ case that : ConcreteWrapper[_] => underlying == that.underlying;
+ case _ => false;
+ }
+}
diff --git a/src/library/scala/collection/jcl/HashMap.scala b/src/library/scala/collection/jcl/HashMap.scala
new file mode 100644
index 0000000000..f87631396e
--- /dev/null
+++ b/src/library/scala/collection/jcl/HashMap.scala
@@ -0,0 +1,8 @@
+package scala.collection.jcl;
+
+/** A map that is backed by a Java hash map.
+ * @author Sean McDirmid
+ */
+class HashMap[K,E](override val underlying : java.util.HashMap) extends ConcreteMapWrapper[K,E] {
+ def this() = this(new java.util.HashMap);
+}
diff --git a/src/library/scala/collection/jcl/HashSet.scala b/src/library/scala/collection/jcl/HashSet.scala
new file mode 100644
index 0000000000..005db81a36
--- /dev/null
+++ b/src/library/scala/collection/jcl/HashSet.scala
@@ -0,0 +1,10 @@
+package scala.collection.jcl;
+
+/** A hash set that is backed by a Java hash set.
+ **
+ ** @author Sean McDirmid
+ **/
+class HashSet[A](override val underlying : java.util.HashSet) extends ConcreteWrapper[A] with SetWrapper[A] {
+ /** Creates an underlying Java hash set. */
+ def this() = this(new java.util.HashSet);
+}
diff --git a/src/library/scala/collection/jcl/IdentityHashMap.scala b/src/library/scala/collection/jcl/IdentityHashMap.scala
new file mode 100644
index 0000000000..e1aa07c72e
--- /dev/null
+++ b/src/library/scala/collection/jcl/IdentityHashMap.scala
@@ -0,0 +1,9 @@
+package scala.collection.jcl;
+
+/** A map that is backed by a Java identity hash map, which compares keys by their reference-based identity
+ * as opposed to using equals and hashCode. An identity hash map will often perform better than traditional hash map because it can utilize linear probing.
+ * @author Sean McDirmid
+ */
+class IdentityHashMap[K,E](override val underlying : java.util.IdentityHashMap) extends ConcreteMapWrapper[K,E] {
+ def this() = this(new java.util.IdentityHashMap);
+}
diff --git a/src/library/scala/collection/jcl/IterableWrapper.scala b/src/library/scala/collection/jcl/IterableWrapper.scala
new file mode 100644
index 0000000000..10d37f5549
--- /dev/null
+++ b/src/library/scala/collection/jcl/IterableWrapper.scala
@@ -0,0 +1,27 @@
+package scala.collection.jcl;
+/** A wrapper around a Java collection that only supports remove mutations.
+ * @author Sean McDirmid
+ */
+trait IterableWrapper[A] extends MutableIterable[A] {
+ protected def underlying : java.util.Collection;
+ override def remove(a : A) = underlying.remove(a);
+ override def removeAll(that : Iterable[A]) = that match {
+ case that : IterableWrapper[_] => underlying.removeAll(that.underlying);
+ case _ => super.removeAll(that);
+ }
+ override def retainAll(that : Iterable[A]) = that match {
+ case that : IterableWrapper[_] => underlying.retainAll(that.underlying);
+ case _ => super.retainAll(that);
+ }
+ override def size = underlying.size;
+ override def isEmpty = underlying.isEmpty;
+ override def clear = underlying.clear;
+ override def elements : MutableIterator[A] = new IteratorWrapper(underlying.iterator);
+ class IteratorWrapper(underlying : java.util.Iterator) extends MutableIterator[A] {
+ // val underlying = IterableWrapper.this.underlying.iterator;
+ def hasNext = underlying.hasNext;
+ def next = underlying.next.asInstanceOf[A];
+ def remove = underlying.remove;
+ }
+
+}
diff --git a/src/library/scala/collection/jcl/LinkedHashMap.scala b/src/library/scala/collection/jcl/LinkedHashMap.scala
new file mode 100644
index 0000000000..f2050d05e3
--- /dev/null
+++ b/src/library/scala/collection/jcl/LinkedHashMap.scala
@@ -0,0 +1,8 @@
+package scala.collection.jcl;
+
+/** A map that is backed by a Java linked hash map, which fixes iteration order in terms of insertion order.
+ * @author Sean McDirmid
+ */
+class LinkedHashMap[K,E](override val underlying : java.util.LinkedHashMap) extends ConcreteMapWrapper[K,E] {
+ def this() = this(new java.util.LinkedHashMap);
+}
diff --git a/src/library/scala/collection/jcl/LinkedHashSet.scala b/src/library/scala/collection/jcl/LinkedHashSet.scala
new file mode 100644
index 0000000000..d3c7485cb8
--- /dev/null
+++ b/src/library/scala/collection/jcl/LinkedHashSet.scala
@@ -0,0 +1,8 @@
+package scala.collection.jcl;
+
+/** A set that is backed by a Java linked hash set, which fixes iteration order in terms of insertion order.
+ * @author Sean McDirmid
+ */
+class LinkedHashSet[A](override val underlying : java.util.LinkedHashSet) extends ConcreteWrapper[A] with SetWrapper[A] {
+ def this() = this(new java.util.LinkedHashSet);
+}
diff --git a/src/library/scala/collection/jcl/LinkedList.scala b/src/library/scala/collection/jcl/LinkedList.scala
new file mode 100644
index 0000000000..d05e68746f
--- /dev/null
+++ b/src/library/scala/collection/jcl/LinkedList.scala
@@ -0,0 +1,17 @@
+package scala.collection.jcl;
+
+/** Creates a buffer backed by a Java linked list. Includes additional peek/poll/removeFirst/removeLast APIs
+ * that are useful in implementing queues and stacks.
+ * @author Sean McDirmid
+ */
+class LinkedList[A](override val underlying : java.util.LinkedList) extends ConcreteWrapper[A] with BufferWrapper[A] {
+ def this() = this(new java.util.LinkedList);
+ override def elements = super[BufferWrapper].elements;
+ override def add(idx : Int, a : A) =
+ if (idx == 0) underlying.addFirst(a);
+ else super.add(idx, a);
+ def peek = underlying.peek.asInstanceOf[A];
+ def poll = underlying.poll.asInstanceOf[A];
+ def removeFirst = underlying.removeFirst.asInstanceOf[A];
+ def removeLast = underlying.removeLast.asInstanceOf[A];
+}
diff --git a/src/library/scala/collection/jcl/Map.scala b/src/library/scala/collection/jcl/Map.scala
new file mode 100644
index 0000000000..a16ba82d53
--- /dev/null
+++ b/src/library/scala/collection/jcl/Map.scala
@@ -0,0 +1,85 @@
+package scala.collection.jcl;
+
+/** A mutable map that is compatible with Java maps.
+ * @author Sean McDirmid
+ */
+trait Map[K,E] extends MutableIterable[Tuple2[K,E]] with scala.collection.mutable.Map[K,E] {
+ override def clear = super[MutableIterable].clear;
+ override def isEmpty = super[MutableIterable].isEmpty;
+ override def keySet : Set[K] = new KeySet;
+ /** The values of this map as a projection, which means
+ removals from the returned collection will remove the element from this map.
+ @returns a projection of this map's elements. */
+ def valueSet : MutableIterable[E] = pmap(._2);
+ def put(key : K, elem : E) : Option[E];
+ def putAll(that : Iterable[Tuple2[K,E]]) : Unit =
+ that.foreach(p => put(p._1, p._2));
+ def remove(key : K) : Option[E] = {
+ val i = elements;
+ while (!i.hasNext) {
+ val result = i.next;
+ if (result._1 == key) {
+ i.remove;
+ return Some(result._2);
+ }
+ }
+ return None;
+ }
+ override def has(pair : Tuple2[K,E]) = get(pair._1) match {
+ case Some(e) if e == pair._2 => true;
+ case _ => false;
+ }
+ override def get(key : K) = elements.find(p => p._1 == key).map(._2);
+ override def update(key : K, e : E) : Unit = put(key,e);
+ override def +(pair : Tuple2[K,E]) : this.type = {
+ put(pair._1,pair._2); this;
+ }
+ override def +=(pair : Tuple2[K,E]) : Unit = put(pair._1, pair._2);
+ override def -(key : K) : this.type = {
+ remove(key); this;
+ }
+ override def -=(key : K) : Unit = remove(key);
+ override def elements : MutableIterator[Tuple2[K,E]];
+ /** Produces a filtered projection of this map that includes only entries of the map
+ * whose keys are true with respect to predicate "p."
+ */
+ def pfilter(p : K => Boolean) : jcl.Map[K,E] = new Filter(p);
+ /**
+ */
+ def lense[F](f : E => F, g : F => E) : jcl.Map[K,F] = new Lense[F](f,g);
+
+ protected class Lense[F](f : E => F, g : F => E) extends jcl.Map[K,F] {
+ override def elements = Map.this.elements.map(k => Tuple2(k._1, f(k._2)));
+ override def remove(key : K) = Map.this.remove(key).map(f);
+ override def put(key : K, elem : F) = Map.this.put(key, g(elem)).map(f);
+ override def get(key : K) = Map.this.get(key).map(f);
+ override def pfilter(p : K => Boolean) : jcl.Map[K,F] =
+ Map.this.pfilter(p).lense(f, g);
+ override def lense[G](f0 : F => G, g0 : G => F) : jcl.Map[K,G] =
+ Map.this.lense[G](x => f0(f(x)), y => g(g0(y)));
+ }
+ protected class Filter(p : K => Boolean) extends jcl.Map[K,E] {
+ override def elements = Map.this.elements.filter(k => p(k._1));
+ override def remove(key : K) = {
+ if (!p(key)) throw new IllegalArgumentException;
+ Map.this.remove(key);
+ }
+ override def contains(key : K) = p(key) && Map.this.contains(key);
+ override def put(key : K, elem : E) = {
+ if (!p(key)) throw new IllegalArgumentException;
+ Map.this.put(key, elem);
+ }
+ override def get(key : K) = {
+ if (!p(key)) None;
+ else Map.this.get(key);
+ }
+ override def pfilter(p0 : K => Boolean) : jcl.Map[K,E] =
+ Map.this.pfilter(k => p(k) && p0(k));
+ }
+ protected class KeySet extends Set[K] {
+ override def add(k : K) = Map.this.put(k, default(k)) == None;
+ override def elements = Map.this.elements.map(._1);
+ override def has(k : K) = Map.this.contains(k);
+ }
+
+}
diff --git a/src/library/scala/collection/jcl/MapWrapper.scala b/src/library/scala/collection/jcl/MapWrapper.scala
new file mode 100644
index 0000000000..5fb1a8d6b4
--- /dev/null
+++ b/src/library/scala/collection/jcl/MapWrapper.scala
@@ -0,0 +1,44 @@
+package scala.collection.jcl;
+
+/** A wrapper around a Java map.
+ * @author Sean McDirmid
+ */
+trait MapWrapper[K,E] extends jcl.Map[K,E] {
+ protected def underlying : java.util.Map;
+ override def size = underlying.size;
+ override def isEmpty = underlying.isEmpty;
+ override def clear = underlying.clear;
+ override def put(key : K, elem : E) = {
+ if (elem == null) throw new IllegalArgumentException;
+ val ret = underlying.put(key,elem);
+ if (ret == null) None else Some(ret.asInstanceOf[E]);
+ }
+ override def putAll(that : Iterable[Tuple2[K,E]]) : Unit = that match {
+ case that : MapWrapper[_,_] => underlying.putAll(that.underlying);
+ case _ => super.putAll(that);
+ }
+ override def remove(key : K) = {
+ val ret = underlying.remove(key);
+ if (ret == null) None else Some(ret.asInstanceOf[E]);
+ }
+ override def contains(key : K) = underlying.containsKey(key);
+ override def keySet : Set[K] = new KeySet;
+ override def valueSet : MutableIterable[E] = new ValueSet;
+ override def elements : MutableIterator[Tuple2[K,E]] = new IteratorWrapper;
+ class IteratorWrapper extends MutableIterator[Tuple2[K,E]] {
+ val underlying = MapWrapper.this.underlying.entrySet.iterator;
+ def hasNext = underlying.hasNext;
+ def remove = underlying.remove;
+ def next = {
+ val next = underlying.next.asInstanceOf[java.util.Map.Entry];
+ Tuple2(next.getKey.asInstanceOf[K],next.getValue.asInstanceOf[E]);
+ }
+ }
+ class KeySet extends super.KeySet with SetWrapper[K] {
+ protected val underlying = MapWrapper.this.underlying.keySet;
+ }
+ class ValueSet extends IterableWrapper[E] {
+ val underlying = MapWrapper.this.underlying.values;
+ override def has(e : E) = MapWrapper.this.underlying.containsValue(e);
+ }
+}
diff --git a/src/library/scala/collection/jcl/MutableIterable.scala b/src/library/scala/collection/jcl/MutableIterable.scala
new file mode 100644
index 0000000000..baf5a0c727
--- /dev/null
+++ b/src/library/scala/collection/jcl/MutableIterable.scala
@@ -0,0 +1,70 @@
+package scala.collection.jcl;
+
+/**
+ * An iterable collection that supports remove operations.
+ * Useful for representing projections of mutable collections that where only
+ * the remove operation makes sense.
+ *
+ * @author Sean McDirmid
+ */
+trait MutableIterable[A] extends Iterable[A] {
+ /** @return true if t is in the collection.
+ **/
+ def has(t : A ) : Boolean = elements.has(t);
+ /** @return true if t was removed from this collection.
+ **/
+ def remove(t : A ) : Boolean = elements.remove(t);
+ /** @return true if any element in that was removed from this collection.
+ **/
+ def removeAll(that : Iterable[A]) : Boolean = {
+ var changed = false;
+ that.foreach(t => changed = elements.remove(t) || changed);
+ changed;
+ }
+ /** Operator shortcut for removeAll. */
+ def --(that : Iterable[A]) : this.type = {
+ removeAll(that); this;
+ }
+
+ /** @return the collection that t was removed from.
+ **/
+ def -(t : A) : this.type = { remove(t); this; }
+ /** retain only elements in the collection that predicate p is true for.
+ **/
+ def retain(p : A => Boolean) : Unit = elements.retain(p);
+ /** retain only elements that are also in that.
+ **/
+ def retainAll(that : Iterable[A]) : Boolean = elements.retain(s => that.exists(t => t == s));
+ /** @return true if the element has no elements.
+ **/
+ def isEmpty : Boolean = !elements.hasNext;
+ /** @return the current number of elements in the collection.
+ **/
+ def size : Int = {
+ var count = 0;
+ val i = elements;
+ while (i.hasNext) { count = count + 1; i.next; }
+ count;
+ }
+ /** clear all elements from the collection.
+ **/
+ def clear : Unit = {
+ val i = elements;
+ while (i.hasNext) {
+ i.next; i.remove;
+ }
+ }
+ /** Creates a non-strict map of this collection. Any removals from the returned
+ ** collection will remove from this collection, while any changes to this collection will also be
+ ** reflected in the mapped collection.
+ ** @return a non-strict map of this collection.
+ **/
+ def pmap[B](f : A => B) : MutableIterable[B] = new Map[B](f);
+ /** The default implementation of a map over mutable iterable collections.
+ **/
+ protected class Map[B](f : A => B) extends MutableIterable[B] {
+ override def elements = MutableIterable.this.elements.map(f);
+ override def toString = elements.toList.mkString("{", ", ", "}");
+ }
+ override def elements : MutableIterator[A];
+}
diff --git a/src/library/scala/collection/jcl/MutableIterator.scala b/src/library/scala/collection/jcl/MutableIterator.scala
new file mode 100644
index 0000000000..4a4530c641
--- /dev/null
+++ b/src/library/scala/collection/jcl/MutableIterator.scala
@@ -0,0 +1,80 @@
+package scala.collection.jcl;
+
+/** An iterator that supports the remove operation.
+ ** These iterators wrap Java iterators, and so have the same fail fast behavior when dealing
+ ** with concurrent modifications.
+ **
+ ** @author Sean McDirmid
+ **/
+trait MutableIterator[A] extends Iterator[A] {
+ def remove : Unit;
+ override def filter(f : A => Boolean) : MutableIterator[A] = {
+ val buffered = this.buffered0;
+ new buffered.Filter(f);
+ }
+ override def map[B](f : A => B) : MutableIterator[B] = new Map(f);
+ /** A type-safe version of contains.
+ **/
+ def has(a : A) = exists(b => a == a);
+ /** Finds and removes the first instance of "a" through the iterator. After execution, the iterator's cursor is located where the removed element existed.
+ ** Returns false if "a" is not encountered in the iterator and the iterator's cursor is located at the end of its elements.
+ **/
+ def remove(a : A) : Boolean = {
+ while (hasNext)
+ if (next == a) { remove; return true; }
+ return false;
+ }
+ /** Removes all elements in the iterator that predicate "p" returns false on.
+ **/
+ def retain(p : A => Boolean) : Boolean = {
+ var changed = false;
+ while (hasNext)
+ if (!p(next)) { remove; changed = true; }
+ changed;
+ }
+
+ private[jcl] def buffered0 : MutableIterator[A]#Buffered = new BufferedImpl;
+
+ /** Standard implementation of a mapped iterator. **/
+ class Map[B](f : A => B) extends MutableIterator[B] {
+ def hasNext = MutableIterator.this.hasNext;
+ def next = f(MutableIterator.this.next);
+ def remove = MutableIterator.this.remove;
+ }
+ private[jcl] trait Buffered extends MutableIterator[A] {
+ private[jcl] override def buffered0 : this.type = this;
+ private[jcl] def peekNext : A;
+ private[jcl] def seekNext(f : A => Boolean) : Option[A] = {
+ while (hasNext && !f(peekNext)) next;
+ if (hasNext) Some(peekNext) else None;
+ }
+ class Filter(p : A => Boolean) extends MutableIterator[A] {
+ private[jcl] def peekNext = Buffered.this.seekNext(p) match {
+ case Some(result) => result;
+ case None => throw new NoSuchElementException;
+ }
+ override def next = {
+ val ret = peekNext; val ret0 = Buffered.this.next; assert(ret == ret0); ret;
+ }
+ override def hasNext : Boolean = seekNext(p) != None;
+ override def remove : Unit = Buffered.this.remove;
+ }
+ }
+ private[jcl] class BufferedImpl extends Buffered {
+ protected var head : A = _;
+ protected def underlying = MutableIterator.this;
+ private[jcl] def peekNext = {
+ if (head == null) head = underlying.next;
+ head;
+ }
+ override def hasNext = head != null || underlying.hasNext;
+ override def next = {
+ val ret = peekNext; head = null.asInstanceOf[A]; ret;
+ }
+ override def remove = {
+ if (head != null) throw new NoSuchElementException;
+ underlying.remove;
+ }
+ override def toString = "buffered[" + underlying + "]";
+ }
+}
diff --git a/src/library/scala/collection/jcl/MutableSeq.scala b/src/library/scala/collection/jcl/MutableSeq.scala
new file mode 100644
index 0000000000..f1ea9fc61b
--- /dev/null
+++ b/src/library/scala/collection/jcl/MutableSeq.scala
@@ -0,0 +1,66 @@
+package scala.collection.jcl;
+
+/** A mutable sequence that supports the remove operation and is ordered.
+ *
+ * @author Sean McDirmid
+ */
+trait MutableSeq[A] extends MutableIterable[A] with Seq[A] {
+ override def elements : SeqIterator[Int,A];
+ override def isEmpty = super[MutableIterable].isEmpty;
+ override def length = size;
+ override def apply(idx : Int) = elements.seek(idx);
+ def pfilter(p : A => Boolean) : MutableSeq[A] = new Filter(p);
+ override def pmap[B](f : A => B) : MutableSeq[B] = new Map[B](f);
+ /** Find the index of "a" in this sequence.
+ * @returns None if the "a" is not in this sequence.
+ */
+ def indexOf(a : A) = elements.indexOf(a);
+
+
+ protected class Filter(p : A => Boolean) extends MutableSeq[A] {
+ def elements : SeqIterator[Int,A] = new FilterIterator(MutableSeq.this.elements);
+ class FilterIterator(underlying : SeqIterator[Int,A]) extends SeqIterator[Int,A] {
+ private var index = 0;
+ protected def seekNext : Option[A] = {
+ while (underlying.hasNext) {
+ val next = underlying.next;
+ if (p(next)) return Some(next);
+ }
+ return None;
+ }
+ protected def seekPrevious : Option[A] = {
+ while (underlying.hasPrevious) {
+ val previous = underlying.previous;
+ if (p(previous)) return Some(previous);
+ }
+ return None;
+ }
+ def hasNext : Boolean = seekNext match {
+ case None => false;
+ case Some(_) => underlying.previous; true;
+ }
+ def nextIndex = index;
+ def next = seekNext match {
+ case None => throw new NoSuchElementException;
+ case Some(result) => index = index + 1; result;
+ }
+ def hasPrevious : Boolean = seekPrevious match {
+ case None => false;
+ case Some(_) => underlying.previous; true;
+ }
+ def previousIndex = {
+ if (index == 0) throw new NoSuchElementException;
+ index - 1;
+ }
+ def previous = seekPrevious match {
+ case None => throw new NoSuchElementException;
+ case Some(result) => index = index - 1; result;
+ }
+ def remove = underlying.remove;
+ }
+ }
+ protected class Map[B](f : A => B) extends super.Map[B](f) with MutableSeq[B] {
+ override def elements = MutableSeq.this.elements.map(f);
+ override def apply(idx : Int) = f(MutableSeq.this.apply(idx));
+ }
+}
diff --git a/src/library/scala/collection/jcl/SeqIterator.scala b/src/library/scala/collection/jcl/SeqIterator.scala
new file mode 100644
index 0000000000..584f2dfb79
--- /dev/null
+++ b/src/library/scala/collection/jcl/SeqIterator.scala
@@ -0,0 +1,41 @@
+package scala.collection.jcl;
+
+/** An iterator for a sequence that can move both forwards and backwards.
+ * over a set of ordered keys.
+ * @author Sean McDirmid
+ */
+trait SeqIterator[K,A] extends MutableIterator[A] {
+ /** @returns The index at the iterator's cursor. */
+ def nextIndex : K;
+ /** @returns The index of the element before the iterator's cursor. */
+ def previousIndex : K;
+ /** @returns The previous element, will move the iterator's cursor backwards. */
+ def previous : A;
+ /** @returns True if and only if the iterator's cursor is not at the beging of the iteration. */
+ def hasPrevious : Boolean;
+
+ /** Winds the iteration forward until index "idx" is found */
+ def seek(idx : K) = {
+ while (nextIndex != idx) next;
+ next;
+ }
+ /** finds the index of the next "a" in this iteration.
+ @returns None if "a" is not found in the iteration. */
+ def indexOf(a : A) : Option[K] = {
+ while (hasNext) {
+ val ret = next;
+ if (ret == a) return Some(previousIndex);
+ }
+ return None;
+ }
+
+ override def map[B](f : A => B) : SeqIterator[K,B] = new Map[B](f);
+ class Map[B](f : A => B) extends super.Map[B](f) with SeqIterator[K,B] {
+ override def hasPrevious = SeqIterator.this.hasPrevious;
+ override def previous = f(SeqIterator.this.previous);
+ override def previousIndex = SeqIterator.this.previousIndex;
+ override def nextIndex = SeqIterator.this.nextIndex;
+ override def map[C](g : B => C) : SeqIterator[K,C] =
+ SeqIterator.this.map(a => g(f(a)));
+ }
+}
diff --git a/src/library/scala/collection/jcl/Set.scala b/src/library/scala/collection/jcl/Set.scala
new file mode 100644
index 0000000000..68a92a7e6e
--- /dev/null
+++ b/src/library/scala/collection/jcl/Set.scala
@@ -0,0 +1,34 @@
+package scala.collection.jcl;
+
+/** Analogous to a Java set.
+ **
+ ** @author Sean McDirmid
+ **/
+trait Set[A] extends Collection[A] with scala.collection.mutable.Set[A] {
+ /** Add will return false if "a" already exists in the set. **/
+ override def add(a : A) : Boolean;
+
+ override def ++(i : Iterable[A]) : this.type = super[Collection].++(i);
+ override def --(i : Iterable[A]) : this.type = super[Collection].--(i);
+ override def +(t : A) : this.type = super[Collection].+(t);
+ override def -(t : A) : this.type = super[Collection].-(t);
+ override def retain(f : A => Boolean) = super[Collection].retain(f);
+ override def isEmpty = super[Collection].isEmpty;
+ override final def contains(a : A) = has(a);
+ override def transform(f : A => A) = {
+ var toAdd : List[A] = Nil;
+ val i = elements;
+ while (i.hasNext) {
+ val i0 = i.next;
+ val i1 = f(i0);
+ if (i0 != i1) {
+ i.remove; toAdd = i1 :: toAdd;
+ }
+ }
+ addAll(toAdd);
+ }
+ override def pfilter(p : A => Boolean) : Set[A] = new Filter(p);
+ class Filter(p : A => Boolean) extends super.Filter(p) with Set[A] {
+ override def filter(p : A => Boolean) = super[Set].filter(p);
+ }
+}
diff --git a/src/library/scala/collection/jcl/SetWrapper.scala b/src/library/scala/collection/jcl/SetWrapper.scala
new file mode 100644
index 0000000000..54d19e6675
--- /dev/null
+++ b/src/library/scala/collection/jcl/SetWrapper.scala
@@ -0,0 +1,10 @@
+package scala.collection.jcl;
+
+/** Used to wrap Java sets.
+ **
+ ** @author Sean McDirmid
+ **/
+trait SetWrapper[A] extends CollectionWrapper[A] with Set[A] {
+ protected def underlying : java.util.Set;
+ override def isEmpty = super[Set].isEmpty;
+}
diff --git a/src/library/scala/collection/jcl/Sorted.scala b/src/library/scala/collection/jcl/Sorted.scala
new file mode 100644
index 0000000000..5381720141
--- /dev/null
+++ b/src/library/scala/collection/jcl/Sorted.scala
@@ -0,0 +1,43 @@
+package scala.collection.jcl;
+
+/** Any collection (including maps) whose keys (or elements) are ordered.
+ **
+ ** @author Sean McDirmid
+ **/
+trait Sorted[K,A] extends MutableIterable[A] {
+ protected type SortedSelf <: Sorted[K,A];
+
+ /** Returns the first key of the collection. */
+ def first : K;
+ /** Returns the last key of the collection. */
+ def last : K;
+ /** Comparison function that orders keys. */
+ def compare(k0 : K, k1 : K) : Int;
+ /** Creates a ranged projection of this collection. Any mutations in the ranged projection
+ ** will update this collection and vice versa.
+ ** @param from The lower-bound (inclusive) of the ranged projection. None if there is no lower bound.
+ ** @param until The upper-bound (exclusive) of the ranged projection. None if there is no upper bound.
+ **/
+ def rangeImpl(from : Option[K], until : Option[K]) : SortedSelf;
+ /** Creates a ranged projection of this collection with no upper-bound.
+ ** @param from The lower-bound (inclusive) of the ranged projection.
+ **/
+ final def from(from : K) : SortedSelf = rangeImpl(Some(from), None);
+ /** Creates a ranged projection of this collection with no lower-bound.
+ ** @param from The upper-bound (exclusive) of the ranged projection.
+ **/
+ final def until(until : K) : SortedSelf = rangeImpl(None, Some(until));
+ /** Creates a ranged projection of this collection with both a lower-bound and an upper-bound.
+ ** @param from The upper-bound (exclusive) of the ranged projection.
+ **/
+ final def range(from : K, until : K) : SortedSelf = rangeImpl(Some(from),Some(until));
+
+ /** A wrapper around Java comparators. */
+ protected class Comparator[K <% Ordered[K]] extends java.util.Comparator {
+ def compare(x0 : Any, x1 : Any) = {
+ val k0 = x0.asInstanceOf[K];
+ val k1 = x1.asInstanceOf[K];
+ k0.compare(k1);
+ }
+ }
+}
diff --git a/src/library/scala/collection/jcl/SortedMap.scala b/src/library/scala/collection/jcl/SortedMap.scala
new file mode 100644
index 0000000000..968a9887e3
--- /dev/null
+++ b/src/library/scala/collection/jcl/SortedMap.scala
@@ -0,0 +1,78 @@
+package scala.collection.jcl;
+
+/** A map whose keys are sorted.
+ * @author Sean McDirmid
+ */
+trait SortedMap[K,E] extends Map[K,E] with Sorted[K,Tuple2[K,E]] {
+ final protected type SortedSelf = SortedMap[K,E];
+ override def compare(k0 : K, k1 : K) : Int;
+ override def first : K = elements.next._1;
+ override def last : K = {
+ val i = elements;
+ var last : K = i.next._1;
+ while (i.hasNext) last = i.next._1;
+ last;
+ }
+ override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] = Range(from, until);
+ override def keySet : SortedSet[K] = new KeySet;
+ override def pfilter(p : K => Boolean) : SortedMap[K,E] = new Filter(p);
+ override def lense[F](f : E => F, g : F => E) : jcl.SortedMap[K,F] = new Lense[F](f,g);
+
+ protected class Lense[F](f : E => F, g : F => E) extends super.Lense[F](f,g) with SortedMap[K,F] {
+ def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0, k1);
+ override def pfilter(p : K => Boolean) : jcl.SortedMap[K,F] =
+ SortedMap.this.pfilter(p).lense(f, g);
+ override def lense[G](f0 : F => G, g0 : G => F) : jcl.SortedMap[K,G] =
+ SortedMap.this.lense[G]({x:E => f0(f(x))}, {y:G => g(g0(y))});
+ override def rangeImpl(from : Option[K], until : Option[K]) =
+ SortedMap.this.rangeImpl(from,until).lense(f,g);
+ }
+ protected class KeySet extends super.KeySet with SortedSet[K] {
+ def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1);
+ override def first = SortedMap.this.first;
+ override def last = SortedMap.this.last;
+ override def rangeImpl(from : Option[K], until : Option[K]) =
+ SortedMap.this.rangeImpl(from,until).keySet;
+ }
+ protected class SuperFilter(p : K => Boolean) extends super.Filter(p);
+ protected class Filter(p : K => Boolean) extends SuperFilter(p) with SortedMap[K,E] {
+ def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1);
+ override def pfilter(p0 : K => Boolean) : SortedMap[K,E] =
+ SortedMap.this.pfilter(k => p(k) && p0(k));
+
+ override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] =
+ SortedMap.this.Range(from, until).pfilter(p);
+ }
+ protected def Range(from : Option[K], until : Option[K]) : SortedMap[K,E] = new Range(from,until);
+ protected class Range(from : Option[K], until : Option[K]) extends SuperFilter(key => {
+ ((from == None || (compare(from.get,key) <= 0)) &&
+ (until == None || (compare(key,until.get) < 0)));
+ }) with SortedMap[K,E] {
+ def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1);
+ private def contains0(key : K) =
+ (from == None || (compare(from.get,key) <= 0)) &&
+ (until == None || (compare(key,until.get) < 0));
+
+ override def contains(key : K) = SortedMap.this.contains(key) && contains0(key);
+ override def get(key : K) = if (!contains0(key)) None else SortedMap.this.get(key);
+ override def put(key : K, elem : E) = {
+ if (!contains0(key)) throw new IllegalArgumentException;
+ SortedMap.this.put(key, elem);
+ }
+ override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] = {
+ if (this.from != None && from == None) return rangeImpl(this.from, until);
+ if (this.until != None && until == None) return rangeImpl(from, this.until);
+ if (from != None && compare(this.from.get, from.get) > 0) return rangeImpl(this.from, until);
+ if (until != None && compare(this.until.get, until.get) < 0) return rangeImpl(from, this.until);
+ SortedMap.this.Range(from, until);
+ }
+ override def pfilter(p : K => Boolean) : SortedMap[K,E] = new Filter(p);
+ protected class Filter(p : K => Boolean) extends SuperFilter(p) with SortedMap[K,E] {
+ def compare(k0 : K, k1 : K) = Range.this.compare(k0, k1);
+ override def pfilter(p0 : K => Boolean) =
+ Range.this.pfilter(key => p(key) && p0(key));
+ override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] =
+ Range.this.rangeImpl(from,until).pfilter(p);
+ }
+ }
+}
diff --git a/src/library/scala/collection/jcl/SortedMapWrapper.scala b/src/library/scala/collection/jcl/SortedMapWrapper.scala
new file mode 100644
index 0000000000..c96aba9ff9
--- /dev/null
+++ b/src/library/scala/collection/jcl/SortedMapWrapper.scala
@@ -0,0 +1,28 @@
+package scala.collection.jcl;
+
+/** A sorted map that wraps an underlying Java sorted map.
+ * @author Sean McDirmid
+ */
+trait SortedMapWrapper[K,E] extends MapWrapper[K,E] with SortedMap[K,E] {
+ protected override def underlying : java.util.SortedMap;
+ /** the comparator function of this sorted map is defined in terms
+ * of the underlying sorted map's comparator.
+ */
+ def compare(k0 : K, k1 : K) = underlying.comparator.compare(k0,k1);
+ override def first = underlying.firstKey.asInstanceOf[K];
+ override def last = underlying.lastKey.asInstanceOf[K];
+ override def keySet : SortedSet[K] = new KeySet;
+ override protected def Range(from : Option[K], until : Option[K]) = new Range(from,until);
+ protected class Range(from : Option[K], until : Option[K]) extends super.Range(from,until) with SortedMapWrapper[K,E] {
+ val underlying = Tuple2(from,until) match {
+ case Tuple2(None,None) => throw new IllegalArgumentException;
+ case Tuple2(Some(from),None) => SortedMapWrapper.this.underlying.tailMap(from);
+ case Tuple2(None,Some(until)) => SortedMapWrapper.this.underlying.headMap(until);
+ case Tuple2(Some(from),Some(until)) => SortedMapWrapper.this.underlying.subMap(from,until);
+ }
+ override def compare(k0 : K, k1 : K) = super[SortedMapWrapper].compare(k0, k1);
+ }
+ protected class KeySet extends super[SortedMap].KeySet with SetWrapper[K] {
+ protected val underlying = SortedMapWrapper.this.underlying.keySet;
+ }
+}
diff --git a/src/library/scala/collection/jcl/SortedSet.scala b/src/library/scala/collection/jcl/SortedSet.scala
new file mode 100644
index 0000000000..c5d5242e21
--- /dev/null
+++ b/src/library/scala/collection/jcl/SortedSet.scala
@@ -0,0 +1,62 @@
+package scala.collection.jcl;
+/** Analogous to a Java sorted set.
+ * @author Sean McDirmid
+ */
+trait SortedSet[A] extends jcl.Set[A] with Sorted[A,A] {
+ final protected type SortedSelf = SortedSet[A];
+ def compare(a0 : A, a1 : A) : Int;
+ def first : A = {
+ val i = elements;
+ if (i.hasNext) i.next;
+ else throw new NoSuchElementException;
+ }
+ def last : A = {
+ var last : A = null.asInstanceOf[A];
+ val i = elements;
+ while (i.hasNext) last = i.next;
+ if (last == null) throw new NoSuchElementException;
+ else last;
+ }
+ override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = new Range(from, until);
+ override def pfilter(p : A => Boolean) : SortedSet[A] = new Filter(p);
+ protected class Filter(p : A => Boolean) extends super.Filter(p) with SortedSet[A] {
+ def compare(a0 : A, a1 : A) : Int = SortedSet.this.compare(a0, a1);
+ }
+
+ protected class Range(from : Option[A], until : Option[A]) extends Filter(key => {
+ (from == None || (compare(from.get,key) <= 0)) &&
+ (until == None || (compare(key,until.get) < 0));
+ }) with SortedSet[A] {
+ if (from == None && until == None) throw new IllegalArgumentException;
+ if (from != None && until != None && !(SortedSet.this.compare(from.get, until.get) < 0))
+ throw new IllegalArgumentException;
+ override def elements : MutableIterator[A] =
+ new RangeIterator(SortedSet.this.elements.buffered0);
+ private def contains1(key : A) =
+ (from == None || (compare(from.get,key) <= 0)) &&
+ (until == None || (compare(key,until.get) < 0));
+ override def has(elem : A) = contains1(elem) && SortedSet.this.has(elem);
+ override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = {
+ if (this.from != None && from == None) return rangeImpl(this.from, until);
+ if (this.until != None && until == None) return rangeImpl(from, this.until);
+ if (from != None && compare(this.from.get, from.get) > 0) return rangeImpl(this.from, until);
+ if (until != None && compare(this.until.get, until.get) < 0) return rangeImpl(from, this.until);
+ SortedSet.this.rangeImpl(from, until);
+ }
+ class RangeIterator(underlying : MutableIterator[A]#Buffered) extends MutableIterator[A] {
+ if (from != None)
+ underlying.seekNext(a => compare(from.get, a) <= 0);
+
+ private def okNext(a : A) =
+ if (until == None) true;
+ else compare(a, until.get) < 0;
+
+ def hasNext = underlying.hasNext && okNext(underlying.peekNext);
+ def next = underlying.seekNext(okNext) match {
+ case Some(result) => underlying.next; result;
+ case None => throw new NoSuchElementException;
+ }
+ def remove = underlying.remove;
+ }
+ }
+}
diff --git a/src/library/scala/collection/jcl/SortedSetWrapper.scala b/src/library/scala/collection/jcl/SortedSetWrapper.scala
new file mode 100644
index 0000000000..e087af93b8
--- /dev/null
+++ b/src/library/scala/collection/jcl/SortedSetWrapper.scala
@@ -0,0 +1,23 @@
+package scala.collection.jcl;
+
+/** A wrapper around a Java sorted set.
+ ** The comparator of the sorted set matches the comparator of this set.
+ @author Sean McDirmid
+ */
+trait SortedSetWrapper[A] extends SortedSet[A] with SetWrapper[A] {
+ protected def underlying : java.util.SortedSet;
+ /** delegates to the comparator of the underlying Java sorted set */
+ override def compare(a0 : A, a1 : A) = underlying.comparator.compare(a0, a1);
+ override def first = underlying.first.asInstanceOf[A];
+ override def last = underlying.last .asInstanceOf[A];
+ override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = new Range(from,until);
+ protected class Range(from : Option[A], until : Option[A]) extends super.Range(from, until) with SortedSetWrapper[A] {
+ val underlying = Tuple2(from,until) match {
+ case Tuple2(None,Some(until)) => SortedSetWrapper.this.underlying.headSet(until);
+ case Tuple2(Some(from),None) => SortedSetWrapper.this.underlying.tailSet(from);
+ case Tuple2(Some(from),Some(until)) => SortedSetWrapper.this.underlying.subSet(from,until);
+ case _ => throw new IllegalArgumentException;
+ }
+ override def elements : MutableIterator[A] = super[SortedSetWrapper].elements;
+ }
+}
diff --git a/src/library/scala/collection/jcl/Tests.scala b/src/library/scala/collection/jcl/Tests.scala
new file mode 100644
index 0000000000..91f9d34943
--- /dev/null
+++ b/src/library/scala/collection/jcl/Tests.scala
@@ -0,0 +1,66 @@
+package scala.collection.jcl;
+
+private[jcl] object Tests {
+ def main(args : Array[String]) : Unit = {
+ hashSet;
+ treeSet;
+ treeMap;
+ }
+ def treeSet : Unit = {
+ val set = new TreeSet[String];
+ set + "aaa" + "bbb" + "ccc" + "ddd" + "eee" + "fff";
+ Console.println(set);
+ val rset : SortedSet[String] = set.range("b", "e");
+ Console.println(rset);
+ rset + "bad";
+ Console.println(rset);
+ Console.println(set);
+ val fset : SortedSet[String] = rset.pfilter(.endsWith("d"));
+ Console.println(fset);
+ fset += "cd";
+ Console.println(set);
+ set.pmap(.length).retain(x => x == 3);
+ Console.println(set);
+ Console.println(rset);
+ Console.println(fset);
+ }
+ def treeMap : Unit = {
+ val map = new TreeMap[String,Integer];
+ map + ("bb" -> 3) + ("cc" -> 4) + ("aa" -> 2) + ("dd" -> 5);
+ //Console.println(map);
+ val rmap : SortedMap[String,Integer] = map.range("b", "d");
+ rmap + ("bad" -> 10);
+ Console.println(rmap);
+ //Console.println(map);
+ val fmap : SortedMap[String,Integer] = rmap.pfilter(k => k.length == 2);
+ Console.println(fmap);
+
+ }
+
+
+ def hashSet = {
+ val set = new HashSet[String];
+ set + "hello" + "world" + "you" + "to";
+ Console.println(set);
+ val fset = set.pfilter(s => s.length <= 3);
+ Console.println(fset);
+ fset += "xxx";
+ Console.println(set);
+ try {
+ fset += "xxxx";
+ throw new Error;
+ } catch {
+ case e : IllegalArgumentException =>
+ case _ => throw new Error;
+ }
+ val mset : MutableIterable[Int] = set.pmap(s => s.length);
+ Console.println(mset);
+ mset.retain(n => n < 5);
+ Console.println(set);
+ val set1 = new HashSet[String] + "1" + "2" + "3";
+ set ++ (set1);
+ Console.println(set);
+ set.transform(s => "x_" + s);
+ Console.println(set);
+ }
+}
diff --git a/src/library/scala/collection/jcl/TreeMap.scala b/src/library/scala/collection/jcl/TreeMap.scala
new file mode 100644
index 0000000000..06cb3fd341
--- /dev/null
+++ b/src/library/scala/collection/jcl/TreeMap.scala
@@ -0,0 +1,8 @@
+package scala.collection.jcl;
+
+/** A sorted map that is backed by a Java tree map.
+ * @author Sean McDirmid
+ */
+class TreeMap[K <% Ordered[K],E] extends ConcreteMapWrapper[K,E] with SortedMapWrapper[K,E] {
+ val underlying = (new java.util.TreeMap(new Comparator[K]));
+}
diff --git a/src/library/scala/collection/jcl/TreeSet.scala b/src/library/scala/collection/jcl/TreeSet.scala
new file mode 100644
index 0000000000..01cfe5036e
--- /dev/null
+++ b/src/library/scala/collection/jcl/TreeSet.scala
@@ -0,0 +1,10 @@
+package scala.collection.jcl;
+
+/** Creates a sorted set that is backed by an underlying Java tree set. Elements
+ * of the sorted set are ordered with respect to the ordered view bound of A.
+ *
+ * @author Sean McDirmid
+ */
+class TreeSet[A <% Ordered[A]] extends ConcreteWrapper[A] with SortedSetWrapper[A] {
+ val underlying = new java.util.TreeSet(new Comparator[A]);
+}
diff --git a/src/library/scala/collection/jcl/WeakHashMap.scala b/src/library/scala/collection/jcl/WeakHashMap.scala
new file mode 100644
index 0000000000..726ad7407e
--- /dev/null
+++ b/src/library/scala/collection/jcl/WeakHashMap.scala
@@ -0,0 +1,11 @@
+package scala.collection.jcl;
+
+/** A map that is backed by a Java weak hash map, whose keys are maintained as weak references.
+ * Because keys are weak references, the garbage collector can collect them if they are not referred to elsewhere.
+ * Useful for implementing caches.
+ *
+ * @author Sean McDirmid
+ */
+class WeakHashMap[K,E](override val underlying : java.util.WeakHashMap) extends ConcreteMapWrapper[K,E] {
+ def this() = this(new java.util.WeakHashMap);
+}