summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/scala/com/google/gimd/UserType.scala87
-rw-r--r--src/test/scala/com/google/gimd/UserTypeTestCase.scala41
-rw-r--r--src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala13
-rw-r--r--src/test/scala/com/google/gimd/jgit/JGitFileTestCase.scala13
-rw-r--r--src/test/scala/com/google/gimd/modification/ModificationTestCase.scala13
-rw-r--r--src/test/scala/com/google/gimd/query/MessageQueryTestCase.scala11
6 files changed, 140 insertions, 38 deletions
diff --git a/src/main/scala/com/google/gimd/UserType.scala b/src/main/scala/com/google/gimd/UserType.scala
index a5fb242..9bf08b1 100644
--- a/src/main/scala/com/google/gimd/UserType.scala
+++ b/src/main/scala/com/google/gimd/UserType.scala
@@ -24,11 +24,90 @@ abstract class UserType[T] {
def toUserObject(itr: Message): T
def toMessage(obj: T) = toMessageBuffer(obj).readOnly
- def toMessageBuffer(obj: T): MessageBuffer = new MessageBuffer ++ fields.map {
- case FieldSpec(name, f1, f2) => f1(name, f2(obj))
- }
+ def toMessageBuffer(obj: T): MessageBuffer =
+ new MessageBuffer ++ fields.flatMap(fieldSpec2Field(obj, _).toList)
def fields: List[FieldSpec[T, _]]
def children: Seq[NestedMember[_]] = Seq()
+
+ protected final def FieldSpecOne[F](name: String, f1: (String, F) => Field, f2: T => F) =
+ new FieldSpecOne(name, f1, f2)
+
+ protected final def FieldSpecOption[F](name: String, f1: (String, F) => Field, f2: T => F,
+ default: F) = new FieldSpecOption(name, f1, f2, default)
+
+ private def fieldSpec2Field[F](obj: T, x: FieldSpec[T, F]) =
+ x.fieldFactoryOption(x.name, x.f2(obj))
}
-case class FieldSpec[T, F](name: String, f1: (String, F) => Field, f2: T => F)
+object UserType {
+ implicit def fieldSpec2SingletonList[T,F](x: FieldSpec[T, F]) = List(x)
+
+ implicit def FieldSpecOne2Int[T](spec: FieldSpecOne[T, Int]) =
+ (m: Message) => m.one(spec.name).intField.value
+
+ implicit def FieldSpecOne2String[T](spec: FieldSpecOne[T, String]) =
+ (m: Message) => m.one(spec.name).stringField.value
+
+ implicit def FieldSpecOne2Timestamp[T](spec: FieldSpecOne[T, Timestamp]) =
+ (m: Message) => m.one(spec.name).timestampField.value
+
+ implicit def FieldSpecOne2Long[T](spec: FieldSpecOne[T, Long]) =
+ (m: Message) => m.one(spec.name).longField.value
+
+ implicit def FieldSpecOne2BigInt[T](spec: FieldSpecOne[T, BigInt]) =
+ (m: Message) => m.one(spec.name).bigIntField.value
+
+ implicit def FieldSpecOne2BigDecimalField[T](spec: FieldSpecOne[T, BigDecimal]) =
+ (m: Message) => m.one(spec.name).bigDecimalField.value
+
+ implicit def FieldSpecOption2Int[T](spec: FieldSpecOption[T, Int]) =
+ (m: Message) => m.oneOption(spec.name).map(_.intField.value).getOrElse(spec.defaultValue)
+
+ implicit def FieldSpecOption2String[T](spec: FieldSpecOption[T, String]) =
+ (m: Message) => m.oneOption(spec.name).map(_.stringField.value).getOrElse(spec.defaultValue)
+
+ implicit def FieldSpecOption2Timestamp[T](spec: FieldSpecOption[T, Timestamp]) =
+ (m: Message) => m.oneOption(spec.name).map(_.timestampField.value).getOrElse(spec.defaultValue)
+
+ implicit def FieldSpecOption2Long[T](spec: FieldSpecOption[T, Long]) =
+ (m: Message) => m.oneOption(spec.name).map(_.longField.value).getOrElse(spec.defaultValue)
+
+ implicit def FieldSpecOption2BigInt[T](spec: FieldSpecOption[T, BigInt]) =
+ (m: Message) => m.oneOption(spec.name).map(_.bigIntField.value).getOrElse(spec.defaultValue)
+
+ implicit def FieldSpecOption2BigDecimalField[T](spec: FieldSpecOption[T, BigDecimal]) =
+ (m: Message) => m.oneOption(spec.name).map(_.bigDecimalField.value).getOrElse(spec.defaultValue)
+}
+
+abstract sealed class FieldSpec[T, F](val name: String,
+ val fieldFactoryOption: (String, F) => Option[Field],
+ val f2: T => F)
+
+final case class FieldSpecOne[T, F](override val name: String,
+ val fieldFactory: (String, F) => Field,
+ override val f2: T => F)
+ extends FieldSpec(name,
+ (name: String, value: F) => Some(fieldFactory(name, value)),
+ { userObject: T =>
+ val result = f2(userObject)
+ if (result == null)
+ error("UserObject '1%s' returned null for field '%2s'.".format(userObject, name))
+ else
+ result
+ })
+
+final case class FieldSpecOption[T, F](override val name: String,
+ val fieldFactory: (String, F) => Field,
+ override val f2: T => F,
+ val defaultValue: F)
+ extends FieldSpec(name,
+ (name: String, value: F) => if (value != defaultValue)
+ Some(fieldFactory(name, value))
+ else
+ None,
+ f2)
+
+
+//TODO FieldSpecMany has to be implemented in a future
+
+
diff --git a/src/test/scala/com/google/gimd/UserTypeTestCase.scala b/src/test/scala/com/google/gimd/UserTypeTestCase.scala
index 9d239c0..7310156 100644
--- a/src/test/scala/com/google/gimd/UserTypeTestCase.scala
+++ b/src/test/scala/com/google/gimd/UserTypeTestCase.scala
@@ -17,15 +17,20 @@ package com.google.gimd
import org.junit.Test
import org.junit.Assert._
+import UserType._
class UserTypeTestCase {
- class MyUserType extends UserType[String] {
- def toUserObject(itr: Message): String = ""
- def fields = Nil
+ case class Person(id: Int, name: String)
+
+ class PersonUserType extends UserType[Person] {
+ val id = FieldSpecOne("id", IntField, _.id)
+ val name = FieldSpecOption("name", StringField, _.name, null)
+ def toUserObject(m: Message) = Person(id(m), name(m))
+ def fields = id :: name
}
- class MyChildUserType extends MyUserType
+ class MyChildUserType extends PersonUserType
abstract class MyWrongUserTypeBase[T] extends UserType[T]
class MyWrongUserType extends MyWrongUserTypeBase[String] {
@@ -35,14 +40,14 @@ class UserTypeTestCase {
@Test
def userTypeClass {
- val ut = new MyUserType
- assertEquals(classOf[String], ut.userTypeClass)
+ val ut = new PersonUserType
+ assertEquals(classOf[Person], ut.userTypeClass)
}
@Test
def userTypeClassInSubtype {
val ut = new MyChildUserType
- assertEquals(classOf[String], ut.userTypeClass)
+ assertEquals(classOf[Person], ut.userTypeClass)
}
@Test{val expected = classOf[IllegalStateException]}
@@ -51,4 +56,26 @@ class UserTypeTestCase {
ut.userTypeClass
}
+ @Test
+ def optionalValueNotPresentInMessage {
+ val msg = Message(Field("id", 2))
+ val ut = new PersonUserType
+ val person = ut.toUserObject(msg)
+ assertEquals(Person(2, null), person)
+ }
+
+ @Test
+ def defaultForOptionalValueInUserObject {
+ val ut = new PersonUserType
+ val msg = ut.toMessage(Person(3, null))
+ assertEquals(Message(Field("id", 3)), msg)
+ }
+
+ @Test
+ def nonDefaultForOptionalValueInUserObject {
+ val ut = new PersonUserType
+ val msg = ut.toMessage(Person(3, "John"))
+ assertEquals(Message(Field("id", 3), Field("name", "John")), msg)
+ }
+
}
diff --git a/src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala b/src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala
index 5cad05c..d82e378 100644
--- a/src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala
+++ b/src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala
@@ -20,25 +20,24 @@ import org.junit.Test
import org.junit.Assert._
import org.spearce.jgit.lib.{Constants, ObjectId}
import query.Predicate
+import UserType._
final class JGitDatabaseTestCase extends AbstractJGitTestCase {
case class SimpleMessage(name: String, value: Int)
object SimpleMessageType extends UserType[SimpleMessage] {
- def toUserObject(m: Message): SimpleMessage = {
- val name = m.one("name").stringField.value
- val value = m.one("value").intField.value
- SimpleMessage(name, value)
- }
- def fields = List(FieldSpec("name", StringField, _.name), FieldSpec("value", IntField, _.value))
+ val name = FieldSpecOne("name", StringField, _.name)
+ val value = FieldSpecOne("value", IntField, _.value)
+ def fields = name :: value
+ def toUserObject(m: Message): SimpleMessage = SimpleMessage(name(m), value(m))
}
object SimpleMessageFileType extends FileType[SimpleMessage] {
val pathPrefix = Some("sm/")
val pathSuffix = Some(".sm")
val userType = SimpleMessageType
- def name(m: Message) = m.one("name").stringField.value
+ def name(m: Message) = userType.name(m)
}
@Test
diff --git a/src/test/scala/com/google/gimd/jgit/JGitFileTestCase.scala b/src/test/scala/com/google/gimd/jgit/JGitFileTestCase.scala
index f11da02..9797b00 100644
--- a/src/test/scala/com/google/gimd/jgit/JGitFileTestCase.scala
+++ b/src/test/scala/com/google/gimd/jgit/JGitFileTestCase.scala
@@ -18,25 +18,24 @@ import file.FileType
import junit.framework.Assert._
import org.junit.Test
import org.spearce.jgit.lib.ObjectId
+import UserType._
class JGitFileTestCase extends AbstractJGitTestCase {
case class SimpleMessage(name: String, value: Int)
object SimpleMessageType extends UserType[SimpleMessage] {
- def toUserObject(m: Message): SimpleMessage = {
- val name = m.one("name").stringField.value
- val value = m.one("value").intField.value
- SimpleMessage(name, value)
- }
- def fields = List(FieldSpec("name", StringField, _.name), FieldSpec("value", IntField, _.value))
+ val name = FieldSpecOne("name", StringField, _.name)
+ val value = FieldSpecOne("value", IntField, _.value)
+ def fields = name :: value
+ def toUserObject(m: Message) = SimpleMessage(name(m), value(m))
}
object SimpleMessageFileType extends FileType[SimpleMessage] {
val pathPrefix = None
val pathSuffix = None
val userType = SimpleMessageType
- def name(m: Message) = m.one("name").stringField.value
+ def name(m: Message) = userType.name(m).toString
}
@Test
diff --git a/src/test/scala/com/google/gimd/modification/ModificationTestCase.scala b/src/test/scala/com/google/gimd/modification/ModificationTestCase.scala
index d30f1cf..2f9e09c 100644
--- a/src/test/scala/com/google/gimd/modification/ModificationTestCase.scala
+++ b/src/test/scala/com/google/gimd/modification/ModificationTestCase.scala
@@ -19,6 +19,7 @@ import file.{FileType, File}
import org.junit.Test
import org.junit.Assert._
import query._
+import UserType._
final class ModificationTestCase {
@@ -26,19 +27,17 @@ final class ModificationTestCase {
case class TreeNode(id: Int, name: String)
object TreeNodeType extends UserType[TreeNode] {
- def toUserObject(m: Message): TreeNode =
- new TreeNode(
- m.one("id").intField.value,
- m.one("name").stringField.value
- )
+ val id = FieldSpecOne("id", IntField, _.id)
+ val name = FieldSpecOne("name", StringField, _.name)
+ def fields = id :: name
override def children = Seq(nestedMember)
- def fields = List(FieldSpec("id", IntField, _.id), FieldSpec("name", StringField, _.name))
+ def toUserObject(m: Message) = new TreeNode(id(m), name(m))
}
object MockFileType extends FileType[TreeNode] {
val pathPrefix = None
val pathSuffix = None
val userType = TreeNodeType
- def name(m: Message) = m.one("id").stringField.value
+ def name(m: Message) = userType.id(m).toString
}
case class MockFile(message: Message) extends File[TreeNode] {
val path = ""
diff --git a/src/test/scala/com/google/gimd/query/MessageQueryTestCase.scala b/src/test/scala/com/google/gimd/query/MessageQueryTestCase.scala
index 21b461b..c8c58eb 100644
--- a/src/test/scala/com/google/gimd/query/MessageQueryTestCase.scala
+++ b/src/test/scala/com/google/gimd/query/MessageQueryTestCase.scala
@@ -17,17 +17,16 @@ package com.google.gimd.query
import file.{File, FileType}
import org.junit.Test
import org.junit.Assert._
+import UserType._
class MessageQueryTestCase {
case class TreeNode(id: Int, name: String)
object TreeNodeType extends UserType[TreeNode] {
- def toUserObject(m: Message): TreeNode =
- new TreeNode(
- m.one("id").intField.value,
- m.one("name").stringField.value
- )
+ val id = FieldSpecOne("id", IntField, _.id)
+ val name = FieldSpecOne("name", StringField, _.name)
+ def fields = id :: name
override def children = Seq(new NestedMember("node", TreeNodeType))
- def fields = List(FieldSpec("id", IntField, _.id), FieldSpec("name", StringField, _.name))
+ def toUserObject(m: Message) = new TreeNode(id(m), name(m))
}
val root = new TreeNode(-1, "a")