views:

49

answers:

1

In modeling an audit table, I've included fields necessary to find the original record being audited (oid: String, className: String). I'd like to programmatically find the MetaMapper for the Mapper class name.

For example, if I have:

class Foo extends Mapper[Foo] {
  def getSingleton = Foo
}

object Foo extends Foo with MetaMapper[Foo] {
}

Given the String "Foo", how would I get a reference to the object Foo? Ultimately I want a reference to a MetaMapper so that I can do a findAll. In my Hibernate days I might have found a class using Class.byName(className) and then called a static method on that class.

Here's what I'm using right now to do this, but it does require maintaining a list of MetaMapper objects and also instantiating classes using MetaMapper#create:

case class Audited(name: String, url: Box[String])
def getAudited : Box[Audited] = {
  // OBJECT_OID and OBJECT_TYPE are for the audited record we are trying to find
  (OBJECT_OID.is, OBJECT_TYPE.is) match {
    case (ooid, otype) if List(ooid,otype).forall(s => StringUtils.isNotBlank(s)) => {
      // maintain a list of objects that are metamappers
      val metas = List(Client)
      (for {
        // create a new instance and check its class name
        meta <- metas.find(meta => meta.create.getClass.getName == otype)
        mapper <- meta.find(By(meta.primaryKeyField, ooid))
      } yield {
        val nameFieldNames = List("NAME")
        val name = mapper.allFields.find(f => nameFieldNames.contains(f.name)) match {
          case Some(field) => tryo(field.is.toString).openOr("")
          case _ => mapper.getClass.getName.split(".").last
        }
        Full(Audited(name, Empty))
      }) openOr Empty
    }
    case _ => Empty
  }
}

Which works, but it's ugly IMHO and requires maintenance of a list of supported MetaMappers

+1  A: 

Why not Audited.getSingleton ? It's in every instance of your Mapped class.....

Oh, ok

So you have an audit table, that audits what's changed in some other table. You should be able to convert the classname, and use the same mechanism you used for java. However, why not just have a one to many mapping between an Audited class, and the audit class?

Jim Barrows
Audited is not the MetaMapper. It's just a case class wrapper to hold some other data. For example, one of my Mapper classes is "Client". I would like to get the Client object that extends MetaMapper. I want to do this for any arbitrary name, not just "Client".
Collin
Jim, thanks for the reply. It's a more generalized problem of not necessarily just loading the Mapper class for a particular classname, but how to get a reference to the *object* that is the Mapper class's singleton.
Collin