bitcoin-atm

bitcoin atm for pyc inc.

git clone https://9o.is/git/bitcoin-atm.git

ClientActorBridge.scala

(3576B)


      1 package inc.pyc.lift_akka
      2 
      3 import scala.xml._
      4 import net.liftweb._
      5 import net.liftweb.common._
      6 import net.liftweb.actor._
      7 import net.liftweb.http._
      8 import net.liftweb.http.js._
      9 import net.liftweb.http.js.JE._
     10 import net.liftweb.http.js.JsCmds._
     11 import net.liftweb.json._
     12 import net.liftmodules.extras.JsExtras
     13 import akka.event.{EventBus, LookupClassification}
     14 
     15 /**
     16  * Lift snippet to initiate a comet actor that subscribes to a
     17  * topic in an Akka event bus system. Client-side javascript Actor
     18  * Bridge must have a function with the topic name to receive updates.
     19  */
     20 abstract class EventRegister extends ClientEventPushBridge {
     21   def comet(in: NodeSeq): NodeSeq = connectActorBridge(in)
     22 }
     23 
     24 /**
     25  * Bridge to push messages from akka's event bus system to Actor Bridge in javascript.
     26  * 
     27  * The topic being listened client-side should be the same as the 
     28  * topic in the event bus server-side.
     29  */
     30 trait ClientEventPushBridge extends ClientActorBridge {
     31 
     32   type Receive = PartialFunction[Any, Unit]
     33   
     34   
     35   /**
     36    * The event bus
     37    */
     38   val bus: LiftActorEventBus
     39   
     40   /**
     41    * Callback function after topic subscription of the event bus.
     42    */
     43   val postSubscribe: () => Unit = () => {}
     44   
     45   /**
     46    * The partial function to handle requests 
     47    * coming from the server or client.
     48    */
     49   val receive: Receive = {
     50     case JString(str) =>
     51   }
     52   
     53   protected def connectActorBridge(in: NodeSeq): NodeSeq = 
     54     super.connectActorBridge(topic, in, {
     55       (session, clientProxy) =>        
     56         
     57         val serverActor = new ScopedLiftActor with LiftActorCompare {
     58           override def lowPriority = receive orElse {
     59             case event =>
     60               clientProxy ! event
     61           }
     62         }
     63       
     64         bus.subscribe(serverActor, topic)
     65         postSubscribe()
     66         serverActor
     67   }) 
     68 }
     69 
     70 /**
     71  * The bridge between ActorBridge in javascript and server-side actors.
     72  */
     73 trait ClientActorBridge extends Logger {
     74   
     75   /**
     76    * Topic (or function) to execute client-side.
     77    */
     78   val topic: String
     79 
     80   /**
     81    * Connects a given `ScopedLiftActor` to the given function name listening from 
     82    * the client-side Actor Bridge.
     83    */
     84   protected def connectActorBridge(topic: String, in: NodeSeq, f: (LiftSession, LiftActor) => ScopedLiftActor): NodeSeq = 
     85     (for (sess <- S.session) yield {
     86       val className = this.getClass.getName.split("""\.""").last
     87       val instaName = lowercase(className)
     88       
     89       val clientProxy = sess.serverActorForClient(s"window.$instaName.apply")
     90       val serverActor: ScopedLiftActor = f(sess, clientProxy)
     91 
     92       S.appendJs(SetExp(JsVar(s"window.$instaName"),
     93       JsExtras.CallNew(s"window.$className", sess.clientActorFor(serverActor)) ))
     94 
     95       in
     96     }) openOr NodeSeq.Empty
     97   
     98   private def lowercase(s: String): String = s(0).toLower + s.substring(1)
     99 }
    100 
    101 
    102 /**
    103  * Message to update `LiftActorEventBus`.
    104  */
    105 case class EventUpdate(topic: String, payload: Any)
    106 
    107 /**
    108  * Bridge between Akka's event bus and Lift actors.
    109  */
    110 abstract class LiftActorEventBus extends EventBus with LookupClassification {
    111   type Event = EventUpdate
    112   type Classifier = String
    113   type Subscriber = LiftActorCompare
    114 
    115   override protected def classify(event: Event): Classifier = event.topic
    116 
    117   override protected def publish(event: Event, subscriber: Subscriber): Unit = {
    118     subscriber ! event.payload
    119   }
    120   
    121   override protected def compareSubscribers(a: Subscriber, b: Subscriber): Int = 
    122     a.compareTo(b)
    123 }
    124 
    125 trait LiftActorCompare extends LiftActor with java.lang.Comparable[LiftActor] {
    126   override def compareTo(a: LiftActor): Int = -1
    127 }