aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/pdsuidomain/formats/json/document
diff options
context:
space:
mode:
authorvlad <vlad@driver.xyz>2017-06-27 17:13:02 -0700
committervlad <vlad@driver.xyz>2017-06-27 17:13:02 -0700
commit5832f63b84d7388441d1200f2442dc1e9de0225c (patch)
tree32f63acdc920c14effc3d0d2822c05c125ad49e4 /src/main/scala/xyz/driver/pdsuidomain/formats/json/document
parent9dd50590d4c8f8b9442d7c21ddd1def9dd453d5e (diff)
downloadrest-query-5832f63b84d7388441d1200f2442dc1e9de0225c.tar.gz
rest-query-5832f63b84d7388441d1200f2442dc1e9de0225c.tar.bz2
rest-query-5832f63b84d7388441d1200f2442dc1e9de0225c.zip
All PDS UI domain models, API case classes, service traits and necessary utils moved to pdsui-commonv0.1.11
Diffstat (limited to 'src/main/scala/xyz/driver/pdsuidomain/formats/json/document')
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala71
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocumentType.scala20
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala114
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiProviderType.scala20
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/document/DocumentUtils.scala24
5 files changed, 249 insertions, 0 deletions
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala
new file mode 100644
index 0000000..be9c65b
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala
@@ -0,0 +1,71 @@
+package xyz.driver.pdsuidomain.formats.json.document
+
+import java.time.{LocalDate, ZoneId, ZonedDateTime}
+
+import xyz.driver.pdsuidomain.entities._
+import play.api.data.validation.ValidationError
+import play.api.libs.functional.syntax._
+import play.api.libs.json._
+import xyz.driver.pdsuicommon.json.JsonSerializer
+
+final case class ApiDocument(id: Long,
+ recordId: Long,
+ physician: Option[String],
+ lastUpdate: Option[ZonedDateTime],
+ typeId: Option[Long],
+ startDate: Option[LocalDate],
+ endDate: Option[LocalDate],
+ provider: Option[String],
+ providerTypeId: Option[Long],
+ status: Option[String],
+ previousStatus: Option[String],
+ assignee: Option[Long],
+ previousAssignee: Option[Long],
+ meta: Option[String])
+
+object ApiDocument {
+
+ private val statusFormat = Format(
+ Reads.StringReads.filter(ValidationError("unknown status")) {
+ case x if DocumentUtils.statusFromString.isDefinedAt(x) => true
+ case _ => false
+ },
+ Writes.StringWrites
+ )
+
+ implicit val format: Format[ApiDocument] = (
+ (JsPath \ "id").format[Long] and
+ (JsPath \ "recordId").format[Long] and
+ (JsPath \ "physician").formatNullable[String] and
+ (JsPath \ "lastUpdate").formatNullable[ZonedDateTime] and
+ (JsPath \ "typeId").formatNullable[Long] and
+ (JsPath \ "startDate").formatNullable[LocalDate] and
+ (JsPath \ "endDate").formatNullable[LocalDate] and
+ (JsPath \ "provider").formatNullable[String] and
+ (JsPath \ "providerTypeId").formatNullable[Long] and
+ (JsPath \ "status").formatNullable(statusFormat) and
+ (JsPath \ "previousStatus").formatNullable(statusFormat) and
+ (JsPath \ "assignee").formatNullable[Long] and
+ (JsPath \ "previousAssignee").formatNullable[Long] and
+ (JsPath \ "meta").formatNullable(Format(Reads { x => JsSuccess(Json.stringify(x)) }, Writes[String](Json.parse)))
+ ) (ApiDocument.apply, unlift(ApiDocument.unapply))
+
+ def fromDomain(document: Document): ApiDocument = {
+ ApiDocument(
+ id = document.id.id,
+ recordId = document.recordId.id,
+ physician = document.physician,
+ lastUpdate = Option(document.lastUpdate).map(ZonedDateTime.of(_, ZoneId.of("Z"))),
+ typeId = document.typeId.map(_.id),
+ startDate = document.startDate,
+ endDate = document.endDate,
+ provider = document.providerName,
+ providerTypeId = document.providerTypeId.map(_.id),
+ status = Option(DocumentUtils.statusToString(document.status)),
+ previousStatus = document.previousStatus.map(DocumentUtils.statusToString),
+ assignee = document.assignee.map(_.id),
+ previousAssignee = document.previousAssignee.map(_.id),
+ meta = document.meta.map(meta => JsonSerializer.serialize(meta.content))
+ )
+ }
+}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocumentType.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocumentType.scala
new file mode 100644
index 0000000..e00da20
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocumentType.scala
@@ -0,0 +1,20 @@
+package xyz.driver.pdsuidomain.formats.json.document
+
+import play.api.libs.functional.syntax._
+import play.api.libs.json.{Format, JsPath}
+import xyz.driver.pdsuidomain.entities.DocumentType
+
+final case class ApiDocumentType(id: Long, name: String)
+
+object ApiDocumentType {
+
+ implicit val format: Format[ApiDocumentType] = (
+ (JsPath \ "id").format[Long] and
+ (JsPath \ "name").format[String]
+ ) (ApiDocumentType.apply, unlift(ApiDocumentType.unapply))
+
+ def fromDomain(documentType: DocumentType) = ApiDocumentType(
+ id = documentType.id.id,
+ name = documentType.name
+ )
+}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala
new file mode 100644
index 0000000..7682bb5
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala
@@ -0,0 +1,114 @@
+package xyz.driver.pdsuidomain.formats.json.document
+
+import java.time.{LocalDate, LocalDateTime}
+
+import xyz.driver.pdsuicommon.domain.{LongId, TextJson}
+import xyz.driver.pdsuidomain.entities.Document.Meta
+import xyz.driver.pdsuidomain.entities._
+import org.davidbild.tristate.Tristate
+import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath
+import play.api.data.validation._
+import play.api.libs.functional.syntax._
+import play.api.libs.json._
+import xyz.driver.pdsuicommon.json.{JsonSerializer, JsonValidationException}
+import xyz.driver.pdsuicommon.validation.{AdditionalConstraints, JsonValidationErrors}
+
+import scala.collection.breakOut
+import scala.util.Try
+
+final case class ApiPartialDocument(recordId: Option[Long],
+ physician: Option[String],
+ typeId: Tristate[Long],
+ startDate: Tristate[LocalDate],
+ endDate: Tristate[LocalDate],
+ provider: Tristate[String],
+ providerTypeId: Tristate[Long],
+ status: Option[String],
+ assignee: Tristate[Long],
+ meta: Tristate[String]) {
+
+ import xyz.driver.pdsuicommon.domain.User
+
+ def applyTo(orig: Document): Document = Document(
+ id = orig.id,
+ status = status.map(DocumentUtils.statusFromString).getOrElse(orig.status),
+ previousStatus = orig.previousStatus,
+ assignee = assignee.map(LongId[User]).cata(Some(_), None, orig.assignee),
+ previousAssignee = orig.previousAssignee,
+ recordId = recordId.map(LongId[MedicalRecord]).getOrElse(orig.recordId),
+ physician = physician.orElse(orig.physician),
+ typeId = typeId.map(LongId[DocumentType]).cata(Some(_), None, orig.typeId),
+ providerName = provider.cata(Some(_), None, orig.providerName),
+ providerTypeId = providerTypeId.map(LongId[ProviderType]).cata(Some(_), None, orig.providerTypeId),
+ meta = meta.cata(x => Some(TextJson(JsonSerializer.deserialize[Meta](x))), None, orig.meta),
+ startDate = startDate.cata(Some(_), None, orig.startDate),
+ endDate = endDate.cata(Some(_), None, orig.endDate),
+ lastUpdate = LocalDateTime.MIN // Should update internally in a business logic module
+ )
+
+ def toDomain: Try[Document] = Try {
+ val validation = Map(JsPath \ "recordId" -> AdditionalConstraints.optionNonEmptyConstraint(recordId))
+
+ val validationErrors: JsonValidationErrors = validation.collect({
+ case (fieldName, e: Invalid) => (fieldName, e.errors)
+ })(breakOut)
+
+ if (validationErrors.isEmpty) {
+ Document(
+ id = LongId(0),
+ recordId = recordId.map(LongId[MedicalRecord]).get,
+ status = Document.Status.New,
+ physician = physician,
+ typeId = typeId.map(LongId[DocumentType]).toOption,
+ startDate = startDate.toOption,
+ endDate = endDate.toOption,
+ providerName = provider.toOption,
+ providerTypeId = providerTypeId.map(LongId[ProviderType]).toOption,
+ meta = meta.map(x => TextJson(JsonSerializer.deserialize[Meta](x))).toOption,
+ previousStatus = None,
+ assignee = None,
+ previousAssignee = None,
+ lastUpdate = LocalDateTime.MIN
+ )
+ } else {
+ throw new JsonValidationException(validationErrors)
+ }
+ }
+}
+
+object ApiPartialDocument {
+
+ private val reads: Reads[ApiPartialDocument] = (
+ (JsPath \ "recordId").readNullable[Long] and
+ (JsPath \ "physician").readNullable[String] and
+ (JsPath \ "typeId").readTristate[Long] and
+ (JsPath \ "startDate").readTristate[LocalDate] and
+ (JsPath \ "endDate").readTristate[LocalDate] and
+ (JsPath \ "provider").readTristate[String] and
+ (JsPath \ "providerTypeId").readTristate[Long] and
+ (JsPath \ "status").readNullable[String](Reads.of[String].filter(ValidationError("unknown status"))({
+ case x if DocumentUtils.statusFromString.isDefinedAt(x) => true
+ case _ => false
+ })) and
+ (JsPath \ "assignee").readTristate[Long] and
+ (JsPath \ "meta").readTristate(Reads { x => JsSuccess(Json.stringify(x)) }).map {
+ case Tristate.Present("{}") => Tristate.Absent
+ case x => x
+ }
+ ) (ApiPartialDocument.apply _)
+
+ private val writes: Writes[ApiPartialDocument] = (
+ (JsPath \ "recordId").writeNullable[Long] and
+ (JsPath \ "physician").writeNullable[String] and
+ (JsPath \ "typeId").writeTristate[Long] and
+ (JsPath \ "startDate").writeTristate[LocalDate] and
+ (JsPath \ "endDate").writeTristate[LocalDate] and
+ (JsPath \ "provider").writeTristate[String] and
+ (JsPath \ "providerTypeId").writeTristate[Long] and
+ (JsPath \ "status").writeNullable[String] and
+ (JsPath \ "assignee").writeTristate[Long] and
+ (JsPath \ "meta").writeTristate(Writes[String](Json.parse))
+ ) (unlift(ApiPartialDocument.unapply))
+
+ implicit val format: Format[ApiPartialDocument] = Format(reads, writes)
+}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiProviderType.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiProviderType.scala
new file mode 100644
index 0000000..7b370ba
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiProviderType.scala
@@ -0,0 +1,20 @@
+package xyz.driver.pdsuidomain.formats.json.document
+
+import play.api.libs.functional.syntax._
+import play.api.libs.json.{Format, JsPath}
+import xyz.driver.pdsuidomain.entities.ProviderType
+
+final case class ApiProviderType(id: Long, name: String)
+
+object ApiProviderType {
+
+ implicit val format: Format[ApiProviderType] = (
+ (JsPath \ "id").format[Long] and
+ (JsPath \ "name").format[String]
+ ) (ApiProviderType.apply, unlift(ApiProviderType.unapply))
+
+ def fromDomain(providerType: ProviderType) = ApiProviderType(
+ id = providerType.id.id,
+ name = providerType.name
+ )
+}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/DocumentUtils.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/DocumentUtils.scala
new file mode 100644
index 0000000..87e449f
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/DocumentUtils.scala
@@ -0,0 +1,24 @@
+package xyz.driver.pdsuidomain.formats.json.document
+
+import xyz.driver.pdsuidomain.entities.Document.Status
+
+object DocumentUtils {
+
+ val statusFromString: PartialFunction[String, Status] = {
+ case "New" => Status.New
+ case "Organized" => Status.Organized
+ case "Extracted" => Status.Extracted
+ case "Done" => Status.Done
+ case "Flagged" => Status.Flagged
+ case "Archived" => Status.Archived
+ }
+
+ def statusToString(x: Status): String = x match {
+ case Status.New => "New"
+ case Status.Organized => "Organized"
+ case Status.Extracted => "Extracted"
+ case Status.Done => "Done"
+ case Status.Flagged => "Flagged"
+ case Status.Archived => "Archived"
+ }
+}