aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/criterion.scala
blob: 83657f5d9ff25701d632b87130f96d0dd9e57a50 (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
package xyz.driver.pdsuidomain.formats.json.sprayformats

import spray.json._
import xyz.driver.pdsuicommon.domain.{LongId, StringId}
import xyz.driver.pdsuidomain.entities._
import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion

object criterion {
  import DefaultJsonProtocol._
  import common._

  implicit val criterionLabelWriter = new JsonWriter[CriterionLabel] {
    override def write(obj: CriterionLabel) = JsObject(
      "labelId"    -> obj.labelId.toJson,
      "categoryId" -> obj.categoryId.toJson,
      "value" -> obj.value.map {
        case true  => "Yes"
        case false => "No"
      }.toJson,
      "isDefining" -> obj.isDefining.toJson
    )
  }

  def jsValueToCriterionLabel(json: JsValue, criterionId: LongId[Criterion]): CriterionLabel = json match {
    case JsObject(fields) =>
      val labelId = fields
        .get("labelId")
        .map(_.convertTo[LongId[Label]])

      val categoryId = fields
        .get("categoryId")
        .map(_.convertTo[LongId[Category]])

      val value = fields
        .get("value")
        .map(_.convertTo[String] match {
          case "Yes" => true
          case "No"  => false
          case other =>
            deserializationError(s"Unknown `value` of CriterionLabel object: expected `yes` or `no`, but got $other")
        })

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

      CriterionLabel(
        id = LongId(0L),
        labelId = labelId,
        criterionId = criterionId,
        categoryId = categoryId,
        value = value,
        isDefining = isDefining
      )

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

  val richCriterionFormat = new RootJsonFormat[RichCriterion] {
    override def write(obj: RichCriterion): JsValue =
      JsObject(
        "id"         -> obj.criterion.id.toJson,
        "meta"       -> Option(obj.criterion.meta).toJson,
        "arms"       -> obj.armIds.toJson,
        "text"       -> obj.criterion.text.toJson,
        "isCompound" -> obj.criterion.isCompound.toJson,
        "labels"     -> obj.labels.map(_.toJson).toJson,
        "trialId"    -> obj.criterion.trialId.toJson
      )

    override def read(json: JsValue): RichCriterion = json match {
      case JsObject(fields) =>
        val id = fields
          .get("id")
          .map(_.convertTo[LongId[Criterion]])
          .getOrElse(LongId[Criterion](0))

        val trialId = fields
          .get("trialId")
          .map(_.convertTo[StringId[Trial]])
          .getOrElse(deserializationError(s"Criterion json object does not contain `trialId` field: $json"))

        val text = fields
          .get("text")
          .map(_.convertTo[String])

        val isCompound = fields
          .get("isCompound")
          .exists(_.convertTo[Boolean])

        val meta = fields
          .get("meta")
          .map(_.convertTo[String])
          .getOrElse("")

        val arms = fields
          .get("arms")
          .map(_.convertTo[List[LongId[Arm]]])
          .getOrElse(List.empty[LongId[Arm]])

        val labels = fields
          .get("labels")
          .map(_.convertTo[List[JsValue]])
          .map(_.map(l => jsValueToCriterionLabel(l, id)))
          .getOrElse(List.empty[CriterionLabel])

        RichCriterion(
          criterion = Criterion(
            id = id,
            trialId = trialId,
            text = text,
            isCompound = isCompound,
            meta = meta
          ),
          armIds = arms,
          labels = labels
        )

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

}