aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlad <vlad@driver.xyz>2017-07-01 03:18:38 -0700
committervlad <vlad@driver.xyz>2017-07-01 03:18:38 -0700
commita9efd6c3fb151fe1bfca1fc5444f11afb9d16a5b (patch)
treecb51f7adc83f92ab036f939653ece29eae80ab99
parentce6973573e67214340fda451ee84171ea98f9a7c (diff)
downloadrest-query-0.1.15.tar.gz
rest-query-0.1.15.tar.bz2
rest-query-0.1.15.zip
Computations implicits was too ad hoc and implicitv0.1.15
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/computation/FutureToComputationOps.scala22
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/computation/Implicits.scala15
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/computation/TryToComputationOps.scala15
-rw-r--r--src/test/scala/xyz/driver/pdsuidomain/formats/json/ApiDocumentSuite.scala78
-rw-r--r--src/test/scala/xyz/driver/pdsuidomain/formats/json/ApiPartialDocumentSuite.scala263
5 files changed, 341 insertions, 52 deletions
diff --git a/src/main/scala/xyz/driver/pdsuicommon/computation/FutureToComputationOps.scala b/src/main/scala/xyz/driver/pdsuicommon/computation/FutureToComputationOps.scala
deleted file mode 100644
index 6951e79..0000000
--- a/src/main/scala/xyz/driver/pdsuicommon/computation/FutureToComputationOps.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package xyz.driver.pdsuicommon.computation
-
-import xyz.driver.pdsuicommon.error.DomainError
-
-import scala.concurrent.{ExecutionContext, Future}
-
-final class FutureToComputationOps[T](val self: Future[T]) extends AnyVal {
-
- def handleDomainError[U, ER](f: PartialFunction[T, U])(implicit unsuitableToErrorsResponse: DomainError => ER,
- ec: ExecutionContext): Future[Either[ER, U]] = {
- self.map {
- case x if f.isDefinedAt(x) => Right(f(x))
- case x: DomainError => Left(unsuitableToErrorsResponse(x))
- case x => throw new RuntimeException(s"Can not process $x")
- }
- }
-
- def toComputation[U, ER](f: PartialFunction[T, U])(implicit unsuitableToErrorsResponse: DomainError => ER,
- ec: ExecutionContext): Computation[ER, U] = {
- Computation(handleDomainError(f))
- }
-}
diff --git a/src/main/scala/xyz/driver/pdsuicommon/computation/Implicits.scala b/src/main/scala/xyz/driver/pdsuicommon/computation/Implicits.scala
deleted file mode 100644
index d5acc2d..0000000
--- a/src/main/scala/xyz/driver/pdsuicommon/computation/Implicits.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package xyz.driver.pdsuicommon.computation
-
-import scala.concurrent.Future
-import scala.util.Try
-
-trait Implicits {
-
- implicit def futureToFutureComputationOps[T](self: Future[T]): FutureToComputationOps[T] = {
- new FutureToComputationOps[T](self)
- }
-
- implicit def tryToTryComputationOps[T](self: Try[T]): TryToComputationOps[T] = {
- new TryToComputationOps[T](self)
- }
-}
diff --git a/src/main/scala/xyz/driver/pdsuicommon/computation/TryToComputationOps.scala b/src/main/scala/xyz/driver/pdsuicommon/computation/TryToComputationOps.scala
deleted file mode 100644
index 45f6d41..0000000
--- a/src/main/scala/xyz/driver/pdsuicommon/computation/TryToComputationOps.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package xyz.driver.pdsuicommon.computation
-
-import scala.concurrent.ExecutionContext
-import scala.util.control.NonFatal
-import scala.util.{Failure, Success, Try}
-
-final class TryToComputationOps[T](val self: Try[T]) extends AnyVal {
-
- def toComputation[ER](implicit exceptionToErrorResponse: Throwable => ER, ec: ExecutionContext): Computation[ER, T] =
- self match {
- case Success(x) => Computation.continue(x)
- case Failure(NonFatal(e)) => Computation.abort(exceptionToErrorResponse(e))
- case Failure(e) => Computation.fail(e)
- }
-}
diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/ApiDocumentSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/ApiDocumentSuite.scala
new file mode 100644
index 0000000..778e62e
--- /dev/null
+++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/ApiDocumentSuite.scala
@@ -0,0 +1,78 @@
+package xyz.driver.pdsuidomain.formats.json
+
+/*
+import java.time.LocalDateTime
+
+import org.scalatest.FreeSpecLike
+import play.api.libs.json.Json
+
+import scala.collection.breakOut
+
+class ApiDocumentSuite extends FreeSpecLike {
+
+ "ApiDocument" - {
+ "conforms to specification when serialized" in {
+ val document = ApiDocument(
+ id = 1L,
+ recordId = 123L,
+ physician = Some("physician"),
+ lastUpdate = LocalDateTime.now(),
+ `type` = "some-type",
+ startDate = LocalDateTime.now(),
+ endDate = Some(LocalDateTime.now()),
+ provider = "test-provider",
+ providerType = "test-provider-type",
+ status = "New",
+ assignee = Some(5L),
+ previousAssignee = None,
+ meta = "{}"
+ )
+
+ val actualJson = serialize(document)
+ val matcher =
+ """^\{
+ |"id":"[^"]+",
+ |"recordId":"[^"]+",
+ |"physician":"[^"]+",
+ |"lastUpdate":"[^"]+",
+ |"type":"[^"]+",
+ |"startDate":"[^"]+",
+ |"endDate":"[^"]+",
+ |"provider":"[^"]+",
+ |"providerType":"[^"]+",
+ |"status":"[^"]+",
+ |"assignee":"[^"]+",
+ |"meta":\{[^\}]*\}
+ |\}""".stripMargin.lines.mkString.r
+
+ assert(
+ matcher.pattern.matcher(actualJson).matches(),
+ s"""see https://driverinc.atlassian.net/wiki/display/RA/REST+API+Specification#RESTAPISpecification-DocumentObject
+ |pattern = ${matcher.pattern}
+ |json = $actualJson""".stripMargin
+ )
+ }
+
+ "has optional fields according to specification" in {
+ val expectedOptionalFields = Set("physician", "endDate", "assignee", "previousAssignee")
+
+ val klass = classOf[ApiDocument]
+ val actualOptionalFields: Set[String] = klass.getDeclaredFields.collect({
+ case x if x.getType == classOf[Option[_]] => x.getName
+ })(breakOut)
+
+ assert(
+ actualOptionalFields === expectedOptionalFields,
+ """actual vs expected
+ |see https://driverinc.atlassian.net/wiki/display/RA/REST+API+Specification#RESTAPISpecification-DocumentObject
+ """.stripMargin.trim
+ )
+ }
+ }
+
+ private def serialize(document: ApiDocument): String = {
+ Json.stringify(Json.toJson(document))
+ }
+
+}
+*/
diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/ApiPartialDocumentSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/ApiPartialDocumentSuite.scala
new file mode 100644
index 0000000..ecd079c
--- /dev/null
+++ b/src/test/scala/xyz/driver/pdsuidomain/formats/json/ApiPartialDocumentSuite.scala
@@ -0,0 +1,263 @@
+package xyz.driver.pdsuidomain.formats.json
+
+/*
+import java.time.LocalDateTime
+
+import xyz.driver.pdsuicommon.domain._
+import org.davidbild.tristate.Tristate
+import org.scalatest.FreeSpecLike
+import play.api.libs.json.Json
+
+class ApiPartialDocumentSuite extends FreeSpecLike {
+
+ "serialization" - {
+ "can be deserialized" in deserialize(defaultJson)
+
+ "endDate" - {
+ def jsonWithEndDate(rawValue: String) = json("endDate" -> rawValue)
+ def jsonWithoutEndDate = json()
+
+ "when specified" - {
+ "if non-empty object - should be parsed as date" in {
+ val rawEndDate = "2007-12-03T10:15:30.000"
+ val apiPartialEntity = deserialize(jsonWithEndDate(quoted(rawEndDate)))
+ assert(apiPartialEntity.endDate.exists(_ == LocalDateTime.parse(rawEndDate)))
+ }
+
+ "if null - should be parsed as Absent" in {
+ val apiPartialEntity = deserialize(jsonWithEndDate("null"))
+ assert(apiPartialEntity.endDate.isAbsent)
+ }
+ }
+
+ "when unspecified - should be parsed as Unspecified" in {
+ val apiPartialEntity = deserialize(jsonWithoutEndDate)
+ assert(apiPartialEntity.endDate.isUnspecified)
+ }
+ }
+
+ "assignee" - {
+ def jsonWithAssignee(rawValue: String) = json("assignee" -> rawValue)
+ def jsonWithoutAssignee = json()
+
+ "when specified" - {
+ "if non-empty object - should be parsed as UUID" in {
+ val rawAssignee = 123
+ val apiPartialEntity = deserialize(jsonWithAssignee(quoted(rawAssignee.toString)))
+ assert(apiPartialEntity.assignee.exists(_ == rawAssignee))
+ }
+
+ "if null - should be parsed as Absent" in {
+ val apiPartialEntity = deserialize(jsonWithAssignee("null"))
+ assert(apiPartialEntity.assignee.isAbsent)
+ }
+ }
+
+ "when unspecified - should be parsed as Unspecified" in {
+ val apiPartialEntity = deserialize(jsonWithoutAssignee)
+ assert(apiPartialEntity.assignee.isUnspecified)
+ }
+ }
+
+ "meta" - {
+ def jsonWithMeta(rawValue: String) = json("meta" -> rawValue)
+ def jsonWithoutMeta = json()
+
+ "when specified" - {
+ "if non-empty object - should be parsed as normalized JSON-string" in {
+ val apiPartialEntity = deserialize(jsonWithMeta(""" { "foo" : 1} """))
+ assert(apiPartialEntity.meta.exists(_ == """{"foo":1}"""))
+ }
+
+ "if null - should be parsed as Absent" in {
+ val apiPartialEntity = deserialize(jsonWithMeta("null"))
+ assert(apiPartialEntity.meta.isAbsent)
+ }
+
+ "if empty object ({}) - should be parsed as Absent (same as null case)" in {
+ val apiPartialEntity = deserialize(jsonWithMeta(" { } "))
+ assert(apiPartialEntity.meta.isAbsent)
+ }
+ }
+
+ "when unspecified - should be parsed as Unspecified" in {
+ val apiPartialEntity = deserialize(jsonWithoutMeta)
+ assert(apiPartialEntity.meta.isUnspecified)
+ }
+ }
+
+ def deserialize(json: String): ApiPartialDocument = {
+ Json.parse(json).as[ApiPartialDocument]
+ }
+ }
+
+ "applyTo" - {
+ "endDate" - {
+ "should choose a value of the api partial document" - {
+ "if it present" in test(Tristate.Present(LocalDateTime.now().plusDays(1)))
+ "if it absent" in test(Tristate.Absent)
+
+ def test(newEndDate: Tristate[LocalDateTime]): Unit = {
+ val origDocument = documentExample
+ val apiPartialDocument = apiPartialDocumentExample.copy(endDate = newEndDate)
+
+ val newDocument = apiPartialDocument.applyTo(origDocument)
+ assert(newDocument.endDate === newEndDate.toOption)
+ }
+ }
+
+ "should choose a value of the original document if it unspecified" in {
+ val newEndDate = Tristate.Unspecified
+ val origDocument = documentExample
+ val apiPartialDocument = apiPartialDocumentExample.copy(endDate = newEndDate)
+
+ val newDocument = apiPartialDocument.applyTo(origDocument)
+ assert(newDocument.endDate == origDocument.endDate)
+ }
+ }
+
+ "assignee" - {
+ "should choose a value of the api partial document" - {
+ "if it present" in test(Tristate.Present(123))
+ "if it absent" in test(Tristate.Absent)
+
+ def test(newAssignee: Tristate[Long]): Unit = {
+ val origDocument = documentExample
+ val apiPartialDocument = apiPartialDocumentExample.copy(assignee = newAssignee)
+
+ val newDocument = apiPartialDocument.applyTo(origDocument)
+ assert(newDocument.assignee === newAssignee.toOption.map(LongId[User]))
+ }
+ }
+
+ "should choose a value of the original document if it unspecified" in {
+ val newAssignee = Tristate.Unspecified
+ val origDocument = documentExample
+ val apiPartialDocument = apiPartialDocumentExample.copy(assignee = newAssignee)
+
+ val newDocument = apiPartialDocument.applyTo(origDocument)
+ assert(newDocument.assignee == origDocument.assignee)
+ }
+ }
+
+ /*"meta" - {
+ val documentId = Id[Document]()
+ def test(origMeta: Option[RawMeta], metaUpdate: Tristate[String], expectedNewMeta: Option[RawMeta]): Unit = {
+ val apiPartialDocument = apiPartialDocumentExample.copy(meta = metaUpdate)
+
+ val actualNewMeta = apiPartialDocument.applyTo(documentId, origMeta)
+ assert(actualNewMeta == expectedNewMeta)
+ }
+
+ "should choose a new meta's value" - {
+ "if it present" - {
+ "when original meta is present" in test(
+ origMeta = Some(RawMeta(documentId, """{"foo":42}""")),
+ metaUpdate = Tristate.Present("""{"bar":1}"""),
+ expectedNewMeta = Some(RawMeta(documentId, """{"bar":1}"""))
+ )
+
+ "when original meta is absent" in test(
+ origMeta = None,
+ metaUpdate = Tristate.Present("""{"bar":1}"""),
+ expectedNewMeta = Some(RawMeta(documentId, """{"bar":1}"""))
+ )
+ }
+
+ "if it absent" - {
+ "when original meta is present" in test(
+ origMeta = Some(RawMeta(documentId, """{"foo":42}""")),
+ metaUpdate = Tristate.Absent,
+ expectedNewMeta = None
+ )
+
+ "when original meta is absent" in test(
+ origMeta = None,
+ metaUpdate = Tristate.Absent,
+ expectedNewMeta = None
+ )
+ }
+ }
+
+ "should choose an original meta if a new one is unspecified" - {
+ "when original meta is present" in test(
+ origMeta = Some(RawMeta(documentId, """{"foo":42}""")),
+ metaUpdate = Tristate.Unspecified,
+ expectedNewMeta = Some(RawMeta(documentId, """{"foo":42}"""))
+ )
+
+ "when original meta is absent" in test(
+ origMeta = None,
+ metaUpdate = Tristate.Unspecified,
+ expectedNewMeta = None
+ )
+ }
+ }*/
+ }
+
+ private def documentExample = Document(
+ id = LongId(1),
+ status = Document.Status.Organized,
+ assignee = Some(LongId(1)),
+ previousAssignee = None,
+ recordId = LongId(1),
+ physician = None,
+ documentType = "type",
+ providerName = "provider name",
+ providerType = "provider type",
+ meta = None,
+ startDate = LocalDateTime.now,
+ endDate = None,
+ lastUpdate = LocalDateTime.now
+ )
+
+ private def apiPartialDocumentExample = ApiPartialDocument(
+ recordId = Some(12),
+ physician = Some("new physician"),
+ `type` = Some("new type"),
+ startDate = Some(LocalDateTime.now),
+ endDate = Tristate.Present(LocalDateTime.now),
+ provider = Some("new provider name"),
+ providerType = Some("new provider type"),
+ status = Some("Extracted"),
+ assignee = Tristate.Present(13),
+ meta = Tristate.Present("""{"foo":42}""")
+ )
+
+ private def quoted(v: String): String = s""""$v""""
+
+ private def defaultJson = json(
+ "endDate" -> quoted("2007-12-03T10:15:30.000"),
+ "assignee" -> quoted("c8b1b818-e1eb-4831-b0c8-26753b109deb"),
+ "meta" -> """{"foo": 1}"""
+ )
+
+ /**
+ * Without fields:
+ * - endDate
+ * - assignee
+ * - meta
+ */
+ private def json(addFields: (String, String)*): String = {
+ val addJson = addFields
+ .collect {
+ case (k, v) if v.nonEmpty => s""" "$k": $v """
+ }
+ .mkString(",\n")
+
+ s"""{
+ |"recordId":"bc542d3d-a928-42b8-824d-ca1520b07500",
+ |"patientId":"foobar",
+ |"caseId":"bazquux",
+ |"physician":"zed",
+ |"lastUpdate":"2007-12-03T10:15:30.000",
+ |"type":"type1",
+ |"startDate":"2007-10-01T09:40:00.000",
+ |"provider":"some provider name",
+ |"providerType":"some provider type",
+ |"status":"New"${if (addJson.isEmpty) "" else ","}
+ |$addJson
+ |}""".stripMargin
+ }
+}
+ */ \ No newline at end of file