aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/pdsuidomain/formats/json
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/xyz/driver/pdsuidomain/formats/json')
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala6
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiInterventionType.scala12
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiPartialIntervention.scala60
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiRecord.scala92
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiUpdateRecord.scala2
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala92
6 files changed, 204 insertions, 60 deletions
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala
index f306a71..072ed25 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala
@@ -12,6 +12,7 @@ final case class ApiIntervention(id: Long,
isActive: Boolean,
arms: List[Long],
trialId: String,
+ deliveryMethod: Option[String],
originalName: String,
originalDosage: String,
originalType: Option[String]) {
@@ -26,7 +27,8 @@ final case class ApiIntervention(id: Long,
originalType = this.originalType.map(id => id.toString),
dosage = this.dosage,
originalDosage = this.originalDosage,
- isActive = this.isActive
+ isActive = this.isActive,
+ deliveryMethod = this.deliveryMethod
)
InterventionWithArms(intervention, this.arms.map { armId =>
@@ -47,6 +49,7 @@ object ApiIntervention {
(JsPath \ "isActive").format[Boolean] and
(JsPath \ "arms").format[List[Long]] and
(JsPath \ "trialId").format[String] and
+ (JsPath \ "deliveryMethod").formatNullable[String] and
(JsPath \ "originalName").format[String] and
(JsPath \ "originalDosage").format[String] and
(JsPath \ "originalType").formatNullable[String]
@@ -64,6 +67,7 @@ object ApiIntervention {
isActive = intervention.isActive,
arms = arms.map(_.armId.id),
trialId = intervention.trialId.id,
+ deliveryMethod = intervention.deliveryMethod,
originalName = intervention.originalName,
originalDosage = intervention.originalDosage,
originalType = intervention.originalType
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiInterventionType.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiInterventionType.scala
index ebef225..3db8bfa 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiInterventionType.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiInterventionType.scala
@@ -2,23 +2,25 @@ package xyz.driver.pdsuidomain.formats.json.intervention
import play.api.libs.functional.syntax._
import play.api.libs.json.{Format, JsPath}
-import xyz.driver.pdsuicommon.domain.LongId
import xyz.driver.pdsuidomain.entities.InterventionType
+import xyz.driver.pdsuidomain.entities.InterventionType.DeliveryMethod
-final case class ApiInterventionType(id: Long, name: String) {
+final case class ApiInterventionType(id: Long, name: String, deliveryMethods: List[String]) {
- def toDomain = InterventionType(id = LongId[InterventionType](id), name = name)
+ def toDomain = InterventionType.typeFromString(name)
}
object ApiInterventionType {
implicit val format: Format[ApiInterventionType] = (
(JsPath \ "id").format[Long] and
- (JsPath \ "name").format[String]
+ (JsPath \ "name").format[String] and
+ (JsPath \ "deliveryMethods").format[List[String]]
)(ApiInterventionType.apply, unlift(ApiInterventionType.unapply))
def fromDomain(interventionType: InterventionType) = ApiInterventionType(
id = interventionType.id.id,
- name = interventionType.name
+ name = interventionType.name,
+ deliveryMethods = interventionType.deliveryMethods.map(DeliveryMethod.methodToString).toList
)
}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiPartialIntervention.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiPartialIntervention.scala
index aa55506..28a8555 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiPartialIntervention.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiPartialIntervention.scala
@@ -1,42 +1,88 @@
package xyz.driver.pdsuidomain.formats.json.intervention
-import xyz.driver.pdsuicommon.domain.LongId
-import xyz.driver.pdsuidomain.entities.{InterventionArm, InterventionWithArms}
+import play.api.data.validation.Invalid
+import xyz.driver.pdsuicommon.domain.{LongId, StringId}
+import xyz.driver.pdsuidomain.entities.{Intervention, InterventionArm, InterventionWithArms, Trial}
import play.api.libs.functional.syntax._
import play.api.libs.json._
+import xyz.driver.pdsuicommon.json.JsonValidationException
+import xyz.driver.pdsuicommon.validation.{AdditionalConstraints, JsonValidationErrors}
-final case class ApiPartialIntervention(typeId: Option[Long],
+import scala.collection.breakOut
+import scala.util.Try
+
+final case class ApiPartialIntervention(name: Option[String],
+ trialId: Option[String],
+ typeId: Option[Long],
dosage: Option[String],
isActive: Option[Boolean],
+ deliveryMethod: Option[String],
arms: Option[List[Long]]) {
def applyTo(orig: InterventionWithArms): InterventionWithArms = {
val origIntervention = orig.intervention
- val draftArmList = arms.map(_.map(x => InterventionArm(LongId(x), orig.intervention.id)))
+ val draftArmList = arms.map(_.map(x => InterventionArm(armId = LongId(x), interventionId = orig.intervention.id)))
orig.copy(
intervention = origIntervention.copy(
+ name = name.getOrElse(origIntervention.name),
typeId = typeId.map(LongId(_)).orElse(origIntervention.typeId),
dosage = dosage.getOrElse(origIntervention.dosage),
- isActive = isActive.getOrElse(origIntervention.isActive)
+ isActive = isActive.getOrElse(origIntervention.isActive),
+ deliveryMethod = deliveryMethod.orElse(origIntervention.deliveryMethod)
),
arms = draftArmList.getOrElse(orig.arms)
)
}
+
+ def toDomain: Try[InterventionWithArms] = Try {
+ val validation = Map(JsPath \ "trialId" -> AdditionalConstraints.optionNonEmptyConstraint(trialId))
+
+ val validationErrors: JsonValidationErrors = validation.collect({
+ case (fieldName, e: Invalid) => (fieldName, e.errors)
+ })(breakOut)
+
+ if (validationErrors.isEmpty) {
+ InterventionWithArms(
+ intervention = Intervention(
+ id = LongId(0),
+ trialId = trialId.map(StringId[Trial]).get,
+ name = name.getOrElse(""),
+ originalName = name.getOrElse(""),
+ typeId = typeId.map(LongId(_)),
+ originalType = Option(""),
+ dosage = dosage.getOrElse(""),
+ originalDosage = dosage.getOrElse(""),
+ isActive = isActive.getOrElse(false),
+ deliveryMethod = deliveryMethod
+ ),
+ arms =
+ arms.map(_.map(x => InterventionArm(armId = LongId(x), interventionId = LongId(0)))).getOrElse(List.empty)
+ )
+ } else {
+ throw new JsonValidationException(validationErrors)
+ }
+ }
}
object ApiPartialIntervention {
private val reads: Reads[ApiPartialIntervention] = (
- (JsPath \ "typeId").readNullable[Long] and
+ (JsPath \ "name").readNullable[String] and
+ (JsPath \ "trialId").readNullable[String] and
+ (JsPath \ "typeId").readNullable[Long] and
(JsPath \ "dosage").readNullable[String] and
(JsPath \ "isActive").readNullable[Boolean] and
+ (JsPath \ "deliveryMethod").readNullable[String] and
(JsPath \ "arms").readNullable[List[Long]]
)(ApiPartialIntervention.apply _)
private val writes: Writes[ApiPartialIntervention] = (
- (JsPath \ "typeId").writeNullable[Long] and
+ (JsPath \ "name").writeNullable[String] and
+ (JsPath \ "trialId").writeNullable[String] and
+ (JsPath \ "typeId").writeNullable[Long] and
(JsPath \ "dosage").writeNullable[String] and
(JsPath \ "isActive").writeNullable[Boolean] and
+ (JsPath \ "deliveryMethod").writeNullable[String] and
(JsPath \ "arms").writeNullable[List[Long]]
)(unlift(ApiPartialIntervention.unapply))
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiRecord.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiRecord.scala
index b255892..e7b58cd 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiRecord.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiRecord.scala
@@ -13,49 +13,11 @@ import play.api.libs.json._
import xyz.driver.pdsuicommon.json.JsonSerializer
import xyz.driver.pdsuicommon.domain.{LongId, StringId, TextJson, UuidId}
-final case class ApiRecord(id: Long,
- patientId: String,
- caseId: Option[String],
- disease: String,
- physician: Option[String],
- lastUpdate: ZonedDateTime,
- status: String,
- previousStatus: Option[String],
- assignee: Option[String],
- previousAssignee: Option[String],
- lastActiveUser: Option[String],
- requestId: UUID,
- meta: String) {
-
- private def extractStatus(status: String): Status =
- Status
- .fromString(status)
- .getOrElse(
- throw new NoSuchElementException(s"Status $status not found")
- )
-
- def toDomain = MedicalRecord(
- id = LongId(this.id),
- status = extractStatus(this.status),
- previousStatus = this.previousStatus.map(extractStatus),
- assignee = this.assignee.map(StringId(_)),
- previousAssignee = this.previousAssignee.map(StringId(_)),
- lastActiveUserId = this.lastActiveUser.map(StringId(_)),
- patientId = UuidId(patientId),
- requestId = RecordRequestId(this.requestId),
- disease = this.disease,
- caseId = caseId.map(CaseId(_)),
- physician = this.physician,
- meta = Some(TextJson(JsonSerializer.deserialize[List[MedicalRecord.Meta]](this.meta))),
- predictedMeta = None,
- predictedDocuments = None,
- lastUpdate = this.lastUpdate.toLocalDateTime()
- )
-
-}
-
object ApiRecord {
+ private val emptyMeta: String =
+ "[]"
+
private val statusFormat = Format(
Reads.StringReads.filter(ValidationError("unknown status")) {
case x if MedicalRecordStatus.statusFromString.isDefinedAt(x) => true
@@ -95,6 +57,52 @@ object ApiRecord {
previousAssignee = record.previousAssignee.map(_.id),
lastActiveUser = record.lastActiveUserId.map(_.id),
requestId = record.requestId.id,
- meta = record.meta.map(x => JsonSerializer.serialize(x.content)).getOrElse("[]")
+ meta = record.meta.map(x => JsonSerializer.serialize(x.content)).getOrElse(emptyMeta)
+ )
+}
+
+final case class ApiRecord(id: Long,
+ patientId: String,
+ caseId: Option[String],
+ disease: String,
+ physician: Option[String],
+ lastUpdate: ZonedDateTime,
+ status: String,
+ previousStatus: Option[String],
+ assignee: Option[String],
+ previousAssignee: Option[String],
+ lastActiveUser: Option[String],
+ requestId: UUID,
+ meta: String) {
+
+ private def extractStatus(status: String): Status =
+ Status
+ .fromString(status)
+ .getOrElse(
+ throw new NoSuchElementException(s"Status $status not found")
+ )
+
+ def toDomain = MedicalRecord(
+ id = LongId(this.id),
+ status = extractStatus(this.status),
+ previousStatus = this.previousStatus.map(extractStatus),
+ assignee = this.assignee.map(StringId(_)),
+ previousAssignee = this.previousAssignee.map(StringId(_)),
+ lastActiveUserId = this.lastActiveUser.map(StringId(_)),
+ patientId = UuidId(patientId),
+ requestId = RecordRequestId(this.requestId),
+ disease = this.disease,
+ caseId = caseId.map(CaseId(_)),
+ physician = this.physician,
+ meta = {
+ if (this.meta == ApiRecord.emptyMeta) {
+ None
+ } else {
+ Some(TextJson(JsonSerializer.deserialize[List[MedicalRecord.Meta]](this.meta)))
+ }
+ },
+ predictedMeta = None,
+ predictedDocuments = None,
+ lastUpdate = this.lastUpdate.toLocalDateTime()
)
}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiUpdateRecord.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiUpdateRecord.scala
index 47bc493..05d5a60 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiUpdateRecord.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiUpdateRecord.scala
@@ -37,7 +37,7 @@ object ApiUpdateRecord {
JsSuccess(Json.stringify(x))
})
.map {
- case Tristate.Present("{}") => Tristate.Absent
+ case Tristate.Present("[]") => Tristate.Absent
case x => x
}
)(ApiUpdateRecord.apply _)
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala
index 9314391..62cb9fa 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala
@@ -1,14 +1,15 @@
package xyz.driver.pdsuidomain.formats.json.sprayformats
import spray.json._
-import xyz.driver.pdsuicommon.domain.LongId
+import xyz.driver.pdsuicommon.domain.{LongId, StringId}
+import xyz.driver.pdsuidomain.entities.InterventionType.DeliveryMethod
import xyz.driver.pdsuidomain.entities._
object intervention {
import DefaultJsonProtocol._
import common._
- implicit val interventionWriter: JsonWriter[InterventionWithArms] = new JsonWriter[InterventionWithArms] {
+ implicit val interventionFormat: JsonFormat[InterventionWithArms] = new RootJsonFormat[InterventionWithArms] {
override def write(obj: InterventionWithArms) =
JsObject(
"id" -> obj.intervention.id.toJson,
@@ -18,14 +19,72 @@ object intervention {
"isActive" -> obj.intervention.isActive.toJson,
"arms" -> obj.arms.map(_.armId).toJson,
"trialId" -> obj.intervention.trialId.toJson,
+ "deliveryMethod" -> obj.intervention.deliveryMethod.toJson,
"originalName" -> obj.intervention.originalName.toJson,
"originalDosage" -> obj.intervention.originalDosage.toJson,
"originalType" -> obj.intervention.originalType.toJson
)
+
+ override def read(json: JsValue): InterventionWithArms = json match {
+ case JsObject(fields) =>
+ val trialId = fields
+ .get("trialId")
+ .map(_.convertTo[StringId[Trial]])
+ .getOrElse(deserializationError(s"Intervention json object does not contain `trialId` field: $json"))
+
+ val typeId = fields
+ .get("typeId")
+ .map(_.convertTo[LongId[InterventionType]])
+
+ val name = fields
+ .get("name")
+ .map(_.convertTo[String])
+ .getOrElse("")
+
+ val dosage = fields
+ .get("dosage")
+ .map(_.convertTo[String])
+ .getOrElse("")
+
+ val isActive = fields
+ .get("isActive")
+ .exists(_.convertTo[Boolean])
+
+ val deliveryMethod = fields
+ .get("deliveryMethod")
+ .map(_.convertTo[String])
+
+ val arms = fields
+ .get("arms")
+ .map(_.convertTo[List[LongId[Arm]]].map(x => InterventionArm(armId = x, interventionId = LongId(0))))
+ .getOrElse(List.empty[InterventionArm])
+
+ InterventionWithArms(
+ intervention = Intervention(
+ id = LongId(0),
+ trialId = trialId,
+ name = name,
+ originalName = name,
+ typeId = typeId,
+ originalType = None,
+ dosage = dosage,
+ originalDosage = dosage,
+ isActive = isActive,
+ deliveryMethod = deliveryMethod
+ ),
+ arms = arms
+ )
+
+ case _ => deserializationError(s"Expected Json Object as create Intervention json, but got $json")
+ }
}
def applyUpdateToInterventionWithArms(json: JsValue, orig: InterventionWithArms): InterventionWithArms = json match {
case JsObject(fields) =>
+ val name = fields
+ .get("name")
+ .map(_.convertTo[String])
+
val typeId = fields
.get("typeId")
.map(_.convertTo[LongId[InterventionType]])
@@ -38,6 +97,10 @@ object intervention {
.get("isActive")
.map(_.convertTo[Boolean])
+ val deliveryMethod = fields
+ .get("deliveryMethod")
+ .map(_.convertTo[String])
+
val origIntervention = orig.intervention
val arms = fields
.get("arms")
@@ -45,9 +108,11 @@ object intervention {
orig.copy(
intervention = origIntervention.copy(
+ name = name.getOrElse(origIntervention.name),
typeId = typeId.orElse(origIntervention.typeId),
dosage = dosage.getOrElse(origIntervention.dosage),
- isActive = isActive.getOrElse(origIntervention.isActive)
+ isActive = isActive.getOrElse(origIntervention.isActive),
+ deliveryMethod = deliveryMethod.orElse(origIntervention.deliveryMethod)
),
arms = arms.getOrElse(orig.arms)
)
@@ -55,6 +120,25 @@ object intervention {
case _ => deserializationError(s"Expected Json Object as partial Intervention, but got $json")
}
- implicit val interventionTypeFormat: RootJsonFormat[InterventionType] = jsonFormat2(InterventionType.apply)
+ implicit val interventionTypeFormat: JsonFormat[InterventionType] = new RootJsonFormat[InterventionType] {
+ override def read(json: JsValue) = json match {
+ case JsObject(fields) =>
+ val name = fields
+ .get("name")
+ .map(_.convertTo[String])
+ .getOrElse(deserializationError(s"Intervention type json object does not contain `name` field: $json"))
+
+ InterventionType.typeFromString(name)
+
+ case _ => deserializationError(s"Expected Json Object as Intervention type, but got $json")
+ }
+
+ override def write(obj: InterventionType) =
+ JsObject(
+ "id" -> obj.id.toJson,
+ "name" -> obj.name.toJson,
+ "deliveryMethods" -> obj.deliveryMethods.map(DeliveryMethod.methodToString).toJson
+ )
+ }
}