Hi again,
I've been working a little bit on this feature, and I wanted to share
the first draft, which is, beware, not working correctly in some
cases:
First I changed, as you said, the Versioned trait to:
trait Versioned {
def transactionId: Long
def historyEventType: HistoryEventType.Value
def versionNumber: Int
}
Second I added a little helper method to create a TransactionTable.
This table is not mandatory to get the different versions of the
entities, but helps keep the changes grouped:
def findTransactionTable =
_tables.find(_.isInstanceOf[TransactionTable[_]])
def transactionTable[A <: KeyedEntity[Long]](builder: () => A)
(implicit mA: Manifest[A]) = {
val t = new TransactionTable[A](tableNameFromClass(mA.erasure),
mA.erasure.asInstanceOf[Class[A]], this, None, builder)
_addTable(t)
t
}
and now the bigger part in Table:
class TransactionTable[A <: KeyedEntity[Long]](n: String, c: Class[A],
schema: Schema, _prefix: Option[String], val builder: () => A)
extends Table[A](n,c,schema, _prefix) {
}
class VersionedTable[A,B <: Versioned](n: String, c: Class[A], schema:
Schema, _prefix: Option[String], val history: Table[B])
extends Table[A](n,c,schema, _prefix) {
override def insert(t: A): A = {
super.insert(t)
history.insert(createVersion(t, HistoryEventType.Created))
t
}
override def insert(e: Iterable[A]):Unit = {
super.insert(e)
val versions = e.map(a => createVersion(a,
HistoryEventType.Created))
history.insert(versions)
}
override def update(o: A)(implicit ev: <:<[A, KeyedEntity[_]]) {
super.update(o)
history.insert(createVersion(o, HistoryEventType.Updated))
}
private def createVersion(a: A, historyEventType:
HistoryEventType.Value):B = {
val copy = history._createInstanceOfRowObject.asInstanceOf[B]
val fmds = history.posoMetaData.fieldsMetaData.map(fmd =>
Pair(fmd, posoMetaData.fieldsMetaData.find(_.nameOfProperty ==
fmd.nameOfProperty)))
fmds.foreach({case(hfmd, fmd) => (fmd.foreach(f => hfmd.set(copy,
f.get(a.asInstanceOf[AnyRef]))))})
val tid =
history.posoMetaData.fieldsMetaData.find(_.nameOfProperty ==
"transactionId")
tid.foreach(_.set(copy, new java.lang.Long(transactionId)))
val het =
history.posoMetaData.fieldsMetaData.find(_.nameOfProperty ==
"historyEventType")
het.foreach(_.set(copy, new Integer(historyEventType.id)))
copy
}
private def transactionId = {
schema.findTransactionTable match {
case Some(t:TransactionTable[_]) =>
Session.currentSession.transactionId match {
case Some(id) => id
case _ => {
val tid = t.insert(t.builder())
Session.currentSession.transactionId = Some(
tid.id)
tid.id
}
}
case _ => 0l
}
}
}
Here I implemented the logic to insert the different versions of the
entities in their VersionTable.
This works pretty well, but for insert(e: Iterable[A]):Unit !!
The problem here is that the id of the entities inserted is not
updated, so that the versions always get 0 in their id field !!
Perhaps you know what to do, to get this working?
To use transactions you only need to add a TransactionTable into your
schema:
val transactions = transactionTable[Transaction] (() =>
new Transaction(0l, new Date, "testuser")
)
Transaction only has to be a KeyedEntity[Long] and you can add
whatever other fields you please.
The builder is used to create the new transaction rows......
What do you think?
Am I going in the right direction??
Thanks for your thoughts!
Roll