/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
// $Id$
package scala.collection.mutable
import Predef._
//import Predef.UnsupportedOperationException
/** This class represents mutable maps. Concrete map implementations
* just have to provide functionality for the abstract methods in
* <code>scala.collection.Map</code> as well as for <code>update</code>,
* and <code>-=</code>.
*
* @author Matthias Zenger
* @author Martin Odersky
* @version 2.0, 31/12/2006
*/
object Map {
/** The empty map of this type; this is implemented as a hashtable */
def empty[A, B] = new HashMap[A, B]
/** The canonical factory for this type
*/
def apply[A, B](elems: Pair[A, B]*) = empty[A, B] ++ elems
}
[cloneable]
trait Map[A, B] extends AnyRef
with collection.Map[A, B]
with Scriptable[Message[Pair[A, B]]]
{
/** This method allows one to add a new mapping from <code>key</code>
* to <code>value</code> to the map. If the map already contains a
* mapping for <code>key</code>, it will be overridden by this
* function.
*
* @param key The key to update
* @param value The new value
*/
def update(key: A, value: B)
/** Add a key/value pair to this map.
* @param kv the key/value pair.
*/
def += (kv: Pair[A, B]) { update(kv._1, kv._2) }
/** Add two or more key/value pairs to this map.
* @param kv1 the first key/value pair.
* @param kv2 the second key/value pair.
* @param kvs the remaining key/value pairs.
*/
def += (kv1: Pair[A, B], kv2: Pair[A, B], kvs: Pair[A, B]*) { this += kv1; this += kv2; this ++= kvs }
/** Add a sequence of key/value pairs to this map.
* @param kvs the iterable object containing all key/value pairs.
*/
def ++= (kvs: Iterable[Pair[A, B]]) { this ++= kvs.elements }
/** Add a sequence of key/value pairs to this map.
* @param kvs the iterator containing all key/value pairs.
*/
def ++= (kvs: Iterator[Pair[A, B]]) { kvs foreach += }
/** Add a key/value pair to this map.
* @param kv the key/value pair.
* @return The map itself with the new binding added in place.
*/
def + (kv: Pair[A, B]): Map[A, B] = { this += kv; this }
/** Add two or more key/value pairs to this map.
* @param kv1 the first key/value pair.
* @param kv2 the second key/value pair.
* @param kvs the remaining key/value pairs.
* @return The map itself with the new bindings added in place.
*/
def + (kv1: Pair[A, B], kv2: Pair[A, B], kvs: Pair[A, B]*): Map[A, B] = {
this.+=(kv1, kv2, kvs: _*); this
}
/** Add a sequence of key/value pairs to this map.
* @param kvs the iterable object containing all key/value pairs.
* @return The itself map with the new bindings added in place.
*/
def ++ (kvs: Iterable[Pair[A, B]]): Map[A, B] = { this ++= kvs; this }
/** Add a sequence of key/value pairs to this map.
* @param kvs the iterator containing all key/value pairs.
* @return The itself map with the new bindings added in place.
*/
def ++ (kvs: Iterator[Pair[A, B]]): Map[A, B] = { this ++= kvs; this }
/** Remove a key from this map, noop if key is not present.
* @param key the key to be removed
*/
def -= (key: A)
/** Remove two or more keys from this map
* @param key1 the first key to be removed
* @param key2 the second key to be removed
* @param keys the remaining keys to be removed
*/
def -= (key1: A, key2: A, keys: A*) { this -= key1; this -= key2; this --= keys }
/** Remove a sequence of keys from this map
* @param keys the keys to be removed
*/
def --= (keys: Iterable[A]) { this --= keys.elements }
/** Remove a sequence of keys from this map
* @param keys the keys to be removed
*/
def --= (keys: Iterator[A]) { keys foreach -= }
/** Remove a key from this map
* @param key the key to be removed
* @return The map itself with the binding for <code>key</code> removed if
* it existed.
*/
def - (key: A): Map[A, B] = { this -= key; this }
/** Remove two or more keys from this map
* @param key1 the first key to be removed
* @param key2 the second key to be removed
* @param keys the remaining keys to be removed
* @return The map itself with all bindings for the given keys removed.
*/
def - (key1: A, key2: A, keys: A*): Map[A, B] = { this.-=(key1, key2, keys: _*); this }
/** Remove a sequence of keys from this map
* @param keys the keys to be removed
* @return The map itself with all bindings for <code>keys</code> removed.
*/
def -- (keys: Iterable[A]): Map[A, B] = { this --= keys; this }
/** Remove a sequence of keys from this map
* @param keys the keys to be removed
* @return The map itself with all bindings for <code>keys</code> removed.
*/
def -- (keys: Iterator[A]): Map[A, B] = { this --= keys; this }
/** Removes all mappings from the map. After this operation is
* completed, the map is empty.
*/
def clear(): Unit = keys foreach -=
/** This function transforms all the values of mappings contained
* in this map with function <code>f</code>.
*
* @param f The transformation to apply
*/
def transform(f: (A, B) => B) {
elements foreach {
case Pair(key, value) => update(key, f(key, value))
}
}
/** This method retains only those mappings for which the predicate
* <code>p</code> returns <code>true</code>.
*
* @param p The test predicate
*/
def retain(p: (A, B) => Boolean): Unit = toList foreach {
case Pair(key, value) => if (!p(key, value)) -=(key)
}
/** Send a message to this scriptable object.
*
* @param cmd the message to send.
*/
def <<(cmd: Message[Pair[A, B]]): Unit = cmd match {
case Include(Pair(k, v)) => update(k, v)
case Update(Pair(k, v)) => update(k, v)
case Remove(Pair(k, _)) => this -= k
case Reset() => clear
case s: Script[_] => s.elements foreach <<
case _ => throw new UnsupportedOperationException("message " + cmd + " not understood")
}
/** Return a clone of this map.
*
* @return a map with the same elements.
*/
override def clone(): Map[A, B] = super.clone().asInstanceOf[Map[A, B]]
/** This method defines syntactic sugar for adding or modifying
* mappings. It is typically used in the following way:
* <pre>
* map += key -> value;
* </pre>
* @deprecated use <code>+={key, value}</code>
*/
[deprecated] def +=(key: A): MapTo = new MapTo(key)
/** <code>incl</code> can be used to add many mappings at the same time
* to the map. The method assumes that a mapping is represented
* by a <code>Pair</code> object who's first component denotes the
* key, and who's second component refers to the value.
*
* @param mappings
* @deprecated use <code>+=</code>
*/
[deprecated] def incl(mappings: Pair[A, B]*): Unit = this ++= mappings.elements
/** This method will remove all the mappings for the given sequence
* of keys from the map.
*
* @param keys
* @deprecated use <code>-=</code>
*/
[deprecated] def excl(keys: A*): Unit = this --= keys.elements
/** This method removes all the mappings for which the predicate
* <code>p</code> returns <code>false</code>.
*
* @deprecated use retain instead
* @param p
*/
[deprecated] override def filter(p: Pair[A, B] => Boolean): Iterable[Pair[A, B]] = {
toList foreach {
case kv @ Pair(key, _) => if (!p(kv)) -=(key)
}
this
}
[deprecated] class MapTo(key: A) {
def ->(value: B): Unit = update(key, value)
}
}