aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala
blob: 352704a75bda07218feb72a0acb464f86ae08937 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package xyz.driver.pdsuidomain.formats.json.sprayformats

import java.time.LocalDateTime
import java.util.UUID

import spray.json._
import xyz.driver.core.json.{EnumJsonFormat, GadtJsonFormat}
import xyz.driver.pdsuicommon.domain.{LongId, TextJson, UuidId}
import xyz.driver.pdsuidomain.entities._

object record {
  import DefaultJsonProtocol._
  import MedicalRecord._
  import common._

  implicit val recordStatusFormat = new EnumJsonFormat[Status](
    "Unprocessed"   -> Status.Unprocessed,
    "PreOrganized"  -> Status.PreOrganized,
    "New"           -> Status.New,
    "Cleaned"       -> Status.Cleaned,
    "PreOrganized"  -> Status.PreOrganized,
    "PreOrganizing" -> Status.PreOrganizing,
    "Reviewed"      -> Status.Reviewed,
    "Organized"     -> Status.Organized,
    "Done"          -> Status.Done,
    "Flagged"       -> Status.Flagged,
    "Archived"      -> Status.Archived
  )

  implicit val requestIdFormat = new RootJsonFormat[RecordRequestId] {
    override def write(requestId: RecordRequestId): JsString = JsString(requestId.toString)
    override def read(json: JsValue): RecordRequestId = json match {
      case JsString(value) => RecordRequestId(UUID.fromString(value))
      case _               => deserializationError(s"Expected string as RecordRequestId, but got $json")
    }
  }

  implicit val caseIdFormat = new RootJsonFormat[CaseId] {
    override def write(caseId: CaseId): JsString = JsString(caseId.toString)
    override def read(json: JsValue): CaseId = json match {
      case JsString(value) => CaseId(value)
      case _               => deserializationError(s"Expected string as CaseId, but got $json")
    }
  }

  implicit val recordMetaTypeFormat: GadtJsonFormat[MedicalRecord.Meta] = {
    import Meta._
    GadtJsonFormat.create[Meta]("meta")({ case m => m.metaType }) {
      case "duplicate" => jsonFormat5(Duplicate.apply)
      case "reorder"   => jsonFormat2(Reorder.apply)
      case "rotation"  => jsonFormat2(Rotation.apply)
    }
  }

  implicit val recordMetaFormat = new RootJsonFormat[TextJson[List[Meta]]] {
    override def write(obj: TextJson[List[Meta]]): JsArray = JsArray(obj.content.map(_.toJson).toVector)
    override def read(json: JsValue): TextJson[List[Meta]] = json match {
      case JsArray(values) => TextJson[List[Meta]](values.map(_.convertTo[Meta]).toList)
      case _               => deserializationError(s"Expected array as Meta, but got $json")
    }
  }

  implicit val recordFormat: RootJsonFormat[MedicalRecord] =
    new RootJsonFormat[MedicalRecord] {
      override def write(record: MedicalRecord): JsValue =
        JsObject(
          "id"               -> record.id.id.toJson,
          "patientId"        -> record.patientId.toJson,
          "caseId"           -> record.caseId.toJson,
          "disease"          -> record.disease.toJson,
          "physician"        -> record.physician.toJson,
          "status"           -> record.status.toJson,
          "previousStatus"   -> record.previousStatus.toJson,
          "assignee"         -> record.assignee.toJson,
          "previousAssignee" -> record.previousAssignee.toJson,
          "requestId"        -> record.requestId.toJson,
          "meta"             -> record.meta.getOrElse(TextJson[List[Meta]](List.empty)).toJson,
          "lastActiveUser"   -> record.lastActiveUserId.toJson,
          "lastUpdate"       -> record.lastUpdate.toJson
        )

      override def read(json: JsValue): MedicalRecord = json match {
        case JsObject(fields) =>
          val disease = fields
            .get("disease")
            .map(_.convertTo[String])
            .getOrElse(deserializationError(s"MedicalRecord json object does not contain `disease` field: $json"))

          val patientId = fields
            .get("patientId")
            .map(_.convertTo[UuidId[Patient]])
            .getOrElse(deserializationError(s"MedicalRecord json object does not contain `patientId` field: $json"))

          val requestId = fields
            .get("requestId")
            .map(_.convertTo[RecordRequestId])
            .getOrElse(deserializationError(s"MedicalRecord json object does not contain `requestId` field: $json"))

          MedicalRecord(
            id = LongId(0),
            status = MedicalRecord.Status.New,
            previousStatus = None,
            assignee = None,
            previousAssignee = None,
            lastActiveUserId = None,
            patientId = patientId,
            requestId = requestId,
            disease = disease,
            caseId = None,
            physician = None,
            meta = None,
            predictedMeta = None,
            predictedDocuments = None,
            lastUpdate = LocalDateTime.now()
          )

        case _ => deserializationError(s"Expected Json Object as MedicalRecord, but got $json")
      }
    }

  def applyUpdateToMedicalRecord(json: JsValue, orig: MedicalRecord): MedicalRecord = json match {
    case JsObject(fields) =>
      val meta = if (fields.contains("meta")) {
        fields
          .get("meta")
          .map(_.convertTo[TextJson[List[Meta]]])
      } else orig.meta
      orig.copy(meta = meta)

    case _ => deserializationError(s"Expected Json Object as partial MedicalRecord, but got $json")
  }

}