Created
January 9, 2012 12:59
-
-
Save makotan/1582844 to your computer and use it in GitHub Desktop.
簡易ワークステートエンジン
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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