Skip to content

Instantly share code, notes, and snippets.

@pr1001
Created February 10, 2011 11:29
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 pr1001/820356 to your computer and use it in GitHub Desktop.
Save pr1001/820356 to your computer and use it in GitHub Desktop.
A grammar-based event logging system in Scala using Lift's Mapper ORM. See the following blog post of a conceptual explanation: http://www.bubblefoundry.com/blog/2010/08/grammar-based-event-logging/
package com.mobtest {
package model {
import net.liftweb.mapper._
import net.liftweb.common.{Box, Full, Empty}
class Event extends LongKeyedMapper[Event] with IdPK with CreatedUpdated {
def getSingleton = Event // companion object
object subject extends MappedLong(this)
object verb extends MappedString(this, 64) {
override def dbIndexed_? = true
}
object directobject extends MappedLong(this) // ie the major object
object indirectobject extends MappedLong(this) // ie the minor object
def toCC = Event.convert(this)
}
object Event extends Event with LongKeyedMetaMapper[Event] {
// override def fieldOrder = List(subject, verb, directobject, indirectobject)
val BaseEventKey = "BaseEvent"
val UnknownEventKey = "UnknownEvent"
val AccountCreatedKey = "AccountCreated"
def convert(event: Event) = event.verb.is match {
case BaseEventKey => BaseEvent(event.createdAt.is.getTime, Full(event.id))
case UnknownEventKey => UnknownEvent(event.createdAt.is.getTime, Full(event.id))
case AccountCreatedKey => AccountCreated(event.subject.is, event.createdAt.is.getTime, Full(event.id))
case _ => UnknownEvent(event.createdAt.is.getTime, Full(event.id))
}
}
// base event has a millisecond timestamp
case class BaseEvent(timestamp: Long, id: Box[Long]) {
def subject: Box[Long] = Empty
def verb: Box[String] = Full(Event.BaseEventKey)
def directobject: Box[Long] = Empty
def indirectobject: Box[Long] = Empty
def toEvent: Event = {
val e = id.flatMap(Event.findByKey(_)) openOr Event.create
e.createdAt(new java.util.Date(timestamp))
// optional values
subject.foreach(s => e.subject(s))
verb.foreach(v => e.verb(v))
directobject.foreach(d => e.directobject(d))
indirectobject.foreach(i => e.indirectobject(i))
// return the Event
e
}
def save: Boolean = this.toEvent.save
}
// Catch-all for when we can't match to a more specific event
case class UnknownEvent(override val timestamp: Long, override val id: Box[Long]) extends BaseEvent(timestamp, id) {
override def verb = Full(Event.UnknownEventKey)
}
// account creation events
// user created own account at time
case class AccountCreated(user: Long, override val timestamp: Long, override val id: Box[Long]) extends BaseEvent(timestamp, id) {
override def subject = Full(user)
override def verb = Full(Event.AccountCreatedKey)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment