/* CookieJarMap implementation of the CookieJar ADT H. Conrad Cunningham Version #1: 15 March 2010 Version #1a: 22 March 2010 Correct Implementation Invariant statement 123456789012345678901234567890123456789012345678901234567890123456789012345678 */ import scala.collection.mutable._ /* Class CookieJarMap implements the CookieJar ADT using Scala's default mutable Map (which is a HashMap) to implement the jar (mathematical bag) of cookies. The keys of the Map are the cookie types and the value is the count of cookies of that type in the jar. If the count is zero, then that key does not appear in the map. IMPLEMENTATION INVARIANT: (ForAll c, i : c IN CookieType && i IN Int :: i == OCCURRENCES(c,Bag) <=> ( (i > 0 => jar(c) = i) && (i == 0 => !jar.contains(c))) ) */ class CookieJarMap[CookieType] extends CookieJar[CookieType] { // CookieJar's bag model is implemented by Map jar. private val jar = Map[CookieType,Int]() def putIn(cookie: CookieType) { if (jar.contains(cookie)) jar(cookie) += 1 else jar(cookie) = 1 } def eat(cookie: CookieType) { if (jar.contains(cookie)) { if (jar(cookie) > 1) jar(cookie) -= 1 else jar -= cookie } else throw new RuntimeException( "Attempt to eat cookie \"" + cookie + "\", which is not in the jar.") } def isEmpty: Boolean = jar.isEmpty def has(cookie: CookieType): Boolean = jar.contains(cookie) /* Redefine toString to return form "CookieJar(e1,e2,e3,...,en)" with all elements of bag in arbitrary order. */ override def toString = "CookieJar(" + jarList.mkString(",") + ")" /* Private method jarList converts the map jar to a list with with appropriate duplicates. */ private def jarList: List[CookieType] = for ((k,c) <- jar.toList; i <- 1 to c) yield k }