From deba20326e3269fee3ef51f8e6841f17453b4155 Mon Sep 17 00:00:00 2001 From: vlad Date: Thu, 28 Sep 2017 13:12:32 -0700 Subject: Simplified Export entities for EVLS --- .../formats/json/sprayformats/export.scala | 97 ++++++++++++---------- 1 file changed, 55 insertions(+), 42 deletions(-) (limited to 'src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala') diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala index 20b6ed0..2a1fe46 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala @@ -1,6 +1,7 @@ package xyz.driver.pdsuidomain.formats.json.sprayformats import spray.json._ +import xyz.driver.pdsuidomain.entities.{Arm, Criterion, Label} import xyz.driver.pdsuidomain.entities.export.patient._ import xyz.driver.pdsuidomain.entities.export.trial.{ExportTrialArm, ExportTrialLabelCriterion, ExportTrialWithLabels} @@ -8,42 +9,24 @@ object export { import DefaultJsonProtocol._ import common._ import record._ + import document._ - implicit val patientLabelEvidenceDocumentFormat: RootJsonFormat[ExportPatientLabelEvidenceDocument] = jsonFormat5( - ExportPatientLabelEvidenceDocument.apply) + implicit val patientLabelEvidenceDocumentFormat: RootJsonFormat[ExportPatientLabelEvidenceDocument] = + jsonFormat5(ExportPatientLabelEvidenceDocument.apply) - implicit val patientLabelEvidenceWriter: JsonWriter[ExportPatientLabelEvidence] = - new JsonWriter[ExportPatientLabelEvidence] { - override def write(obj: ExportPatientLabelEvidence): JsValue = - JsObject( - "evidenceId" -> obj.id.toJson, - "labelValue" -> obj.value.toJson, - "evidenceText" -> obj.evidenceText.toJson, - "document" -> obj.document.toJson - ) - } + implicit val patientLabelEvidenceFormat: RootJsonFormat[ExportPatientLabelEvidence] = + jsonFormat(ExportPatientLabelEvidence.apply, "evidenceId", "labelValue", "evidenceText", "document") - implicit val patientLabelWriter: JsonWriter[ExportPatientLabel] = new JsonWriter[ExportPatientLabel] { - override def write(obj: ExportPatientLabel): JsValue = - JsObject( - "labelId" -> obj.id.toJson, - "evidence" -> obj.evidences.map(_.toJson).toJson - ) - } + implicit val patientLabelFormat: RootJsonFormat[ExportPatientLabel] = + jsonFormat(ExportPatientLabel.apply, "labelId", "evidence") - implicit val patientWithLabelsWriter: JsonWriter[ExportPatientWithLabels] = new JsonWriter[ExportPatientWithLabels] { - override def write(obj: ExportPatientWithLabels): JsValue = - JsObject( - "patientId" -> obj.patientId.toJson, - "labelVersion" -> obj.labelVersion.toJson, - "labels" -> obj.labels.map(_.toJson).toJson - ) - } + implicit val patientWithLabelsFormat: RootJsonFormat[ExportPatientWithLabels] = + jsonFormat(ExportPatientWithLabels.apply, "patientId", "labelVersion", "labels") implicit val trialArmFormat: RootJsonFormat[ExportTrialArm] = jsonFormat2(ExportTrialArm.apply) - implicit val trialLabelCriterionWriter: JsonWriter[ExportTrialLabelCriterion] = - new JsonWriter[ExportTrialLabelCriterion] { + implicit val trialLabelCriterionFormat: RootJsonFormat[ExportTrialLabelCriterion] = + new RootJsonFormat[ExportTrialLabelCriterion] { override def write(obj: ExportTrialLabelCriterion): JsValue = JsObject( "value" -> obj.value @@ -60,19 +43,49 @@ object export { "isCompound" -> obj.isCompound.toJson, "isDefining" -> obj.isDefining.toJson ) - } - implicit val trialWithLabelsWriter: JsonWriter[ExportTrialWithLabels] = new JsonWriter[ExportTrialWithLabels] { - override def write(obj: ExportTrialWithLabels) = - JsObject( - "nctId" -> obj.nctId.toJson, - "trialId" -> obj.trialId.toJson, - "disease" -> obj.condition.toJson, - "lastReviewed" -> obj.lastReviewed.toJson, - "labelVersion" -> obj.labelVersion.toJson, - "arms" -> obj.arms.toJson, - "criteria" -> obj.criteria.map(_.toJson).toJson - ) - } + override def read(json: JsValue): ExportTrialLabelCriterion = { + + val fields = Seq("value", "labelId", "criterionId", "criterionText", "armIds", "isCompound", "isDefining") + + json.asJsObject.getFields(fields: _*) match { + case Seq(JsString(valueString), + labelId, + criterionId, + JsString(criterionText), + JsArray(armIdsVector), + JsBoolean(isCompound), + JsBoolean(isDefining)) => + val value = valueString match { + case "Yes" => Option(true) + case "No" => Option(false) + case "Unknown" => Option.empty[Boolean] + } + + ExportTrialLabelCriterion( + longIdFormat[Criterion].read(criterionId), + value, + longIdFormat[Label].read(labelId), + armIdsVector.map(longIdFormat[Arm].read).toSet, + criterionText, + isCompound, + isDefining + ) + + case _ => + deserializationError( + s"Cannot find required fields ${fields.mkString(", ")} in ExportTrialLabelCriterion object!") + } + } + } + implicit val trialWithLabelsFormat: RootJsonFormat[ExportTrialWithLabels] = + jsonFormat(ExportTrialWithLabels.apply, + "nctId", + "trialId", + "disease", + "lastReviewed", + "labelVersion", + "arms", + "criteria") } -- cgit v1.2.3 From b5e0d5f91b52013bc11ef3ea586a54bb001577bc Mon Sep 17 00:00:00 2001 From: vlad Date: Sun, 1 Oct 2017 12:50:54 -0700 Subject: Fixing IN in filters, Model from EVLS added to common, Reusing domain model labels --- build.sbt | 4 +- .../pdsuicommon/db/SlickPostgresQueryBuilder.scala | 3 +- .../driver/pdsuicommon/db/SlickQueryBuilder.scala | 3 +- .../pdsuicommon/parsers/SearchFilterParser.scala | 23 +++-- .../utils/CustomSwaggerJsonFormats.scala | 2 +- .../driver/pdsuidomain/entities/Criterion.scala | 5 +- .../pdsuidomain/entities/ExtractedData.scala | 3 +- .../xyz/driver/pdsuidomain/entities/Keyword.scala | 3 +- .../xyz/driver/pdsuidomain/entities/Label.scala | 31 ------- .../driver/pdsuidomain/entities/PatientLabel.scala | 1 + .../entities/PatientLabelEvidenceView.scala | 1 + .../pdsuidomain/entities/RawPatientLabel.scala | 1 + .../pdsuidomain/entities/RawTrialLabel.scala | 1 + .../driver/pdsuidomain/entities/eligibility.scala | 63 +++++++++++++ .../export/patient/ExportPatientLabel.scala | 3 +- .../export/trial/ExportTrialLabelCriterion.scala | 3 +- .../driver/pdsuidomain/fakes/entities/common.scala | 41 +++++++-- .../pdsuidomain/fakes/entities/eligibility.scala | 72 +++++++++++++++ .../driver/pdsuidomain/fakes/entities/export.scala | 35 +++++++ .../pdsuidomain/fakes/entities/rep/Common.scala | 35 ------- .../fakes/entities/rep/DocumentGen.scala | 7 +- .../fakes/entities/rep/ExportPatientGen.scala | 11 +-- .../fakes/entities/rep/ExtractedDataGen.scala | 17 ++-- .../fakes/entities/rep/MedicalRecordGen.scala | 7 +- .../fakes/entities/rep/ProviderTypeGen.scala | 14 --- .../pdsuidomain/fakes/entities/trialcuration.scala | 3 +- .../formats/json/category/ApiCategory.scala | 23 ----- .../formats/json/keyword/ApiKeyword.scala | 23 ----- .../formats/json/label/ApiCriterionLabel.scala | 5 +- .../formats/json/label/ApiExtractedDataLabel.scala | 5 +- .../pdsuidomain/formats/json/label/ApiLabel.scala | 22 ----- .../json/patient/trial/ApiPatientCriterion.scala | 3 +- .../formats/json/sprayformats/criterion.scala | 3 +- .../formats/json/sprayformats/documenttype.scala | 1 - .../formats/json/sprayformats/eligibility.scala | 101 +++++++++++++++++++++ .../formats/json/sprayformats/export.scala | 3 +- .../formats/json/sprayformats/extracteddata.scala | 3 +- .../json/sprayformats/patientcriterion.scala | 1 + .../formats/json/sprayformats/providerttype.scala | 12 --- .../formats/json/sprayformats/providertype.scala | 12 +++ .../services/EligibilityVerificationService.scala | 18 ++++ .../services/PatientCriterionService.scala | 1 + .../services/PatientEligibleTrialService.scala | 1 + .../services/PatientLabelEvidenceService.scala | 1 + .../pdsuidomain/services/PatientLabelService.scala | 1 + .../fake/FakeEligibilityVerificationService.scala | 28 ++++++ .../services/fake/FakeTrialService.scala | 3 +- .../rest/RestEligibilityVerificationService.scala | 43 +++++++++ .../parsers/SearchFilterParserSuite.scala | 13 ++- 49 files changed, 494 insertions(+), 224 deletions(-) delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/entities/Label.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/entities/eligibility.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/fakes/entities/eligibility.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/fakes/entities/export.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/Common.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/ProviderTypeGen.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/category/ApiCategory.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/keyword/ApiKeyword.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiLabel.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/eligibility.scala delete mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/providerttype.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/providertype.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/services/EligibilityVerificationService.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/services/fake/FakeEligibilityVerificationService.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/services/rest/RestEligibilityVerificationService.scala (limited to 'src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala') diff --git a/build.sbt b/build.sbt index 837a1f0..66c0f7b 100644 --- a/build.sbt +++ b/build.sbt @@ -18,8 +18,8 @@ lazy val core = (project in file(".")) "io.github.cloudify" %% "spdf" % "1.4.0", "org.davidbild" %% "tristate-core" % "0.2.0", "org.davidbild" %% "tristate-play" % "0.2.0" exclude ("com.typesafe.play", "play-json"), - "xyz.driver" %% "core" % "0.16.7", - "xyz.driver" %% "domain-model" % "0.12.26", + "xyz.driver" %% "core" % "1.2.1", + "xyz.driver" %% "domain-model" % "0.17.1", "ch.qos.logback" % "logback-classic" % "1.1.7", "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.4", "com.github.spullara.mustache.java" % "scala-extensions-2.11" % "0.9.4", diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/SlickPostgresQueryBuilder.scala b/src/main/scala/xyz/driver/pdsuicommon/db/SlickPostgresQueryBuilder.scala index f882441..a56ab9a 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/db/SlickPostgresQueryBuilder.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/db/SlickPostgresQueryBuilder.scala @@ -2,8 +2,7 @@ package xyz.driver.pdsuicommon.db import java.time.{LocalDateTime, ZoneOffset} -import slick.driver.JdbcProfile -import slick.jdbc.GetResult +import slick.jdbc.{JdbcProfile, GetResult} import xyz.driver.core.database.SlickDal import xyz.driver.pdsuicommon.logging._ diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/SlickQueryBuilder.scala b/src/main/scala/xyz/driver/pdsuicommon/db/SlickQueryBuilder.scala index ab2757b..0daa84d 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/db/SlickQueryBuilder.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/db/SlickQueryBuilder.scala @@ -3,8 +3,7 @@ package xyz.driver.pdsuicommon.db import java.sql.PreparedStatement import java.time.LocalDateTime -import slick.driver.JdbcProfile -import slick.jdbc.{PositionedParameters, SQLActionBuilder, SetParameter} +import slick.jdbc.{JdbcProfile, PositionedParameters, SQLActionBuilder, SetParameter} import xyz.driver.pdsuicommon.db.Sorting.{Dimension, Sequential} import xyz.driver.pdsuicommon.db.SortingOrder.{Ascending, Descending} diff --git a/src/main/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParser.scala b/src/main/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParser.scala index e0adeb8..e46e11c 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParser.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParser.scala @@ -15,10 +15,7 @@ object SearchFilterParser { private object BinaryAtomFromTuple { def unapply(input: (SearchFilterExpr.Dimension, (String, Any))): Option[SearchFilterExpr.Atom.Binary] = { val (dimensionName, (strOperation, value)) = input - val updatedValue = value match { - case s: String => s.safeTrim - case a => a - } + val updatedValue = trimIfString(value) parseOperation(strOperation.toLowerCase).map { op => SearchFilterExpr.Atom.Binary(dimensionName, op, updatedValue.asInstanceOf[AnyRef]) @@ -30,15 +27,24 @@ object SearchFilterParser { // Compiler warning: unchecked since it is eliminated by erasure, if we user Seq[String] def unapply(input: (SearchFilterExpr.Dimension, (String, Seq[_]))): Option[SearchFilterExpr.Atom.NAry] = { val (dimensionName, (strOperation, xs)) = input + val updatedValues = xs.map(trimIfString) + if (strOperation.toLowerCase == "in") { - val values = xs.asInstanceOf[Seq[String]].map(_.safeTrim) - Some(SearchFilterExpr.Atom.NAry(dimensionName, SearchFilterNAryOperation.In, values)) + Some( + SearchFilterExpr.Atom + .NAry(dimensionName, SearchFilterNAryOperation.In, updatedValues.map(_.asInstanceOf[AnyRef]))) } else { None } } } + private def trimIfString(value: Any) = + value match { + case s: String => s.safeTrim + case a => a + } + private val operationsMapping = { import xyz.driver.pdsuicommon.db.SearchFilterBinaryOperation._ @@ -96,7 +102,7 @@ object SearchFilterParser { private val nAryValueParser: Parser[String] = P(CharPred(_ != ',').rep(min = 1).!) - private val longParser: Parser[Long] = P(CharIn('0' to '9').rep(1).!.map(_.toLong)) + private val longParser: Parser[Long] = P(CharIn('0' to '9').rep(min = 1).!.map(_.toLong)) private val binaryAtomParser: Parser[SearchFilterExpr.Atom.Binary] = P( dimensionParser ~ whitespaceParser ~ ( @@ -109,7 +115,8 @@ object SearchFilterParser { private val nAryAtomParser: Parser[SearchFilterExpr.Atom.NAry] = P( dimensionParser ~ whitespaceParser ~ ( - naryOperatorParser ~/ whitespaceParser ~/ nAryValueParser.!.rep(min = 1, sep = ",") + naryOperatorParser ~ whitespaceParser ~ + (longParser.rep(min = 1, sep = ",") | nAryValueParser.!.rep(min = 1, sep = ",")) ) ~ End ).map { case NAryAtomFromTuple(atom) => atom diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/CustomSwaggerJsonFormats.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/CustomSwaggerJsonFormats.scala index 4ecf915..a3f48d1 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/CustomSwaggerJsonFormats.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/utils/CustomSwaggerJsonFormats.scala @@ -89,7 +89,7 @@ object CustomSwaggerJsonFormats { classOf[DocumentHistory.State] -> documenthistory.documentStateFormat.write(rep.DocumentGen.nextDocumentHistoryState()), classOf[ProviderType] -> - providertype.providerTypeFormat.write(rep.ProviderTypeGen.nextProviderType()), + providertype.providerTypeFormat.write(rep.MedicalRecordGen.nextProviderType()), classOf[TextJson[List[MedicalRecord.Meta]]] -> record.recordMetaFormat.write(rep.MedicalRecordGen.nextMedicalRecordMetasJson()), classOf[MedicalRecord] -> diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Criterion.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Criterion.scala index 0dfb33f..7f065d4 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Criterion.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/Criterion.scala @@ -1,5 +1,6 @@ package xyz.driver.pdsuidomain.entities +import xyz.driver.entities.labels.{Label, LabelCategory} import xyz.driver.pdsuicommon.domain.{LongId, StringId} import xyz.driver.pdsuicommon.logging._ import xyz.driver.pdsuidomain.entities.Criterion.Meta.Evidence @@ -10,7 +11,7 @@ final case class Criterion(id: LongId[Criterion], isCompound: Boolean, meta: String) { - def isValid(): Boolean = text.nonEmpty && Option(meta).isDefined + def isValid: Boolean = text.nonEmpty && Option(meta).isDefined } object Criterion { @@ -41,7 +42,7 @@ object CriterionArm { final case class CriterionLabel(id: LongId[CriterionLabel], labelId: Option[LongId[Label]], criterionId: LongId[Criterion], - categoryId: Option[LongId[Category]], + categoryId: Option[LongId[LabelCategory]], value: Option[Boolean], isDefining: Boolean) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/ExtractedData.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/ExtractedData.scala index 32258dc..fbd468f 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/ExtractedData.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/ExtractedData.scala @@ -1,5 +1,6 @@ package xyz.driver.pdsuidomain.entities +import xyz.driver.entities.labels.{Label, LabelCategory} import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, TextJson} import xyz.driver.pdsuicommon.logging._ import xyz.driver.pdsuidomain.entities.ExtractedData.Meta @@ -43,5 +44,5 @@ object ExtractedDataLabel { final case class ExtractedDataLabel(id: LongId[ExtractedDataLabel], dataId: LongId[ExtractedData], labelId: Option[LongId[Label]], - categoryId: Option[LongId[Category]], + categoryId: Option[LongId[LabelCategory]], value: Option[FuzzyValue]) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Keyword.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Keyword.scala index 3683efc..a984f92 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Keyword.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/Keyword.scala @@ -1,5 +1,6 @@ package xyz.driver.pdsuidomain.entities +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.domain.LongId import xyz.driver.pdsuicommon.logging._ @@ -17,7 +18,7 @@ final case class KeywordWithLabels(keyword: Keyword, labels: List[Label]) object KeywordWithLabels { implicit def toPhiString(x: KeywordWithLabels): PhiString = { import x._ - phi"KeywordWithLabels(keyword=$keyword, $labels)" + phi"KeywordWithLabels(keyword=$keyword, ${Unsafe(labels)}" } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Label.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Label.scala deleted file mode 100644 index eea39de..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Label.scala +++ /dev/null @@ -1,31 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.logging._ - -final case class Category(id: LongId[Category], name: String) - -object Category { - implicit def toPhiString(x: Category): PhiString = { - import x._ - phi"Category(id=$id, name=${Unsafe(name)})" - } -} - -final case class Label(id: LongId[Label], categoryId: LongId[Category], name: String, description: String) - -object Label { - implicit def toPhiString(x: Label): PhiString = { - import x._ - phi"Label($id, categoryId=${Unsafe(categoryId)}, name=${Unsafe(name)}, description=${Unsafe(description)})" - } -} - -final case class CategoryWithLabels(category: Category, labels: List[Label]) - -object CategoryWithLabels { - implicit def toPhiString(x: CategoryWithLabels): PhiString = { - import x._ - phi"CategoryWithLabels(category=$category, labels=$labels)" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabel.scala index 633a347..d10c7d2 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabel.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabel.scala @@ -1,5 +1,6 @@ package xyz.driver.pdsuidomain.entities +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, UuidId} import xyz.driver.pdsuicommon.logging._ diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabelEvidenceView.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabelEvidenceView.scala index 34e3741..3311d96 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabelEvidenceView.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabelEvidenceView.scala @@ -2,6 +2,7 @@ package xyz.driver.pdsuidomain.entities import java.time.LocalDate +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.domain._ import xyz.driver.pdsuicommon.logging._ diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientLabel.scala index 184782b..689eaa4 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientLabel.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientLabel.scala @@ -2,6 +2,7 @@ package xyz.driver.pdsuidomain.entities import java.time.LocalDate +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, UuidId} import xyz.driver.pdsuicommon.logging._ diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala index 9e69c87..bdbc4ea 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala @@ -2,6 +2,7 @@ package xyz.driver.pdsuidomain.entities import java.time.LocalDateTime +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} import xyz.driver.pdsuicommon.logging._ diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/eligibility.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/eligibility.scala new file mode 100644 index 0000000..aa7a7d2 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/eligibility.scala @@ -0,0 +1,63 @@ +package xyz.driver.pdsuidomain.entities + +import xyz.driver.core.Id +import xyz.driver.core.date.Date +import xyz.driver.entities.assays.AssayType +import xyz.driver.entities.clinic.{ClinicalRecord, TestOrder} +import xyz.driver.entities.common.FullName +import xyz.driver.entities.labels.{Label, LabelValue} +import xyz.driver.entities.patient.CancerType +import xyz.driver.entities.process.ProcessStepExecutionStatus +import xyz.driver.entities.report.Report +import xyz.driver.pdsuidomain.entities.export.trial.ExportTrialWithLabels + +object eligibility { + + sealed trait EvidenceDocument { + val documentType: DocumentType + val providerType: ProviderType + val providerName: Option[String] + val date: Option[Date] + val isDriverDocument: Boolean + } + + final case class MolecularEvidenceDocument(documentType: DocumentType, + providerType: ProviderType, + providerName: Option[String], + date: Option[Date], + reportId: Id[Report], + reportType: AssayType, + isDriverDocument: Boolean = true) + extends EvidenceDocument + + final case class ClinicalEvidenceDocument(documentId: Id[ClinicalEvidenceDocument], + documentType: DocumentType, + providerType: ProviderType, + providerName: Option[String], + date: Option[Date], + requestId: Id[ClinicalRecord], + isDriverDocument: Boolean = false) + extends EvidenceDocument + + // Some fields are optional because they are not in the backend response + final case class Evidence(evidenceId: Option[Id[Evidence]], + evidenceText: String, + labelValue: LabelValue, + document: EvidenceDocument, + isPrimaryValue: Option[Boolean] = None) + + final case class LabelWithEvidence(label: Label, evidence: Seq[Evidence] = Seq.empty) + + final case class LabelMismatchRank(label: Label, + score: Int, + trials: Seq[ExportTrialWithLabels], + evidence: Seq[Evidence]) + final case class MismatchRankedLabels(data: Seq[LabelMismatchRank], labelVersion: Int) + + final case class MatchedPatient(patientId: Id[MatchedPatient], + name: FullName[MatchedPatient], + birthDate: Date, + orderId: Id[TestOrder], + disease: CancerType, + patientDataStatus: ProcessStepExecutionStatus) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabel.scala index c69fc09..2edd707 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabel.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabel.scala @@ -1,8 +1,9 @@ package xyz.driver.pdsuidomain.entities.export.patient +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.domain.LongId import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.{Label, RawPatientLabel} +import xyz.driver.pdsuidomain.entities.RawPatientLabel final case class ExportPatientLabel(id: LongId[Label], evidences: List[ExportPatientLabelEvidence]) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialLabelCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialLabelCriterion.scala index 7bff22c..1f06e0d 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialLabelCriterion.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialLabelCriterion.scala @@ -1,8 +1,9 @@ package xyz.driver.pdsuidomain.entities.export.trial +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.domain._ import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.{Arm, Criterion, Label, RawTrialLabel} +import xyz.driver.pdsuidomain.entities.{Arm, Criterion, RawTrialLabel} final case class ExportTrialLabelCriterion(criterionId: LongId[Criterion], value: Option[Boolean], diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/common.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/common.scala index b259b07..7318ff6 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/common.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/common.scala @@ -2,26 +2,28 @@ package xyz.driver.pdsuidomain.fakes.entities import java.time.{LocalDate, LocalDateTime, LocalTime} -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} +import xyz.driver.core.generators.{nextDouble, nextOption} +import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, StringId, UuidId} import xyz.driver.pdsuidomain.entities.{Trial, TrialHistory} + import scala.util.Random object common { import xyz.driver.core.generators - def nextUuidId[T] = UuidId[T](generators.nextUuid()) + def nextUuidId[T]: UuidId[T] = UuidId[T](generators.nextUuid()) - def nextLongId[T] = LongId[T](generators.nextInt(Int.MaxValue).toLong) + def nextLongId[T]: LongId[T] = LongId[T](generators.nextInt(Int.MaxValue).toLong) - def nextStringId[T] = StringId[T](generators.nextString(maxLength = 20)) + def nextStringId[T]: StringId[T] = StringId[T](generators.nextString(maxLength = 20)) - def nextTrialStatus = generators.oneOf[Trial.Status](Trial.Status.All) + def nextTrialStatus: Trial.Status = generators.oneOf[Trial.Status](Trial.Status.All) - def nextPreviousTrialStatus = generators.oneOf[Trial.Status](Trial.Status.AllPrevious) + def nextPreviousTrialStatus: Trial.Status = generators.oneOf[Trial.Status](Trial.Status.AllPrevious) - def nextLocalDateTime = LocalDateTime.of(nextLocalDate, LocalTime.MIDNIGHT) + def nextLocalDateTime: LocalDateTime = LocalDateTime.of(nextLocalDate, LocalTime.MIDNIGHT) - def nextLocalDate = LocalDate.of( + def nextLocalDate: LocalDate = LocalDate.of( 1970 + Random.nextInt(68), 1 + Random.nextInt(12), 1 + Random.nextInt(28) // all months have at least 28 days @@ -33,4 +35,27 @@ object common { def nextTrialState = generators.oneOf[TrialHistory.State](TrialHistory.State.All) + def genBoundedRange[T](from: T, to: T)(implicit ord: Ordering[T]): (T, T) = { + if (ord.compare(from, to) > 0) { + to -> from + } else { + from -> to + } + } + + def genBoundedRangeOption[T](from: T, to: T)(implicit ord: Ordering[T]): (Option[T], Option[T]) = { + val ranges = nextOption(from).map { left => + val range = genBoundedRange(left, to) + range._1 -> nextOption(range._2) + } + + ranges.map(_._1) -> ranges.flatMap(_._2) + } + + def nextFuzzyValue(): FuzzyValue = + generators.oneOf[FuzzyValue](FuzzyValue.All) + + def nextStartAndEndPages: (Option[Double], Option[Double]) = + genBoundedRangeOption[Double](nextDouble(), nextDouble()) + } diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/eligibility.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/eligibility.scala new file mode 100644 index 0000000..7dc50be --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/eligibility.scala @@ -0,0 +1,72 @@ +package xyz.driver.pdsuidomain.fakes.entities + +import xyz.driver.core.generators +import xyz.driver.entities.clinic.{ClinicalRecord, TestOrder} +import xyz.driver.entities.patient.CancerType +import xyz.driver.entities.report.Report +import xyz.driver.fakes +import xyz.driver.pdsuidomain.entities.eligibility._ + +object eligibility { + import xyz.driver.core.generators._ + + def nextMolecularEvidenceDocument(): MolecularEvidenceDocument = + MolecularEvidenceDocument( + documentType = xyz.driver.pdsuidomain.fakes.entities.rep.DocumentGen.nextDocumentType(), + providerType = xyz.driver.pdsuidomain.fakes.entities.rep.MedicalRecordGen.nextProviderType(), + providerName = nextOption(nextString(100)), + date = nextOption(nextDate()), + reportId = nextId[Report](), + reportType = fakes.entities.assays.nextAssayType(), + isDriverDocument = nextBoolean() + ) + + def nextClinicalEvidenceDocument(): ClinicalEvidenceDocument = + ClinicalEvidenceDocument( + documentType = xyz.driver.pdsuidomain.fakes.entities.rep.DocumentGen.nextDocumentType(), + providerType = xyz.driver.pdsuidomain.fakes.entities.rep.MedicalRecordGen.nextProviderType(), + providerName = nextOption(nextString(100)), + date = nextOption(nextDate()), + documentId = nextId[ClinicalEvidenceDocument](), + requestId = nextId[ClinicalRecord](), + isDriverDocument = nextBoolean() + ) + + def nextEvidenceDocument(): EvidenceDocument = + oneOf[EvidenceDocument](nextMolecularEvidenceDocument(), + nextClinicalEvidenceDocument(), + nextClinicalEvidenceDocument()) // For more clinical documents + + def nextEvidence(): Evidence = + Evidence( + evidenceId = Option(nextId[Evidence]()), + evidenceText = nextString(100), + labelValue = xyz.driver.fakes.entities.labels.nextLabelValue(), + nextEvidenceDocument(), + isPrimaryValue = nextOption(nextBoolean()) + ) + + def nextLabelWithEvidence(): LabelWithEvidence = + LabelWithEvidence(label = fakes.entities.labels.nextLabel(), evidence = Seq.empty) + + def nextLabelMismatchRank(): LabelMismatchRank = + LabelMismatchRank( + label = fakes.entities.labels.nextLabel(), + score = nextInt(100), + trials = seqOf(xyz.driver.pdsuidomain.fakes.entities.export.nextExportTrialWithLabels()), + evidence = seqOf(nextEvidence()) + ) + + def nextMismatchRankedLabels(): MismatchRankedLabels = + MismatchRankedLabels(data = seqOf(nextLabelMismatchRank()), labelVersion = nextInt(100)) + + def nextMatchedPatient(): MatchedPatient = + MatchedPatient( + patientId = nextId[MatchedPatient](), + name = fakes.entities.common.nextFullName[MatchedPatient](), + birthDate = nextDate(), + orderId = nextId[TestOrder](), + disease = generators.oneOf[CancerType](CancerType.Breast, CancerType.Lung, CancerType.Prostate), + patientDataStatus = fakes.entities.process.nextProcessStepExecutionStatus() + ) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/export.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/export.scala new file mode 100644 index 0000000..7f3c410 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/export.scala @@ -0,0 +1,35 @@ +package xyz.driver.pdsuidomain.fakes.entities + +import xyz.driver.entities.labels.Label +import xyz.driver.pdsuidomain.entities.{Arm, Criterion, Trial} +import xyz.driver.pdsuidomain.entities.export.trial._ + +object export { + import xyz.driver.core.generators._ + import common._ + + def nextExportTrialArm(): ExportTrialArm = + ExportTrialArm(armId = nextLongId[Arm], armName = nextString(100)) + + def nextExportTrialLabelCriterion(): ExportTrialLabelCriterion = + ExportTrialLabelCriterion( + criterionId = nextLongId[Criterion], + value = nextOption[Boolean](nextBoolean()), + labelId = nextLongId[Label], + armIds = setOf(nextLongId[Arm]), + criteria = nextString(100), + isCompound = nextBoolean(), + isDefining = nextBoolean() + ) + + def nextExportTrialWithLabels(): ExportTrialWithLabels = + ExportTrialWithLabels( + nctId = nextStringId[Trial], + trialId = nextUuidId[Trial], + condition = nextString(100), + lastReviewed = nextLocalDateTime, + labelVersion = nextInt(100).toLong, + arms = listOf(nextExportTrialArm()), + criteria = listOf(nextExportTrialLabelCriterion()) + ) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/Common.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/Common.scala deleted file mode 100644 index 9618eed..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/Common.scala +++ /dev/null @@ -1,35 +0,0 @@ -package xyz.driver.pdsuidomain.fakes.entities.rep - -import xyz.driver.core.generators -import xyz.driver.core.generators._ -import xyz.driver.pdsuicommon.domain.FuzzyValue - -private[rep] object Common { - def genBoundedRange[T](from: T, to: T)(implicit ord: Ordering[T]): (T, T) = { - if (ord.compare(from, to) > 0) { - to -> from - } else { - from -> to - } - } - - def genBoundedRangeOption[T](from: T, to: T)(implicit ord: Ordering[T]): (Option[T], Option[T]) = { - val ranges = nextOption(from) - .map(left => genBoundedRange(left, to)) - .map { - case (left, right) => - left -> nextOption(right) - } - - ranges.map(_._1) -> ranges.flatMap(_._2) - } - - def nextFuzzyValue(): FuzzyValue = { - generators.oneOf[FuzzyValue](FuzzyValue.All) - } - - def nextStartAndEndPages: (Option[Double], Option[Double]) = { - genBoundedRangeOption[Double](nextDouble(), nextDouble()) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/DocumentGen.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/DocumentGen.scala index 10349bb..6d5330e 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/DocumentGen.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/DocumentGen.scala @@ -4,6 +4,7 @@ import java.time.LocalDate import xyz.driver.core.generators import xyz.driver.core.generators.{nextBoolean, nextDouble, nextOption, nextString} +import xyz.driver.pdsuidomain.fakes.entities.common._ import xyz.driver.pdsuicommon.domain.{LongId, TextJson, User} import xyz.driver.pdsuidomain.entities._ import xyz.driver.pdsuidomain.fakes.entities.common.{nextLocalDate, nextLocalDateTime, nextLongId, nextStringId} @@ -17,13 +18,13 @@ object DocumentGen { } private def nextDates() = - Common.genBoundedRangeOption[LocalDate](nextLocalDate, nextLocalDate) + genBoundedRangeOption[LocalDate](nextLocalDate, nextLocalDate) private def nextStartAndEndPagesOption() = - Common.nextStartAndEndPages + nextStartAndEndPages private def nextStartAndEndPage() = - Common.genBoundedRange(nextDouble(), nextDouble()) + genBoundedRange(nextDouble(), nextDouble()) def nextDocumentStatus(): Document.Status = Document.Status.New diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/ExportPatientGen.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/ExportPatientGen.scala index c2909f3..e3ef6bc 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/ExportPatientGen.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/ExportPatientGen.scala @@ -1,14 +1,11 @@ package xyz.driver.pdsuidomain.fakes.entities.rep import xyz.driver.core.generators._ +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.domain.{LongId, UuidId} +import xyz.driver.pdsuidomain.fakes.entities.common._ import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.entities.export.patient.{ - ExportPatientLabel, - ExportPatientLabelEvidence, - ExportPatientLabelEvidenceDocument, - ExportPatientWithLabels -} +import xyz.driver.pdsuidomain.entities.export.patient._ import xyz.driver.pdsuidomain.fakes.entities.common.{nextLocalDate, nextLongId} object ExportPatientGen { @@ -41,7 +38,7 @@ object ExportPatientGen { def nextExportPatientLabelEvidence(documentId: LongId[Document]): ExportPatientLabelEvidence = { ExportPatientLabelEvidence( id = nextLongId[ExtractedData], - value = Common.nextFuzzyValue(), + value = nextFuzzyValue(), evidenceText = nextString(), document = nextExportPatientLabelEvidenceDocument(documentId) ) diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/ExtractedDataGen.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/ExtractedDataGen.scala index 8ac07d0..8e77445 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/ExtractedDataGen.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/ExtractedDataGen.scala @@ -1,6 +1,7 @@ package xyz.driver.pdsuidomain.fakes.entities.rep import xyz.driver.core.generators._ +import xyz.driver.entities.labels.{Label, LabelCategory} import xyz.driver.pdsuicommon.domain.{LongId, TextJson} import xyz.driver.pdsuidomain.entities._ import xyz.driver.pdsuidomain.entities.ExtractedData.Meta @@ -46,7 +47,7 @@ object ExtractedDataGen { def nextExtractedDataMetaEvidence(): Meta.Evidence = { val layersPosition = - Common.genBoundedRange[ExtractedData.Meta.TextLayerPosition]( + genBoundedRange[ExtractedData.Meta.TextLayerPosition]( nextExtractedDataMetaTextLayerPosition(), nextExtractedDataMetaTextLayerPosition() ) @@ -65,14 +66,8 @@ object ExtractedDataGen { ) } - def nextExtractedDataMetaJson(): TextJson[Meta] = { - TextJson( - ExtractedData.Meta( - nextExtractedDataMetaKeyword(), - nextExtractedDataMetaEvidence() - ) - ) - } + def nextExtractedDataMetaJson(): TextJson[Meta] = + TextJson(ExtractedData.Meta(nextExtractedDataMetaKeyword(), nextExtractedDataMetaEvidence())) def nextExtractedData(documentId: LongId[Document]): ExtractedData = { ExtractedData( @@ -89,8 +84,8 @@ object ExtractedDataGen { id = nextLongId[ExtractedDataLabel], dataId = nextLongId[ExtractedData], labelId = nextOption(nextLongId[Label]), - categoryId = nextOption(nextLongId[Category]), - value = nextOption(Common.nextFuzzyValue()) + categoryId = nextOption(nextLongId[LabelCategory]), + value = nextOption(nextFuzzyValue()) ) } diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/MedicalRecordGen.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/MedicalRecordGen.scala index 7221e66..023dc00 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/MedicalRecordGen.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/MedicalRecordGen.scala @@ -4,7 +4,7 @@ import xyz.driver.pdsuidomain.entities._ import xyz.driver.core.generators import xyz.driver.core.generators._ import xyz.driver.pdsuicommon.domain.{LongId, TextJson, User} -import xyz.driver.pdsuidomain.fakes.entities.common.{nextLocalDateTime, nextLongId, nextStringId, nextUuidId} +import xyz.driver.pdsuidomain.fakes.entities.common._ object MedicalRecordGen { private val maxItemsInCollectionNumber: Int = 50 @@ -126,7 +126,7 @@ object MedicalRecordGen { } def nextMedicalRecordIssue(): MedicalRecordIssue = { - val pages = Common.nextStartAndEndPages + val pages = nextStartAndEndPages MedicalRecordIssue( id = nextLongId[MedicalRecordIssue], @@ -141,4 +141,7 @@ object MedicalRecordGen { ) } + def nextProviderType(): ProviderType = + ProviderType(id = nextLongId[ProviderType], name = nextString()) + } diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/ProviderTypeGen.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/ProviderTypeGen.scala deleted file mode 100644 index 168f7af..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/rep/ProviderTypeGen.scala +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.driver.pdsuidomain.fakes.entities.rep - -import xyz.driver.core.generators.nextString -import xyz.driver.pdsuidomain.entities.ProviderType -import xyz.driver.pdsuidomain.fakes.entities.common.nextLongId - -object ProviderTypeGen { - def nextProviderType(): ProviderType = { - ProviderType( - id = nextLongId[ProviderType], - name = nextString() - ) - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/trialcuration.scala b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/trialcuration.scala index fe5bf09..fcd833a 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/trialcuration.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/fakes/entities/trialcuration.scala @@ -1,5 +1,6 @@ package xyz.driver.pdsuidomain.fakes.entities +import xyz.driver.entities.labels.{Label, LabelCategory} import xyz.driver.pdsuicommon.domain.{LongId, User} import xyz.driver.pdsuidomain.entities._ import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion @@ -51,7 +52,7 @@ object trialcuration { id = nextLongId[CriterionLabel], labelId = Option(nextLongId[Label]), criterionId = criterionId, - categoryId = Option(nextLongId[Category]), + categoryId = Option(nextLongId[LabelCategory]), value = Option(generators.nextBoolean()), isDefining = generators.nextBoolean() ) diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/category/ApiCategory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/category/ApiCategory.scala deleted file mode 100644 index f1e15f3..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/category/ApiCategory.scala +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.category - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuidomain.entities.CategoryWithLabels -import xyz.driver.pdsuidomain.formats.json.label.ApiLabel - -final case class ApiCategory(id: Long, name: String, labels: List[ApiLabel]) - -object ApiCategory { - - implicit val format: Format[ApiCategory] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] and - (JsPath \ "labels").format[List[ApiLabel]] - )(ApiCategory.apply, unlift(ApiCategory.unapply)) - - def fromDomain(categoryWithLabels: CategoryWithLabels) = ApiCategory( - id = categoryWithLabels.category.id.id, - name = categoryWithLabels.category.name, - labels = categoryWithLabels.labels.map(x => ApiLabel(x.id.id, x.name, x.categoryId.id)) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/keyword/ApiKeyword.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/keyword/ApiKeyword.scala deleted file mode 100644 index a9d02fc..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/keyword/ApiKeyword.scala +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.keyword - -import xyz.driver.pdsuidomain.entities.KeywordWithLabels -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuidomain.formats.json.label.ApiLabel - -final case class ApiKeyword(id: Long, keyword: String, labels: List[ApiLabel]) - -object ApiKeyword { - - implicit val format: Format[ApiKeyword] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "keyword").format[String] and - (JsPath \ "labels").format[List[ApiLabel]] - )(ApiKeyword.apply, unlift(ApiKeyword.unapply)) - - def fromDomain(keywordWithLabels: KeywordWithLabels) = ApiKeyword( - id = keywordWithLabels.keyword.id.id, - keyword = keywordWithLabels.keyword.keyword, - labels = keywordWithLabels.labels.map(x => ApiLabel(x.id.id, x.name, x.categoryId.id)) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiCriterionLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiCriterionLabel.scala index 7a65af8..d486749 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiCriterionLabel.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiCriterionLabel.scala @@ -1,10 +1,11 @@ package xyz.driver.pdsuidomain.formats.json.label import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId} -import xyz.driver.pdsuidomain.entities.{Category, Criterion, CriterionLabel, Label} +import xyz.driver.pdsuidomain.entities.{Criterion, CriterionLabel} import play.api.data.validation.ValidationError import play.api.libs.functional.syntax._ import play.api.libs.json._ +import xyz.driver.entities.labels.{Label, LabelCategory} /** * @param value Yes|No @@ -18,7 +19,7 @@ final case class ApiCriterionLabel(labelId: Option[Long], id = LongId(0L), labelId = labelId.map(LongId[Label]), criterionId = criterionId, - categoryId = categoryId.map(LongId[Category]), + categoryId = categoryId.map(LongId[LabelCategory]), value = value.map { case "Yes" => true case "No" => false diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiExtractedDataLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiExtractedDataLabel.scala index cb45025..f8161af 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiExtractedDataLabel.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiExtractedDataLabel.scala @@ -1,10 +1,11 @@ package xyz.driver.pdsuidomain.formats.json.label import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId} -import xyz.driver.pdsuidomain.entities.{Category, ExtractedData, ExtractedDataLabel, Label} +import xyz.driver.pdsuidomain.entities.{ExtractedData, ExtractedDataLabel} import play.api.data.validation.ValidationError import play.api.libs.functional.syntax._ import play.api.libs.json._ +import xyz.driver.entities.labels.{Label, LabelCategory} final case class ApiExtractedDataLabel(id: Option[Long], categoryId: Option[Long], value: Option[String]) { @@ -12,7 +13,7 @@ final case class ApiExtractedDataLabel(id: Option[Long], categoryId: Option[Long id = LongId(0), dataId = dataId, labelId = id.map(LongId[Label]), - categoryId = categoryId.map(LongId[Category]), + categoryId = categoryId.map(LongId[LabelCategory]), value = value.map(FuzzyValue.fromString) ) } diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiLabel.scala deleted file mode 100644 index 042b380..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiLabel.scala +++ /dev/null @@ -1,22 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.label - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuidomain.entities.Label - -final case class ApiLabel(id: Long, name: String, categoryId: Long) - -object ApiLabel { - - implicit val format: Format[ApiLabel] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] and - (JsPath \ "categoryId").format[Long] - )(ApiLabel.apply, unlift(ApiLabel.unapply)) - - def fromDomain(x: Label) = ApiLabel( - id = x.id.id, - name = x.name, - categoryId = x.categoryId.id - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPatientCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPatientCriterion.scala index 75347f4..6eeb40b 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPatientCriterion.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPatientCriterion.scala @@ -3,10 +3,11 @@ package xyz.driver.pdsuidomain.formats.json.patient.trial import java.time.{ZoneId, ZonedDateTime} import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId} -import xyz.driver.pdsuidomain.entities.{Label, PatientCriterion, PatientCriterionArm} +import xyz.driver.pdsuidomain.entities.{PatientCriterion, PatientCriterionArm} import play.api.data.validation.ValidationError import play.api.libs.functional.syntax._ import play.api.libs.json.{Format, JsPath, Reads, Writes} +import xyz.driver.entities.labels.Label final case class ApiPatientCriterion(id: Long, labelId: Long, diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/criterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/criterion.scala index 732bcad..743f885 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/criterion.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/criterion.scala @@ -1,6 +1,7 @@ package xyz.driver.pdsuidomain.formats.json.sprayformats import spray.json._ +import xyz.driver.entities.labels.{Label, LabelCategory} import xyz.driver.pdsuicommon.domain.{LongId, StringId} import xyz.driver.pdsuidomain.entities._ import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion @@ -29,7 +30,7 @@ object criterion { val categoryId = fields .get("categoryId") - .map(_.convertTo[LongId[Category]]) + .map(_.convertTo[LongId[LabelCategory]]) val value = fields .get("value") diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documenttype.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documenttype.scala index 8119d35..7ec6ef5 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documenttype.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documenttype.scala @@ -1,7 +1,6 @@ package xyz.driver.pdsuidomain.formats.json.sprayformats import spray.json._ -import xyz.driver.pdsuidomain.entities._ import xyz.driver.pdsuidomain.entities.DocumentType object documenttype { diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/eligibility.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/eligibility.scala new file mode 100644 index 0000000..30ceae2 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/eligibility.scala @@ -0,0 +1,101 @@ +package xyz.driver.pdsuidomain.formats.json.sprayformats + +import spray.json._ +import DefaultJsonProtocol._ +import xyz.driver.core.Id +import xyz.driver.core.json._ +import xyz.driver.entities.labels.LabelValue +import xyz.driver.pdsuidomain.entities.eligibility._ + +object eligibility { + import xyz.driver.formats.json.assay._ + import xyz.driver.formats.json.common._ + import xyz.driver.formats.json.labels._ + import xyz.driver.formats.json.process._ + import xyz.driver.pdsuidomain.formats.json.sprayformats.document._ + import xyz.driver.pdsuidomain.formats.json.sprayformats.record._ + import xyz.driver.pdsuidomain.formats.json.sprayformats.export._ + + implicit val molecularDocumentFormat: RootJsonFormat[MolecularEvidenceDocument] = jsonFormat7( + MolecularEvidenceDocument) + implicit val clinicalDocumentFormat: RootJsonFormat[ClinicalEvidenceDocument] = jsonFormat7(ClinicalEvidenceDocument) + + implicit val evidenceDocumentFormat: RootJsonFormat[EvidenceDocument] = + GadtJsonFormat.create[EvidenceDocument]("documentType") { + case _: MolecularEvidenceDocument => "Molecular" + case _: ClinicalEvidenceDocument => "Clinical" + } { + case "Molecular" => molecularDocumentFormat + case "Clinical" => clinicalDocumentFormat + } + + implicit object evidenceFormat extends RootJsonFormat[Evidence] { + + override def write(evidence: Evidence): JsValue = { + JsObject( + "evidenceId" -> evidence.evidenceId.toJson, + "evidenceText" -> evidence.evidenceText.toJson, + "labelValue" -> evidence.labelValue.toJson, + "document" -> evidence.document.toJson, + "isPrimaryValue" -> evidence.isPrimaryValue.toJson + ) + } + + override def read(json: JsValue): Evidence = { + json match { + case JsObject(fields) => + val evidenceId = fields + .get("evidenceId") + .map(_.convertTo[Id[Evidence]]) + + val evidenceText = fields + .get("evidenceText") + .map(_.convertTo[String]) + .getOrElse(deserializationError(s"Evidence json object do not contain 'evidenceText' field: $json")) + + val labelValue = fields + .get("labelValue") + .map(_.convertTo[LabelValue]) + .getOrElse(deserializationError(s"Evidence json object do not contain 'labelValue' field: $json")) + + val isDriverDocument = fields + .get("document") + .flatMap { + case JsObject(fieldMap) => + fieldMap + .get("isDriverDocument") + .map(_.convertTo[Boolean]) + case _ => deserializationError(s"Expected Json Object as 'isDriverDocument', but got $json") + } + .getOrElse(deserializationError(s"Evidence json object do not contain 'document' field: $json")) + + val document = customDocumentParser(isDriverDocument, fields, json) + + val isPrimaryValue = fields + .get("isPrimaryValue") + .map(_.convertTo[Option[Boolean]]) + .getOrElse(deserializationError(s"Evidence json object do not contain 'isPrimaryValue' field: $json")) + + Evidence(evidenceId, evidenceText, labelValue, document, isPrimaryValue) + case _ => deserializationError(s"Expected Json Object as 'Evidence', but got $json") + } + } + + def customDocumentParser(isDriverDocument: Boolean, + fields: Map[String, JsValue], + json: JsValue): EvidenceDocument = { + fields.get("document").fold { deserializationError(s"Expected Json Object as 'Document', but got $json") } { + document => + if (isDriverDocument) document.convertTo[MolecularEvidenceDocument] + else document.convertTo[ClinicalEvidenceDocument] + } + } + } + + implicit def labelWithEvidenceJsonFormat: RootJsonFormat[LabelWithEvidence] = jsonFormat2(LabelWithEvidence) + + implicit def labelRankingFormat: RootJsonFormat[LabelMismatchRank] = jsonFormat4(LabelMismatchRank) + implicit def labelRankingsFormat: RootJsonFormat[MismatchRankedLabels] = jsonFormat2(MismatchRankedLabels) + + implicit def matchedPatientFormat: RootJsonFormat[MatchedPatient] = jsonFormat6(MatchedPatient) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala index 2a1fe46..39d5c59 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala @@ -1,7 +1,8 @@ package xyz.driver.pdsuidomain.formats.json.sprayformats import spray.json._ -import xyz.driver.pdsuidomain.entities.{Arm, Criterion, Label} +import xyz.driver.entities.labels.Label +import xyz.driver.pdsuidomain.entities.{Arm, Criterion} import xyz.driver.pdsuidomain.entities.export.patient._ import xyz.driver.pdsuidomain.entities.export.trial.{ExportTrialArm, ExportTrialLabelCriterion, ExportTrialWithLabels} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/extracteddata.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/extracteddata.scala index 42473bc..d6eadbd 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/extracteddata.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/extracteddata.scala @@ -1,6 +1,7 @@ package xyz.driver.pdsuidomain.formats.json.sprayformats import spray.json._ +import xyz.driver.entities.labels.{Label, LabelCategory} import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, TextJson} import xyz.driver.pdsuidomain.entities._ import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData @@ -39,7 +40,7 @@ object extracteddata { val categoryId = fields .get("categoryId") - .map(_.convertTo[LongId[Category]]) + .map(_.convertTo[LongId[LabelCategory]]) val value = fields .get("value") diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientcriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientcriterion.scala index 53e927d..b091746 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientcriterion.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientcriterion.scala @@ -1,6 +1,7 @@ package xyz.driver.pdsuidomain.formats.json.sprayformats import spray.json._ +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId} import xyz.driver.pdsuidomain.entities._ import xyz.driver.pdsuidomain.services.PatientCriterionService.DraftPatientCriterion diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/providerttype.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/providerttype.scala deleted file mode 100644 index 385feb2..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/providerttype.scala +++ /dev/null @@ -1,12 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuidomain.entities.ProviderType - -object providertype { - import DefaultJsonProtocol._ - import common._ - - implicit val providerTypeFormat: RootJsonFormat[ProviderType] = jsonFormat2(ProviderType.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/providertype.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/providertype.scala new file mode 100644 index 0000000..385feb2 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/providertype.scala @@ -0,0 +1,12 @@ +package xyz.driver.pdsuidomain.formats.json.sprayformats + +import spray.json._ +import xyz.driver.pdsuidomain.entities.ProviderType + +object providertype { + import DefaultJsonProtocol._ + import common._ + + implicit val providerTypeFormat: RootJsonFormat[ProviderType] = jsonFormat2(ProviderType.apply) + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/EligibilityVerificationService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/EligibilityVerificationService.scala new file mode 100644 index 0000000..d3e977e --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/EligibilityVerificationService.scala @@ -0,0 +1,18 @@ +package xyz.driver.pdsuidomain.services + +import xyz.driver.core.Id +import xyz.driver.core.rest.ServiceRequestContext +import xyz.driver.entities.patient.CancerType +import xyz.driver.pdsuidomain.entities.eligibility.{MatchedPatient, MismatchRankedLabels} +import xyz.driver.pdsuidomain.entities.{Arm, Patient} + +import scala.concurrent.Future +import scalaz.ListT + +trait EligibilityVerificationService { + + def getMatchedPatients()(implicit ctx: ServiceRequestContext): ListT[Future, MatchedPatient] + + def getMismatchRankedLabels(patientId: Id[Patient], cancerType: CancerType, excludedArms: Seq[Id[Arm]])( + implicit ctx: ServiceRequestContext): Future[MismatchRankedLabels] +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala index 9ff3879..6d85f85 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala @@ -2,6 +2,7 @@ package xyz.driver.pdsuidomain.services import java.time.LocalDateTime +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain._ diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala index 2c17f74..abb3f8a 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala @@ -1,5 +1,6 @@ package xyz.driver.pdsuidomain.services +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} import xyz.driver.pdsuicommon.domain.{LongId, UuidId} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala index 56e2e3d..6871f3e 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala @@ -1,5 +1,6 @@ package xyz.driver.pdsuidomain.services +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain.{LongId, UuidId} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala index 71b8bd4..2a4d7fc 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala @@ -1,5 +1,6 @@ package xyz.driver.pdsuidomain.services +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain._ diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/fake/FakeEligibilityVerificationService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/fake/FakeEligibilityVerificationService.scala new file mode 100644 index 0000000..c5531f9 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/fake/FakeEligibilityVerificationService.scala @@ -0,0 +1,28 @@ +package xyz.driver.pdsuidomain.services.fake + +import xyz.driver.core.rest.ServiceRequestContext +import xyz.driver.core.{Id, generators} +import xyz.driver.entities.patient +import xyz.driver.pdsuidomain.entities.eligibility.MismatchRankedLabels +import xyz.driver.pdsuidomain.entities.{Arm, Patient, eligibility} +import xyz.driver.pdsuidomain.services.EligibilityVerificationService + +import scala.concurrent.Future +import scalaz.ListT + +class FakeEligibilityVerificationService extends EligibilityVerificationService { + + override def getMatchedPatients()(implicit ctx: ServiceRequestContext): ListT[Future, eligibility.MatchedPatient] = + ListT.listT[Future]( + Future.successful(List(xyz.driver.pdsuidomain.fakes.entities.eligibility.nextMatchedPatient()))) + + override def getMismatchRankedLabels( + patientId: Id[Patient], + cancerType: patient.CancerType, + excludedArms: Seq[Id[Arm]])(implicit ctx: ServiceRequestContext): Future[eligibility.MismatchRankedLabels] = + Future.successful( + MismatchRankedLabels( + generators.seqOf(xyz.driver.pdsuidomain.fakes.entities.eligibility.nextLabelMismatchRank()), + labelVersion = generators.nextInt(10) + )) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/fake/FakeTrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/fake/FakeTrialService.scala index 3793c1f..9aeb820 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/fake/FakeTrialService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/fake/FakeTrialService.scala @@ -6,10 +6,11 @@ import akka.NotUsed import akka.stream.scaladsl.Source import akka.util.ByteString import xyz.driver.core.generators +import xyz.driver.entities.labels.Label import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext import xyz.driver.pdsuicommon.db._ import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.{Arm, Criterion, Label, Trial} +import xyz.driver.pdsuidomain.entities.{Arm, Criterion, Trial} import xyz.driver.pdsuidomain.entities.export.trial.{ExportTrialArm, ExportTrialLabelCriterion, ExportTrialWithLabels} import xyz.driver.pdsuidomain.services.TrialService diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestEligibilityVerificationService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestEligibilityVerificationService.scala new file mode 100644 index 0000000..07757e3 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestEligibilityVerificationService.scala @@ -0,0 +1,43 @@ +package xyz.driver.pdsuidomain.services.rest + +import akka.http.scaladsl.model.Uri +import akka.stream.Materializer +import spray.json.DefaultJsonProtocol +import xyz.driver.core.Id +import xyz.driver.core.rest.{RestService, ServiceRequestContext, ServiceTransport} +import xyz.driver.entities.patient +import xyz.driver.pdsuidomain.entities.eligibility.{MatchedPatient, MismatchRankedLabels} +import xyz.driver.pdsuidomain.entities.{Arm, Patient, eligibility} +import xyz.driver.pdsuidomain.services.EligibilityVerificationService + +import scala.concurrent.{ExecutionContext, Future} +import scalaz.ListT +import scalaz.Scalaz.futureInstance + +class RestEligibilityVerificationService(transport: ServiceTransport, baseUri: Uri)( + implicit protected val materializer: Materializer, + protected val exec: ExecutionContext +) extends EligibilityVerificationService with RestService { + + import DefaultJsonProtocol._ + import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ + import xyz.driver.pdsuidomain.formats.json.sprayformats.eligibility._ + + override def getMatchedPatients()(implicit ctx: ServiceRequestContext): ListT[Future, eligibility.MatchedPatient] = { + val request = get(baseUri, s"/v1/patients") + listResponse[MatchedPatient](transport.sendRequest(ctx)(request)) + } + + override def getMismatchRankedLabels(patientId: Id[Patient], + cancerType: patient.CancerType, + excludedArms: Seq[Id[Arm]])( + implicit ctx: ServiceRequestContext): Future[eligibility.MismatchRankedLabels] = { + + val query = + Seq("disease" -> cancerType.toString.toUpperCase, "ineligible_arms" -> excludedArms.map(_.value).mkString(",")) + + val request = get(baseUri, s"/v1/patients/$patientId/labels", query) + optionalResponse[MismatchRankedLabels](transport.sendRequest(ctx)(request)) + .getOrElse(throw new Exception(s"The data of patient $patientId is not ready yet")) + } +} diff --git a/src/test/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParserSuite.scala b/src/test/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParserSuite.scala index ba67d13..5deaecb 100644 --- a/src/test/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParserSuite.scala +++ b/src/test/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParserSuite.scala @@ -14,7 +14,7 @@ import xyz.driver.pdsuicommon.db.SearchFilterNAryOperation.In import xyz.driver.pdsuicommon.utils.Utils import xyz.driver.pdsuicommon.utils.Utils._ -import scala.util.Success +import scala.util._ object SearchFilterParserSuite { @@ -133,6 +133,17 @@ class SearchFilterParserSuite extends FreeSpecLike with Checkers { } "n-ary" - { + "actual record Ids" - { + "should not be parsed with text values" in { + val filter = SearchFilterParser.parse(Seq("filters" -> "id IN 1,5")) + filter match { + case Success(_) => () + case Failure(t) => t.printStackTrace() + } + assert(filter === Success(SearchFilterExpr.Atom.NAry(Dimension(None, "id"), In, Seq(Long.box(1), Long.box(5))))) + } + } + "in" in check { val testQueryGen = queryGen( dimensionGen = Gen.identifier, -- cgit v1.2.3