Skip to content

Instantly share code, notes, and snippets.

@makotan
Created January 9, 2012 12:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save makotan/1582844 to your computer and use it in GitHub Desktop.
Save makotan/1582844 to your computer and use it in GitHub Desktop.
簡易ワークステートエンジン
package sburi
import scala.collection.mutable.MapBuilder
trait PersistentPlugin[Entity,IdType] {
def setStatus(e :Entity , state : String)
def save(e :Entity)
def getStatus(e :Entity) :Option[String]
def get(id:IdType) : Option[Entity]
}
abstract class BuriBuilder(val processName: String) {
import scala.collection.mutable.ListBuffer
import scala.collection.mutable.MapBuilder
private val transitions = new ListBuffer[Transition]
private val activitis = new MapBuilder[String,Activity,Map[String,Activity]](Map.empty)
private val startActivityNames = new ListBuffer[String]
type IdType
type Entity
val persistent :PersistentPlugin[Entity,IdType]
private def addActivities(a:Activity) {
activitis += ( a.activityName -> a )
a match {
case s:StartActivity =>
startActivityNames += s.activityName
case _ =>
}
}
def += (t:Transit) = {
transitions += t
addActivities(t.preAct)
addActivities(t.nextAct)
}
def += (t:TransitSelection[Entity]) = {
transitions += t
addActivities(t.preAct)
t.nextList.map{ addActivities }
}
def buildBuri() : Buri[Entity,IdType] = {
new Buri(transitions.toList,
persistent,
activitis.result() ,
startActivityNames.toList)
}
}
class Buri[Entity,IdType](
transitions: List[Transition],
persistent :PersistentPlugin[Entity,IdType],
activitis :Map[String,Activity],
startActivityNames: List[String]) {
def entry(e:Entity) : Unit = {
entry(e,None)
}
def entry(e:Entity,status:String) : Unit = {
entry(e,Some(status))
}
def toNextStatus(e:Entity) : Unit = {
toNextStatus(e,None,None)
}
def toNextStatus(e:Entity,action:String,currentStatus:List[String]) : Unit = {
toNextStatus(e,Some(action),Some(currentStatus))
}
def toNextStatus(e:Entity,action:String) : Unit = {
toNextStatus(e,Some(action),None)
}
def toNextStatus(e:Entity,currentStatus:List[String]) : Unit = {
toNextStatus(e,None,Some(currentStatus))
}
protected def entry(e:Entity,status:Option[String]) : Unit = {
val newStatus = status match {
case None =>
startActivityNames.size match {
case 1 =>
startActivityNames(0)
case size => throw new BuriSetupException("entry status required . startActivityNames.size is " + size );
}
case Some(s) => s
}
getStatus(e) match {
case None => toNextStatus(e ,None, newStatus)
case Some(s) =>
if(s == newStatus) {
toNextStatus(e ,None, newStatus)
} else {
throw new BuriSetupException("entity status("+s+") . use entity is None status")
}
}
}
protected def toNextStatus(e:Entity,action:Option[String],currentStatus:Option[List[String]]) : Unit = {
val currentStateName = getStatus(e) match {
case None => throw new BuriSetupException("not has Status")
case Some(s) => currentStatus match {
case None => s
case Some(list) =>
list filter{ls => s == ls} size match {
case 0 => throw new BuriSetupException("current status list not hit ")
case 1 => s
case size => throw new BuriSetupException("current status over match")
}
}
}
toNextStatus(e,action,currentStateName)
}
protected def toNextStatus(e:Entity,action:Option[String],currentStateName:String) : Unit = {
val startTransition = getActNameToTransition(currentStateName) match {
case None => return
case Some(tr) => tr
}
processAct(e , action , startTransition)
}
protected def getActNameToTransition(actName : String) : Option[Transition] = {
val startTransitions = activitis.get(actName) match {
case None => throw new BuriSetupException("status name is not activity")
case Some(act) => transitions filter{ _.preAct.activityName == act.activityName }
}
startTransitions size match {
case 0 => activitis.get(actName) match {
case act: EndActivity => None
case _ => throw new BuriSetupException("transition is not find startActivity " + actName)
}
case 1 => Some(startTransitions.head)
case size => throw new BuriSetupException("transition many find startActivity " + actName)
}
}
// @scala.annotation.tailrec
protected def processAct(e:Entity , action: Option[String] , tr: Transition) {
val nextAct = tr match {
case t : Transit => t.nextAct
case t : TransitSelection[Entity] =>
val nextAct = t.f(e,action)
t.nextList filter( _ == nextAct ) size match {
case 1 => nextAct
case _ => throw new BuriSetupException("TransitSelection is not targetList")
}
}
nextAct match {
case p: Procedure[Entity] => p.process( e )
case _ =>
}
nextAct match {
case s: Status =>
persistent.setStatus(e,s.activityName)
return
case _ =>
}
getActNameToTransition(nextAct.activityName) match {
case None => ""
case Some(trans) => processAct(e , action , trans)
}
}
def delete(e:Entity) = {
val sname = persistent.getStatus(e) match {
case None => throw new BuriException("not status name")
case Some(sname) => sname
}
val act = activitis.get(sname)
act match {
case Some(a) => a match {
case a: UseDelete =>
persistent.setStatus(e,"Delete")
persistent.save(e)
case _ => throw new BuriException("non delete Activity")
}
case None => throw new BuriException("non delete Activity")
}
}
def update(e:Entity) = {
val sname = persistent.getStatus(e) match {
case None => throw new BuriException("not status name")
case Some(sname) => sname
}
val act = activitis.get(sname)
act match {
case Some(a) => a match {
case a: UseUpdate => persistent.save(e)
case _ => throw new BuriException("non update Activity")
}
case None => throw new BuriException("non update Activity")
}
}
def getStatus(e:Entity) : Option[String] = persistent.getStatus(e)
}
class BuriException(msg:String) extends Exception(msg)
class BuriSetupException(msg:String) extends BuriException(msg)
trait Status
trait UseUpdate
trait UseDelete extends Status
trait Procedure[Entity] {
def process(entity: Entity) {}
}
class Activity(val activityName: String)
class StartActivity(activityName: String) extends Activity(activityName)
class EndActivity(activityName: String) extends Activity(activityName) with Status
object Activity {
def apply(actName:String) = new Activity(actName)
}
object StartActivity {
def apply(actName:String) = new StartActivity(actName)
}
object EndActivity {
def apply(actName:String) = new EndActivity(actName)
}
trait Transition {
val preAct:Activity
}
class Transit(val preAct:Activity , val nextAct:Activity) extends Transition
class TransitSelection[Entity](val preAct:Activity , val nextList:List[Activity] ,val f : (Entity,Option[String]) => Activity) extends Transition
class TransitBuilder(preAct:Activity) {
var nextList:List[Activity] = List()
def -> (nextAct:Activity) = new Transit(preAct,nextAct)
def ->(list:List[Activity]) : TransitBuilder = {
nextList = list
this
}
def >>[Entity] (f : (Entity,Option[String]) => Activity) = new TransitSelection(preAct,nextList,f)
}
object TransitBuilder {
implicit def activiyToTransitBuilder(preAct:Activity) = new TransitBuilder(preAct)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment