From a8722061eee0cb300a32ea30484a267ec6004368 Mon Sep 17 00:00:00 2001 From: Matthias Zenger Date: Wed, 25 Jun 2003 10:50:11 +0000 Subject: Support files for the Publish/Subscriber mechan... Support files for the Publish/Subscriber mechanism; this set of files implements, in particular, a rollback mechanism for any collection type. The mechanism is designed that it can consistently reset a whole set of containers to a consistent state. --- sources/scala/History.scala | 36 +++++++++++++++++++++++++++++++ sources/scala/Inclusion.scala | 13 ++++++++++++ sources/scala/Modification.scala | 13 ++++++++++++ sources/scala/ObservableMap.scala | 40 +++++++++++++++++++++++++++++++++++ sources/scala/ObservableUpdate.scala | 13 ++++++++++++ sources/scala/Removal.scala | 13 ++++++++++++ sources/scala/Reset.scala | 13 ++++++++++++ sources/scala/RevertableHistory.scala | 25 ++++++++++++++++++++++ sources/scala/Undo.scala | 15 +++++++++++++ 9 files changed, 181 insertions(+) create mode 100644 sources/scala/History.scala create mode 100644 sources/scala/Inclusion.scala create mode 100644 sources/scala/Modification.scala create mode 100644 sources/scala/ObservableMap.scala create mode 100644 sources/scala/ObservableUpdate.scala create mode 100644 sources/scala/Removal.scala create mode 100644 sources/scala/Reset.scala create mode 100644 sources/scala/RevertableHistory.scala create mode 100644 sources/scala/Undo.scala diff --git a/sources/scala/History.scala b/sources/scala/History.scala new file mode 100644 index 0000000000..115fb850dc --- /dev/null +++ b/sources/scala/History.scala @@ -0,0 +1,36 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +** $Id$ +\* */ + +package scala; + + +/** History[A, B] objects may subscribe to events of + * type A published by an object of type B. + * The history subscriber object records all published events + * up to maximum number of maxHistory events. + */ +class History[A, B] with Subscriber[A, B] { + + protected val log: Queue[Pair[B, A]] = new Queue[Pair[B, A]]; + + val maxHistory: Int = 32000; + + def update(pub: B, event: A): Unit = { + if (log.length >= maxHistory) { + val old = log.dequeue; + } + log.enqueue(Pair(pub, event)); + } + + def getHistory: Iterator[Pair[B, A]] = log.toList.elements; + + def historySize: Int = log.length; + + def clear: Unit = log.clear; +} diff --git a/sources/scala/Inclusion.scala b/sources/scala/Inclusion.scala new file mode 100644 index 0000000000..52ee525d08 --- /dev/null +++ b/sources/scala/Inclusion.scala @@ -0,0 +1,13 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +** $Id$ +\* */ + +package scala; + + +case class Inclusion[A](elem: A) extends ObservableUpdate[A]; diff --git a/sources/scala/Modification.scala b/sources/scala/Modification.scala new file mode 100644 index 0000000000..4da13bd61a --- /dev/null +++ b/sources/scala/Modification.scala @@ -0,0 +1,13 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +** $Id$ +\* */ + +package scala; + + +case class Modification[A](old: A, nu: A) extends ObservableUpdate[A]; diff --git a/sources/scala/ObservableMap.scala b/sources/scala/ObservableMap.scala new file mode 100644 index 0000000000..420a0feeaa --- /dev/null +++ b/sources/scala/ObservableMap.scala @@ -0,0 +1,40 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +** $Id$ +\* */ + +package scala; + + +abstract class ObservableMap[A, B, This <: ObservableMap[A, B, This]]: This + extends MutableMap[A, B] + with Publisher[ObservableUpdate[Pair[A, B]] with Undo, This] { + + override def update(key: A, value: B): Unit = get(key) match { + case None => super.update(key, value); + publish(new Inclusion(Pair(key, value)) with Undo { + def undo = remove(key); + }); + case Some(old) => super.update(key, value); + publish(new Modification(Pair(key, old), Pair(key, value)) with Undo { + def undo = update(key, old._2); + }); + } + + override def remove(key: A): Unit = get(key) match { + case None => + case Some(old) => super.remove(key); + publish(new Removal(Pair(key, old)) with Undo { + def undo = update(key, old); + }); + } + + override def clear: Unit = { + super.clear; + publish(new Reset() with Undo { def undo = error("cannot undo"); }); + } +} diff --git a/sources/scala/ObservableUpdate.scala b/sources/scala/ObservableUpdate.scala new file mode 100644 index 0000000000..fabe049f40 --- /dev/null +++ b/sources/scala/ObservableUpdate.scala @@ -0,0 +1,13 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +** $Id$ +\* */ + +package scala; + + +trait ObservableUpdate[+A]; diff --git a/sources/scala/Removal.scala b/sources/scala/Removal.scala new file mode 100644 index 0000000000..37b062709e --- /dev/null +++ b/sources/scala/Removal.scala @@ -0,0 +1,13 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +** $Id$ +\* */ + +package scala; + + +case class Removal[A](elem: A) extends ObservableUpdate[A]; diff --git a/sources/scala/Reset.scala b/sources/scala/Reset.scala new file mode 100644 index 0000000000..b458560251 --- /dev/null +++ b/sources/scala/Reset.scala @@ -0,0 +1,13 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +** $Id$ +\* */ + +package scala; + + +case class Reset[A]() extends ObservableUpdate[A]; diff --git a/sources/scala/RevertableHistory.scala b/sources/scala/RevertableHistory.scala new file mode 100644 index 0000000000..760f5dcea6 --- /dev/null +++ b/sources/scala/RevertableHistory.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +** $Id$ +\* */ + +package scala; + + +/** Subscriber[-A, -B] objects may subscribe to events of + * type A published by an object of type B. + */ +class RevertableHistory[A <: Undo, B] extends History[A, B] with Undo { + + def undo: Unit = { + val old = log.toList.reverse; + clear; + old.foreach { + case Pair(sub, event) => event.undo; + } + } +} diff --git a/sources/scala/Undo.scala b/sources/scala/Undo.scala new file mode 100644 index 0000000000..4349851e5a --- /dev/null +++ b/sources/scala/Undo.scala @@ -0,0 +1,15 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +** $Id$ +\* */ + +package scala; + + +trait Undo { + def undo: Unit; +} -- cgit v1.2.3