src/Pure/General/multi_map.scala
author wenzelm
Sat, 09 Nov 2013 18:00:36 +0100
changeset 54381 9c1f21365326
parent 52975 457c006f91bb
child 55488 60c159d490a2
permissions -rw-r--r--
tuned;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/General/multi_map.scala
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     2
    Module:     PIDE
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     3
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     4
Maps with multiple entries per key.
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     5
*/
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     6
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     7
package isabelle
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     8
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     9
import scala.collection.generic.{ImmutableMapFactory, CanBuildFrom}
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    10
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    11
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    12
object Multi_Map extends ImmutableMapFactory[Multi_Map]
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    13
{
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    14
  private val empty_val: Multi_Map[Any, Nothing] = new Multi_Map[Any, Nothing](Map.empty)
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    15
  override def empty[A, B] = empty_val.asInstanceOf[Multi_Map[A, B]]
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    16
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    17
  implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), Multi_Map[A, B]] =
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    18
    new MapCanBuildFrom[A, B]
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    19
}
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    20
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    21
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    22
final class Multi_Map[A, +B] private(rep: Map[A, List[B]])
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    23
  extends scala.collection.immutable.Map[A, B]
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    24
  with scala.collection.immutable.MapLike[A, B, Multi_Map[A, B]]
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    25
{
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    26
  /* Multi_Map operations */
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    27
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    28
  def get_list(a: A): List[B] = rep.getOrElse(a, Nil)
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    29
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    30
  def insert[B1 >: B](a: A, b: B1): Multi_Map[A, B1] =
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    31
  {
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    32
    val bs = get_list(a)
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    33
    if (bs.contains(b)) this
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    34
    else new Multi_Map(rep + (a -> (b :: bs)))
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    35
  }
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    36
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    37
  def remove[B1 >: B](a: A, b: B1): Multi_Map[A, B1] =
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    38
  {
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    39
    val bs = get_list(a)
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    40
    if (bs.contains(b)) {
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    41
      bs.filterNot(_ == b) match {
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    42
        case Nil => new Multi_Map(rep - a)
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    43
        case bs1 => new Multi_Map(rep + (a -> bs1))
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    44
      }
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    45
    }
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    46
    else this
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    47
  }
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    48
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    49
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    50
  /* Map operations */
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    51
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    52
  override def stringPrefix = "Multi_Map"
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    53
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    54
  override def empty = Multi_Map.empty
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    55
  override def isEmpty: Boolean = rep.isEmpty
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    56
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    57
  override def keySet: Set[A] = rep.keySet
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    58
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    59
  override def iterator: Iterator[(A, B)] =
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    60
    for ((a, bs) <- rep.iterator; b <- bs.iterator) yield (a, b)
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    61
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    62
  def get(a: A): Option[B] = get_list(a).headOption
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    63
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    64
  def + [B1 >: B](p: (A, B1)): Multi_Map[A, B1] = insert(p._1, p._2)
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    65
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    66
  def - (a: A): Multi_Map[A, B] =
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    67
    if (rep.isDefinedAt(a)) new Multi_Map(rep - a) else this
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    68
}