diff options
322 files changed, 1106 insertions, 16630 deletions
diff --git a/.travis.yml b/.travis.yml index 6155e77..4a859d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,4 +6,5 @@ jdk: scala: - 2.11.8 -script: "sbt clean test" +script: + - echo 'credentials += Credentials("Artifactory Realm", "drivergrp.jfrog.io", "sbt-publisher", sys.env("ARTIFACTORY_PASSWORD"))' > project/credentials.sbt "sbt clean test" @@ -1,3 +1,19 @@ -# PDS UI Common Library +# REST Query library -To make a change, create a PR, merge to master, do `sbt scalafmt`, follow instructions. +Allows to read queries from the REST requests (query parameters) and map them to the typed SQL Slick queries. +Supports ANDs and ORs, pagination and sorting. + +Queries can be build in the code as well (e.g., for testing): + +``` +SearchFilterExpr.Atom.NAry("id", In, objects.map(x => Long.box(x.id))) +``` + +or + +``` +SearchFilterExpr.Union(Seq( + SearchFilterExpr.Atom.Binary("status", Eq, "New"), + SearchFilterExpr.Atom.Binary("status", Eq, "Verified") +) +``` @@ -2,33 +2,17 @@ import sbt._ import Keys._ lazy val core = (project in file(".")) - .driverLibrary("pds-ui-common") - .settings(scalastyleSettings ++ wartRemoverSettings ++ formatSettings) - .settings(wartremoverErrors in (Compile, compile) --= Seq( - Wart.ImplicitConversion, Wart.MutableDataStructures, Wart.TraversableOps, Wart.OptionPartial)) + .driverLibrary("rest-query") + .settings(lintingSettings ++ formatSettings) .settings(sources in (Compile, doc) := Seq.empty, publishArtifact in (Compile, packageDoc) := false) .settings(libraryDependencies ++= Seq( - "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.8.3", - "com.github.pureconfig" %% "pureconfig" % "0.7.2", - "com.lihaoyi" %% "fastparse" % "0.3.7", - "com.typesafe.akka" %% "akka-http" % "10.0.9", - "com.typesafe.play" %% "play" % "2.5.15", + "com.typesafe.akka" %% "akka-http" % "10.0.10", + "com.lihaoyi" %% "fastparse" % "1.0.0", + "xyz.driver" %% "core" % "1.6.12", "com.typesafe.scala-logging" %% "scala-logging" % "3.5.0", - "io.getquill" %% "quill-jdbc" % "1.2.1", - "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.3", - "xyz.driver" %% "domain-model" % "0.12.5", + "org.slf4j" % "slf4j-api" % "1.7.21", "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", - "com.google.cloud" % "google-cloud-storage" % "1.2.1", - "com.sendgrid" % "sendgrid-java" % "3.1.0" exclude ("org.mockito", "mockito-core"), "com.typesafe" % "config" % "1.3.0", - "org.asynchttpclient" % "async-http-client" % "2.0.24", - "org.slf4j" % "slf4j-api" % "1.7.21", - "ai.x" %% "diff" % "1.2.0-get-simple-name-fix" % "test", "org.scalacheck" %% "scalacheck" % "1.13.4" % "test", "org.scalatest" %% "scalatest" % "3.0.1" % "test" )) diff --git a/project/build.properties b/project/build.properties index 3507256..9abea12 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1,4 +1 @@ -#Activator-generated Properties -#Wed Jul 06 16:08:49 PDT 2016 -template.uuid=a675a7df-bee3-48df-9eaa-688d99e5814e -sbt.version=0.13.16 +sbt.version=1.0.3 diff --git a/project/plugins.sbt b/project/plugins.sbt index 83fdd9a..1ef8b09 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,3 @@ resolvers += "releases" at "https://drivergrp.jfrog.io/drivergrp/releases" -credentials += Credentials("Artifactory Realm", "drivergrp.jfrog.io", "sbt-publisher", "ANC-d8X-Whm-USS") -addSbtPlugin("xyz.driver" % "sbt-settings" % "0.7.39") +addSbtPlugin("xyz.driver" % "sbt-settings" % "1.0.6") diff --git a/src/main/scala/xyz/driver/pdsuicommon/Config.scala b/src/main/scala/xyz/driver/pdsuicommon/Config.scala deleted file mode 100644 index 25686b8..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/Config.scala +++ /dev/null @@ -1,21 +0,0 @@ -package xyz.driver.pdsuicommon - -import pureconfig._ - -import scala.util.{Failure, Success, Try} - -object Config { - - implicit def productHint[T]: ProductHint[T] = ProductHint(ConfigFieldMapping(CamelCase, CamelCase)) - - def loadConfig[Config](implicit reader: ConfigReader[Config]): Try[Config] = pureconfig.loadConfig match { - case Right(x) => Success(x) - case Left(e) => Failure(new RuntimeException(e.toString)) - } - - def loadConfig[Config](namespace: String)(implicit reader: ConfigReader[Config]): Try[Config] = - pureconfig.loadConfig(namespace) match { - case Right(x) => Success(x) - case Left(e) => Failure(new RuntimeException(e.toString)) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/acl/ACL.scala b/src/main/scala/xyz/driver/pdsuicommon/acl/ACL.scala deleted file mode 100644 index f2a0ef0..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/acl/ACL.scala +++ /dev/null @@ -1,270 +0,0 @@ -package xyz.driver.pdsuicommon.acl - -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext - -/** - * @see https://driverinc.atlassian.net/wiki/display/RA/User+permissions#UserPermissions-AccessControlList - */ -object ACL extends PhiLogging { - - import xyz.driver.pdsuicommon.domain.User.Role - import Role._ - - type AclCheck = Role => Boolean - - val Forbid: AclCheck = _ => false - - val Allow: AclCheck = _ => true - - // Common - - object UserHistory - extends BaseACL( - label = "user history", - read = Set(TreatmentMatchingAdmin) - ) - - object Queue - extends BaseACL( - label = "queue", - create = Set(SystemUser), - read = Set(SystemUser), - update = Set(SystemUser) - ) - - // REP - - object MedicalRecord - extends BaseACL( - label = "medical record", - read = RepRoles + RoutesCurator + TreatmentMatchingAdmin + ResearchOncologist + SystemUser, - update = RepRoles - DocumentExtractor - ) - - object MedicalRecordHistory - extends BaseACL( - label = "medical record history", - read = Set(RecordAdmin) - ) - - object MedicalRecordIssue - extends BaseACL( - label = "medical record issue", - create = Set(RecordCleaner, RecordOrganizer, RecordAdmin), - read = Set(RecordCleaner, RecordOrganizer, RecordAdmin), - update = Set(RecordCleaner, RecordOrganizer, RecordAdmin), - delete = Set(RecordCleaner, RecordOrganizer, RecordAdmin) - ) - - object Document - extends BaseACL( - label = "document", - create = Set(RecordOrganizer, RecordAdmin), - read = RepRoles - RecordCleaner + RoutesCurator + TreatmentMatchingAdmin + ResearchOncologist, - update = RepRoles - RecordCleaner, - delete = Set(RecordOrganizer, RecordAdmin) - ) - - object DocumentHistory - extends BaseACL( - label = "document history", - read = Set(RecordAdmin) - ) - - object DocumentIssue - extends BaseACL( - label = "document issue", - create = Set(RecordAdmin, DocumentExtractor), - read = Set(RecordAdmin, DocumentExtractor), - update = Set(RecordAdmin, DocumentExtractor), - delete = Set(RecordAdmin, DocumentExtractor) - ) - - object ExtractedData - extends BaseACL( - label = "extracted data", - create = Set(DocumentExtractor, RecordAdmin), - read = Set(DocumentExtractor, RecordAdmin, RoutesCurator, TreatmentMatchingAdmin, ResearchOncologist), - update = Set(DocumentExtractor, RecordAdmin), - delete = Set(DocumentExtractor, RecordAdmin) - ) - - object ProviderType - extends BaseACL( - label = "provider type", - read = RepRoles + RoutesCurator + TreatmentMatchingAdmin + ResearchOncologist - ) - - object DocumentType - extends BaseACL( - label = "document type", - read = RepRoles + RoutesCurator + TreatmentMatchingAdmin + ResearchOncologist - ) - - object Message - extends BaseACL( - label = "message", - create = RepRoles ++ TreatmentMatchingRoles, - read = RepRoles ++ TreatmentMatchingRoles, - update = RepRoles ++ TreatmentMatchingRoles, - delete = RepRoles ++ TreatmentMatchingRoles - ) - - // TC - - object Trial - extends BaseACL( - label = "trial", - read = TcRoles + RoutesCurator + TreatmentMatchingAdmin + ResearchOncologist + SystemUser, - update = TcRoles - ) - - object TrialHistory - extends BaseACL( - label = "trial history", - read = Set(TrialAdmin) - ) - - object TrialIssue - extends BaseACL( - label = "trial issue", - create = TcRoles, - read = TcRoles, - update = TcRoles, - delete = TcRoles - ) - - object StudyDesign - extends BaseACL( - label = "study design", - read = Set(TrialSummarizer, TrialAdmin) - ) - - object Hypothesis - extends BaseACL( - label = "hypothesis", - read = Set(TrialSummarizer, TrialAdmin) ++ TreatmentMatchingRoles - ) - - object Criterion - extends BaseACL( - label = "criterion", - create = Set(CriteriaCurator, TrialAdmin), - read = Set(CriteriaCurator, TrialAdmin, RoutesCurator, TreatmentMatchingAdmin, ResearchOncologist), - update = Set(CriteriaCurator, TrialAdmin), - delete = Set(CriteriaCurator, TrialAdmin) - ) - - object Arm - extends BaseACL( - label = "arm", - create = Set(TrialSummarizer, TrialAdmin), - read = TcRoles, - update = Set(TrialSummarizer, TrialAdmin), - delete = Set(TrialSummarizer, TrialAdmin) - ) - - object Intervention - extends BaseACL( - label = "intervention", - read = Set(TrialSummarizer, TrialAdmin), - update = Set(TrialSummarizer, TrialAdmin) - ) - - object InterventionType - extends BaseACL( - label = "intervention type", - read = Set(TrialSummarizer, TrialAdmin) - ) - - // EV - - object Patient - extends BaseACL( - label = "patient", - read = TreatmentMatchingRoles + ResearchOncologist + SystemUser, - update = TreatmentMatchingRoles - ) - - object PatientHistory - extends BaseACL( - label = "patient history", - read = Set(TreatmentMatchingAdmin) - ) - - object PatientIssue - extends BaseACL( - label = "patient issue", - create = TreatmentMatchingRoles, - read = TreatmentMatchingRoles, - update = TreatmentMatchingRoles, - delete = TreatmentMatchingRoles - ) - - object PatientLabel - extends BaseACL( - label = "patient label", - read = TreatmentMatchingRoles + ResearchOncologist, - update = TreatmentMatchingRoles - ) - - object PatientCriterion - extends BaseACL( - label = "patient criterion", - read = TreatmentMatchingRoles + ResearchOncologist, - update = TreatmentMatchingRoles - ) - - object PatientLabelEvidence - extends BaseACL( - label = "patient label evidence", - read = TreatmentMatchingRoles + ResearchOncologist - ) - - object EligibleTrial - extends BaseACL( - label = "eligible trial", - read = Set(RoutesCurator, TreatmentMatchingAdmin, ResearchOncologist), - update = Set(RoutesCurator, TreatmentMatchingAdmin) - ) - - object PatientHypothesis - extends BaseACL( - label = "patient hypothesis", - read = Set(RoutesCurator, TreatmentMatchingAdmin), - update = Set(RoutesCurator, TreatmentMatchingAdmin) - ) - - // Utility code - - abstract class BaseACL(label: String, - create: AclCheck = Forbid, - read: AclCheck = Forbid, - update: AclCheck = Forbid, - delete: AclCheck = Forbid) { - - def isCreateAllow()(implicit requestContext: AuthenticatedRequestContext): Boolean = { - check("create", create)(requestContext.executor.roles) - } - - def isReadAllow()(implicit requestContext: AuthenticatedRequestContext): Boolean = { - check("read", read)(requestContext.executor.roles) - } - - def isUpdateAllow()(implicit requestContext: AuthenticatedRequestContext): Boolean = { - check("update", update)(requestContext.executor.roles) - } - - def isDeleteAllow()(implicit requestContext: AuthenticatedRequestContext): Boolean = { - check("delete", delete)(requestContext.executor.roles) - } - - private def check(action: String, isAllowed: AclCheck)(executorRoles: Set[Role]): Boolean = { - loggedError( - executorRoles.exists(isAllowed), - phi"${Unsafe(executorRoles.mkString(", "))} has no access to ${Unsafe(action)} a ${Unsafe(label)}" - ) - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/auth/AnonymousRequestContext.scala b/src/main/scala/xyz/driver/pdsuicommon/auth/AnonymousRequestContext.scala deleted file mode 100644 index c677ef8..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/auth/AnonymousRequestContext.scala +++ /dev/null @@ -1,11 +0,0 @@ -package xyz.driver.pdsuicommon.auth - -class AnonymousRequestContext(val requestId: RequestId) { - - override def equals(that: Any): Boolean = { - that.getClass == classOf[AnonymousRequestContext] && - that.asInstanceOf[AnonymousRequestContext].requestId == requestId - } - - override def hashCode(): Int = requestId.hashCode() -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/auth/AuthenticatedRequestContext.scala b/src/main/scala/xyz/driver/pdsuicommon/auth/AuthenticatedRequestContext.scala deleted file mode 100644 index 5c07a9a..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/auth/AuthenticatedRequestContext.scala +++ /dev/null @@ -1,36 +0,0 @@ -package xyz.driver.pdsuicommon.auth - -import xyz.driver.entities.users.AuthUserInfo -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.domain.User - -class AuthenticatedRequestContext(val driverUser: AuthUserInfo, - override val requestId: RequestId, - val authToken: String) - extends AnonymousRequestContext(requestId) { - - val executor: User = new User(driverUser) - - override def equals(that: Any): Boolean = { - that.getClass == this.getClass && { - val another = that.asInstanceOf[AuthenticatedRequestContext] - another.executor == executor && another.requestId == requestId - } - } - - override def hashCode(): Int = { - val initial = 37 - val first = initial * 17 + executor.hashCode() - first * 17 + requestId.hashCode() - } -} - -object AuthenticatedRequestContext { - - def apply(driverUser: AuthUserInfo, authToken: String = "") = - new AuthenticatedRequestContext(driverUser, RequestId(), authToken) - - implicit def toPhiString(x: AuthenticatedRequestContext): PhiString = { - phi"AuthenticatedRequestContext(executor=${x.executor}, requestId=${x.requestId})" - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/auth/RequestId.scala b/src/main/scala/xyz/driver/pdsuicommon/auth/RequestId.scala deleted file mode 100644 index 9982bb0..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/auth/RequestId.scala +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.driver.pdsuicommon.auth - -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.auth.RequestId._ -import xyz.driver.pdsuicommon.utils.RandomUtils - -final case class RequestId(value: String = RandomUtils.randomString(IdLength)) - -object RequestId { - - private val IdLength = 20 - - implicit def toPhiString(x: RequestId): PhiString = phi"RequestId(${Unsafe(x.value)})" -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/compat/EitherOps.scala b/src/main/scala/xyz/driver/pdsuicommon/compat/EitherOps.scala deleted file mode 100644 index d069f86..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/compat/EitherOps.scala +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.driver.pdsuicommon.compat - -final class EitherOps[A, B](val self: Either[A, B]) extends AnyVal { - - def map[B2](f: B => B2): Either[A, B2] = flatMap { x => - Right(f(x)) - } - - def flatMap[B2](f: B => Either[A, B2]): Either[A, B2] = self match { - case Left(x) => Left(x) - case Right(x) => f(x) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/compat/Implicits.scala b/src/main/scala/xyz/driver/pdsuicommon/compat/Implicits.scala deleted file mode 100644 index 147c9e8..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/compat/Implicits.scala +++ /dev/null @@ -1,7 +0,0 @@ -package xyz.driver.pdsuicommon.compat - -object Implicits { - - implicit def toEitherOps[A, B](self: Either[A, B]): EitherOps[A, B] = new EitherOps(self) - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/computation/Computation.scala b/src/main/scala/xyz/driver/pdsuicommon/computation/Computation.scala deleted file mode 100644 index a9430e3..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/computation/Computation.scala +++ /dev/null @@ -1,124 +0,0 @@ -package xyz.driver.pdsuicommon.computation - -import scala.concurrent.{ExecutionContext, Future} - -/** - * Takes care of computations - * - * Success(either) - the computation will be continued. - * Failure(error) - the computation was failed with unhandled error. - * - * Either[Result, T]: - * Left(result) is a final and handled result, another computations (map, flatMap) will be ignored. - * Right(T) is a current result. Functions in map/flatMap will continue the computation. - * - * Example: - * {{{ - * import scala.concurrent.ExecutionContext.Implicits.global - * import scala.concurrent.{ExecutionContext, Future} - * import xyz.driver.pdsuicommon.computation.Computation - * - * def successful = for { - * x <- Computation.continue(1) - * y <- Computation.continue(2) - * } yield s"\$x + \$y" - * - * // Prints "Success(1 + 2)" - * successful.join.onComplete(print) - * - * def failed = for { - * x <- Computation.abort("Failed on x") - * _ = print("Second step") - * y <- Computation.continue(2) - * } yield s"\$x + \$y" - * - * // Prints "Success(Failed on x)" - * failed.join.onComplete(print) - * }}} - * - * TODO: Make future private - * - * @param future The final flow in a future. - * @tparam R Type of result for aborted computation. - * @tparam T Type of result for continued computation. - */ -final case class Computation[+R, +T](future: Future[Either[R, T]]) { - - def flatMap[R2, T2](f: T => Computation[R2, T2])(implicit ec: ExecutionContext, ev: R <:< R2): Computation[R2, T2] = { - Computation(future.flatMap { - case Left(x) => Future.successful(Left(x)) - case Right(x) => f(x).future - }) - } - - def processExceptions[R2](f: PartialFunction[Throwable, R2])(implicit ev1: R <:< R2, - ec: ExecutionContext): Computation[R2, T] = { - val strategy = f.andThen(x => Left(x): Either[R2, T]) - val castedFuture: Future[Either[R2, T]] = future.map { - case Left(x) => Left(x) - case Right(x) => Right(x) - } - Computation(castedFuture.recover(strategy)) - } - - def map[T2](f: T => T2)(implicit ec: ExecutionContext): Computation[R, T2] = flatMap { a => - Computation.continue(f(a)) - } - - def mapLeft[R2](f: R => R2)(implicit ec: ExecutionContext): Computation[R2, T] = { - Computation(future.map { - case Left(x) => Left(f(x)) - case Right(x) => Right(x) - }) - } - - def mapAll[R2, T2](onLeft: R => Computation[R2, T2])(onRight: T => Computation[R2, T2])( - onFailure: () => Computation[R2, T2])(implicit ec: ExecutionContext): Computation[R2, T2] = { - - Computation(future.flatMap(_.fold(onLeft, onRight).future).recoverWith { - case _ => onFailure().future - }) - } - - def andThen(f: T => Any)(implicit ec: ExecutionContext): Computation[R, T] = map { a => - f(a) - a - } - - def filter(f: T => Boolean)(implicit ec: ExecutionContext): Computation[R, T] = map { a => - if (f(a)) a - else throw new NoSuchElementException("When filtering") - } - - def withFilter(f: T => Boolean)(implicit ec: ExecutionContext): Computation[R, T] = filter(f) - - def foreach[T2](f: T => T2)(implicit ec: ExecutionContext): Unit = future.foreach { - case Right(x) => f(x) - case _ => - } - - def toFuture[R2](resultFormatter: T => R2)(implicit ec: ExecutionContext, ev: R <:< R2): Future[R2] = future.map { - case Left(x) => x - case Right(x) => resultFormatter(x) - } - - def toFuture[R2](implicit ec: ExecutionContext, ev1: R <:< R2, ev2: T <:< R2): Future[R2] = future.map { - case Left(x) => x - case Right(x) => x - } -} - -object Computation { - - def continue[T](x: T): Computation[Nothing, T] = Computation(Future.successful(Right(x))) - - def abort[R](result: R): Computation[R, Nothing] = Computation(Future.successful(Left(result))) - - def fail(exception: Throwable): Computation[Nothing, Nothing] = Computation(Future.failed(exception)) - - def fromFuture[T](input: Future[T])(implicit ec: ExecutionContext): Computation[Nothing, T] = Computation { - input.map { x => - Right(x) - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueue.scala b/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueue.scala deleted file mode 100644 index 8213262..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueue.scala +++ /dev/null @@ -1,84 +0,0 @@ -package xyz.driver.pdsuicommon.concurrent - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue.Item -import xyz.driver.pdsuicommon.logging._ - -import scala.concurrent.Future - -object BridgeUploadQueue { - - /** - * @param kind For example documents - * @param tag For example, a patient's id: 1 - * @param attempts Which attempt - * @param created When the task was created - * @param nextAttempt Time of the next attempt - */ - final case class Item(kind: String, - tag: String, - created: LocalDateTime, - attempts: Int, - nextAttempt: LocalDateTime, - completed: Boolean, - dependencyKind: Option[String], - dependencyTag: Option[String]) { - - def dependency: Option[Dependency] = { - dependencyKind - .zip(dependencyTag) - .headOption - .map(Function.tupled(Dependency.apply)) - } - - } - - object Item { - - implicit def toPhiString(x: Item): PhiString = { - import x._ - phi"BridgeUploadQueue.Item(kind=${Unsafe(kind)}, tag=${Unsafe(tag)}, " + - phi"attempts=${Unsafe(attempts)}, start=$created, nextAttempt=$nextAttempt, completed=$completed, " + - phi"dependency=$dependency)" - } - - def apply(kind: String, tag: String, dependency: Option[Dependency] = None): Item = { - val now = LocalDateTime.now() - - Item( - kind = kind, - tag = tag, - created = now, - attempts = 0, - nextAttempt = now, - completed = false, - dependencyKind = dependency.map(_.kind), - dependencyTag = dependency.map(_.tag) - ) - } - - } - - final case class Dependency(kind: String, tag: String) - - object Dependency { - - implicit def toPhiString(x: Dependency): PhiString = { - import x._ - phi"Dependency(kind=${Unsafe(kind)}, tag=${Unsafe(tag)})" - } - } -} - -trait BridgeUploadQueue { - - def add(item: Item): Future[Item] - - def get(kind: String): Future[Option[Item]] - - def complete(kind: String, tag: String): Future[Unit] - - def tryRetry(item: Item): Future[Option[Item]] - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapter.scala b/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapter.scala deleted file mode 100644 index 3bf9192..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapter.scala +++ /dev/null @@ -1,140 +0,0 @@ -package xyz.driver.pdsuicommon.concurrent - -import java.time.LocalDateTime -import java.time.temporal.ChronoUnit - -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue.Item -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueueRepositoryAdapter.Strategy -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.db.repositories.BridgeUploadQueueRepository -import xyz.driver.pdsuicommon.logging._ - -import scala.concurrent.duration.{Duration, FiniteDuration} -import scala.concurrent.{ExecutionContext, Future} -import scala.util.Try - -object BridgeUploadQueueRepositoryAdapter { - - /** - * Defines how we work with queue, when an user attempts to remove/tryRetry an item. - */ - sealed trait Strategy { - - def onComplete: Strategy.OnComplete - - def on(attempt: Int): Strategy.OnAttempt - - } - - object Strategy { - - /** - * Works forever, but has a limit for intervals. - */ - final case class LimitExponential(startInterval: FiniteDuration, - intervalFactor: Double, - maxInterval: FiniteDuration, - onComplete: OnComplete) - extends Strategy { - - override def on(attempt: Int): OnAttempt = { - OnAttempt.Continue(intervalFor(attempt).min(maxInterval)) - } - - private def intervalFor(attempt: Int): Duration = { - Try(startInterval * Math.pow(intervalFactor, attempt.toDouble)) - .getOrElse(maxInterval) - } - } - - /** - * Used only in tests. - */ - final case class Stop(onComplete: OnComplete = OnComplete.Delete) extends Strategy { - - override def on(attempt: Int) = OnAttempt.Complete - - } - - /** - * Used only in tests. - */ - final case class Constant(interval: FiniteDuration) extends Strategy { - - override val onComplete = OnComplete.Delete - - override def on(attempt: Int) = OnAttempt.Continue(interval) - - } - - sealed trait OnComplete - object OnComplete { - case object Delete extends OnComplete - case object Mark extends OnComplete - - implicit def toPhiString(x: OnAttempt): PhiString = Unsafe(x.toString) - } - - sealed trait OnAttempt - object OnAttempt { - case object Complete extends OnAttempt - final case class Continue(interval: Duration) extends OnAttempt - - implicit def toPhiString(x: OnAttempt): PhiString = Unsafe(x.toString) - } - } -} - -class BridgeUploadQueueRepositoryAdapter(strategy: Strategy, repository: BridgeUploadQueueRepository, dbIo: DbIo)( - implicit executionContext: ExecutionContext) - extends BridgeUploadQueue with PhiLogging { - - override def add(item: Item): Future[Item] = dbIo.runAsync(repository.add(item)) - - override def get(kind: String): Future[Option[Item]] = dbIo.runAsync(repository.getOne(kind)) - - override def complete(kind: String, tag: String): Future[Unit] = { - import Strategy.OnComplete._ - - strategy.onComplete match { - case Delete => dbIo.runAsync(repository.delete(kind, tag)) - case Mark => - dbIo.runAsyncTx { - repository.getById(kind, tag) match { - case Some(x) => repository.update(x.copy(completed = true)) - case None => throw new RuntimeException(s"Can not find the task: kind=$kind, tag=$tag") - } - } - } - } - - /** - * Tries to continue the task or complete it - */ - override def tryRetry(item: Item): Future[Option[Item]] = { - import Strategy.OnAttempt._ - - logger.trace(phi"tryRetry($item)") - - val newAttempts = item.attempts + 1 - val action = strategy.on(newAttempts) - logger.debug(phi"Action for ${Unsafe(newAttempts)}: $action") - - action match { - case Continue(newInterval) => - val draftItem = item.copy( - attempts = newAttempts, - nextAttempt = LocalDateTime.now().plus(newInterval.toMillis, ChronoUnit.MILLIS) - ) - - logger.debug(draftItem) - dbIo.runAsync { - Some(repository.update(draftItem)) - } - - case Complete => - logger.warn(phi"All attempts are out for $item, complete the task") - complete(item.kind, item.tag).map(_ => None) - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/concurrent/Cron.scala b/src/main/scala/xyz/driver/pdsuicommon/concurrent/Cron.scala deleted file mode 100644 index 6659088..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/concurrent/Cron.scala +++ /dev/null @@ -1,93 +0,0 @@ -package xyz.driver.pdsuicommon.concurrent - -import java.io.Closeable -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.atomic.AtomicBoolean -import java.util.{Timer, TimerTask} - -import com.typesafe.scalalogging.StrictLogging -import org.slf4j.MDC -import xyz.driver.pdsuicommon.error.ExceptionFormatter -import xyz.driver.pdsuicommon.utils.RandomUtils - -import scala.concurrent.duration.FiniteDuration -import scala.concurrent.{ExecutionContext, Future} -import scala.util.{Failure, Success, Try} - -class Cron(settings: Cron.Settings) extends Closeable with StrictLogging { - - import Cron._ - - private val timer = new Timer("cronTimer", true) - - private val jobs = ConcurrentHashMap.newKeySet[String]() - - def register(name: String)(job: () => Future[Unit])(implicit ec: ExecutionContext): Unit = { - logger.trace("register({})", name) - val disableList = settings.disable.split(",").map(_.trim).toList - if (disableList.contains(name)) logger.info("The task '{}' is disabled", name) - else { - settings.intervals.get(name) match { - case None => - logger.error("Can not find an interval for task '{}', check the settings", name) - throw new IllegalArgumentException(s"Can not find an interval for task '$name', check the settings") - - case Some(period) => - logger.info("register a new task '{}' with a period of {}ms", name, period.toMillis.asInstanceOf[AnyRef]) - timer.schedule(new SingletonTask(name, job), 0, period.toMillis) - } - } - - jobs.add(name) - } - - /** - * Checks unused jobs - */ - def verify(): Unit = { - import scala.collection.JavaConverters._ - - val unusedJobs = settings.intervals.keySet -- jobs.asScala.toSet - unusedJobs.foreach { job => - logger.warn(s"The job '$job' is listed, but not registered or ignored") - } - } - - override def close(): Unit = { - timer.cancel() - } -} - -object Cron { - - final case class Settings(disable: String, intervals: Map[String, FiniteDuration]) - - private class SingletonTask(taskName: String, job: () => Future[Unit])(implicit ec: ExecutionContext) - extends TimerTask with StrictLogging { - - private val isWorking = new AtomicBoolean(false) - - override def run(): Unit = { - if (isWorking.compareAndSet(false, true)) { - MDC.put("userId", "cron") - MDC.put("requestId", RandomUtils.randomString(15)) - - logger.info("Start '{}'", taskName) - Try { - job() - .andThen { - case Success(_) => logger.info("'{}' is completed", taskName) - case Failure(e) => logger.error(s"Job '{}' is failed: ${ExceptionFormatter.format(e)}", taskName) - } - .onComplete(_ => isWorking.set(false)) - } match { - case Success(_) => - case Failure(e) => - logger.error("Can't start '{}'", taskName, e) - } - } else { - logger.debug("The previous job '{}' is in progress", taskName) - } - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/concurrent/InMemoryBridgeUploadQueue.scala b/src/main/scala/xyz/driver/pdsuicommon/concurrent/InMemoryBridgeUploadQueue.scala deleted file mode 100644 index 658b5b1..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/concurrent/InMemoryBridgeUploadQueue.scala +++ /dev/null @@ -1,37 +0,0 @@ -package xyz.driver.pdsuicommon.concurrent - -import java.util.concurrent.LinkedBlockingQueue -import java.util.function.Predicate - -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue.Item -import xyz.driver.pdsuicommon.logging.PhiLogging - -import scala.collection.JavaConverters._ -import scala.concurrent.Future - -/** - * Use it only for tests - */ -class InMemoryBridgeUploadQueue extends BridgeUploadQueue with PhiLogging { - - private val queue = new LinkedBlockingQueue[Item]() - - override def add(item: Item): Future[Item] = { - queue.add(item) - Future.successful(item) - } - - override def tryRetry(item: Item): Future[Option[Item]] = Future.successful(Some(item)) - - override def get(kind: String): Future[Option[Item]] = { - val r = queue.iterator().asScala.find(_.kind == kind) - Future.successful(r) - } - - override def complete(kind: String, tag: String): Future[Unit] = { - queue.removeIf(new Predicate[Item] { - override def test(t: Item): Boolean = t.kind == kind && t.tag == tag - }) - Future.successful(()) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/concurrent/MdcExecutionContext.scala b/src/main/scala/xyz/driver/pdsuicommon/concurrent/MdcExecutionContext.scala deleted file mode 100644 index 3dee8ea..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/concurrent/MdcExecutionContext.scala +++ /dev/null @@ -1,35 +0,0 @@ -package xyz.driver.pdsuicommon.concurrent - -import org.slf4j.MDC - -import scala.concurrent.{ExecutionContext, ExecutionContextExecutor} - -object MdcExecutionContext { - def from(orig: ExecutionContext): ExecutionContext = new MdcExecutionContext(orig) -} - -class MdcExecutionContext(orig: ExecutionContext) extends ExecutionContextExecutor { - - def execute(runnable: Runnable): Unit = { - val parentMdcContext = MDC.getCopyOfContextMap - - orig.execute(new Runnable { - def run(): Unit = { - val saveMdcContext = MDC.getCopyOfContextMap - setContextMap(parentMdcContext) - - try { - runnable.run() - } finally { - setContextMap(saveMdcContext) - } - } - }) - } - - private[this] def setContextMap(context: java.util.Map[String, String]): Unit = - Option(context).fold(MDC.clear())(MDC.setContextMap) - - def reportFailure(t: Throwable): Unit = orig.reportFailure(t) - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/concurrent/MdcThreadFactory.scala b/src/main/scala/xyz/driver/pdsuicommon/concurrent/MdcThreadFactory.scala deleted file mode 100644 index d1dc3ae..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/concurrent/MdcThreadFactory.scala +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.driver.pdsuicommon.concurrent - -import java.util.concurrent.ThreadFactory - -import org.slf4j.MDC - -object MdcThreadFactory { - def from(orig: ThreadFactory): ThreadFactory = new MdcThreadFactory(orig) -} - -class MdcThreadFactory(orig: ThreadFactory) extends ThreadFactory { - - override def newThread(runnable: Runnable): Thread = { - val parentMdcContext = MDC.getCopyOfContextMap - - orig.newThread(new Runnable { - def run(): Unit = { - val saveMdcContext = MDC.getCopyOfContextMap - setContextMap(parentMdcContext) - - try { - runnable.run() - } finally { - setContextMap(saveMdcContext) - } - } - }) - } - - private[this] def setContextMap(context: java.util.Map[String, String]): Unit = - Option(context).fold(MDC.clear())(MDC.setContextMap) - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/concurrent/SafeBridgeUploadQueue.scala b/src/main/scala/xyz/driver/pdsuicommon/concurrent/SafeBridgeUploadQueue.scala deleted file mode 100644 index 2f7fe6c..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/concurrent/SafeBridgeUploadQueue.scala +++ /dev/null @@ -1,60 +0,0 @@ -package xyz.driver.pdsuicommon.concurrent - -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue.Dependency -import xyz.driver.pdsuicommon.concurrent.SafeBridgeUploadQueue.{DependencyResolver, SafeTask, Tag} -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.serialization.Marshaller - -import scala.concurrent.{ExecutionContext, Future} - -object SafeBridgeUploadQueue { - - trait Tag extends Product with Serializable - - final case class SafeTask[T <: Tag](tag: T, private[SafeBridgeUploadQueue] val queueItem: BridgeUploadQueue.Item) - - object SafeTask { - implicit def toPhiString[T <: Tag](x: SafeTask[T]): PhiString = { - import x._ - phi"SafeTask(tag=${Unsafe(tag)}, $queueItem)" - } - } - - trait DependencyResolver[T <: Tag] { - def getDependency(tag: T): Option[Dependency] - } - -} - -class SafeBridgeUploadQueue[T <: Tag](kind: String, origQueue: BridgeUploadQueue)( - implicit tagMarshaller: Marshaller[T, String], - dependencyResolver: DependencyResolver[T], - executionContext: ExecutionContext) { - - type Task = SafeTask[T] - - def add(tag: T): Future[BridgeUploadQueue.Item] = - origQueue.add( - BridgeUploadQueue.Item( - kind = kind, - tag = tagMarshaller.write(tag), - dependency = dependencyResolver.getDependency(tag) - )) - - def tryRetry(task: Task): Future[Option[Task]] = wrap(origQueue.tryRetry(task.queueItem)) - - def get: Future[Option[Task]] = wrap(origQueue.get(kind)) - - def complete(tag: T): Future[Unit] = origQueue.complete(kind, tagMarshaller.write(tag)) - - private def wrap(x: Future[Option[BridgeUploadQueue.Item]]): Future[Option[Task]] = x.map(_.map(cover)) - - private def cover(rawTask: BridgeUploadQueue.Item): Task = { - val tag = tagMarshaller - .read(rawTask.tag) - .getOrElse(throw new IllegalArgumentException(s"Can not parse tag '${rawTask.tag}'")) - - SafeTask(tag, rawTask) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/DbCommand.scala b/src/main/scala/xyz/driver/pdsuicommon/db/DbCommand.scala deleted file mode 100644 index 0af104e..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/DbCommand.scala +++ /dev/null @@ -1,15 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import scala.concurrent.Future - -trait DbCommand { - def runSync(): Unit - def runAsync(transactions: DbIo): Future[Unit] -} - -object DbCommand { - val Empty: DbCommand = new DbCommand { - override def runSync(): Unit = {} - override def runAsync(transactions: DbIo): Future[Unit] = Future.successful(()) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/DbCommandFactory.scala b/src/main/scala/xyz/driver/pdsuicommon/db/DbCommandFactory.scala deleted file mode 100644 index 1e2fb74..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/DbCommandFactory.scala +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import scala.concurrent.{ExecutionContext, Future} - -trait DbCommandFactory[T] { - def createCommand(orig: T)(implicit ec: ExecutionContext): Future[DbCommand] -} - -object DbCommandFactory { - def empty[T]: DbCommandFactory[T] = new DbCommandFactory[T] { - override def createCommand(orig: T)(implicit ec: ExecutionContext): Future[DbCommand] = - Future.successful(DbCommand.Empty) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/DbIo.scala b/src/main/scala/xyz/driver/pdsuicommon/db/DbIo.scala deleted file mode 100644 index 7c290d1..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/DbIo.scala +++ /dev/null @@ -1,13 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import scala.concurrent.Future - -/** - * Where queries should run - */ -trait DbIo { - def runAsync[T](f: => T): Future[T] - def runSync[T](f: => T): T = f - def runAsyncTx[T](f: => T): Future[T] - def runSyncTx[T](f: => T): Unit -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/EntityExtractorDerivation.scala b/src/main/scala/xyz/driver/pdsuicommon/db/EntityExtractorDerivation.scala deleted file mode 100644 index 02ba322..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/EntityExtractorDerivation.scala +++ /dev/null @@ -1,66 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import java.sql.ResultSet - -import io.getquill.NamingStrategy -import io.getquill.dsl.EncodingDsl - -import scala.language.experimental.macros -import scala.reflect.macros.blackbox - -trait EntityExtractorDerivation[Naming <: NamingStrategy] { this: EncodingDsl => - - /* - Simple Quill extractor derivation for [[T]] - Only case classes available. Type parameters is not supported - */ - def entityExtractor[T]: (ResultSet => T) = macro EntityExtractorDerivation.impl[T] -} - -object EntityExtractorDerivation { - def impl[T: c.WeakTypeTag](c: blackbox.Context): c.Tree = { - import c.universe._ - val namingStrategy = c.prefix.actualType - .baseType(c.weakTypeOf[EntityExtractorDerivation[NamingStrategy]].typeSymbol) - .typeArgs - .head - .typeSymbol - .companion - val functionBody = { - val tpe = weakTypeOf[T] - val resultOpt = tpe.decls.collectFirst { - // Find first constructor of T - case cons: MethodSymbol if cons.isConstructor => - // Create param list for constructor - val params = cons.paramLists.flatten.map { param => - val t = param.typeSignature - val paramName = param.name.toString - val col = q"$namingStrategy.column($paramName)" - // Resolve implicit decoders (from SqlContext) and apply ResultSet for each - val d = q"implicitly[${c.prefix}.Decoder[$t]]" - // Minus 1 cause Quill JDBC decoders make plus one. - // ¯\_(ツ)_/¯ - val i = q"row.findColumn($col) - 1" - val decoderName = TermName(paramName + "Decoder") - val valueName = TermName(paramName + "Value") - ( - q"val $decoderName = $d", - q"val $valueName = $decoderName($i, row)", - valueName - ) - } - // Call constructor with param list - q""" - ..${params.map(_._1)} - ..${params.map(_._2)} - new $tpe(..${params.map(_._3)}) - """ - } - resultOpt match { - case Some(result) => result - case None => c.abort(c.enclosingPosition, s"Can not derive extractor for $tpe. Constructor not found.") - } - } - q"(row: java.sql.ResultSet) => $functionBody" - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/EntityNotFoundException.scala b/src/main/scala/xyz/driver/pdsuicommon/db/EntityNotFoundException.scala deleted file mode 100644 index d765833..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/EntityNotFoundException.scala +++ /dev/null @@ -1,10 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import xyz.driver.pdsuicommon.domain.Id - -class EntityNotFoundException(id: String, tableName: String) - extends RuntimeException(s"Entity with id $id is not found in $tableName table") { - - def this(id: Id[_], tableName: String) = this(id.toString, tableName) - def this(id: Long, tableName: String) = this(id.toString, tableName) -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/FakeDbIo.scala b/src/main/scala/xyz/driver/pdsuicommon/db/FakeDbIo.scala deleted file mode 100644 index ac42a34..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/FakeDbIo.scala +++ /dev/null @@ -1,9 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import scala.concurrent.Future - -object FakeDbIo extends DbIo { - override def runAsync[T](f: => T): Future[T] = Future.successful(f) - override def runAsyncTx[T](f: => T): Future[T] = Future.successful(f) - override def runSyncTx[T](f: => T): Unit = f -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala b/src/main/scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala deleted file mode 100644 index 44f177c..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/JdbcDbIo.scala +++ /dev/null @@ -1,28 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import xyz.driver.pdsuicommon.logging._ - -import scala.concurrent.Future -import scala.util.{Failure, Success, Try} - -class JdbcDbIo(sqlContext: TransactionalContext) extends DbIo with PhiLogging { - - override def runAsync[T](f: => T): Future[T] = { - Future(f)(sqlContext.executionContext) - } - - override def runAsyncTx[T](f: => T): Future[T] = { - import sqlContext.executionContext - - Future(sqlContext.transaction(f)).andThen { - case Failure(e) => logger.error(phi"Can't run a transaction: $e") - } - } - - override def runSyncTx[T](f: => T): Unit = { - Try(sqlContext.transaction(f)) match { - case Success(_) => - case Failure(e) => logger.error(phi"Can't run a transaction: $e") - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/MySqlContext.scala b/src/main/scala/xyz/driver/pdsuicommon/db/MySqlContext.scala deleted file mode 100644 index 9d2664d..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/MySqlContext.scala +++ /dev/null @@ -1,90 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import java.io.Closeable -import java.time._ -import java.util.concurrent.Executors -import javax.sql.DataSource - -import com.typesafe.config.Config -import io.getquill._ -import xyz.driver.pdsuicommon.concurrent.MdcExecutionContext -import xyz.driver.pdsuicommon.db.MySqlContext.Settings -import xyz.driver.pdsuicommon.error.IncorrectIdException -import xyz.driver.pdsuicommon.logging._ - -import scala.concurrent.ExecutionContext -import scala.util.control.NonFatal -import scala.util.{Failure, Success, Try} - -object MySqlContext extends PhiLogging { - - final case class DbCredentials(user: String, - password: String, - host: String, - port: Int, - dbName: String, - dbCreateFlag: Boolean, - dbContext: String, - connectionParams: String, - url: String) - - final case class Settings(credentials: DbCredentials, connection: Config, threadPoolSize: Int) - - def apply(settings: Settings): MySqlContext = { - // Prevent leaking credentials to a log - Try(JdbcContextConfig(settings.connection).dataSource) match { - case Success(dataSource) => new MySqlContext(dataSource, settings) - case Failure(NonFatal(e)) => - logger.error(phi"Can not load dataSource, error: ${Unsafe(e.getClass.getName)}") - throw new IllegalArgumentException("Can not load dataSource from config. Check your database and config") - } - } -} - -class MySqlContext(dataSource: DataSource with Closeable, settings: Settings) - extends MysqlJdbcContext[MysqlEscape](dataSource) with TransactionalContext - with EntityExtractorDerivation[Literal] { - - private val tpe = Executors.newFixedThreadPool(settings.threadPoolSize) - - implicit val executionContext: ExecutionContext = { - val orig = ExecutionContext.fromExecutor(tpe) - MdcExecutionContext.from(orig) - } - - override def close(): Unit = { - super.close() - tpe.shutdownNow() - } - - /** - * Overrode, because Quill JDBC optionDecoder pass null inside decoders. - * If custom decoder don't have special null handler, it will failed. - * - * @see https://github.com/getquill/quill/issues/535 - */ - implicit override def optionDecoder[T](implicit d: Decoder[T]): Decoder[Option[T]] = - decoder( - sqlType = d.sqlType, - row => - index => { - try { - val res = d(index - 1, row) - if (row.wasNull) { - None - } else { - Some(res) - } - } catch { - case _: NullPointerException => None - case _: IncorrectIdException => None - } - } - ) - - final implicit class LocalDateTimeDbOps(val left: LocalDateTime) { - - // scalastyle:off - def <=(right: LocalDateTime): Quoted[Boolean] = quote(infix"$left <= $right".as[Boolean]) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/MysqlQueryBuilder.scala b/src/main/scala/xyz/driver/pdsuicommon/db/MysqlQueryBuilder.scala deleted file mode 100644 index e2936e3..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/MysqlQueryBuilder.scala +++ /dev/null @@ -1,88 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import java.sql.ResultSet - -import xyz.driver.pdsuicommon.logging._ -import io.getquill.{MySQLDialect, MysqlEscape} - -import scala.collection.breakOut - -object MysqlQueryBuilder extends PhiLogging { - import xyz.driver.pdsuicommon.db.QueryBuilder._ - - def apply[T](tableName: String, - lastUpdateFieldName: Option[String], - nullableFields: Set[String], - links: Set[TableLink], - runner: Runner[T], - countRunner: CountRunner): MysqlQueryBuilder[T] = { - val parameters = MysqlQueryBuilderParameters( - tableData = TableData(tableName, lastUpdateFieldName, nullableFields), - links = links.map(x => x.foreignTableName -> x)(breakOut) - ) - new MysqlQueryBuilder[T](parameters)(runner, countRunner) - } - - def apply[T](tableName: String, - lastUpdateFieldName: Option[String], - nullableFields: Set[String], - links: Set[TableLink], - extractor: (ResultSet) => T)(implicit sqlContext: MySqlContext): MysqlQueryBuilder[T] = { - - val runner: Runner[T] = { parameters => - val (sql, binder) = parameters.toSql(namingStrategy = MysqlEscape) - logger.trace(phi"Query for execute: ${Unsafe(sql)}") - sqlContext.executeQuery[T](sql, binder, { resultSet => - extractor(resultSet) - }) - } - - val countRunner: CountRunner = { parameters => - val (sql, binder) = parameters.toSql(countQuery = true, namingStrategy = MysqlEscape) - logger.trace(phi"Query for execute: ${Unsafe(sql)}") - sqlContext - .executeQuery[CountResult]( - sql, - binder, { resultSet => - val count = resultSet.getInt(1) - val lastUpdate = if (parameters.tableData.lastUpdateFieldName.isDefined) { - Option(sqlContext.localDateTimeDecoder.decoder(2, resultSet)) - } else None - - (count, lastUpdate) - } - ) - .head - } - - apply[T]( - tableName = tableName, - lastUpdateFieldName = lastUpdateFieldName, - nullableFields = nullableFields, - links = links, - runner = runner, - countRunner = countRunner - ) - } -} - -class MysqlQueryBuilder[T](parameters: MysqlQueryBuilderParameters)(implicit runner: QueryBuilder.Runner[T], - countRunner: QueryBuilder.CountRunner) - extends QueryBuilder[T, MySQLDialect, MysqlEscape](parameters) { - - def withFilter(newFilter: SearchFilterExpr): QueryBuilder[T, MySQLDialect, MysqlEscape] = { - new MysqlQueryBuilder[T](parameters.copy(filter = newFilter)) - } - - def withSorting(newSorting: Sorting): QueryBuilder[T, MySQLDialect, MysqlEscape] = { - new MysqlQueryBuilder[T](parameters.copy(sorting = newSorting)) - } - - def withPagination(newPagination: Pagination): QueryBuilder[T, MySQLDialect, MysqlEscape] = { - new MysqlQueryBuilder[T](parameters.copy(pagination = Some(newPagination))) - } - - def resetPagination: QueryBuilder[T, MySQLDialect, MysqlEscape] = { - new MysqlQueryBuilder[T](parameters.copy(pagination = None)) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/QueryBuilder.scala b/src/main/scala/xyz/driver/pdsuicommon/db/QueryBuilder.scala deleted file mode 100644 index aa32166..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/QueryBuilder.scala +++ /dev/null @@ -1,340 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import java.sql.PreparedStatement -import java.time.LocalDateTime - -import io.getquill.NamingStrategy -import io.getquill.context.sql.idiom.SqlIdiom -import xyz.driver.pdsuicommon.db.Sorting.{Dimension, Sequential} -import xyz.driver.pdsuicommon.db.SortingOrder.{Ascending, Descending} - -import scala.collection.mutable.ListBuffer - -object QueryBuilder { - - type Runner[T] = QueryBuilderParameters => Seq[T] - - type CountResult = (Int, Option[LocalDateTime]) - - type CountRunner = QueryBuilderParameters => CountResult - - /** - * Binder for PreparedStatement - */ - type Binder = PreparedStatement => PreparedStatement - - final case class TableData(tableName: String, - lastUpdateFieldName: Option[String] = None, - nullableFields: Set[String] = Set.empty) - - val AllFields = Set("*") - -} - -final case class TableLink(keyColumnName: String, foreignTableName: String, foreignKeyColumnName: String) - -object QueryBuilderParameters { - val AllFields = Set("*") -} - -sealed trait QueryBuilderParameters { - - def tableData: QueryBuilder.TableData - def links: Map[String, TableLink] - def filter: SearchFilterExpr - def sorting: Sorting - def pagination: Option[Pagination] - - def findLink(tableName: String): TableLink = links.get(tableName) match { - case None => throw new IllegalArgumentException(s"Cannot find a link for `$tableName`") - case Some(link) => link - } - - def toSql(countQuery: Boolean = false, namingStrategy: NamingStrategy): (String, QueryBuilder.Binder) = { - toSql(countQuery, QueryBuilderParameters.AllFields, namingStrategy) - } - - def toSql(countQuery: Boolean, fields: Set[String], namingStrategy: NamingStrategy): (String, QueryBuilder.Binder) = { - val escapedTableName = namingStrategy.table(tableData.tableName) - val fieldsSql: String = if (countQuery) { - val suffix: String = (tableData.lastUpdateFieldName match { - case Some(lastUpdateField) => s", max($escapedTableName.${namingStrategy.column(lastUpdateField)})" - case None => "" - }) - "count(*)" + suffix - } else { - if (fields == QueryBuilderParameters.AllFields) { - s"$escapedTableName.*" - } else { - fields - .map { field => - s"$escapedTableName.${namingStrategy.column(field)}" - } - .mkString(", ") - } - } - val (where, bindings) = filterToSql(escapedTableName, filter, namingStrategy) - val orderBy = sortingToSql(escapedTableName, sorting, namingStrategy) - - val limitSql = limitToSql() - - val sql = new StringBuilder() - sql.append("select ") - sql.append(fieldsSql) - sql.append("\nfrom ") - sql.append(escapedTableName) - - val filtersTableLinks: Seq[TableLink] = { - import SearchFilterExpr._ - def aux(expr: SearchFilterExpr): Seq[TableLink] = expr match { - case Atom.TableName(tableName) => List(findLink(tableName)) - case Intersection(xs) => xs.flatMap(aux) - case Union(xs) => xs.flatMap(aux) - case _ => Nil - } - aux(filter) - } - - val sortingTableLinks: Seq[TableLink] = Sorting.collect(sorting) { - case Dimension(Some(foreignTableName), _, _) => findLink(foreignTableName) - } - - // Combine links from sorting and filter without duplicates - val foreignTableLinks = (filtersTableLinks ++ sortingTableLinks).distinct - - foreignTableLinks.foreach { - case TableLink(keyColumnName, foreignTableName, foreignKeyColumnName) => - val escapedForeignTableName = namingStrategy.table(foreignTableName) - - sql.append("\ninner join ") - sql.append(escapedForeignTableName) - sql.append(" on ") - - sql.append(escapedTableName) - sql.append('.') - sql.append(namingStrategy.column(keyColumnName)) - - sql.append(" = ") - - sql.append(escapedForeignTableName) - sql.append('.') - sql.append(namingStrategy.column(foreignKeyColumnName)) - } - - if (where.nonEmpty) { - sql.append("\nwhere ") - sql.append(where) - } - - if (orderBy.nonEmpty && !countQuery) { - sql.append("\norder by ") - sql.append(orderBy) - } - - if (limitSql.nonEmpty && !countQuery) { - sql.append("\n") - sql.append(limitSql) - } - - (sql.toString, binder(bindings)) - } - - /** - * Converts filter expression to SQL expression. - * - * @return Returns SQL string and list of values for binding in prepared statement. - */ - protected def filterToSql(escapedTableName: String, - filter: SearchFilterExpr, - namingStrategy: NamingStrategy): (String, List[AnyRef]) = { - import SearchFilterBinaryOperation._ - import SearchFilterExpr._ - - def isNull(string: AnyRef) = Option(string).isEmpty || string.toString.toLowerCase == "null" - - def placeholder(field: String) = "?" - - def escapeDimension(dimension: SearchFilterExpr.Dimension) = { - val tableName = dimension.tableName.fold(escapedTableName)(namingStrategy.table) - s"$tableName.${namingStrategy.column(dimension.name)}" - } - - def filterToSqlMultiple(operands: Seq[SearchFilterExpr]) = operands.collect { - case x if !SearchFilterExpr.isEmpty(x) => filterToSql(escapedTableName, x, namingStrategy) - } - - filter match { - case x if isEmpty(x) => - ("", List.empty) - - case AllowAll => - ("1", List.empty) - - case DenyAll => - ("0", List.empty) - - case Atom.Binary(dimension, Eq, value) if isNull(value) => - (s"${escapeDimension(dimension)} is NULL", List.empty) - - case Atom.Binary(dimension, NotEq, value) if isNull(value) => - (s"${escapeDimension(dimension)} is not NULL", List.empty) - - case Atom.Binary(dimension, NotEq, value) if tableData.nullableFields.contains(dimension.name) => - // In MySQL NULL <> Any === NULL - // So, to handle NotEq for nullable fields we need to use more complex SQL expression. - // http://dev.mysql.com/doc/refman/5.7/en/working-with-null.html - val escapedColumn = escapeDimension(dimension) - val sql = s"($escapedColumn is null or $escapedColumn != ${placeholder(dimension.name)})" - (sql, List(value)) - - case Atom.Binary(dimension, op, value) => - val operator = op match { - case Eq => "=" - case NotEq => "!=" - case Like => "like" - case Gt => ">" - case GtEq => ">=" - case Lt => "<" - case LtEq => "<=" - } - (s"${escapeDimension(dimension)} $operator ${placeholder(dimension.name)}", List(value)) - - case Atom.NAry(dimension, op, values) => - val sqlOp = op match { - case SearchFilterNAryOperation.In => "in" - case SearchFilterNAryOperation.NotIn => "not in" - } - - val bindings = ListBuffer[AnyRef]() - val sqlPlaceholder = placeholder(dimension.name) - val formattedValues = if (values.nonEmpty) { - values - .map { value => - bindings += value - sqlPlaceholder - } - .mkString(", ") - } else "NULL" - (s"${escapeDimension(dimension)} $sqlOp ($formattedValues)", bindings.toList) - - case Intersection(operands) => - val (sql, bindings) = filterToSqlMultiple(operands).unzip - (sql.mkString("(", " and ", ")"), bindings.flatten.toList) - - case Union(operands) => - val (sql, bindings) = filterToSqlMultiple(operands).unzip - (sql.mkString("(", " or ", ")"), bindings.flatten.toList) - } - } - - protected def limitToSql(): String - - /** - * @param escapedMainTableName Should be escaped - */ - protected def sortingToSql(escapedMainTableName: String, sorting: Sorting, namingStrategy: NamingStrategy): String = { - sorting match { - case Dimension(optSortingTableName, field, order) => - val sortingTableName = optSortingTableName.map(namingStrategy.table).getOrElse(escapedMainTableName) - val fullName = s"$sortingTableName.${namingStrategy.column(field)}" - - s"$fullName ${orderToSql(order)}" - - case Sequential(xs) => - xs.map(sortingToSql(escapedMainTableName, _, namingStrategy)).mkString(", ") - } - } - - protected def orderToSql(x: SortingOrder): String = x match { - case Ascending => "asc" - case Descending => "desc" - } - - protected def binder(bindings: List[AnyRef])(bind: PreparedStatement): PreparedStatement = { - bindings.zipWithIndex.foreach { - case (binding, index) => - bind.setObject(index + 1, binding) - } - - bind - } - -} - -final case class PostgresQueryBuilderParameters(tableData: QueryBuilder.TableData, - links: Map[String, TableLink] = Map.empty, - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Sorting = Sorting.Empty, - pagination: Option[Pagination] = None) - extends QueryBuilderParameters { - - def limitToSql(): String = { - pagination.map { pagination => - val startFrom = (pagination.pageNumber - 1) * pagination.pageSize - s"limit ${pagination.pageSize} OFFSET $startFrom" - } getOrElse "" - } - -} - -/** - * @param links Links to another tables grouped by foreignTableName - */ -final case class MysqlQueryBuilderParameters(tableData: QueryBuilder.TableData, - links: Map[String, TableLink] = Map.empty, - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Sorting = Sorting.Empty, - pagination: Option[Pagination] = None) - extends QueryBuilderParameters { - - def limitToSql(): String = - pagination - .map { pagination => - val startFrom = (pagination.pageNumber - 1) * pagination.pageSize - s"limit $startFrom, ${pagination.pageSize}" - } - .getOrElse("") - -} - -abstract class QueryBuilder[T, D <: SqlIdiom, N <: NamingStrategy](val parameters: QueryBuilderParameters)( - implicit runner: QueryBuilder.Runner[T], - countRunner: QueryBuilder.CountRunner) { - - def run: Seq[T] = runner(parameters) - - def runCount: QueryBuilder.CountResult = countRunner(parameters) - - /** - * Runs the query and returns total found rows without considering of pagination. - */ - def runWithCount: (Seq[T], Int, Option[LocalDateTime]) = { - val (total, lastUpdate) = runCount - (run, total, lastUpdate) - } - - def withFilter(newFilter: SearchFilterExpr): QueryBuilder[T, D, N] - - def withFilter(filter: Option[SearchFilterExpr]): QueryBuilder[T, D, N] = { - filter.fold(this)(withFilter) - } - - def resetFilter: QueryBuilder[T, D, N] = withFilter(SearchFilterExpr.Empty) - - def withSorting(newSorting: Sorting): QueryBuilder[T, D, N] - - def withSorting(sorting: Option[Sorting]): QueryBuilder[T, D, N] = { - sorting.fold(this)(withSorting) - } - - def resetSorting: QueryBuilder[T, D, N] = withSorting(Sorting.Empty) - - def withPagination(newPagination: Pagination): QueryBuilder[T, D, N] - - def withPagination(pagination: Option[Pagination]): QueryBuilder[T, D, N] = { - pagination.fold(this)(withPagination) - } - - def resetPagination: QueryBuilder[T, D, N] - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/TransactionalContext.scala b/src/main/scala/xyz/driver/pdsuicommon/db/TransactionalContext.scala deleted file mode 100644 index 9883b9e..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/TransactionalContext.scala +++ /dev/null @@ -1,11 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import scala.concurrent.ExecutionContext - -trait TransactionalContext { - - implicit def executionContext: ExecutionContext - - def transaction[T](f: => T): T - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/BridgeUploadQueueRepository.scala b/src/main/scala/xyz/driver/pdsuicommon/db/repositories/BridgeUploadQueueRepository.scala deleted file mode 100644 index 4c25afa..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/BridgeUploadQueueRepository.scala +++ /dev/null @@ -1,21 +0,0 @@ -package xyz.driver.pdsuicommon.db.repositories - -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue -import xyz.driver.pdsuicommon.db.MysqlQueryBuilder - -trait BridgeUploadQueueRepository extends Repository { - - type EntityT = BridgeUploadQueue.Item - - def add(draft: EntityT): EntityT - - def getById(kind: String, tag: String): Option[EntityT] - - def getOne(kind: String): Option[BridgeUploadQueue.Item] - - def update(entity: EntityT): EntityT - - def delete(kind: String, tag: String): Unit - - def buildQuery: MysqlQueryBuilder[EntityT] -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/Repository.scala b/src/main/scala/xyz/driver/pdsuicommon/db/repositories/Repository.scala deleted file mode 100644 index d671e80..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/Repository.scala +++ /dev/null @@ -1,4 +0,0 @@ -package xyz.driver.pdsuicommon.db.repositories - -// For further usage and migration to Postgres and slick -trait Repository extends RepositoryLogging diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/RepositoryLogging.scala b/src/main/scala/xyz/driver/pdsuicommon/db/repositories/RepositoryLogging.scala deleted file mode 100644 index d1ec1da..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/db/repositories/RepositoryLogging.scala +++ /dev/null @@ -1,62 +0,0 @@ -package xyz.driver.pdsuicommon.db.repositories - -import xyz.driver.pdsuicommon.logging._ - -trait RepositoryLogging extends PhiLogging { - - protected def logCreatedOne[T](x: T)(implicit toPhiString: T => PhiString): T = { - logger.info(phi"An entity was created: $x") - x - } - - protected def logCreatedMultiple[T <: Iterable[_]](xs: T)(implicit toPhiString: T => PhiString): T = { - if (xs.nonEmpty) { - logger.info(phi"Entities were created: $xs") - } - xs - } - - protected def logUpdatedOne(rowsAffected: Long): Long = { - rowsAffected match { - case 0 => logger.trace(phi"The entity is up to date") - case 1 => logger.info(phi"The entity was updated") - case x => logger.warn(phi"The ${Unsafe(x)} entities were updated") - } - rowsAffected - } - - protected def logUpdatedOneUnimportant(rowsAffected: Long): Long = { - rowsAffected match { - case 0 => logger.trace(phi"The entity is up to date") - case 1 => logger.trace(phi"The entity was updated") - case x => logger.warn(phi"The ${Unsafe(x)} entities were updated") - } - rowsAffected - } - - protected def logUpdatedMultiple(rowsAffected: Long): Long = { - rowsAffected match { - case 0 => logger.trace(phi"All entities are up to date") - case x => logger.info(phi"The ${Unsafe(x)} entities were updated") - } - rowsAffected - } - - protected def logDeletedOne(rowsAffected: Long): Long = { - rowsAffected match { - case 0 => logger.trace(phi"The entity does not exist") - case 1 => logger.info(phi"The entity was deleted") - case x => logger.warn(phi"Deleted ${Unsafe(x)} entities, expected one") - } - rowsAffected - } - - protected def logDeletedMultiple(rowsAffected: Long): Long = { - rowsAffected match { - case 0 => logger.trace(phi"Entities do not exist") - case x => logger.info(phi"Deleted ${Unsafe(x)} entities") - } - rowsAffected - } - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/domain/Email.scala b/src/main/scala/xyz/driver/pdsuicommon/domain/Email.scala deleted file mode 100644 index 092ad40..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/domain/Email.scala +++ /dev/null @@ -1,3 +0,0 @@ -package xyz.driver.pdsuicommon.domain - -final case class Email(value: String) diff --git a/src/main/scala/xyz/driver/pdsuicommon/domain/FuzzyValue.scala b/src/main/scala/xyz/driver/pdsuicommon/domain/FuzzyValue.scala deleted file mode 100644 index 4e98f40..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/domain/FuzzyValue.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuicommon.domain - -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.utils.Utils - -sealed trait FuzzyValue - -object FuzzyValue { - case object Yes extends FuzzyValue - case object No extends FuzzyValue - case object Maybe extends FuzzyValue - - val All: Set[FuzzyValue] = Set(Yes, No, Maybe) - - def fromBoolean(x: Boolean): FuzzyValue = if (x) Yes else No - - implicit def toPhiString(x: FuzzyValue): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) - - val fromString: PartialFunction[String, FuzzyValue] = { - case "Yes" => Yes - case "No" => No - case "Maybe" => Maybe - } - - def valueToString(x: FuzzyValue): String = x match { - case Yes => "Yes" - case No => "No" - case Maybe => "Maybe" - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/domain/Id.scala b/src/main/scala/xyz/driver/pdsuicommon/domain/Id.scala deleted file mode 100644 index e238245..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/domain/Id.scala +++ /dev/null @@ -1,51 +0,0 @@ -package xyz.driver.pdsuicommon.domain - -import java.util.UUID - -import xyz.driver.pdsuicommon.logging._ - -sealed trait Id[+T] - -final case class CompoundId[Id1 <: Id[_], Id2 <: Id[_]](part1: Id1, part2: Id2) extends Id[(Id1, Id2)] - -final case class LongId[+T](id: Long) extends Id[T] { - override def toString: String = id.toString - - def is(longId: Long): Boolean = { - id == longId - } -} - -object LongId { - implicit def toPhiString[T](x: LongId[T]): PhiString = Unsafe(s"LongId(${x.id})") -} - -final case class StringId[+T](id: String) extends Id[T] { - override def toString: String = id - - def is(stringId: String): Boolean = { - id == stringId - } -} - -object StringId { - implicit def toPhiString[T](x: StringId[T]): PhiString = Unsafe(s"StringId(${x.id})") -} - -final case class UuidId[+T](id: UUID) extends Id[T] { - override def toString: String = id.toString -} - -object UuidId { - - /** - * @note May fail, if `string` is invalid UUID. - */ - def apply[T](string: String): UuidId[T] = new UuidId[T](UUID.fromString(string)) - - def apply[T](): UuidId[T] = new UuidId[T](UUID.randomUUID()) - - implicit def ordering[T] = Ordering.by[UuidId[T], String](_.toString) - - implicit def toPhiString[T](x: UuidId[T]): PhiString = Unsafe(s"UuidId(${x.id})") -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/domain/TextJson.scala b/src/main/scala/xyz/driver/pdsuicommon/domain/TextJson.scala deleted file mode 100644 index ee4d884..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/domain/TextJson.scala +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.driver.pdsuicommon.domain - -import xyz.driver.pdsuicommon.logging._ - -final case class TextJson[+T](content: T) { - def map[U](f: T => U): TextJson[U] = copy(f(content)) -} - -object TextJson { - - implicit def toPhiString[T](x: TextJson[T])(implicit inner: T => PhiString): PhiString = { - phi"TextJson(${x.content})" - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/domain/User.scala b/src/main/scala/xyz/driver/pdsuicommon/domain/User.scala deleted file mode 100644 index f75f391..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/domain/User.scala +++ /dev/null @@ -1,163 +0,0 @@ -package xyz.driver.pdsuicommon.domain - -import java.math.BigInteger -import java.security.SecureRandom -import java.time.{Instant, LocalDateTime, ZoneId} - -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.domain.User.Role -import xyz.driver.pdsuicommon.utils.Utils - -final case class User(id: StringId[User], - email: Email, - name: String, - roles: Set[Role], - latestActivity: Option[LocalDateTime], - deleted: Option[LocalDateTime]) { - - def this(driverUser: xyz.driver.entities.users.AuthUserInfo) { - this( - id = StringId[xyz.driver.pdsuicommon.domain.User](driverUser.id.value), - email = Email(driverUser.email.toString), - name = driverUser.name.toString, - roles = driverUser.roles.flatMap(User.mapRoles), - latestActivity = - driverUser.lastLoginTime.map(t => Instant.ofEpochMilli(t.millis).atZone(ZoneId.of("Z")).toLocalDateTime), - deleted = Option.empty[LocalDateTime] - ) - } -} - -object User { - - sealed trait Role extends Product with Serializable { - - /** - * Bit representation of this role - */ - def bit: Int - - def is(that: Role): Boolean = this == that - - def oneOf(roles: Role*): Boolean = roles.contains(this) - - def oneOf(roles: Set[Role]): Boolean = roles.contains(this) - } - - object Role extends PhiLogging { - case object RecordAdmin extends Role { val bit = 1 << 0 } - case object RecordCleaner extends Role { val bit = 1 << 1 } - case object RecordOrganizer extends Role { val bit = 1 << 2 } - case object DocumentExtractor extends Role { val bit = 1 << 3 } - case object TrialSummarizer extends Role { val bit = 1 << 4 } - case object CriteriaCurator extends Role { val bit = 1 << 5 } - case object TrialAdmin extends Role { val bit = 1 << 6 } - case object EligibilityVerifier extends Role { val bit = 1 << 7 } - case object TreatmentMatchingAdmin extends Role { val bit = 1 << 8 } - case object RoutesCurator extends Role { val bit = 1 << 9 } - case object SystemUser extends Role { val bit = 1 << 10 } - case object ResearchOncologist extends Role { val bit = 1 << 11 } - - val RepRoles = Set[Role](RecordAdmin, RecordCleaner, RecordOrganizer, DocumentExtractor) - - val TcRoles = Set[Role](TrialSummarizer, CriteriaCurator, TrialAdmin) - - val TreatmentMatchingRoles = Set[Role](RoutesCurator, EligibilityVerifier, TreatmentMatchingAdmin) - - val PepRoles = Set[Role](ResearchOncologist) - - val All = RepRoles ++ TcRoles ++ TreatmentMatchingRoles ++ PepRoles + SystemUser - - def apply(bitMask: Int): Role = { - def extractRole(role: Role): Set[Role] = - if ((bitMask & role.bit) != 0) Set(role) else Set.empty[Role] - - val roles = All.flatMap(extractRole) - roles.size match { - case 1 => roles.head - case _ => - logger.error(phi"Can't convert a bit mask ${Unsafe(bitMask)} to any role") - throw new IllegalArgumentException() - } - } - - implicit def toPhiString(x: Role): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - implicit def toPhiString(x: User): PhiString = { - import x._ - phi"User(id=$id, roles=${Unsafe(roles.map(_.toString).mkString(", "))})" - } - - // SecureRandom is thread-safe, see the implementation - private val random = new SecureRandom() - - def createPassword: String = new BigInteger(240, random).toString(32) - - def mapRoles(coreRole: xyz.driver.core.auth.Role): Set[xyz.driver.pdsuicommon.domain.User.Role] = { - coreRole match { - case xyz.driver.entities.auth.AdministratorRole => - Set( - xyz.driver.pdsuicommon.domain.User.Role.SystemUser, - xyz.driver.pdsuicommon.domain.User.Role.RecordAdmin, - xyz.driver.pdsuicommon.domain.User.Role.TrialAdmin, - xyz.driver.pdsuicommon.domain.User.Role.TreatmentMatchingAdmin - ) - case xyz.driver.entities.auth.RecordAdmin => - Set(xyz.driver.pdsuicommon.domain.User.Role.RecordAdmin) - case xyz.driver.entities.auth.RecordCleaner => - Set(xyz.driver.pdsuicommon.domain.User.Role.RecordCleaner) - case xyz.driver.entities.auth.RecordOrganizer => - Set(xyz.driver.pdsuicommon.domain.User.Role.RecordOrganizer) - case xyz.driver.entities.auth.DocumentExtractor => - Set(xyz.driver.pdsuicommon.domain.User.Role.DocumentExtractor) - case xyz.driver.entities.auth.TrialSummarizer => - Set(xyz.driver.pdsuicommon.domain.User.Role.TrialSummarizer) - case xyz.driver.entities.auth.CriteriaCurator => - Set(xyz.driver.pdsuicommon.domain.User.Role.CriteriaCurator) - case xyz.driver.entities.auth.TrialAdmin => - Set(xyz.driver.pdsuicommon.domain.User.Role.TrialAdmin) - case xyz.driver.entities.auth.EligibilityVerifier => - Set(xyz.driver.pdsuicommon.domain.User.Role.EligibilityVerifier) - case xyz.driver.entities.auth.TreatmentMatchingAdmin => - Set(xyz.driver.pdsuicommon.domain.User.Role.TreatmentMatchingAdmin) - case xyz.driver.entities.auth.RoutesCurator => - Set(xyz.driver.pdsuicommon.domain.User.Role.RoutesCurator) - case xyz.driver.entities.auth.ResearchOncologist => - Set(xyz.driver.pdsuicommon.domain.User.Role.ResearchOncologist) - case _ => - Set.empty[xyz.driver.pdsuicommon.domain.User.Role] - } - } - - def mapRolesToDriver(pdsuiRole: xyz.driver.pdsuicommon.domain.User.Role): Set[xyz.driver.core.auth.Role] = { - pdsuiRole match { - case xyz.driver.pdsuicommon.domain.User.Role.SystemUser => - Set(xyz.driver.entities.auth.AdministratorRole) - case xyz.driver.pdsuicommon.domain.User.Role.RecordAdmin => - Set(xyz.driver.entities.auth.RecordAdmin) - case xyz.driver.pdsuicommon.domain.User.Role.RecordCleaner => - Set(xyz.driver.entities.auth.RecordCleaner) - case xyz.driver.pdsuicommon.domain.User.Role.RecordOrganizer => - Set(xyz.driver.entities.auth.RecordOrganizer) - case xyz.driver.pdsuicommon.domain.User.Role.DocumentExtractor => - Set(xyz.driver.entities.auth.DocumentExtractor) - case xyz.driver.pdsuicommon.domain.User.Role.TrialSummarizer => - Set(xyz.driver.entities.auth.TrialSummarizer) - case xyz.driver.pdsuicommon.domain.User.Role.CriteriaCurator => - Set(xyz.driver.entities.auth.CriteriaCurator) - case xyz.driver.pdsuicommon.domain.User.Role.TrialAdmin => - Set(xyz.driver.entities.auth.TrialAdmin) - case xyz.driver.pdsuicommon.domain.User.Role.EligibilityVerifier => - Set(xyz.driver.entities.auth.EligibilityVerifier) - case xyz.driver.pdsuicommon.domain.User.Role.TreatmentMatchingAdmin => - Set(xyz.driver.entities.auth.TreatmentMatchingAdmin) - case xyz.driver.pdsuicommon.domain.User.Role.RoutesCurator => - Set(xyz.driver.entities.auth.RoutesCurator) - case xyz.driver.pdsuicommon.domain.User.Role.ResearchOncologist => - Set(xyz.driver.entities.auth.ResearchOncologist) - case _ => - Set.empty[xyz.driver.core.auth.Role] - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/DomainError.scala b/src/main/scala/xyz/driver/pdsuicommon/error/DomainError.scala deleted file mode 100644 index c761414..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/error/DomainError.scala +++ /dev/null @@ -1,41 +0,0 @@ -package xyz.driver.pdsuicommon.error - -import xyz.driver.pdsuicommon.logging.{PhiString, Unsafe} -import xyz.driver.pdsuicommon.utils.Utils - -trait DomainError { - - protected def userMessage: String - - def getMessage: String = userMessage - -} - -object DomainError { - - // 404 error - trait NotFoundError extends DomainError - - // 401 error - trait AuthenticationError extends DomainError - - // 403 error - trait AuthorizationError extends DomainError - - implicit def toPhiString(x: DomainError): PhiString = { - // userMessage possibly can contain a personal information, - // so we should prevent it to be printed in logs. - Unsafe(Utils.getClassSimpleName(x.getClass)) - } -} - -/** Subclasses of this exception correspond to subclasses of DomainError. They - * are used in REST service implementations to fail futures rather than - * returning successful futures, completed with corresponding DomainErrors. */ -// scalastyle:off null -@SuppressWarnings(Array("org.wartremover.warts.Null")) -class DomainException(message: String, cause: Throwable = null) extends RuntimeException(message, cause) -class NotFoundException(message: String) extends DomainException(message) // 404 -class AuthenticationException(message: String) extends DomainException(message) // 401 -class AuthorizationException(message: String) extends DomainException(message) // 403 -// scalastyle:on null diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala deleted file mode 100644 index 5574c01..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala +++ /dev/null @@ -1,17 +0,0 @@ -package xyz.driver.pdsuicommon.error - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, Reads, Writes} - -@SuppressWarnings(Array("org.wartremover.warts.Enumeration")) -object ErrorCode extends Enumeration { - - type ErrorCode = Value - val Unspecified = Value(1) - - private val fromJsonReads: Reads[ErrorCode] = Reads.of[Int].map(ErrorCode.apply) - private val toJsonWrites: Writes[ErrorCode] = Writes.of[Int].contramap(_.id) - - implicit val jsonFormat: Format[ErrorCode] = Format(fromJsonReads, toJsonWrites) - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala deleted file mode 100644 index 3761cc5..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala +++ /dev/null @@ -1,83 +0,0 @@ -package xyz.driver.pdsuicommon.error - -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import ErrorCode.{ErrorCode, Unspecified} -import ErrorsResponse.ResponseError -import xyz.driver.pdsuicommon.auth.{AnonymousRequestContext, RequestId} -import xyz.driver.pdsuicommon.utils.Utils -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import play.api.mvc.Results -import xyz.driver.pdsuicommon.validation.JsonValidationErrors - -final case class ErrorsResponse(errors: Seq[ResponseError], requestId: RequestId) - -object ErrorsResponse { - - /** - * @param data Any data that can be associated with particular error.Ex.: error field name - * @param message Error message - * @param code Unique error code - * - * @see https://driverinc.atlassian.net/wiki/display/RA/REST+API+Specification#RESTAPISpecification-HTTPStatuscodes - */ - final case class ResponseError(data: Option[String], message: String, code: ErrorCode) - - object ResponseError { - - implicit val responseErrorJsonFormat: Format[ResponseError] = ( - (JsPath \ "data").formatNullable[String] and - (JsPath \ "message").format[String] and - (JsPath \ "code").format[ErrorCode] - )(ResponseError.apply, unlift(ResponseError.unapply)) - - } - - implicit val errorsResponseJsonFormat: Format[ErrorsResponse] = ( - (JsPath \ "errors").format[Seq[ResponseError]] and - (JsPath \ "requestId").format[String] - )((errs, req) => ErrorsResponse.apply(errs, RequestId(req)), res => (res.errors, res.requestId.value)) - - // deprecated, will be removed in REP-436 - def fromString(message: String, httpStatus: Results#Status)( - implicit context: AnonymousRequestContext): ErrorsResponse = { - new ErrorsResponse( - errors = Seq( - ResponseError( - data = None, - message = message, - code = Unspecified - )), - requestId = context.requestId - ) - } - - // scalastyle:off null - def fromExceptionMessage(e: Throwable, httpStatus: Results#Status = Results.InternalServerError)( - implicit context: AnonymousRequestContext): ErrorsResponse = { - val message = if (e.getMessage == null || e.getMessage.isEmpty) { - Utils.getClassSimpleName(e.getClass) - } else { - e.getMessage - } - - fromString(message, httpStatus) - } - // scalastyle:on null - - // deprecated, will be removed in REP-436 - def fromJsonValidationErrors(validationErrors: JsonValidationErrors)( - implicit context: AnonymousRequestContext): ErrorsResponse = { - val errors = validationErrors.map { - case (path, xs) => - ResponseError( - data = Some(path.toString()), - message = xs.map(_.message).mkString("\n"), - code = Unspecified - ) - } - - new ErrorsResponse(errors, context.requestId) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/ExceptionFormatter.scala b/src/main/scala/xyz/driver/pdsuicommon/error/ExceptionFormatter.scala deleted file mode 100644 index c9578b3..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/error/ExceptionFormatter.scala +++ /dev/null @@ -1,18 +0,0 @@ -package xyz.driver.pdsuicommon.error - -import java.io.{ByteArrayOutputStream, PrintStream} - -object ExceptionFormatter { - - def format(e: Throwable): String = s"$e\n${printStackTrace(e)}" - - def printStackTrace(e: Throwable): String = { - val baos = new ByteArrayOutputStream() - val ps = new PrintStream(baos) - - e.printStackTrace(ps) - - ps.close() - baos.toString() - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/FailedValidationException.scala b/src/main/scala/xyz/driver/pdsuicommon/error/FailedValidationException.scala deleted file mode 100644 index 7137255..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/error/FailedValidationException.scala +++ /dev/null @@ -1,5 +0,0 @@ -package xyz.driver.pdsuicommon.error - -import xyz.driver.pdsuicommon.validation.ValidationError - -class FailedValidationException(val error: ValidationError) extends RuntimeException("The validation is failed") diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/IncorrectIdException.scala b/src/main/scala/xyz/driver/pdsuicommon/error/IncorrectIdException.scala deleted file mode 100644 index 5705229..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/error/IncorrectIdException.scala +++ /dev/null @@ -1,3 +0,0 @@ -package xyz.driver.pdsuicommon.error - -final case class IncorrectIdException(message: String) extends Exception(message) diff --git a/src/main/scala/xyz/driver/pdsuicommon/http/AsyncHttpClientFetcher.scala b/src/main/scala/xyz/driver/pdsuicommon/http/AsyncHttpClientFetcher.scala deleted file mode 100644 index 085dcd8..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/http/AsyncHttpClientFetcher.scala +++ /dev/null @@ -1,90 +0,0 @@ -package xyz.driver.pdsuicommon.http - -import java.io.Closeable -import java.net.URL -import java.util.concurrent.{ExecutorService, Executors} - -import com.typesafe.scalalogging.StrictLogging -import org.asynchttpclient._ -import org.slf4j.MDC -import xyz.driver.pdsuicommon.concurrent.MdcThreadFactory -import xyz.driver.pdsuicommon.utils.RandomUtils - -import scala.concurrent.duration.FiniteDuration -import scala.concurrent.{ExecutionContext, Future, Promise} - -class AsyncHttpClientFetcher(settings: AsyncHttpClientFetcher.Settings) - extends HttpFetcher with Closeable with StrictLogging { - - private val es: ExecutorService = { - val threadFactory = MdcThreadFactory.from(Executors.defaultThreadFactory()) - Executors.newSingleThreadExecutor(threadFactory) - } - - private implicit val executionContext = ExecutionContext.fromExecutor(es) - - private def httpClientConfig: DefaultAsyncHttpClientConfig = { - val builder = new DefaultAsyncHttpClientConfig.Builder() - builder.setConnectTimeout(settings.connectTimeout.toMillis.toInt) - builder.setReadTimeout(settings.readTimeout.toMillis.toInt) - // builder.setThreadFactory(threadFactory) // Doesn't help to push MDC context into AsyncCompletionHandler - builder.build() - } - - private val httpClient = new DefaultAsyncHttpClient(httpClientConfig) - - override def apply(url: URL): Future[Array[Byte]] = { - val fingerPrint = RandomUtils.randomString(10) - - // log all outcome connections - logger.info("{}, apply({})", fingerPrint, url) - val promise = Promise[Response]() - - httpClient - .prepareGet(url.toString) - .execute(new AsyncCompletionHandler[Response] { - override def onCompleted(response: Response): Response = { - promise.success(response) - response - } - - override def onThrowable(t: Throwable): Unit = { - promise.failure(t) - super.onThrowable(t) - } - }) - - // Promises have their own ExecutionContext - // So, we have to hack it. - val parentMdcContext = MDC.getCopyOfContextMap - promise.future.flatMap { response => - setContextMap(parentMdcContext) - - if (response.getStatusCode == 200) { - // DO NOT LOG body, it could be PHI - val bytes = response.getResponseBodyAsBytes - logger.debug("{}, size is {}B", fingerPrint, bytes.size.asInstanceOf[AnyRef]) - Future.successful(bytes) - } else { - logger.error("{}, HTTP {}", fingerPrint, response.getStatusCode.asInstanceOf[AnyRef]) - logger.trace(response.getResponseBody().take(100)) - Future.failed(new IllegalStateException("An unexpected response from the server")) - } - } - } - - private[this] def setContextMap(context: java.util.Map[String, String]): Unit = - Option(context).fold(MDC.clear())(MDC.setContextMap) - - override def close(): Unit = { - httpClient.close() - es.shutdown() - } - -} - -object AsyncHttpClientFetcher { - - final case class Settings(connectTimeout: FiniteDuration, readTimeout: FiniteDuration) - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/http/AsyncHttpClientUploader.scala b/src/main/scala/xyz/driver/pdsuicommon/http/AsyncHttpClientUploader.scala deleted file mode 100644 index d7bc3d3..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/http/AsyncHttpClientUploader.scala +++ /dev/null @@ -1,115 +0,0 @@ -package xyz.driver.pdsuicommon.http - -import java.io.Closeable -import java.net.URI -import java.util.concurrent.{ExecutorService, Executors} - -import xyz.driver.pdsuicommon.concurrent.MdcThreadFactory -import xyz.driver.pdsuicommon.http.AsyncHttpClientUploader._ -import xyz.driver.pdsuicommon.utils.RandomUtils -import com.typesafe.scalalogging.StrictLogging -import org.asynchttpclient._ -import org.slf4j.MDC - -import scala.concurrent.duration.FiniteDuration -import scala.concurrent.{ExecutionContext, Future, Promise} - -class AsyncHttpClientUploader(settings: Settings) extends Closeable with StrictLogging { - - private val es: ExecutorService = { - val threadFactory = MdcThreadFactory.from(Executors.defaultThreadFactory()) - Executors.newSingleThreadExecutor(threadFactory) - } - - private implicit val executionContext = ExecutionContext.fromExecutor(es) - - private def httpClientConfig: DefaultAsyncHttpClientConfig = { - val builder = new DefaultAsyncHttpClientConfig.Builder() - builder.setConnectTimeout(settings.connectTimeout.toMillis.toInt) - builder.setRequestTimeout(settings.requestTimeout.toMillis.toInt) - // builder.setThreadFactory(threadFactory) // Doesn't help to push MDC context into AsyncCompletionHandler - builder.build() - } - - private val httpClient = new DefaultAsyncHttpClient(httpClientConfig) - - def run(method: Method, uri: URI, contentType: String, data: String): Future[Unit] = { - // log all outcome connections - val fingerPrint = RandomUtils.randomString(10) - logger.info("{}, apply(method={}, uri={}, contentType={})", fingerPrint, method, uri, contentType) - val promise = Promise[Response]() - - val q = new RequestBuilder(method.toString) - .setUrl(uri.toString) - .setBody(data) - - settings.defaultHeaders.foreach { - case (k, v) => - q.setHeader(k, v) - } - - q.addHeader("Content-Type", contentType) - - httpClient - .prepareRequest(q) - .execute(new AsyncCompletionHandler[Unit] { - override def onCompleted(response: Response): Unit = { - promise.success(response) - } - - override def onThrowable(t: Throwable): Unit = { - promise.failure(t) - super.onThrowable(t) - } - }) - - // see AsyncHttpClientFetcher - val parentMdcContext = MDC.getCopyOfContextMap - promise.future.flatMap { response => - setContextMap(parentMdcContext) - - val statusCode = response.getStatusCode - // https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_Success - if (statusCode >= 200 && statusCode < 300) { - logger.debug("{}, success", fingerPrint) - Future.successful(()) - } else { - logger.error( - "{}, HTTP {}, BODY:\n{}", - fingerPrint, - response.getStatusCode.asInstanceOf[AnyRef], - response.getResponseBody.take(100) - ) - Future.failed(new IllegalStateException("An unexpected response from the server")) - } - } - } - - private[this] def setContextMap(context: java.util.Map[String, String]): Unit = - Option(context).fold(MDC.clear())(MDC.setContextMap) - - override def close(): Unit = { - httpClient.close() - es.shutdown() - } -} - -object AsyncHttpClientUploader { - - final case class Settings(connectTimeout: FiniteDuration, - requestTimeout: FiniteDuration, - defaultHeaders: Map[String, String] = Map.empty) - - sealed trait Method - - object Method { - - case object Put extends Method { - override val toString = "PUT" - } - - case object Post extends Method { - override val toString = "POST" - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala b/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala deleted file mode 100644 index feb224a..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala +++ /dev/null @@ -1,102 +0,0 @@ -package xyz.driver.pdsuicommon.http - -import akka.http.scaladsl.server._ -import akka.http.scaladsl.server.Directives._ -import akka.http.scaladsl.model._ -import xyz.driver.core.rest.ContextHeaders -import xyz.driver.entities.users.AuthUserInfo -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.error._ -import xyz.driver.pdsuicommon.error.DomainError._ -import xyz.driver.pdsuicommon.error.ErrorsResponse.ResponseError -import xyz.driver.pdsuicommon.parsers._ -import xyz.driver.pdsuicommon.db.{Pagination, Sorting, SearchFilterExpr} -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ -import xyz.driver.core.rest.AuthProvider - -import scala.util._ - -trait Directives { - - val paginated: Directive1[Pagination] = parameterSeq.flatMap { params => - PaginationParser.parse(params) match { - case Success(pagination) => provide(pagination) - case Failure(ex) => failWith(ex) - } - } - - def sorted(validDimensions: Set[String] = Set.empty): Directive1[Sorting] = parameterSeq.flatMap { params => - SortingParser.parse(validDimensions, params) match { - case Success(sorting) => provide(sorting) - case Failure(ex) => failWith(ex) - } - } - - val dimensioned: Directive1[Dimensions] = parameterSeq.flatMap { params => - DimensionsParser.tryParse(params) match { - case Success(dims) => provide(dims) - case Failure(ex) => failWith(ex) - } - } - - val searchFiltered: Directive1[SearchFilterExpr] = parameterSeq.flatMap { params => - SearchFilterParser.parse(params) match { - case Success(sorting) => provide(sorting) - case Failure(ex) => failWith(ex) - } - } - - def StringIdInPath[T]: PathMatcher1[StringId[T]] = - PathMatchers.Segment.map((id) => StringId(id.toString.toLowerCase)) - - def LongIdInPath[T]: PathMatcher1[LongId[T]] = - PathMatchers.LongNumber.map((id) => LongId(id)) - - def UuidIdInPath[T]: PathMatcher1[UuidId[T]] = - PathMatchers.JavaUUID.map((id) => UuidId(id)) - - def failFast[A](reply: A): A = reply match { - case err: NotFoundError => throw new NotFoundException(err.getMessage) - case err: AuthenticationError => throw new AuthenticationException(err.getMessage) - case err: AuthorizationError => throw new AuthorizationException(err.getMessage) - case err: DomainError => throw new DomainException(err.getMessage) - case other => other - } - - def domainExceptionHandler(req: RequestId) = { - def errorResponse(err: DomainError) = - ErrorsResponse(Seq(ResponseError(None, err.getMessage, ErrorCode.Unspecified)), req) - ExceptionHandler { - case err: AuthenticationError => complete(StatusCodes.Unauthorized -> errorResponse(err)) - case err: AuthorizationError => complete(StatusCodes.Forbidden -> errorResponse(err)) - case err: NotFoundError => complete(StatusCodes.NotFound -> errorResponse(err)) - case err: DomainError => complete(StatusCodes.BadRequest -> errorResponse(err)) - } - } - - val tracked: Directive1[RequestId] = optionalHeaderValueByName(ContextHeaders.TrackingIdHeader) flatMap { - case Some(id) => provide(RequestId(id)) - case None => provide(RequestId()) - } - - val handleDomainExceptions: Directive0 = tracked.flatMap { - case id => - handleExceptions(domainExceptionHandler(id)) - } - - implicit class AuthProviderWrapper(provider: AuthProvider[AuthUserInfo]) { - val authenticate: Directive1[AuthenticatedRequestContext] = (provider.authorize() & tracked) tflatMap { - case (core, requestId) => - provide( - new AuthenticatedRequestContext( - core.authenticatedUser, - requestId, - core.contextHeaders(ContextHeaders.AuthenticationTokenHeader) - )) - } - } - -} - -object Directives extends Directives diff --git a/src/main/scala/xyz/driver/pdsuicommon/http/package.scala b/src/main/scala/xyz/driver/pdsuicommon/http/package.scala deleted file mode 100644 index 20b1c97..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/http/package.scala +++ /dev/null @@ -1,9 +0,0 @@ -package xyz.driver.pdsuicommon - -import java.net.URL - -import scala.concurrent.Future - -package object http { - type HttpFetcher = URL => Future[Array[Byte]] -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala b/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala deleted file mode 100644 index 4ff4034..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala +++ /dev/null @@ -1,15 +0,0 @@ -package xyz.driver.pdsuicommon.json - -import play.api.libs.json.JsResult - -import scala.util.{Failure, Success, Try} - -final class JsResultOps[T](val self: JsResult[T]) extends AnyVal { - - def toTry: Try[T] = { - self.fold[Try[T]]( - errors => Failure(new JsonValidationException(errors)), - Success(_) - ) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/json/JsonSerializer.scala b/src/main/scala/xyz/driver/pdsuicommon/json/JsonSerializer.scala deleted file mode 100644 index a53f1dd..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/json/JsonSerializer.scala +++ /dev/null @@ -1,26 +0,0 @@ -package xyz.driver.pdsuicommon.json - -import java.text.SimpleDateFormat - -import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule -import com.fasterxml.jackson.module.scala.DefaultScalaModule -import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper - -object JsonSerializer { - - private val mapper = new ObjectMapper() with ScalaObjectMapper - mapper.registerModule(DefaultScalaModule) - mapper.registerModule(new JavaTimeModule) - mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")) - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL) - - def serialize(value: Any): String = { - mapper.writeValueAsString(value) - } - - def deserialize[T](value: String)(implicit m: Manifest[T]): T = { - mapper.readValue(value) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/json/JsonValidationException.scala b/src/main/scala/xyz/driver/pdsuicommon/json/JsonValidationException.scala deleted file mode 100644 index 21750b4..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/json/JsonValidationException.scala +++ /dev/null @@ -1,5 +0,0 @@ -package xyz.driver.pdsuicommon.json - -import xyz.driver.pdsuicommon.validation.JsonValidationErrors - -class JsonValidationException(val errors: JsonValidationErrors) extends Exception diff --git a/src/main/scala/xyz/driver/pdsuicommon/json/Serialization.scala b/src/main/scala/xyz/driver/pdsuicommon/json/Serialization.scala deleted file mode 100644 index 8231ddb..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/json/Serialization.scala +++ /dev/null @@ -1,46 +0,0 @@ -package xyz.driver.pdsuicommon.json - -import java.net.URI - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities.CaseId - -object Serialization { - - // @TODO Test and check all items in an array - private def seqJsonReads[T](implicit argFormat: Reads[T]): Reads[Seq[T]] = Reads { - case JsArray(xs) => - JsSuccess(xs.map { x => - argFormat.reads(x).get - }) - case x => JsError(s"Expected JsArray, but got $x") - } - - private def seqJsonWrites[T](implicit argFormat: Writes[T]): Writes[Seq[T]] = Writes { xs => - JsArray(xs.map(argFormat.writes)) - } - - implicit def seqJsonFormat[T](implicit f: Format[T]): Format[Seq[T]] = Format(seqJsonReads[T], seqJsonWrites[T]) - - private val uriJsonReads: Reads[URI] = Reads.StringReads.map(URI.create) - private val uriJsonWrites: Writes[URI] = Writes(uri => JsString(uri.toString)) - implicit val uriJsonFormat: Format[URI] = Format(uriJsonReads, uriJsonWrites) - - private def uuidIdJsonReads[T]: Reads[UuidId[T]] = Reads.uuidReads.map(x => UuidId[T](x)) - private def uuidIdJsonWrites[T]: Writes[UuidId[T]] = Writes.UuidWrites.contramap(_.id) - implicit def uuidIdJsonFormat[T]: Format[UuidId[T]] = Format(uuidIdJsonReads, uuidIdJsonWrites) - - private def longIdJsonReads[T]: Reads[LongId[T]] = Reads.LongReads.map(x => LongId[T](x)) - private def longIdJsonWrites[T]: Writes[LongId[T]] = Writes.LongWrites.contramap(_.id) - implicit def longIdJsonFormat[T]: Format[LongId[T]] = Format(longIdJsonReads, longIdJsonWrites) - - private val emailJsonReads: Reads[Email] = Reads.email.map(Email.apply) - private val emailJsonWrites: Writes[Email] = Writes(email => JsString(email.value)) - implicit val emailJsonFormat: Format[Email] = Format(emailJsonReads, emailJsonWrites) - - private val caseIdJsonReads: Reads[CaseId] = Reads.StringReads.map(CaseId(_)) - private val caseIdJsonWrites: Writes[CaseId] = Writes(caseId => JsString(caseId.id)) - implicit val caseIdJsonFormat: Format[CaseId] = Format(caseIdJsonReads, caseIdJsonWrites) -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/logging/DefaultPhiLogger.scala b/src/main/scala/xyz/driver/pdsuicommon/logging/DefaultPhiLogger.scala deleted file mode 100644 index 045f37a..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/logging/DefaultPhiLogger.scala +++ /dev/null @@ -1,17 +0,0 @@ -package xyz.driver.pdsuicommon.logging - -import org.slf4j.{Logger => Underlying} - -class DefaultPhiLogger private[logging] (underlying: Underlying) extends PhiLogger { - - def error(message: PhiString): Unit = underlying.error(message.text) - - def warn(message: PhiString): Unit = underlying.warn(message.text) - - def info(message: PhiString): Unit = underlying.info(message.text) - - def debug(message: PhiString): Unit = underlying.debug(message.text) - - def trace(message: PhiString): Unit = underlying.trace(message.text) - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/logging/Implicits.scala b/src/main/scala/xyz/driver/pdsuicommon/logging/Implicits.scala deleted file mode 100644 index 109d52a..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/logging/Implicits.scala +++ /dev/null @@ -1,62 +0,0 @@ -package xyz.driver.pdsuicommon.logging - -import java.io.File -import java.net.{URI, URL} -import java.nio.file.Path -import java.time.{LocalDate, LocalDateTime} -import java.util.UUID - -import scala.concurrent.duration.Duration - -trait Implicits { - - // DO NOT ADD! - // phi"$fullName" is easier to write, than phi"${Unsafe(fullName)}" - // If you wrote the second version, it means that you know, what you doing. - // implicit def toPhiString(s: String): PhiString = Unsafe(s) - - implicit def toPhiStringContext(sc: StringContext): PhiStringContext = new PhiStringContext(sc) - - implicit def booleanToPhiString(x: Boolean): PhiString = Unsafe(x.toString) - - implicit def uriToPhiString(x: URI): PhiString = Unsafe(x.toString) - - implicit def urlToPhiString(x: URL): PhiString = Unsafe(x.toString) - - implicit def pathToPhiString(x: Path): PhiString = Unsafe(x.toString) - - implicit def fileToPhiString(x: File): PhiString = Unsafe(x.toString) - - implicit def localDateTimeToPhiString(x: LocalDateTime): PhiString = Unsafe(x.toString) - - implicit def localDateToPhiString(x: LocalDate): PhiString = Unsafe(x.toString) - - implicit def durationToPhiString(x: Duration): PhiString = Unsafe(x.toString) - - implicit def uuidToPhiString(x: UUID): PhiString = Unsafe(x.toString) - - implicit def tuple2ToPhiString[T1, T2](x: (T1, T2))(implicit inner1: T1 => PhiString, - inner2: T2 => PhiString): PhiString = x match { - case (a, b) => phi"($a, $b)" - } - - implicit def tuple3ToPhiString[T1, T2, T3](x: (T1, T2, T3))(implicit inner1: T1 => PhiString, - inner2: T2 => PhiString, - inner3: T3 => PhiString): PhiString = x match { - case (a, b, c) => phi"($a, $b, $c)" - } - - implicit def optionToPhiString[T](opt: Option[T])(implicit inner: T => PhiString): PhiString = opt match { - case None => phi"None" - case Some(x) => phi"Some($x)" - } - - implicit def iterableToPhiString[T](xs: Iterable[T])(implicit inner: T => PhiString): PhiString = { - Unsafe(xs.map(inner(_).text).mkString("Col(", ", ", ")")) - } - - implicit def throwableToPhiString(x: Throwable): PhiString = { - Unsafe(Option(x.getMessage).getOrElse(x.getClass.getName)) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/logging/PhiLogger.scala b/src/main/scala/xyz/driver/pdsuicommon/logging/PhiLogger.scala deleted file mode 100644 index 741ef18..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/logging/PhiLogger.scala +++ /dev/null @@ -1,15 +0,0 @@ -package xyz.driver.pdsuicommon.logging - -trait PhiLogger { - - def error(message: PhiString): Unit - - def warn(message: PhiString): Unit - - def info(message: PhiString): Unit - - def debug(message: PhiString): Unit - - def trace(message: PhiString): Unit - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/logging/PhiLogging.scala b/src/main/scala/xyz/driver/pdsuicommon/logging/PhiLogging.scala deleted file mode 100644 index e7730ea..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/logging/PhiLogging.scala +++ /dev/null @@ -1,20 +0,0 @@ -package xyz.driver.pdsuicommon.logging - -import org.slf4j.LoggerFactory - -trait PhiLogging extends Implicits { - - protected val logger: PhiLogger = new DefaultPhiLogger(LoggerFactory.getLogger(getClass.getName)) - - /** - * Logs the failMessage on an error level, if isSuccessful is false. - * @return isSuccessful - */ - protected def loggedError(isSuccessful: Boolean, failMessage: PhiString): Boolean = { - if (!isSuccessful) { - logger.error(failMessage) - } - isSuccessful - } - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/logging/PhiString.scala b/src/main/scala/xyz/driver/pdsuicommon/logging/PhiString.scala deleted file mode 100644 index 78ac62e..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/logging/PhiString.scala +++ /dev/null @@ -1,6 +0,0 @@ -package xyz.driver.pdsuicommon.logging - -class PhiString(private[logging] val text: String) { - // scalastyle:off - @inline def +(that: PhiString) = new PhiString(this.text + that.text) -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/logging/PhiStringContext.scala b/src/main/scala/xyz/driver/pdsuicommon/logging/PhiStringContext.scala deleted file mode 100644 index 97819de..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/logging/PhiStringContext.scala +++ /dev/null @@ -1,8 +0,0 @@ -package xyz.driver.pdsuicommon.logging - -final class PhiStringContext(val sc: StringContext) extends AnyVal { - def phi(args: PhiString*): PhiString = { - val phiArgs = args.map(_.text) - new PhiString(sc.s(phiArgs: _*)) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/logging/TimeLogger.scala b/src/main/scala/xyz/driver/pdsuicommon/logging/TimeLogger.scala deleted file mode 100644 index 297b0e1..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/logging/TimeLogger.scala +++ /dev/null @@ -1,13 +0,0 @@ -package xyz.driver.pdsuicommon.logging - -import java.time.{LocalDateTime, ZoneId} - -import xyz.driver.pdsuicommon.domain.{StringId, User} - -object TimeLogger extends PhiLogging { - - def logTime(userId: StringId[User], label: String, obj: String): Unit = { - val now = LocalDateTime.now(ZoneId.of("Z")) - logger.info(phi"User id=$userId performed an action at ${Unsafe(label)}=$now with a ${Unsafe(obj)} ") - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/logging/Unsafe.scala b/src/main/scala/xyz/driver/pdsuicommon/logging/Unsafe.scala deleted file mode 100644 index c3ebe80..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/logging/Unsafe.scala +++ /dev/null @@ -1,7 +0,0 @@ -package xyz.driver.pdsuicommon.logging - -/** - * Use it with care! - */ -final case class Unsafe[T](private[logging] val value: T) - extends PhiString(Option(value).map(_.toString).getOrElse("<null>")) diff --git a/src/main/scala/xyz/driver/pdsuicommon/logging/package.scala b/src/main/scala/xyz/driver/pdsuicommon/logging/package.scala deleted file mode 100644 index 2905108..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/logging/package.scala +++ /dev/null @@ -1,3 +0,0 @@ -package xyz.driver.pdsuicommon - -package object logging extends Implicits diff --git a/src/main/scala/xyz/driver/pdsuicommon/pdf/PdfRenderer.scala b/src/main/scala/xyz/driver/pdsuicommon/pdf/PdfRenderer.scala deleted file mode 100644 index 93be2cc..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/pdf/PdfRenderer.scala +++ /dev/null @@ -1,12 +0,0 @@ -package xyz.driver.pdsuicommon.pdf - -import java.nio.file.Path - -trait PdfRenderer { - - def render(html: String, documentName: String, force: Boolean = false): Path - - def delete(documentName: String): Unit - - def getPath(fileName: String): Path -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/pdf/WkHtmlToPdfRenderer.scala b/src/main/scala/xyz/driver/pdsuicommon/pdf/WkHtmlToPdfRenderer.scala deleted file mode 100644 index 8141b7f..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/pdf/WkHtmlToPdfRenderer.scala +++ /dev/null @@ -1,105 +0,0 @@ -package xyz.driver.pdsuicommon.pdf - -import java.io.IOException -import java.nio.file._ - -import io.github.cloudify.scala.spdf._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.pdf.WkHtmlToPdfRenderer.Settings - -object WkHtmlToPdfRenderer { - - final case class Settings(downloadsDir: String) { - - lazy val downloadsPath: Path = getPathFrom(downloadsDir) - - private def getPathFrom(x: String): Path = { - val dirPath = - if (x.startsWith("/")) Paths.get(x) - else { - val workingDir = Paths.get(".") - workingDir.resolve(x) - } - - dirPath.toAbsolutePath.normalize() - } - } -} - -class WkHtmlToPdfRenderer(settings: Settings) extends PdfRenderer with PhiLogging { - - private val pdf = Pdf(new PdfConfig { - disableJavascript := true - disableExternalLinks := true - disableInternalLinks := true - printMediaType := Some(true) - orientation := Portrait - pageSize := "A4" - lowQuality := true - }) - - override def render(html: String, documentName: String, force: Boolean = false): Path = { - checkedCreate(html, documentName, force) - } - - override def delete(documentName: String): Unit = { - logger.trace(phi"delete(${Unsafe(documentName)})") - - val file = getPath(documentName) - logger.debug(phi"File: $file") - if (Files.deleteIfExists(file)) { - logger.info(phi"Deleted") - } else { - logger.warn(phi"Doesn't exist") - } - } - - override def getPath(documentName: String): Path = { - settings.downloadsPath.resolve(s"$documentName.pdf").toAbsolutePath - } - - protected def checkedCreate[SourceT: SourceDocumentLike](src: SourceT, fileName: String, force: Boolean): Path = { - logger.trace(phi"checkedCreate(fileName=${Unsafe(fileName)}, force=$force)") - - val dest = getPath(fileName) - logger.debug(phi"Destination file: $dest") - - if (force || !dest.toFile.exists()) { - logger.trace(phi"Force refresh the file") - val newDocPath = forceCreate(src, dest) - logger.info(phi"Updated") - newDocPath - } else if (dest.toFile.exists()) { - logger.trace(phi"Already exists") - dest - } else { - logger.trace(phi"The file does not exist") - val newDocPath = forceCreate(src, dest) - logger.info(phi"Created") - newDocPath - } - } - - protected def forceCreate[SourceT: SourceDocumentLike](src: SourceT, dest: Path): Path = { - logger.trace(phi"forceCreate[${Unsafe(src.getClass.getName)}](dest=$dest)") - - val destTemp = Files.createTempFile("driver", ".pdf") - val destTempFile = destTemp.toFile - - Files.createDirectories(dest.getParent) - - val retCode = pdf.run(src, destTempFile) - lazy val pdfSize = destTempFile.length() - if (retCode != 0) { - // Try to google "wkhtmltopdf returns {retCode}" - throw new IOException(s"Can create the document, the return code is $retCode") - } else if (pdfSize == 0) { - // Anything could happen, e.g. https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2540 - throw new IOException("The pdf is empty") - } else { - logger.debug(phi"Size: ${Unsafe(pdfSize)}B") - Files.move(destTemp, dest, StandardCopyOption.REPLACE_EXISTING) - dest - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/resources/ResourcesStorage.scala b/src/main/scala/xyz/driver/pdsuicommon/resources/ResourcesStorage.scala deleted file mode 100644 index 2be7ed7..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/resources/ResourcesStorage.scala +++ /dev/null @@ -1,36 +0,0 @@ -package xyz.driver.pdsuicommon.resources - -import scala.io.{Codec, Source} - -trait ResourcesStorage { - - /** - * @param resourcePath Don't forget / at start - */ - def getFirstLine(resourcePath: String): String -} - -object RealResourcesStorage extends ResourcesStorage { - - def getFirstLine(resourcePath: String): String = { - val resourceUrl = getClass.getResource(resourcePath) - Option(resourceUrl) match { - case Some(url) => - val source = Source.fromURL(resourceUrl)(Codec.UTF8) - try { - val lines = source.getLines() - if (lines.isEmpty) throw new RuntimeException(s"'$resourcePath' is empty") - else lines.next() - } finally { - source.close() - } - case None => - throw new RuntimeException(s"Can not find the '$resourcePath'!") - } - } -} - -object FakeResourcesStorage extends ResourcesStorage { - - def getFirstLine(resourcePath: String): String = "" -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/serialization/Marshaller.scala b/src/main/scala/xyz/driver/pdsuicommon/serialization/Marshaller.scala deleted file mode 100644 index 6702de2..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/serialization/Marshaller.scala +++ /dev/null @@ -1,6 +0,0 @@ -package xyz.driver.pdsuicommon.serialization - -trait Marshaller[T, Repr] { - def read(x: Repr): Option[T] - def write(x: T): Repr -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala b/src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala deleted file mode 100644 index 5158dab..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala +++ /dev/null @@ -1,34 +0,0 @@ -package xyz.driver.pdsuicommon.serialization - -import akka.http.scaladsl.server.{RejectionError, ValidationRejection} -import akka.http.scaladsl.unmarshalling.Unmarshaller -import play.api.libs.json.{Reads, Writes} -import play.api.libs.json.Json -import akka.http.scaladsl.marshalling.ToEntityMarshaller -import akka.http.scaladsl.unmarshalling.FromEntityUnmarshaller -import akka.http.scaladsl.model.MediaTypes.`application/json` - -trait PlayJsonSupport { - import akka.http.scaladsl.marshalling.Marshaller - - implicit def playJsonUnmarshaller[A: Reads]: FromEntityUnmarshaller[A] = { - val reads = implicitly[Reads[A]] - Unmarshaller.stringUnmarshaller - .forContentTypes(`application/json`) - .map(Json.parse) - .map(reads.reads) - .map(_.recoverTotal { error => - throw RejectionError(ValidationRejection(s"Error reading JSON response as ${reads}.")) - }) - } - - implicit def playJsonMarshaller[A: Writes]: ToEntityMarshaller[A] = { - Marshaller - .stringMarshaller(`application/json`) - .compose(Json.prettyPrint) - .compose(implicitly[Writes[A]].writes) - } - -} - -object PlayJsonSupport extends PlayJsonSupport diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/CharOps.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/CharOps.scala deleted file mode 100644 index cee9c73..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/CharOps.scala +++ /dev/null @@ -1,31 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -final class CharOps(val self: Char) extends AnyVal { - - import CharOps._ - - def isSafeWhitespace: Boolean = Whitespace.matches(self) - - def isSafeControl: Boolean = JavaIsoControl.matches(self) -} - -// From Guava -private object CharOps { - - object Whitespace { - private val Table: String = - "\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000" + - "\u2029\u000B\u3000\u2008\u2003\u205F\u3000\u1680" + - "\u0009\u0020\u2006\u2001\u202F\u00A0\u000C\u2009" + - "\u3000\u2004\u3000\u3000\u2028\n\u2007\u3000" - - private val Multiplier: Int = 1682554634 - private val Shift: Int = Integer.numberOfLeadingZeros(Table.length - 1) - - def matches(c: Char): Boolean = Table.charAt((Multiplier * c) >>> Shift) == c - } - - object JavaIsoControl { - def matches(c: Char): Boolean = c <= '\u001f' || (c >= '\u007f' && c <= '\u009f') - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/FutureUtils.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/FutureUtils.scala deleted file mode 100644 index e8b1f5c..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/FutureUtils.scala +++ /dev/null @@ -1,18 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -import scala.concurrent.{ExecutionContext, Future} -import scala.util.{Failure, Try} - -object FutureUtils { - - def executeSynchronously[T](f: ExecutionContext => Future[T]): Try[T] = { - val future = f { - new ExecutionContext { - override def reportFailure(cause: Throwable): Unit = cause.printStackTrace() - - override def execute(runnable: Runnable): Unit = runnable.run() - } - } - future.value.getOrElse(Failure(new IllegalStateException("Can not evaluate the result of future"))) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/Implicits.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/Implicits.scala deleted file mode 100644 index 9411beb..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/Implicits.scala +++ /dev/null @@ -1,29 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -import play.api.libs.json.JsResult -import xyz.driver.pdsuicommon.json.JsResultOps - -import scala.collection.generic.CanBuildFrom - -object Implicits { - - final class ConditionalAppend[U, T[U] <: TraversableOnce[U]](val c: T[U]) extends AnyVal { - def condAppend(cond: => Boolean, value: U)(implicit cbf: CanBuildFrom[T[U], U, T[U]]): T[U] = { - val col = cbf() - if (cond) { - ((col ++= c) += value).result - } else { - c.asInstanceOf[T[U]] - } - } - } - - implicit def traversableConditionalAppend[U, T[U] <: TraversableOnce[U]](c: T[U]): ConditionalAppend[U, T] = - new ConditionalAppend[U, T](c) - - implicit def toMapOps[K, V](x: Map[K, V]): MapOps[K, V] = new MapOps(x) - - implicit def toCharOps(self: Char): CharOps = new CharOps(self) - implicit def toStringOps(self: String): StringOps = new StringOps(self) - implicit def toJsResultOps[T](self: JsResult[T]): JsResultOps[T] = new JsResultOps(self) -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/MapOps.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/MapOps.scala deleted file mode 100644 index ac9a162..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/MapOps.scala +++ /dev/null @@ -1,10 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -final class MapOps[K, V](val self: Map[K, V]) extends AnyVal { - - def swap: Map[V, Set[K]] = { - self.toList - .groupBy { case (_, v) => v } - .mapValues(_.map { case (k, _) => k }.toSet) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/RandomUtils.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/RandomUtils.scala deleted file mode 100644 index faf8703..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/RandomUtils.scala +++ /dev/null @@ -1,19 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -import java.util.concurrent.ThreadLocalRandom - -import scala.collection._ - -object RandomUtils { - - private def Random = ThreadLocalRandom.current() - - private val chars: Seq[Char] = ('0' to '9') ++ ('a' to 'z') - - def randomString(len: Int): String = { - (0 until len).map({ _ => - val i = Random.nextInt(0, chars.size) - chars(i) - })(breakOut) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/ServiceUtils.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/ServiceUtils.scala deleted file mode 100644 index cf53e6b..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/ServiceUtils.scala +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -import xyz.driver.pdsuicommon.db.SearchFilterBinaryOperation.Eq -import xyz.driver.pdsuicommon.db.SearchFilterExpr -import xyz.driver.pdsuicommon.db.SearchFilterExpr.{Atom, Dimension} -import xyz.driver.pdsuicommon.logging._ - -import scala.util.{Failure, Success, Try} - -object ServiceUtils extends PhiLogging { - - def findEqFilter(filter: SearchFilterExpr, fieldName: String): Option[SearchFilterExpr] = { - findEqFilter(filter, Dimension(None, fieldName)) - } - - def findEqFilter(filter: SearchFilterExpr, dimension: Dimension): Option[SearchFilterExpr] = { - filter.find { - case Atom.Binary(dimension, Eq, _) => true - case _ => false - } - } - - def convertIdInFilterToLong(value: AnyRef): Option[Long] = { - Try(value.toString.toLong) match { - case Success(id) => - Option(id) - case Failure(e) => - logger.error(phi"Incorrect id format in filter $e") - None - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/StringOps.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/StringOps.scala deleted file mode 100644 index eaac761..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/StringOps.scala +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -import xyz.driver.pdsuicommon.utils.Implicits.toCharOps - -final class StringOps(val self: String) extends AnyVal { - - def safeTrim: String = { - def shouldKeep(c: Char): Boolean = !c.isSafeControl && !c.isSafeWhitespace - - if (self.isEmpty) { - "" - } else { - val start = self.indexWhere(shouldKeep) - val end = self.lastIndexWhere(shouldKeep) - - if (start >= 0 && end >= 0) { - self.substring(start, end + 1) - } else { - "" - } - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/Utils.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/Utils.scala deleted file mode 100644 index 02c9e28..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/Utils.scala +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -import java.time.LocalDateTime - -object Utils { - - implicit val localDateTimeOrdering: Ordering[LocalDateTime] = Ordering.fromLessThan(_ isBefore _) - - /** - * Hack to avoid scala compiler bug with getSimpleName - * @see https://issues.scala-lang.org/browse/SI-2034 - */ - def getClassSimpleName(klass: Class[_]): String = { - try { - klass.getSimpleName - } catch { - case _: InternalError => - val fullName = klass.getName.stripSuffix("$") - val fullClassName = fullName.substring(fullName.lastIndexOf(".") + 1) - fullClassName.substring(fullClassName.lastIndexOf("$") + 1) - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/WriteableImplicits.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/WriteableImplicits.scala deleted file mode 100644 index 6c04dfa..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/WriteableImplicits.scala +++ /dev/null @@ -1,17 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -import play.api.http.{ContentTypes, Writeable} -import play.api.libs.json.{Json, Writes} - -// @TODO this should be an object with a method, that gets HTTP-headers and returns suitable Writeable -trait WriteableImplicits { - - // Write JSON by default at now - implicit def defaultWriteable[T](implicit inner: Writes[T]) = Writeable[T]( - { x: T => - Writeable.writeableOf_JsValue.transform(Json.toJson(x)) - }, - Option(ContentTypes.JSON) - ) - -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/WritesUtils.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/WritesUtils.scala deleted file mode 100644 index 3476a1e..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/WritesUtils.scala +++ /dev/null @@ -1,21 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -import play.api.libs.json._ - -object WritesUtils { - - def filterKeys[T](p: String => Boolean)(implicit w: Writes[T]): Writes[T] = { - filter { - case (key, _) => p(key) - } - } - - def filter[T](p: (String, JsValue) => Boolean)(implicit w: Writes[T]): Writes[T] = { - w.transform { input: JsValue => - input match { - case JsObject(map) => JsObject(map.filter(Function.tupled(p))) - case x => x - } - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/validation/AdditionalConstraints.scala b/src/main/scala/xyz/driver/pdsuicommon/validation/AdditionalConstraints.scala deleted file mode 100644 index cb1082f..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/validation/AdditionalConstraints.scala +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.driver.pdsuicommon.validation - -import org.davidbild.tristate.Tristate -import play.api.data.validation._ - -object AdditionalConstraints { - - val nonNegativePrintedNumber: Constraint[String] = { - Constraints.pattern("^\\d+$".r, "printedInt.nonNegative", "must be a non-negative number") - } - - val positivePrintedNumber: Constraint[String] = { - Constraints.pattern("^[1-9]\\d*$".r, "printedInt.positive", "must be a positive number") - } - - val optionNonEmptyConstraint: Constraint[Option[Any]] = { - Constraint("option.nonEmpty") { - case Some(x) => Valid - case None => Invalid("is empty") - } - } - - val tristateSpecifiedConstraint: Constraint[Tristate[Any]] = { - Constraint("tristate.specified") { - case Tristate.Unspecified => Invalid("unspecified") - case _ => Valid - } - } - - val uuid: Constraint[String] = { - Constraints.pattern("""[\da-z]{8}-[\da-z]{4}-[\da-z]{4}-[\da-z]{4}-[\da-z]{12}""".r, "uuid", "invalid uuid") - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/validation/ValidationError.scala b/src/main/scala/xyz/driver/pdsuicommon/validation/ValidationError.scala deleted file mode 100644 index 9f466f8..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/validation/ValidationError.scala +++ /dev/null @@ -1,3 +0,0 @@ -package xyz.driver.pdsuicommon.validation - -final case class ValidationError(message: String) diff --git a/src/main/scala/xyz/driver/pdsuicommon/validation/Validators.scala b/src/main/scala/xyz/driver/pdsuicommon/validation/Validators.scala deleted file mode 100644 index a41f87a..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/validation/Validators.scala +++ /dev/null @@ -1,39 +0,0 @@ -package xyz.driver.pdsuicommon.validation - -import xyz.driver.pdsuicommon.json.JsonSerializer -import xyz.driver.pdsuicommon.logging._ - -import scala.util.control.NonFatal - -object Validators extends PhiLogging { - - type Validator[Input, Refined] = Input => Either[ValidationError, Refined] - - def generic[T, R](message: String)(f: PartialFunction[T, R]): Validator[T, R] = { value => - if (f.isDefinedAt(value)) Right(f(value)) - else Left(ValidationError(message)) - } - - def nonEmpty[T](field: String): Validator[Option[T], T] = generic(s"$field is empty") { - case Some(x) => x - } - - def nonEmptyString(field: String): Validator[String, String] = generic(s"$field is empty") { - case x if x.nonEmpty => x - } - - def deserializableTo[Refined](field: String)(value: String)( - implicit m: Manifest[Refined]): Either[ValidationError, Refined] = { - try { - Right(JsonSerializer.deserialize[Refined](value)) - } catch { - case NonFatal(e) => - logger.error(phi"Can not deserialize the ${Unsafe(field)}: $e") - Left(ValidationError(s"$field is invalid")) - } - } - - def success[T](result: T): Either[Nothing, T] = Right(result) - - def fail(message: String): Either[ValidationError, Nothing] = Left(ValidationError(message)) -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/validation/package.scala b/src/main/scala/xyz/driver/pdsuicommon/validation/package.scala deleted file mode 100644 index 9a31a93..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/validation/package.scala +++ /dev/null @@ -1,8 +0,0 @@ -package xyz.driver.pdsuicommon - -import play.api.data.validation.{ValidationError => PlayValidationError} -import play.api.libs.json.JsPath - -package object validation { - type JsonValidationErrors = Seq[(JsPath, Seq[PlayValidationError])] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Arm.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Arm.scala deleted file mode 100644 index 2190b8d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Arm.scala +++ /dev/null @@ -1,20 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuicommon.logging._ - -final case class Arm(id: LongId[Arm], - name: String, - originalName: String, - trialId: StringId[Trial], - deleted: Option[LocalDateTime] = None) - -object Arm { - - implicit def toPhiString(x: Arm): PhiString = { - import x._ - phi"Arm(id=$id, name=${Unsafe(x.name)}, trialId=${Unsafe(x.trialId)})" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/CaseId.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/CaseId.scala deleted file mode 100644 index 751545e..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/CaseId.scala +++ /dev/null @@ -1,10 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.util.UUID - -final case class CaseId(id: String) - -object CaseId { - - def apply() = new CaseId(UUID.randomUUID().toString) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Criterion.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Criterion.scala deleted file mode 100644 index 0dfb33f..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Criterion.scala +++ /dev/null @@ -1,55 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.Criterion.Meta.Evidence - -final case class Criterion(id: LongId[Criterion], - trialId: StringId[Trial], - text: Option[String], - isCompound: Boolean, - meta: String) { - - def isValid(): Boolean = text.nonEmpty && Option(meta).isDefined -} - -object Criterion { - - final case class Meta(evidence: Evidence) - - object Meta { - final case class Evidence(pageRatio: Double, start: TextLayerPosition, end: TextLayerPosition) - final case class TextLayerPosition(page: Integer, index: Integer, offset: Integer) - } - - implicit def toPhiString(x: Criterion): PhiString = { - import x._ - phi"Criterion(id=$id, trialId=$trialId, isCompound=$isCompound)" - } -} - -final case class CriterionArm(criterionId: LongId[Criterion], armId: LongId[Arm]) - -object CriterionArm { - - implicit def toPhiString(x: CriterionArm): PhiString = { - import x._ - phi"CriterionArm(criterionId=$criterionId, armId=$armId)" - } -} - -final case class CriterionLabel(id: LongId[CriterionLabel], - labelId: Option[LongId[Label]], - criterionId: LongId[Criterion], - categoryId: Option[LongId[Category]], - value: Option[Boolean], - isDefining: Boolean) - -object CriterionLabel { - - implicit def toPhiString(x: CriterionLabel): PhiString = { - import x._ - phi"CriterionLabel(id=$id, labelId=$labelId, criterionId=$criterionId, " + - phi"categoryId=$categoryId, value=$value, isDefining=$isDefining)" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/DirectReport.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/DirectReport.scala deleted file mode 100644 index 42ac55b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/DirectReport.scala +++ /dev/null @@ -1,41 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDate - -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuicommon.utils.Utils -import xyz.driver.pdsuidomain.entities.DirectReport.ReportType - -object DirectReport { - - sealed trait ReportType extends Product with Serializable { - def oneOf(xs: ReportType*): Boolean = xs.contains(this) - - def oneOf(xs: Set[ReportType]): Boolean = xs.contains(this) - } - - object ReportType { - case object IHC extends ReportType - case object DNA extends ReportType - case object CFDNA extends ReportType - - val All = Set(IHC, DNA, CFDNA) - implicit def toPhiString(x: ReportType): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - implicit def toPhiString(x: DirectReport): PhiString = { - import x._ - phi"DirectReport(id=$id, patientId=$patientId, reportType=$reportType, date=${Unsafe(date)}, " + - phi"documentType=${Unsafe(documentType)}, providerType=${Unsafe(providerType)}, " + - phi"providerName=${Unsafe(providerName)})" - } -} - -final case class DirectReport(id: UuidId[DirectReport], - patientId: UuidId[Patient], - reportType: ReportType, - date: LocalDate, - documentType: String, - providerType: String, - providerName: String) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Document.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Document.scala deleted file mode 100644 index 1f73184..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Document.scala +++ /dev/null @@ -1,317 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.{LocalDate, LocalDateTime, ZoneId} - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.core.{JsonGenerator, JsonParser} -import com.fasterxml.jackson.databind._ -import com.fasterxml.jackson.databind.annotation.{JsonDeserialize, JsonSerialize} -import xyz.driver.pdsuicommon.compat.Implicits._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.utils.Utils -import xyz.driver.pdsuicommon.validation.Validators -import xyz.driver.pdsuicommon.validation.Validators.Validator -import xyz.driver.pdsuidomain.entities.Document.Meta - -final case class ProviderType(id: LongId[ProviderType], name: String) - -object ProviderType { - sealed trait ProviderTypeName - case object MedicalOncology extends ProviderTypeName - case object Surgery extends ProviderTypeName - case object Pathology extends ProviderTypeName - case object MolecularPathology extends ProviderTypeName - case object LaboratoryMedicine extends ProviderTypeName - case object Radiology extends ProviderTypeName - case object InterventionalRadiology extends ProviderTypeName - case object RadiationOncology extends ProviderTypeName - case object PrimaryCare extends ProviderTypeName - case object Cardiology extends ProviderTypeName - case object Dermatology extends ProviderTypeName - case object Ophthalmology extends ProviderTypeName - case object Gastroenterology extends ProviderTypeName - case object Neurology extends ProviderTypeName - case object Psychiatry extends ProviderTypeName - case object Gynecology extends ProviderTypeName - case object InfectiousDisease extends ProviderTypeName - case object Immunology extends ProviderTypeName - case object Nephrology extends ProviderTypeName - case object Rheumatology extends ProviderTypeName - case object Cytology extends ProviderTypeName - case object Otolaryngology extends ProviderTypeName - case object Anesthesiology extends ProviderTypeName - case object Urology extends ProviderTypeName - case object PalliativeCare extends ProviderTypeName - case object EmergencyMedicine extends ProviderTypeName - case object SocialWork extends ProviderTypeName - case object NA extends ProviderTypeName - case object Other extends ProviderTypeName - - def fromString(txt: String): Option[ProviderTypeName] = { - txt match { - case "Medical Oncology" => Some(MedicalOncology) - case "Surgery" => Some(Surgery) - case "Pathology" => Some(Pathology) - case "Molecular Pathology" => Some(MolecularPathology) - case "LaboratoryMedicine" => Some(LaboratoryMedicine) - case "Radiology" => Some(Radiology) - case "Interventional Radiology" => Some(InterventionalRadiology) - case "Radiation Oncology" => Some(RadiationOncology) - case "Primary Care" => Some(PrimaryCare) - case "Cardiology" => Some(Cardiology) - case "Dermatology" => Some(Dermatology) - case "Ophthalmology" => Some(Ophthalmology) - case "Gastroenterology" => Some(Gastroenterology) - case "Neurology" => Some(Neurology) - case "Psychiatry" => Some(Psychiatry) - case "Gynecology" => Some(Gynecology) - case "Infectious Disease" => Some(InfectiousDisease) - case "Immunology" => Some(Immunology) - case "Nephrology" => Some(Nephrology) - case "Rheumatology" => Some(Rheumatology) - case "Cytology" => Some(Cytology) - case "Otolaryngology" => Some(Otolaryngology) - case "Anesthesiology" => Some(Anesthesiology) - case "Urology" => Some(Urology) - case "Palliative Care" => Some(PalliativeCare) - case "Emergency Medicine" => Some(EmergencyMedicine) - case "Social Work" => Some(SocialWork) - case "N/A" => Some(NA) - case "Other" => Some(Other) - case _ => None - } - } - - implicit def toPhiString(x: ProviderType): PhiString = { - import x._ - phi"ProviderType(id=$id, category=${Unsafe(name)})" - } -} - -final case class DocumentType(id: LongId[DocumentType], name: String) - -object DocumentType { - sealed trait DocumentTypeName - case object OutpatientPhysicianNote extends DocumentTypeName - case object DischargeNote extends DocumentTypeName - case object LaboratoryReport extends DocumentTypeName - case object MedicationList extends DocumentTypeName - case object HospitalizationNote extends DocumentTypeName - case object PathologyReport extends DocumentTypeName - case object RadiologyReport extends DocumentTypeName - case object OperativeProcedureReport extends DocumentTypeName - case object MedicationAdministration extends DocumentTypeName - case object SocialWorkCaseManagementNote extends DocumentTypeName - case object NonPhysicianProviderNote extends DocumentTypeName - case object Administrative extends DocumentTypeName - - def fromString(txt: String): Option[DocumentTypeName] = { - txt match { - case "Outpatient Physician Note" => Some(OutpatientPhysicianNote) - case "Discharge Note" => Some(DischargeNote) - case "Laboratory Report" => Some(LaboratoryReport) - case "Medication List" => Some(MedicationList) - case "Hospitalization Note" => Some(HospitalizationNote) - case "Pathology Report" => Some(PathologyReport) - case "Radiology Report" => Some(RadiologyReport) - case "Operative/Procedure Report" => Some(OperativeProcedureReport) - case "Medication Administration" => Some(MedicationAdministration) - case "Social Work/Case Management Note" => Some(SocialWorkCaseManagementNote) - case "Non-physician Provider Note" => Some(NonPhysicianProviderNote) - case "Administrative" => Some(Administrative) - case _ => None - } - } - - implicit def toPhiString(x: DocumentType): PhiString = { - import x._ - phi"DocumentType(id=$id, name=${Unsafe(name)})" - } -} - -object Document { - - final case class Meta(predicted: Option[Boolean], startPage: Double, endPage: Double) { - - /** - * Return a regular meta: this meta is considered as not predicted - */ - def confirmed: Meta = copy(predicted = predicted.map(_ => false)) - } - - class DocumentStatusSerializer extends JsonSerializer[Status] { - def serialize(value: Status, gen: JsonGenerator, serializers: SerializerProvider): Unit = { - gen.writeString(value.toString.toUpperCase) - } - } - - class DocumentStatusDeserializer extends JsonDeserializer[Status] { - def deserialize(parser: JsonParser, context: DeserializationContext): Status = { - val value = parser.getValueAsString - Option(value).fold[Document.Status](Status.New /* Default document status */ ) { v => - Status.All.find(_.toString.toUpperCase == v) match { - case None => throw new RuntimeJsonMappingException(s"$v is not valid Document.Status") - case Some(status) => status - } - } - } - } - - // Product with Serializable fixes issue: - // Set(New, Organized) has type Set[Status with Product with Serializable] - @JsonDeserialize(using = classOf[DocumentStatusDeserializer]) - @JsonSerialize(using = classOf[DocumentStatusSerializer]) - sealed trait Status extends Product with Serializable { - - def oneOf(xs: Status*): Boolean = xs.contains(this) - - def oneOf(xs: Set[Status]): Boolean = xs.contains(this) - - } - - object Status { - case object New extends Status - case object Organized extends Status - case object Extracted extends Status - case object Done extends Status - case object Flagged extends Status - case object Archived extends Status - - val All = Set[Status](New, Organized, Extracted, Done, Flagged, Archived) - val AllPrevious = Set[Status](Organized, Extracted) - - def fromString(status: String): Option[Status] = status match { - case "New" => Some(Status.New) - case "Organized" => Some(Status.Organized) - case "Extracted" => Some(Status.Extracted) - case "Done" => Some(Status.Done) - case "Flagged" => Some(Status.Flagged) - case "Archived" => Some(Status.Archived) - case _ => None - } - - def statusToString(x: Status): String = x match { - case Status.New => "New" - case Status.Organized => "Organized" - case Status.Extracted => "Extracted" - case Status.Done => "Done" - case Status.Flagged => "Flagged" - case Status.Archived => "Archived" - } - - implicit def toPhiString(x: Status): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - sealed trait RequiredType extends Product with Serializable { - - def oneOf(xs: RequiredType*): Boolean = xs.contains(this) - - def oneOf(xs: Set[RequiredType]): Boolean = xs.contains(this) - - } - - object RequiredType { - case object OPN extends RequiredType - case object PN extends RequiredType - - val All = Set[RequiredType](OPN, PN) - - def fromString(tpe: String): Option[RequiredType] = tpe match { - case "OPN" => Some(RequiredType.OPN) - case "PN" => Some(RequiredType.PN) - case _ => None - } - - def requiredTypeToString(x: RequiredType): String = x match { - case RequiredType.OPN => "OPN" - case RequiredType.PN => "PN" - } - - implicit def toPhiString(x: RequiredType): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - implicit def toPhiString(x: Document): PhiString = { - import x._ - phi"Document(id=$id, status=$status, assignee=$assignee, " + - phi"previousAssignee=$previousAssignee, lastActiveUserId=$lastActiveUserId, recordId=$recordId)" - } - - val validator: Validator[Document, Document] = { input => - for { - typeId <- Validators.nonEmpty("typeId")(input.typeId) - - providerTypeId <- Validators.nonEmpty("providerTypeId")(input.providerTypeId) - - meta <- Validators.nonEmpty("meta")(input.meta) - - startDate <- Validators.nonEmpty("startDate")(input.startDate) - - isOrderRight <- input.endDate match { - case Some(endDate) if startDate.isAfter(endDate) => - Validators.fail("The start date should be less, than the end one") - - case _ => Validators.success(true) - } - - areDatesInThePast <- { - val dates = List(input.startDate, input.endDate).flatten - val now = LocalDate.now() - val hasInvalid = dates.exists(_.isAfter(now)) - - if (hasInvalid) Validators.fail("Dates should be in the past") - else Validators.success(true) - } - } yield input - } - -} - -@JsonIgnoreProperties(value = Array("valid")) -final case class Document(id: LongId[Document] = LongId(0L), - status: Document.Status, - previousStatus: Option[Document.Status], - assignee: Option[StringId[User]], - previousAssignee: Option[StringId[User]], - lastActiveUserId: Option[StringId[User]], - recordId: LongId[MedicalRecord], - physician: Option[String], - typeId: Option[LongId[DocumentType]], // not null - providerName: Option[String], // not null - providerTypeId: Option[LongId[ProviderType]], // not null - requiredType: Option[Document.RequiredType], - meta: Option[TextJson[Meta]], // not null - startDate: Option[LocalDate], // not null - endDate: Option[LocalDate], - lastUpdate: LocalDateTime) { - - import Document.Status._ - - if (previousStatus.nonEmpty) { - assert(AllPrevious.contains(previousStatus.get), s"Previous status has invalid value: ${previousStatus.get}") - } - - def getRequiredType(documentTypeName: String, providerTypeName: String): Option[Document.RequiredType] = { - import DocumentType.{OutpatientPhysicianNote, PathologyReport} - import ProviderType.MedicalOncology - - (DocumentType.fromString(documentTypeName), ProviderType.fromString(providerTypeName), startDate) match { - case (Some(OutpatientPhysicianNote), Some(MedicalOncology), Some(date)) - if !(date.isAfter(LocalDate.now(ZoneId.of("Z"))) || date.isBefore( - LocalDate.now(ZoneId.of("Z")).minusMonths(6))) => - Some(Document.RequiredType.OPN) - - case (Some(PathologyReport), _, _) => Some(Document.RequiredType.PN) - - case _ => None - } - } - - // TODO: with the current business logic code this constraint sometimes harmful - // require(status match { - // case Document.Status.New if assignee.isDefined => false - // case Document.Status.Done if assignee.isDefined => false - // case _ => true - // }, "Assignee can't be defined in New or Done statuses") - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/DocumentHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/DocumentHistory.scala deleted file mode 100644 index a82da12..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/DocumentHistory.scala +++ /dev/null @@ -1,90 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.{LocalDateTime, ZoneId} - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.utils.Utils -import xyz.driver.pdsuidomain.entities.DocumentHistory._ - -object DocumentHistory { - - implicit def toPhiString(x: DocumentHistory): PhiString = { - import x._ - phi"DocumentHistory(id=$id, executor=$executor, documentId=$documentId, state=$state, action=$action, " + - phi"created=$created)" - } - - sealed trait State - object State { - case object Extract extends State - case object Review extends State - case object Flag extends State - - val All: Set[State] = Set[State](Extract, Review, Flag) - - val fromString: PartialFunction[String, State] = { - case "Extract" => State.Extract - case "Review" => State.Review - case "Flag" => State.Flag - } - - def stateToString(x: State): String = x match { - case State.Extract => "Extract" - case State.Review => "Review" - case State.Flag => "Flag" - } - - implicit def toPhiString(x: State): PhiString = - Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - sealed trait Action extends Product with Serializable { - - def oneOf(xs: Action*): Boolean = xs.contains(this) - - def oneOf(xs: Set[Action]): Boolean = xs.contains(this) - - } - - object Action { - case object Start extends Action - case object Submit extends Action - case object Unassign extends Action - case object Resolve extends Action - case object Flag extends Action - case object Archive extends Action - - val All: Set[Action] = - Set[Action](Start, Submit, Unassign, Resolve, Flag, Archive) - - val fromString: PartialFunction[String, Action] = { - case "Start" => Action.Start - case "Submit" => Action.Submit - case "Unassign" => Action.Unassign - case "Resolve" => Action.Resolve - case "Flag" => Action.Flag - case "Archive" => Action.Archive - } - - def actionToString(x: Action): String = x match { - case Action.Start => "Start" - case Action.Submit => "Submit" - case Action.Unassign => "Unassign" - case Action.Resolve => "Resolve" - case Action.Flag => "Flag" - case Action.Archive => "Archive" - } - - implicit def toPhiString(x: Action): PhiString = - Unsafe(Utils.getClassSimpleName(x.getClass)) - } - -} - -final case class DocumentHistory(id: LongId[DocumentHistory], - executor: StringId[User], - documentId: LongId[Document], - state: State, - action: Action, - created: LocalDateTime = LocalDateTime.now(ZoneId.of("Z"))) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/DocumentIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/DocumentIssue.scala deleted file mode 100644 index 0ec8b00..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/DocumentIssue.scala +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuicommon.logging._ - -final case class DocumentIssue(id: LongId[DocumentIssue], - userId: StringId[User], - documentId: LongId[Document], - startPage: Option[Double], - endPage: Option[Double], - lastUpdate: LocalDateTime, - isDraft: Boolean, - text: String, - archiveRequired: Boolean) - -object DocumentIssue { - implicit def toPhiString(x: DocumentIssue): PhiString = { - import x._ - phi"DocumentIssue(id=$id, userId=$userId, documentId=$documentId)" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/ExtractedData.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/ExtractedData.scala deleted file mode 100644 index 32258dc..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/ExtractedData.scala +++ /dev/null @@ -1,47 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, TextJson} -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.ExtractedData.Meta - -final case class ExtractedData(id: LongId[ExtractedData] = LongId(0L), - documentId: LongId[Document], - keywordId: Option[LongId[Keyword]], - evidenceText: Option[String], - meta: Option[TextJson[Meta]]) { - - def isValid: Boolean = evidenceText.getOrElse("") != "" && meta.nonEmpty - -} - -object ExtractedData { - - final case class Meta(keyword: Meta.Keyword, evidence: Meta.Evidence) - - object Meta { - final case class Evidence(pageRatio: Double, start: TextLayerPosition, end: TextLayerPosition) - - final case class TextLayerPosition(page: Integer, index: Integer, offset: Integer) - - final case class Keyword(page: Integer, pageRatio: Option[Double], index: Integer, sortIndex: String) - } - - implicit def toPhiString(x: ExtractedData): PhiString = { - import x._ - phi"ExtractedData(id=$id, documentId=$documentId, keywordId=$keywordId)" - } -} - -object ExtractedDataLabel { - - implicit def toPhiString(x: ExtractedDataLabel): PhiString = { - import x._ - phi"ExtractedDataLabel(id=$id, dataId=$dataId, labelId=$labelId, categoryId=$categoryId, value=$value)" - } -} - -final case class ExtractedDataLabel(id: LongId[ExtractedDataLabel], - dataId: LongId[ExtractedData], - labelId: Option[LongId[Label]], - categoryId: Option[LongId[Category]], - value: Option[FuzzyValue]) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Hypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Hypothesis.scala deleted file mode 100644 index 47b87ff..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Hypothesis.scala +++ /dev/null @@ -1,13 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuicommon.logging._ - -final case class Hypothesis(id: UuidId[Hypothesis], name: String, treatmentType: String, description: String) - -object Hypothesis { - implicit def toPhiString(x: Hypothesis): PhiString = { - import x._ - phi"Hypothesis(id=$id, name=${Unsafe(name)})" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Intervention.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Intervention.scala deleted file mode 100644 index e691547..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Intervention.scala +++ /dev/null @@ -1,48 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuicommon.logging._ - -final case class InterventionType(id: LongId[InterventionType], name: String) - -object InterventionType { - implicit def toPhiString(x: InterventionType): PhiString = { - import x._ - phi"InterventionType(id=$id, name=${Unsafe(name)})" - } -} - -final case class InterventionArm(armId: LongId[Arm], interventionId: LongId[Intervention]) - -object InterventionArm { - implicit def toPhiString(x: InterventionArm): PhiString = { - import x._ - phi"InterventionArm(armId=$armId, interventionId=$interventionId)" - } -} - -final case class Intervention(id: LongId[Intervention], - trialId: StringId[Trial], - name: String, - originalName: String, - typeId: Option[LongId[InterventionType]], - originalType: Option[String], - description: String, - originalDescription: String, - isActive: Boolean) - -object Intervention { - implicit def toPhiString(x: Intervention): PhiString = { - import x._ - phi"Intervention(id=$id, trialId=$trialId, name=${Unsafe(name)}, typeId=$typeId, isActive=$isActive)" - } -} - -final case class InterventionWithArms(intervention: Intervention, arms: List[InterventionArm]) - -object InterventionWithArms { - implicit def toPhiString(x: InterventionWithArms): PhiString = { - import x._ - phi"InterventionWithArms(intervention=$intervention, arms=$arms)" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Keyword.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Keyword.scala deleted file mode 100644 index 3683efc..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Keyword.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 Keyword(id: LongId[Keyword], keyword: String) - -object Keyword { - implicit def toPhiString(x: Keyword): PhiString = { - import x._ - phi"Keyword(id=$id, keyword=${Unsafe(keyword)})" - } -} - -final case class KeywordWithLabels(keyword: Keyword, labels: List[Label]) - -object KeywordWithLabels { - implicit def toPhiString(x: KeywordWithLabels): PhiString = { - import x._ - phi"KeywordWithLabels(keyword=$keyword, $labels)" - } -} - -final case class KeywordLabel(keywordId: LongId[Keyword], labelId: LongId[Label]) - -object KeywordLabel { - implicit def toPhiString(x: KeywordLabel): PhiString = { - import x._ - phi"KeywordLabel($keywordId, $labelId)" - } -} 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/MedicalRecord.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala deleted file mode 100644 index 9b33af4..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala +++ /dev/null @@ -1,184 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.nio.channels.ReadableByteChannel -import java.time.LocalDateTime - -import com.fasterxml.jackson.annotation.JsonSubTypes.Type -import com.fasterxml.jackson.annotation.{JsonProperty, JsonSubTypes, JsonTypeInfo} -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.utils.Utils -import xyz.driver.pdsuidomain.entities.MedicalRecord.Meta -import xyz.driver.pdsuidomain.entities.MedicalRecord.Meta.{Duplicate, Reorder, Rotation} - -object MedicalRecord { - - @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") - @JsonSubTypes( - Array( - new Type(value = classOf[Duplicate], name = "duplicate"), - new Type(value = classOf[Reorder], name = "reorder"), - new Type(value = classOf[Rotation], name = "rotation") - )) - trait Meta { - @JsonProperty("type") def metaType: String - def predicted: Option[Boolean] - - /** - * Return a regular meta: this meta is considered as not predicted - */ - def confirmed: Meta - } - - object Meta { - - final case class Duplicate(predicted: Option[Boolean], - startPage: Double, - endPage: Double, - startOriginalPage: Double, - endOriginalPage: Option[Double]) - extends Meta { - override val metaType = "duplicate" - override def confirmed: Duplicate = copy(predicted = predicted.map(_ => false)) - } - - object Duplicate { - implicit def toPhiString(x: Duplicate): PhiString = { - import x._ - phi"Duplicate(predicted=${x.predicted}, startPage=${Unsafe(startPage)}, endPage=${Unsafe(endPage)}, " + - phi"startOriginalPage=${Unsafe(startOriginalPage)}, endOriginalPage=${Unsafe(endOriginalPage)}" - } - } - - final case class Reorder(predicted: Option[Boolean], items: Seq[Int]) extends Meta { - override val metaType = "reorder" - override def confirmed: Reorder = copy(predicted = predicted.map(_ => false)) - } - - object Reorder { - implicit def toPhiString(x: Reorder): PhiString = { - import x._ - phi"Reorder(predicted=${x.predicted}, items=${Unsafe(items.toString)})" - } - } - - final case class Rotation(predicted: Option[Boolean], items: Map[String, Int]) extends Meta { - override val metaType = "rotation" - override def confirmed: Rotation = copy(predicted = predicted.map(_ => false)) - } - - object Rotation { - implicit def toPhiString(x: Rotation): PhiString = { - import x._ - phi"Rotation(predicted=${x.predicted}, items=${Unsafe(items.toString)})" - } - } - - implicit def toPhiString(input: Meta): PhiString = input match { - case x: Duplicate => Duplicate.toPhiString(x) - case x: Reorder => Reorder.toPhiString(x) - case x: Rotation => Rotation.toPhiString(x) - } - - } - - // Product with Serializable fixes issue: - // Set(New, Cleaned) has type Set[Status with Product with Serializable] - sealed trait Status extends Product with Serializable { - - def oneOf(xs: Status*): Boolean = xs.contains(this) - - def oneOf(xs: Set[Status]): Boolean = xs.contains(this) - - } - object Status { - case object Unprocessed extends Status - case object PreCleaning extends Status - case object New extends Status - case object Cleaned extends Status - case object PreOrganized extends Status - case object PreOrganizing extends Status - case object Reviewed extends Status - case object Organized extends Status - case object Done extends Status - case object Flagged extends Status - case object Archived extends Status - - def fromString(status: String): Option[Status] = status match { - case "Unprocessed" => Some(Unprocessed) - case "PreCleaning" => Some(PreCleaning) - case "New" => Some(New) - case "Cleaned" => Some(Cleaned) - case "PreOrganized" => Some(PreOrganized) - case "PreOrganizing" => Some(PreOrganizing) - case "Reviewed" => Some(Reviewed) - case "Organized" => Some(Organized) - case "Done" => Some(Done) - case "Flagged" => Some(Flagged) - case "Archived" => Some(Archived) - case _ => None - } - - val All = Set[Status]( - Unprocessed, - PreCleaning, - New, - Cleaned, - PreOrganized, - PreOrganizing, - Reviewed, - Organized, - Done, - Flagged, - Archived - ) - - val AllPrevious = Set[Status](New, Cleaned, Reviewed, Organized) - - implicit def toPhiString(x: Status): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - sealed trait PdfSource - - object PdfSource { - case object Empty extends PdfSource - - /** @param createResource Constructor of the resource which is represents the file */ - final case class Channel(createResource: () => ReadableByteChannel) extends PdfSource - } - - implicit def toPhiString(x: MedicalRecord): PhiString = { - import x._ - phi"MedicalRecord(id=$id, status=$status, assignee=$assignee, " + - phi"previousAssignee=$previousAssignee, lastActiveUserId=$lastActiveUserId)" - } -} - -final case class MedicalRecord(id: LongId[MedicalRecord], - status: MedicalRecord.Status, - previousStatus: Option[MedicalRecord.Status], - assignee: Option[StringId[User]], - previousAssignee: Option[StringId[User]], - lastActiveUserId: Option[StringId[User]], - patientId: UuidId[Patient], - requestId: RecordRequestId, - disease: String, - caseId: Option[CaseId], - physician: Option[String], - meta: Option[TextJson[List[Meta]]], - predictedMeta: Option[TextJson[List[Meta]]], - predictedDocuments: Option[TextJson[List[Document]]], - lastUpdate: LocalDateTime) { - - import MedicalRecord.Status._ - - if (previousStatus.nonEmpty) { - assert(AllPrevious.contains(previousStatus.get), s"Previous status has invalid value: ${previousStatus.get}") - } - - // TODO: with the current business logic code this constraint sometimes harmful - // require(status match { - // case MedicalRecord.Status.Done if assignee.isDefined => false - // case _ => true - // }, "Assignee can't be defined in Done status") -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecordHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecordHistory.scala deleted file mode 100644 index d01433c..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecordHistory.scala +++ /dev/null @@ -1,93 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.{LocalDateTime, ZoneId} - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.utils.Utils -import xyz.driver.pdsuidomain.entities.MedicalRecordHistory._ - -object MedicalRecordHistory { - - implicit def toPhiString(x: MedicalRecordHistory): PhiString = { - import x._ - phi"MedicalRecordHistory(id=$id, executor=$executor, recordId=$recordId, state=$state, action=$action, " + - phi"created=$created)" - } - - sealed trait State - object State { - case object Clean extends State - case object Organize extends State - case object Review extends State - case object Flag extends State - - val All: Set[State] = Set[State](Clean, Organize, Review, Flag) - - val fromString: PartialFunction[String, State] = { - case "Clean" => State.Clean - case "Organize" => State.Organize - case "Review" => State.Review - case "Flag" => State.Flag - } - - def stateToString(x: State): String = x match { - case State.Clean => "Clean" - case State.Organize => "Organize" - case State.Review => "Review" - case State.Flag => "Flag" - } - - implicit def toPhiString(x: State): PhiString = - Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - sealed trait Action extends Product with Serializable { - - def oneOf(xs: Action*): Boolean = xs.contains(this) - - def oneOf(xs: Set[Action]): Boolean = xs.contains(this) - - } - - object Action { - case object Start extends Action - case object Submit extends Action - case object Unassign extends Action - case object Resolve extends Action - case object Flag extends Action - case object Archive extends Action - - val All: Set[Action] = - Set[Action](Start, Submit, Unassign, Resolve, Flag, Archive) - - val fromString: PartialFunction[String, Action] = { - case "Start" => Action.Start - case "Submit" => Action.Submit - case "Unassign" => Action.Unassign - case "Resolve" => Action.Resolve - case "Flag" => Action.Flag - case "Archive" => Action.Archive - } - - def actionToString(x: Action): String = x match { - case Action.Start => "Start" - case Action.Submit => "Submit" - case Action.Unassign => "Unassign" - case Action.Resolve => "Resolve" - case Action.Flag => "Flag" - case Action.Archive => "Archive" - } - - implicit def toPhiString(x: Action): PhiString = - Unsafe(Utils.getClassSimpleName(x.getClass)) - } - -} - -final case class MedicalRecordHistory(id: LongId[MedicalRecordHistory], - executor: StringId[User], - recordId: LongId[MedicalRecord], - state: State, - action: Action, - created: LocalDateTime = LocalDateTime.now(ZoneId.of("Z"))) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecordIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecordIssue.scala deleted file mode 100644 index 0d5a498..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecordIssue.scala +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuicommon.logging._ - -final case class MedicalRecordIssue(id: LongId[MedicalRecordIssue], - userId: StringId[User], - recordId: LongId[MedicalRecord], - startPage: Option[Double], - endPage: Option[Double], - lastUpdate: LocalDateTime, - isDraft: Boolean, - text: String, - archiveRequired: Boolean) - -object MedicalRecordIssue { - implicit def toPhiString(x: MedicalRecordIssue): PhiString = { - import x._ - phi"MedicalRecordIssue(id=$id, userId=$userId, recordId=$recordId)" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Message.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Message.scala deleted file mode 100644 index 3bdbac8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Message.scala +++ /dev/null @@ -1,34 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User, UuidId} -import xyz.driver.pdsuicommon.logging._ - -final case class Message(id: LongId[Message], - text: String, - lastUpdate: LocalDateTime, - userId: StringId[User], - isDraft: Boolean, - recordId: Option[LongId[MedicalRecord]], - documentId: Option[LongId[Document]], - patientId: Option[UuidId[Patient]], - trialId: Option[StringId[Trial]], - startPage: Option[Double], - endPage: Option[Double], - evidence: Option[String], - archiveRequired: Option[Boolean], - meta: Option[String]) - -object Message { - implicit def toPhiString(x: Message): PhiString = { - import x._ - - val entityId: Option[String] = recordId - .map(_.toString) - .orElse(documentId.map(_.toString)) - .orElse(patientId.map(_.toString)) - - phi"Message(id=$id, userId=$userId, isDraft=$isDraft, entityId=${Unsafe(entityId)}" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Patient.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Patient.scala deleted file mode 100644 index 6be0b88..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Patient.scala +++ /dev/null @@ -1,71 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.{LocalDate, LocalDateTime} - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.utils.Utils - -object Patient { - - // Product with Serizalizable fixes issue: - // Set(New, Verified) has type Set[Status with Product with Serializable] - sealed trait Status extends Product with Serializable { - def oneOf(xs: Status*): Boolean = xs.contains(this) - - def oneOf(xs: Set[Status]): Boolean = xs.contains(this) - } - - object Status { - case object New extends Status - case object Verified extends Status - case object Reviewed extends Status - case object Curated extends Status - case object Flagged extends Status - case object Done extends Status - - val AllPrevious = Set[Status]( - New, - Verified, - Reviewed, - Curated - ) - - val All = Set[Status]( - New, - Verified, - Reviewed, - Curated, - Flagged, - Done - ) - - implicit def toPhiString(x: Status): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - implicit def toPhiString(x: Patient): PhiString = { - import x._ - phi"Patient(id=$id, status=$status, previousStatus=$previousStatus, lastActiveUserId=$lastActiveUserId" + - phi"assignee=$assignee, previousAssignee=$previousAssignee)" - } -} - -final case class Patient(id: UuidId[Patient], - status: Patient.Status, - name: String, - dob: LocalDate, - assignee: Option[StringId[User]], - previousStatus: Option[Patient.Status], - previousAssignee: Option[StringId[User]], - lastActiveUserId: Option[StringId[User]], - isUpdateRequired: Boolean, - condition: String, - orderId: PatientOrderId, - lastUpdate: LocalDateTime) { - - import Patient.Status._ - - if (previousStatus.nonEmpty) { - assert(AllPrevious.contains(previousStatus.get), s"Previous status has invalid value: ${previousStatus.get}") - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientCriterion.scala deleted file mode 100644 index 469b21c..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientCriterion.scala +++ /dev/null @@ -1,67 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, StringId} -import xyz.driver.pdsuicommon.logging._ - -object PatientCriterion { - implicit def toPhiString(x: PatientCriterion): PhiString = { - import x._ - phi"PatientCriterion(id=$id, patientLabelId=$patientLabelId, trialId=${Unsafe(trialId)}, nctId=${Unsafe(nctId)}, " + - phi"criterionId=$criterionId, criterionValue=${Unsafe(criterionValue)}, " + - phi"isImplicitMatch=$criterionIsDefining), criterionIsDefining=${Unsafe(criterionIsDefining)}, " + - phi"eligibilityStatus=${Unsafe(eligibilityStatus)}, verifiedEligibilityStatus=${Unsafe(verifiedEligibilityStatus)}, " + - phi"isVerified=${Unsafe(isVerified)}, lastUpdate=${Unsafe(lastUpdate)}" - } - - /** - * @see https://driverinc.atlassian.net/wiki/display/MTCH/EV+Business+Process - */ - def getEligibilityStatus(criterionValue: Option[Boolean], primaryValue: Option[FuzzyValue]): Option[FuzzyValue] = { - primaryValue match { - case None => None - case Some(FuzzyValue.Maybe) => Some(FuzzyValue.Maybe) - case Some(_) if criterionValue.isEmpty => Some(FuzzyValue.Maybe) - case Some(status) => - Some( - FuzzyValue.fromBoolean( - FuzzyValue.fromBoolean( - criterionValue.getOrElse(throw new IllegalArgumentException("Criterion should not be empty"))) == status - )) - } - } - -} - -/** - * @param eligibilityStatus - a value, that selects an eligibility verifier (EV) - * @param verifiedEligibilityStatus - a copy of eligibilityStatus, when a patient goes to routes curator (RC) - * @param isVerified - is EV selected the eligibilityStatus? - */ -final case class PatientCriterion(id: LongId[PatientCriterion], - patientLabelId: LongId[PatientLabel], - trialId: Long, - nctId: StringId[Trial], - criterionId: LongId[Criterion], - criterionText: String, - criterionValue: Option[Boolean], - criterionIsDefining: Boolean, - eligibilityStatus: Option[FuzzyValue], - verifiedEligibilityStatus: Option[FuzzyValue], - isVerified: Boolean, - isVisible: Boolean, - lastUpdate: LocalDateTime) { - def isIneligibleForEv: Boolean = eligibilityStatus.contains(FuzzyValue.No) && isVerified -} - -object PatientCriterionArm { - - implicit def toPhiString(x: PatientCriterionArm): PhiString = { - import x._ - phi"PatientCriterionArm(patientCriterionId=$patientCriterionId, armId=$armId, armName=${Unsafe(armName)})" - } - -} - -final case class PatientCriterionArm(patientCriterionId: LongId[PatientCriterion], armId: LongId[Arm], armName: String) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientEligibleTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientEligibleTrial.scala deleted file mode 100644 index 8ee5b3c..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientEligibleTrial.scala +++ /dev/null @@ -1,83 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, StringId, UuidId} -import xyz.driver.pdsuicommon.logging._ - -object PatientTrialArm { - - implicit def toPhiString(x: PatientTrialArm): PhiString = { - import x._ - phi"PatientTrialArm(armId=$armId, trialArmGroupId=$trialArmGroupId)" - } -} - -final case class PatientTrialArm(armId: LongId[Arm], trialArmGroupId: LongId[PatientTrialArmGroup]) - -object PatientEligibleTrial { - implicit def toPhiString(x: PatientEligibleTrial): PhiString = { - import x._ - phi"PatientEligibleTrial(id=$id, patientId=$patientId, trialId=$trialId, hypothesisId=$hypothesisId)" - } -} - -final case class PatientEligibleTrial(id: UuidId[PatientEligibleTrial], - patientId: UuidId[Patient], - trialId: StringId[Trial], - hypothesisId: UuidId[Hypothesis]) - -object PatientTrialArmGroup { - - implicit def toPhiString(x: PatientTrialArmGroup): PhiString = { - import x._ - phi"PatientTrialArmGroup(id=$id, eligibleTrialId=$eligibleTrialId, " + - phi"eligibilityStatus=${Unsafe(eligibilityStatus)}, " + - phi"verifiedEligibilityStatus=${Unsafe(verifiedEligibilityStatus)}, isVerified=$isVerified)" - } - - /** - * @see https://driverinc.atlassian.net/wiki/display/DMPD/EV+Business+Process - */ - def getEligibilityStatusForRc(criterionList: TraversableOnce[PatientCriterion]): Option[FuzzyValue] = { - def isEligible: Boolean = criterionList.forall(_.verifiedEligibilityStatus.contains(FuzzyValue.Yes)) - def isIneligible: Boolean = criterionList.exists(_.verifiedEligibilityStatus.contains(FuzzyValue.No)) - def isUnknown: Boolean = criterionList.forall(_.verifiedEligibilityStatus.isEmpty) - - if (isEligible) Some(FuzzyValue.Yes) - else if (isIneligible) Some(FuzzyValue.No) - else if (isUnknown) None - else Some(FuzzyValue.Maybe) - } -} - -final case class PatientTrialArmGroup(id: LongId[PatientTrialArmGroup], - eligibleTrialId: UuidId[PatientEligibleTrial], - eligibilityStatus: Option[FuzzyValue], - verifiedEligibilityStatus: Option[FuzzyValue], - isVerified: Boolean) - -object PatientTrialArmGroupView { - - implicit def toPhiString(x: PatientTrialArmGroupView): PhiString = { - import x._ - phi"PatientTrialArmGroupView(id=$id, patientId=$patientId, trialId=$trialId, " + - phi"hypothesisId=$hypothesisId, eligibilityStatus=${Unsafe(eligibilityStatus)}, " + - phi"verifiedEligibilityStatus=${Unsafe(verifiedEligibilityStatus)}, isVerified=$isVerified)" - } -} - -final case class PatientTrialArmGroupView(id: LongId[PatientTrialArmGroup], - patientId: UuidId[Patient], - trialId: StringId[Trial], - hypothesisId: UuidId[Hypothesis], - eligibilityStatus: Option[FuzzyValue], - verifiedEligibilityStatus: Option[FuzzyValue], - isVerified: Boolean) { - - def applyTo(trialArmGroup: PatientTrialArmGroup) = { - trialArmGroup.copy( - eligibilityStatus = this.eligibilityStatus, - verifiedEligibilityStatus = this.verifiedEligibilityStatus, - isVerified = this.isVerified - ) - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientHistory.scala deleted file mode 100644 index 39817c4..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientHistory.scala +++ /dev/null @@ -1,92 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.{LocalDateTime, ZoneId} - -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User, UuidId} -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.utils.Utils -import xyz.driver.pdsuidomain.entities.PatientHistory.{Action, State} - -object PatientHistory { - - implicit def toPhiString(x: PatientHistory): PhiString = { - import x._ - phi"PatientHistory(id=$id, executor=$executor, patientId=$patientId, state=$state, action=$action, created=$created)" - } - - sealed trait State - object State { - case object Verify extends State - case object Curate extends State - case object Review extends State - case object Flag extends State - - val All: Set[State] = Set[State](Verify, Curate, Review, Flag) - - val fromString: PartialFunction[String, State] = { - case "Verify" => State.Verify - case "Curate" => State.Curate - case "Review" => State.Review - case "Flag" => State.Flag - } - - def stateToString(x: State): String = x match { - case State.Verify => "Verify" - case State.Curate => "Curate" - case State.Review => "Review" - case State.Flag => "Flag" - } - - implicit def toPhiString(x: State): PhiString = - Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - sealed trait Action extends Product with Serializable { - - def oneOf(xs: Action*): Boolean = xs.contains(this) - - def oneOf(xs: Set[Action]): Boolean = xs.contains(this) - - } - - object Action { - case object Start extends Action - case object Submit extends Action - case object Unassign extends Action - case object Resolve extends Action - case object Flag extends Action - case object Archive extends Action - - val All: Set[Action] = - Set[Action](Start, Submit, Unassign, Resolve, Flag, Archive) - - val fromString: PartialFunction[String, Action] = { - case "Start" => Action.Start - case "Submit" => Action.Submit - case "Unassign" => Action.Unassign - case "Resolve" => Action.Resolve - case "Flag" => Action.Flag - case "Archive" => Action.Archive - } - - def actionToString(x: Action): String = x match { - case Action.Start => "Start" - case Action.Submit => "Submit" - case Action.Unassign => "Unassign" - case Action.Resolve => "Resolve" - case Action.Flag => "Flag" - case Action.Archive => "Archive" - } - - implicit def toPhiString(x: Action): PhiString = - Unsafe(Utils.getClassSimpleName(x.getClass)) - } - -} - -final case class PatientHistory(id: LongId[PatientHistory], - executor: StringId[User], - patientId: UuidId[Patient], - state: State, - action: Action, - created: LocalDateTime = LocalDateTime.now(ZoneId.of("Z"))) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientHypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientHypothesis.scala deleted file mode 100644 index 23bb546..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientHypothesis.scala +++ /dev/null @@ -1,18 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuicommon.logging._ - -object PatientHypothesis { - implicit def toPhiString(x: PatientHypothesis): PhiString = { - import x._ - phi"PatientHypothesis(id=$id, patientId=$patientId, hypothesisId=$hypothesisId, " + - phi"rationale=${Unsafe(rationale)}, matchedTrials=${Unsafe(matchedTrials)})" - } -} - -final case class PatientHypothesis(id: UuidId[PatientHypothesis], - patientId: UuidId[Patient], - hypothesisId: UuidId[Hypothesis], - rationale: Option[String], - matchedTrials: Long) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientIssue.scala deleted file mode 100644 index f616754..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientIssue.scala +++ /dev/null @@ -1,21 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ - -final case class PatientIssue(id: LongId[PatientIssue], - userId: StringId[User], - patientId: UuidId[Patient], - lastUpdate: LocalDateTime, - isDraft: Boolean, - text: String, - archiveRequired: Boolean) - -object PatientIssue { - implicit def toPhiString(x: PatientIssue): PhiString = { - import x._ - phi"PatientIssue(id=$id, userId=$userId, patientId=$patientId)" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabel.scala deleted file mode 100644 index 633a347..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabel.scala +++ /dev/null @@ -1,38 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, UuidId} -import xyz.driver.pdsuicommon.logging._ - -object PatientLabel { - implicit def toPhiString(x: PatientLabel): PhiString = { - import x._ - phi"PatientLabel(id=$id, patientId=$patientId, labelId=$labelId, " + - phi"score=${Unsafe(score)}, primaryValue=${Unsafe(primaryValue)}, " + - phi"verifiedPrimaryValue=${Unsafe(verifiedPrimaryValue)})" - } -} - -final case class PatientLabel(id: LongId[PatientLabel], - patientId: UuidId[Patient], - labelId: LongId[Label], - score: Int, - primaryValue: Option[FuzzyValue], - verifiedPrimaryValue: Option[FuzzyValue], - isImplicitMatch: Boolean, - isVisible: Boolean) - -object PatientLabelEvidence { - implicit def toPhiString(x: PatientLabelEvidence): PhiString = { - import x._ - phi"PatientLabelEvidence(id=$id, patientLabelId=$patientLabelId, value=${Unsafe(value)}, " + - phi"documentId=$documentId, evidenceId=$evidenceId, reportId=$reportId)" - } -} - -final case class PatientLabelEvidence(id: LongId[PatientLabelEvidence], - patientLabelId: LongId[PatientLabel], - value: FuzzyValue, - evidenceText: String, - reportId: Option[UuidId[DirectReport]], - documentId: Option[LongId[Document]], - evidenceId: Option[LongId[ExtractedData]]) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabelEvidenceView.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabelEvidenceView.scala deleted file mode 100644 index 34e3741..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientLabelEvidenceView.scala +++ /dev/null @@ -1,28 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDate - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ - -object PatientLabelEvidenceView { - implicit def toPhiString(x: PatientLabelEvidenceView): PhiString = { - import x._ - phi"PatientLabelEvidenceView(id=$id, value=$value, documentId=$documentId, " + - phi"evidenceId=$evidenceId, reportId=$reportId, patientId=$patientId, labelId=$labelId, " + - phi"isImplicitMatch=$isImplicitMatch)" - } -} - -final case class PatientLabelEvidenceView(id: LongId[PatientLabelEvidence], - value: FuzzyValue, - evidenceText: String, - documentId: Option[LongId[Document]], - evidenceId: Option[LongId[ExtractedData]], - reportId: Option[UuidId[DirectReport]], - documentType: String, - date: Option[LocalDate], // Document.startDate is optional - providerType: String, - patientId: UuidId[Patient], - labelId: LongId[Label], - isImplicitMatch: Boolean) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientOrderId.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/PatientOrderId.scala deleted file mode 100644 index 50a97ce..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/PatientOrderId.scala +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.util.UUID - -final case class PatientOrderId(id: UUID) { - override def toString: String = id.toString -} - -object PatientOrderId { - - def apply() = new PatientOrderId(UUID.randomUUID()) - - def apply(x: String) = new PatientOrderId(UUID.fromString(x)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientDocument.scala deleted file mode 100644 index b66483c..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientDocument.scala +++ /dev/null @@ -1,28 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDate - -import xyz.driver.pdsuicommon.domain.{LongId, UuidId} -import xyz.driver.pdsuicommon.logging._ - -final case class RawPatientDocument(disease: String, - patientId: UuidId[Patient], - requestId: RecordRequestId, - recordId: LongId[MedicalRecord], - recordStatus: MedicalRecord.Status, - documentId: LongId[Document], - documentType: String, - documentProviderType: String, - documentStartDate: LocalDate, - documentStatus: Document.Status) - -object RawPatientDocument { - - implicit def toPhiString(x: RawPatientDocument): PhiString = { - import x._ - phi"RawPatientDocument(disease=${Unsafe(disease)}, patientId=$patientId, requestId=$requestId, " + - phi"recordId=$recordId, recordStatus=$recordStatus, documentId=$documentId, " + - phi"documentType=${Unsafe(documentType)}, providerType=${Unsafe(documentProviderType)}, " + - phi"startDate=$documentStartDate, documentStatus=$documentStatus)" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientLabel.scala deleted file mode 100644 index 6114661..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientLabel.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDate - -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, UuidId} -import xyz.driver.pdsuicommon.logging._ - -final case class RawPatientLabel(patientId: UuidId[Patient], - labelId: LongId[Label], - value: FuzzyValue, - evidenceId: LongId[ExtractedData], - evidenceText: String, - disease: String, - documentId: LongId[Document], - requestId: RecordRequestId, - documentType: String, - providerType: String, - startDate: LocalDate, - endDate: Option[LocalDate]) - -object RawPatientLabel { - - implicit def toPhiString(x: RawPatientLabel): PhiString = { - import x._ - phi"RawPatientLabel(patientId=$patientId, labelId=$labelId, value=$value, evidenceId=${Unsafe(evidenceId)}, " + - phi"evidenceText=${Unsafe(evidenceText)}, documentId=$documentId, requestId=${Unsafe(requestId)}, " + - phi"documentType=${Unsafe(documentType)}, providerType=${Unsafe(providerType)}, " + - phi"startDate=$startDate, endDate=$endDate)" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala deleted file mode 100644 index 9e69c87..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala +++ /dev/null @@ -1,31 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuicommon.logging._ - -final case class RawTrialLabel(nctId: StringId[Trial], - trialId: UuidId[Trial], - condition: String, - lastReviewed: LocalDateTime, - armName: String, - armId: LongId[Arm], - labelId: LongId[Label], - value: Option[Boolean], - criterionId: LongId[Criterion], - criteria: String, - criterionArmId: LongId[Arm], - isCompound: Boolean, - isDefining: Boolean) - -object RawTrialLabel { - - implicit def toPhiString(x: RawTrialLabel): PhiString = { - import x._ - phi"RawTrialLabel(nctId=$nctId, trialId=$trialId, condition=${Unsafe(condition)}, lastReviewed=$lastReviewed, " + - phi"armId=$armId, armName=${Unsafe(armName)}, labelId=$labelId, value=$value, " + - phi"criterionId=$criterionId, criteria=${Unsafe(criteria)}, criterionArmId=$criterionArmId, " + - phi"isCompound=$isCompound, isDefining=$isDefining)" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/RecordRequestId.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/RecordRequestId.scala deleted file mode 100644 index 5df87c2..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/RecordRequestId.scala +++ /dev/null @@ -1,15 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.util.UUID -import xyz.driver.pdsuicommon.logging._ - -final case class RecordRequestId(id: UUID) { - override def toString: String = id.toString -} - -object RecordRequestId { - - def apply() = new RecordRequestId(UUID.randomUUID()) - - implicit def toPhiString(x: RecordRequestId): PhiString = phi"${x.id}" -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/ScrapedTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/ScrapedTrial.scala deleted file mode 100644 index e7ee1cb..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/ScrapedTrial.scala +++ /dev/null @@ -1,81 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDateTime -import java.util.UUID - -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.domain.UuidId - -final case class ScrapedStudyDesign(value: String) - -final case class ScrapedOverall(affiliation: String, - status: String, - facilityName: Option[String], - firstName: Option[String], - lastName: Option[String], - phone: Option[String], - phoneExt: Option[String], - email: Option[String], - isBackup: Boolean) - -final case class ScrapedInterventionType(value: String) - -final case class ScrapedIntervention(name: String, - kind: ScrapedInterventionType, - description: Option[String], - isSynonym: Boolean) - -object ScrapedIntervention { - - implicit def toPhiString(x: ScrapedIntervention): PhiString = - phi"ScrapedIntervention(${Unsafe(x.name)})" -} - -final case class ScrapedArm(name: String, kind: Option[String], interventions: Set[ScrapedIntervention]) - -object ScrapedArm { - - implicit def toPhiString(x: ScrapedArm): PhiString = { - import x._ - phi"ScrapedArm(name=${Unsafe(name)}, inverventions=$interventions)" - } -} - -final case class ScrapedTrialChecksum(eligibilityCriteria: String, - briefSummary: String, - detailedDescription: String, - armDescription: String) - -object ScrapedTrialChecksum { - - implicit def toPhiString(x: ScrapedTrialChecksum): PhiString = { - import x._ - phi"ScrapedTrialChecksum(eligibilityCriteria=${Unsafe(eligibilityCriteria)}, briefSummary=${Unsafe(briefSummary)}, " + - phi"detailedDescription=${Unsafe(detailedDescription)}, armDescription=${Unsafe(armDescription)}" - } -} - -object ScrapedTrial { - - implicit def toPhiString(x: ScrapedTrial): PhiString = { - import x._ - phi"ScrapedTrial(rawId=$rawId, nctId=${Unsafe(nctId)}, arms=$arms, checksum=$checksum)" - } -} - -final case class ScrapedTrial(rawId: UuidId[ScrapedTrial], - createdAt: LocalDateTime, - disease: String, - nctId: String, - nctUuid: UUID, - title: Option[String], - startDate: Option[LocalDateTime], - phase: String, - studyDesign: Option[ScrapedStudyDesign], - overall: Set[ScrapedOverall], - // // see ClinicalTrialRaw - // trialHtml: String, - // eligibilityText: String, - lastReviewed: LocalDateTime, - arms: Set[ScrapedArm], - checksum: ScrapedTrialChecksum) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala deleted file mode 100644 index db4def2..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala +++ /dev/null @@ -1,105 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User, UuidId} -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.utils.Utils -import xyz.driver.pdsuidomain.entities.Trial.{Condition, Status} - -final case class StudyDesign(id: LongId[StudyDesign], name: String) - -object StudyDesign { - implicit def toPhiString(x: StudyDesign): PhiString = { - import x._ - phi"StudyDesign(id=$id, category=${Unsafe(name)})" - } -} - -object Trial { - - sealed trait Status { - def oneOf(xs: Status*): Boolean = xs.contains(this) - def oneOf(xs: Set[Status]): Boolean = xs.contains(this) - } - - object Status { - case object New extends Status - case object ReviewSummary extends Status - case object Summarized extends Status - case object PendingUpdate extends Status - case object Update extends Status - case object ReviewCriteria extends Status - case object Done extends Status - case object Flagged extends Status - case object Archived extends Status - - val All = Set[Status]( - New, - ReviewSummary, - Summarized, - PendingUpdate, - Update, - ReviewCriteria, - Done, - Flagged, - Archived - ) - - val AllPrevious = Set[Status](New, ReviewSummary, Summarized, ReviewCriteria) - - implicit def toPhiString(x: Status): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - implicit def toPhiString(x: Trial): PhiString = { - import x._ - phi"Trial(id=$id, externalId=$externalId, status=$status, previousStatus=$previousStatus, " + - phi"lastActiveUserId=$lastActiveUserId, assignee=$assignee, previousAssignee=$previousAssignee, " - } - - final case class Locations(locations: List[String]) - - sealed trait Condition - - object Condition { - - case object Breast extends Condition - case object Lung extends Condition - case object Prostate extends Condition - - def fromString(condition: String): Option[Condition] = condition match { - case "Breast" => Some(Breast) - case "Lung" => Some(Lung) - case "Prostate" => Some(Prostate) - case _ => None - } - - val All: Set[Condition] = Set(Breast, Lung, Prostate) - } -} - -final case class Trial(id: StringId[Trial], - externalId: UuidId[Trial], - status: Status, - assignee: Option[StringId[User]], - previousStatus: Option[Status], - previousAssignee: Option[StringId[User]], - lastActiveUserId: Option[StringId[User]], - lastUpdate: LocalDateTime, - condition: Condition, - phase: String, - hypothesisId: Option[UuidId[Hypothesis]], - studyDesignId: Option[LongId[StudyDesign]], - originalStudyDesign: Option[String], - isPartner: Boolean, - overview: Option[String], - overviewTemplate: String, - isUpdated: Boolean, - title: String, - originalTitle: String) { - import Trial.Status._ - - if (previousStatus.nonEmpty) { - assert(AllPrevious.contains(previousStatus.get), s"Previous status has invalid value: ${previousStatus.get}") - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/TrialHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/TrialHistory.scala deleted file mode 100644 index c73aefe..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/TrialHistory.scala +++ /dev/null @@ -1,92 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.{LocalDateTime, ZoneId} - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.utils.Utils -import TrialHistory._ - -object TrialHistory { - - implicit def toPhiString(x: TrialHistory): PhiString = { - import x._ - phi"TrialHistory(id=$id, executor=$executor, trialId=$trialId, state=$state, action=$action, created=$created)" - } - - sealed trait State - object State { - case object Summarize extends State - case object Criteriarize extends State - case object Review extends State - case object Flag extends State - - val All: Set[State] = Set[State](Summarize, Criteriarize, Review, Flag) - - val fromString: PartialFunction[String, State] = { - case "Summarize" => State.Summarize - case "Criteriarize" => State.Criteriarize - case "Review" => State.Review - case "Flag" => State.Flag - } - - def stateToString(x: State): String = x match { - case State.Summarize => "Summarize" - case State.Criteriarize => "Criteriarize" - case State.Review => "Review" - case State.Flag => "Flag" - } - - implicit def toPhiString(x: State): PhiString = - Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - sealed trait Action extends Product with Serializable { - - def oneOf(xs: Action*): Boolean = xs.contains(this) - - def oneOf(xs: Set[Action]): Boolean = xs.contains(this) - - } - - object Action { - case object Start extends Action - case object Submit extends Action - case object Unassign extends Action - case object Resolve extends Action - case object Flag extends Action - case object Archive extends Action - - val All: Set[Action] = - Set[Action](Start, Submit, Unassign, Resolve, Flag, Archive) - - val fromString: PartialFunction[String, Action] = { - case "Start" => Action.Start - case "Submit" => Action.Submit - case "Unassign" => Action.Unassign - case "Resolve" => Action.Resolve - case "Flag" => Action.Flag - case "Archive" => Action.Archive - } - - def actionToString(x: Action): String = x match { - case Action.Start => "Start" - case Action.Submit => "Submit" - case Action.Unassign => "Unassign" - case Action.Resolve => "Resolve" - case Action.Flag => "Flag" - case Action.Archive => "Archive" - } - - implicit def toPhiString(x: Action): PhiString = - Unsafe(Utils.getClassSimpleName(x.getClass)) - } - -} - -final case class TrialHistory(id: LongId[TrialHistory], - executor: StringId[User], - trialId: StringId[Trial], - state: State, - action: Action, - created: LocalDateTime = LocalDateTime.now(ZoneId.of("Z"))) diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/TrialIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/TrialIssue.scala deleted file mode 100644 index 2514f4d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/TrialIssue.scala +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuicommon.logging._ - -final case class TrialIssue(id: LongId[TrialIssue], - userId: StringId[User], - trialId: StringId[Trial], - lastUpdate: LocalDateTime, - isDraft: Boolean, - text: String, - evidence: String, - archiveRequired: Boolean, - meta: String) - -object TrialIssue { - implicit def toPhiString(x: TrialIssue): PhiString = { - import x._ - phi"TrialIssue(id=$id, userId=$userId, trialId=$trialId)" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/UserHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/UserHistory.scala deleted file mode 100644 index 9be26b9..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/UserHistory.scala +++ /dev/null @@ -1,145 +0,0 @@ -package xyz.driver.pdsuidomain.entities - -import java.time.{LocalDateTime, ZoneId} - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuicommon.utils.Utils - -final case class UserHistory(id: LongId[UserHistory], - executor: StringId[User], - recordId: Option[LongId[MedicalRecord]] = None, - documentId: Option[LongId[Document]] = None, - trialId: Option[StringId[Trial]] = None, - patientId: Option[UuidId[Patient]] = None, - state: UserHistory.State, - action: UserHistory.Action, - created: LocalDateTime = LocalDateTime.now(ZoneId.of("Z"))) - -object UserHistory { - - def forDocument(executor: StringId[User], - documentId: LongId[Document], - state: UserHistory.State, - action: UserHistory.Action): UserHistory = UserHistory( - id = LongId(0L), - executor = executor, - documentId = Some(documentId), - state = state, - action = action - ) - - def forRecord(executor: StringId[User], - recordId: LongId[MedicalRecord], - state: UserHistory.State, - action: UserHistory.Action): UserHistory = UserHistory( - id = LongId(0L), - executor = executor, - recordId = Some(recordId), - state = state, - action = action - ) - - def forPatient(executor: StringId[User], - patientId: UuidId[Patient], - state: UserHistory.State, - action: UserHistory.Action): UserHistory = UserHistory( - id = LongId(0L), - executor = executor, - patientId = Some(patientId), - state = state, - action = action - ) - - sealed trait State extends Product with Serializable { - - def oneOf(xs: State*): Boolean = xs.contains(this) - - def oneOf(xs: Set[State]): Boolean = xs.contains(this) - } - - object State { - case object Clean extends State - case object Organize extends State - case object Extract extends State - case object Summarize extends State - case object Criteriarize extends State - case object Verify extends State - case object Curate extends State - case object Review extends State - case object Flag extends State - - val All: Set[State] = Set[State](Clean, Organize, Extract, Summarize, Criteriarize, Verify, Curate, Review, Flag) - - val fromString: PartialFunction[String, State] = { - case "Clean" => State.Clean - case "Organize" => State.Organize - case "Extract" => State.Extract - case "Summarize" => State.Summarize - case "Criteriarize" => State.Criteriarize - case "Verify" => State.Verify - case "Curate" => State.Curate - case "Review" => State.Review - case "Flag" => State.Flag - } - - def stateToString(x: State): String = x match { - case State.Clean => "Clean" - case State.Organize => "Organize" - case State.Extract => "Extract" - case State.Summarize => "Summarize" - case State.Criteriarize => "Criteriarize" - case State.Verify => "Verify" - case State.Curate => "Curate" - case State.Review => "Review" - case State.Flag => "Flag" - } - - implicit def toPhiString(x: State): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - sealed trait Action extends Product with Serializable { - - def oneOf(xs: Action*): Boolean = xs.contains(this) - - def oneOf(xs: Set[Action]): Boolean = xs.contains(this) - } - - object Action { - case object Start extends Action - case object Submit extends Action - case object Unassign extends Action - case object Resolve extends Action - case object Flag extends Action - case object Archive extends Action - - val All: Set[Action] = Set[Action](Start, Submit, Unassign, Resolve, Flag, Archive) - - val fromString: PartialFunction[String, Action] = { - case "Start" => Action.Start - case "Submit" => Action.Submit - case "Unassign" => Action.Unassign - case "Resolve" => Action.Resolve - case "Flag" => Action.Flag - case "Archive" => Action.Archive - } - - def actionToString(x: Action): String = x match { - case Action.Start => "Start" - case Action.Submit => "Submit" - case Action.Unassign => "Unassign" - case Action.Resolve => "Resolve" - case Action.Flag => "Flag" - case Action.Archive => "Archive" - } - - implicit def toPhiString(x: Action): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass)) - } - - implicit def toPhiString(x: UserHistory): PhiString = { - import x._ - phi"UserHistory(id=$id, executor=$executor, recordId=$recordId, " + - phi"documentId=$documentId, trialId=$trialId, patientId=$patientId, " + - phi"state=$state, action=$action, created=$created)" - } -} 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 deleted file mode 100644 index c69fc09..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabel.scala +++ /dev/null @@ -1,19 +0,0 @@ -package xyz.driver.pdsuidomain.entities.export.patient - -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.{Label, RawPatientLabel} - -final case class ExportPatientLabel(id: LongId[Label], evidences: List[ExportPatientLabelEvidence]) - -object ExportPatientLabel extends PhiLogging { - - implicit def toPhiString(x: ExportPatientLabel): PhiString = { - import x._ - phi"ExportPatientLabel(id=$id, evidences=$evidences)" - } - - def fromRaw(labelId: LongId[Label], rawPatientLabels: List[RawPatientLabel]): ExportPatientLabel = { - ExportPatientLabel(id = labelId, evidences = rawPatientLabels.map(ExportPatientLabelEvidence.fromRaw)) - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabelEvidence.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabelEvidence.scala deleted file mode 100644 index fb40339..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabelEvidence.scala +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.driver.pdsuidomain.entities.export.patient - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.{ExtractedData, RawPatientLabel} - -final case class ExportPatientLabelEvidence(id: LongId[ExtractedData], - value: FuzzyValue, - evidenceText: String, - document: ExportPatientLabelEvidenceDocument) - -object ExportPatientLabelEvidence { - - implicit def toPhiString(x: ExportPatientLabelEvidence): PhiString = { - import x._ - phi"ExportPatientLabelEvidence(id=${Unsafe(id)}, value=$value, " + - phi"evidenceText=${Unsafe(evidenceText)}, document=$document)" - } - - def fromRaw(x: RawPatientLabel) = ExportPatientLabelEvidence( - id = x.evidenceId, - value = x.value, - evidenceText = x.evidenceText, - document = ExportPatientLabelEvidenceDocument( - x.documentId, - x.requestId, - x.documentType, - x.providerType, - x.startDate - ) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabelEvidenceDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabelEvidenceDocument.scala deleted file mode 100644 index 99912bc..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientLabelEvidenceDocument.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuidomain.entities.export.patient - -import java.time.LocalDate - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.{Document, RawPatientLabel, RecordRequestId} - -final case class ExportPatientLabelEvidenceDocument(documentId: LongId[Document], - requestId: RecordRequestId, - documentType: String, - providerType: String, - date: LocalDate) - -object ExportPatientLabelEvidenceDocument extends PhiLogging { - - implicit def toPhiString(x: ExportPatientLabelEvidenceDocument): PhiString = { - import x._ - phi"ExportPatientLabelEvidenceDocument(documentId=$documentId, requestId=$requestId, " + - phi"documentType=${Unsafe(documentType)}, providerType=${Unsafe(providerType)}, date=$date)" - } - - def fromRaw(x: RawPatientLabel) = ExportPatientLabelEvidenceDocument( - documentId = x.documentId, - requestId = x.requestId, - documentType = x.documentType, - providerType = x.providerType, - date = x.startDate - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientWithLabels.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientWithLabels.scala deleted file mode 100644 index bd6173b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/export/patient/ExportPatientWithLabels.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.entities.export.patient - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.{Patient, RawPatientLabel} - -import scala.collection.breakOut - -final case class ExportPatientWithLabels(patientId: UuidId[Patient], - labelVersion: Long, - labels: List[ExportPatientLabel]) - -object ExportPatientWithLabels { - - implicit def toPhiString(x: ExportPatientWithLabels): PhiString = { - import x._ - phi"ExportPatientWithLabels(patientId=$patientId, version=${Unsafe(labelVersion)}, labels=$labels)" - } - - def fromRaw(patientId: UuidId[Patient], rawPatientRefs: List[RawPatientLabel]) = ExportPatientWithLabels( - patientId = patientId, - labelVersion = 1L, // TODO It is needed to replace this mock label version. - labels = rawPatientRefs - .groupBy(_.labelId) - .map(Function.tupled(ExportPatientLabel.fromRaw))(breakOut) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialArm.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialArm.scala deleted file mode 100644 index 5a9a406..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialArm.scala +++ /dev/null @@ -1,15 +0,0 @@ -package xyz.driver.pdsuidomain.entities.export.trial - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.Arm - -final case class ExportTrialArm(armId: LongId[Arm], armName: String) - -object ExportTrialArm { - - implicit def toPhiString(x: ExportTrialArm): PhiString = { - import x._ - phi"ExportTrialArm(armId=$armId, armName=${Unsafe(armName)})" - } -} 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 deleted file mode 100644 index 7bff22c..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialLabelCriterion.scala +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.driver.pdsuidomain.entities.export.trial - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.{Arm, Criterion, Label, RawTrialLabel} - -final case class ExportTrialLabelCriterion(criterionId: LongId[Criterion], - value: Option[Boolean], - labelId: LongId[Label], - armIds: Set[LongId[Arm]], - criteria: String, - isCompound: Boolean, - isDefining: Boolean) - -object ExportTrialLabelCriterion { - - implicit def toPhiString(x: ExportTrialLabelCriterion): PhiString = { - import x._ - phi"TrialLabelCriterion(criterionId=$criterionId, value=$value, labelId=$labelId, " + - phi"criteria=${Unsafe(criteria)}, isCompound=$isCompound, isDefining=$isDefining)" - } - - def fromRaw(x: RawTrialLabel, armIds: Set[LongId[Arm]]) = ExportTrialLabelCriterion( - criterionId = x.criterionId, - value = x.value, - labelId = x.labelId, - armIds = armIds, - criteria = x.criteria, - isCompound = x.isCompound, - isDefining = x.isDefining - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialWithLabels.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialWithLabels.scala deleted file mode 100644 index 60b74ff..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/entities/export/trial/ExportTrialWithLabels.scala +++ /dev/null @@ -1,57 +0,0 @@ -package xyz.driver.pdsuidomain.entities.export.trial - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.{RawTrialLabel, Trial} - -import scala.collection.breakOut - -final case class ExportTrialWithLabels(nctId: StringId[Trial], - trialId: UuidId[Trial], - condition: String, - lastReviewed: LocalDateTime, - labelVersion: Long, - arms: List[ExportTrialArm], - criteria: List[ExportTrialLabelCriterion]) - -object ExportTrialWithLabels { - - implicit def toPhiString(x: ExportTrialWithLabels): PhiString = { - import x._ - phi"TrialWithLabels(nctId=$nctId, trialId=$trialId, condition=${Unsafe(condition)}, " + - phi"lastReviewed=$lastReviewed, labelVersion=${Unsafe(labelVersion)}, arms=$arms, criteria=$criteria)" - } - - def fromRaw(rawData: List[RawTrialLabel]): ExportTrialWithLabels = { - val trials: Set[StringId[Trial]] = rawData.map(_.nctId)(breakOut) - - assert(trials.size == 1, "There are more than one trials in the rawData") - val trial = rawData.head - - ExportTrialWithLabels( - nctId = trial.nctId, - trialId = trial.trialId, - condition = trial.condition, - lastReviewed = trial.lastReviewed, - labelVersion = 1, // TODO It is needed to replace this mock label version. - arms = rawData - .groupBy(_.armId) - .map { - case (armId, rawTrials) => - ExportTrialArm(armId, rawTrials.head.armName) - }(breakOut), - criteria = rawData - .groupBy { x => - (x.criterionId, x.labelId) - } - .map { - case (_, rawTrialLabels) => - val armIds = rawTrialLabels.map(_.criterionArmId).toSet - ExportTrialLabelCriterion.fromRaw(rawTrialLabels.head, armIds) - }(breakOut) - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/ListResponse.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/ListResponse.scala deleted file mode 100644 index 3fbeac8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/ListResponse.scala +++ /dev/null @@ -1,56 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.db.Pagination -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ListResponse[+T](items: Seq[T], meta: ListResponse.Meta) - -object ListResponse { - - final case class Meta(itemsCount: Int, pageNumber: Int, pageSize: Int, lastUpdate: Option[LocalDateTime]) - - object Meta { - def apply(itemsCount: Int, pagination: Pagination, lastUpdate: Option[LocalDateTime]): Meta = { - Meta(itemsCount, pagination.pageNumber, pagination.pageSize, lastUpdate) - } - } - - private val listResponseMetaJsonReads: Reads[Meta] = { - ((JsPath \ "itemsCount").read[Int] and - (JsPath \ "pageNumber").read[Int] and - (JsPath \ "pageSize").read[Int] and - (JsPath \ "lastUpdate").readNullable[LocalDateTime]).apply { - (itemsCount: Int, pageNumber: Int, pageSize: Int, lastUpdate: Option[LocalDateTime]) => - Meta(itemsCount, pageNumber, pageSize, lastUpdate) - } - } - - implicit val listResponseMetaJsonWrites: Writes[Meta] = ( - (JsPath \ "itemsCount").write[Int] and - (JsPath \ "pageNumber").write[Int] and - (JsPath \ "pageSize").write[Int] and - (JsPath \ "lastUpdate").write[Option[LocalDateTime]] - )(unlift(Meta.unapply)) - - implicit val listResponseMetaJsonFormat: Format[Meta] = Format( - listResponseMetaJsonReads, - listResponseMetaJsonWrites - ) - - implicit def listResponseJsonWrites[T](implicit f: Writes[T]): Writes[ListResponse[T]] = - ( - (JsPath \ "items").write[Seq[T]] and - (JsPath \ "meta").write[Meta] - )(unlift(ListResponse.unapply[T])) - - implicit def listResponseJsonFormat[T](implicit f: Format[T]): Format[ListResponse[T]] = - ( - (JsPath \ "items").format(seqJsonFormat[T]) and - (JsPath \ "meta").format[Meta] - )(ListResponse.apply[T], unlift(ListResponse.unapply[T])) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiArm.scala deleted file mode 100644 index 32e2b54..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiArm.scala +++ /dev/null @@ -1,35 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.arm - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.Arm -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ApiArm(id: Long, name: String, originalName: String, trialId: String) { - - def toDomain: Arm = Arm( - id = LongId(this.id), - name = this.name, - originalName = this.originalName, - trialId = StringId(this.trialId), - deleted = None // if we have an ApiArm object, the Arm itself has not been deleted - ) - -} - -object ApiArm { - - implicit val format: Format[ApiArm] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] and - (JsPath \ "originalName").format[String] and - (JsPath \ "trialId").format[String] - )(ApiArm.apply, unlift(ApiArm.unapply)) - - def fromDomain(arm: Arm): ApiArm = ApiArm( - id = arm.id.id, - name = arm.name, - originalName = arm.originalName, - trialId = arm.trialId.id - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiCreateArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiCreateArm.scala deleted file mode 100644 index 5168e94..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiCreateArm.scala +++ /dev/null @@ -1,20 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.arm - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.Arm -import play.api.libs.json.{Format, Json} - -final case class ApiCreateArm(name: String, trialId: String) { - - def toDomain = Arm( - id = LongId(0), - name = name, - trialId = StringId(trialId), - originalName = name - ) -} - -object ApiCreateArm { - - implicit val format: Format[ApiCreateArm] = Json.format[ApiCreateArm] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiPartialArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiPartialArm.scala deleted file mode 100644 index f85d7ff..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiPartialArm.scala +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.arm - -import xyz.driver.pdsuidomain.entities.Arm -import play.api.libs.json.{Format, Json} - -final case class ApiPartialArm(name: String) { - - def applyTo(arm: Arm): Arm = arm.copy(name = name) -} - -object ApiPartialArm { - - implicit val format: Format[ApiPartialArm] = Json.format -} 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/criterion/ApiCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiCriterion.scala deleted file mode 100644 index 4986b17..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiCriterion.scala +++ /dev/null @@ -1,55 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.criterion - -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{Arm, Criterion, Trial} -import xyz.driver.pdsuidomain.formats.json.label.ApiCriterionLabel -import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion - -final case class ApiCriterion(id: Long, - meta: Option[String], - arms: Seq[Long], - text: Option[String], - isCompound: Boolean, - labels: Seq[ApiCriterionLabel], - trialId: String) { - - def toDomain = RichCriterion( - criterion = Criterion( - id = LongId[Criterion](id), - trialId = StringId[Trial](trialId), - text, - isCompound, - meta.getOrElse("") - ), - armIds = arms.map(LongId[Arm]), - labels = labels.map(_.toDomain(LongId[Criterion](id))) - ) -} - -object ApiCriterion { - - implicit val format: Format[ApiCriterion] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "meta").formatNullable(Format(Reads { x => - JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) and - (JsPath \ "arms").format(seqJsonFormat[Long]) and - (JsPath \ "text").formatNullable[String] and - (JsPath \ "isCompound").format[Boolean] and - (JsPath \ "labels").format(seqJsonFormat[ApiCriterionLabel]) and - (JsPath \ "trialId").format[String] - )(ApiCriterion.apply, unlift(ApiCriterion.unapply)) - - def fromDomain(richCriterion: RichCriterion) = ApiCriterion( - id = richCriterion.criterion.id.id, - meta = Option(richCriterion.criterion.meta), - arms = richCriterion.armIds.map(_.id), - text = richCriterion.criterion.text, - isCompound = richCriterion.criterion.isCompound, - labels = richCriterion.labels.map(ApiCriterionLabel.fromDomain), - trialId = richCriterion.criterion.trialId.id - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiNewCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiNewCriterion.scala deleted file mode 100644 index ab7641f..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiNewCriterion.scala +++ /dev/null @@ -1,43 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.criterion - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import xyz.driver.pdsuidomain.entities._ -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuidomain.formats.json.label.ApiCriterionLabel -import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion - -final case class ApiNewCriterion(meta: Option[String], - arms: Option[Seq[Long]], - text: Option[String], - isCompound: Option[Boolean], - labels: Seq[ApiCriterionLabel], - trialId: String) { - - def toDomain = RichCriterion( - criterion = Criterion( - id = LongId(0L), - meta = meta.getOrElse(""), - trialId = StringId(trialId), - isCompound = isCompound.getOrElse(false), - text = text - ), - armIds = arms.getOrElse(Seq.empty).map(LongId[Arm]), - labels = labels.map(_.toDomain(LongId(Long.MaxValue))) // A developer should specify right criterionId himself - ) -} - -object ApiNewCriterion { - - implicit val format: Format[ApiNewCriterion] = ( - (JsPath \ "meta").formatNullable(Format(Reads { x => - JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) and - (JsPath \ "arms").formatNullable(seqJsonFormat[Long]) and - (JsPath \ "text").formatNullable[String] and - (JsPath \ "isCompound").formatNullable[Boolean] and - (JsPath \ "labels").format(seqJsonFormat[ApiCriterionLabel]) and - (JsPath \ "trialId").format[String] - )(ApiNewCriterion.apply, unlift(ApiNewCriterion.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiUpdateCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiUpdateCriterion.scala deleted file mode 100644 index 2bcda56..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/criterion/ApiUpdateCriterion.scala +++ /dev/null @@ -1,60 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.criterion - -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import xyz.driver.pdsuidomain.entities.{Arm, Criterion} -import org.davidbild.tristate._ -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuidomain.formats.json.label.ApiCriterionLabel -import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion - -final case class ApiUpdateCriterion(meta: Tristate[String], - arms: Tristate[Seq[Long]], - text: Option[String], - isCompound: Option[Boolean], - labels: Tristate[Seq[ApiCriterionLabel]]) { - - def applyTo(orig: RichCriterion): RichCriterion = RichCriterion( - criterion = applyTo(orig.criterion), - armIds = arms.cata(_.map(LongId[Arm]), Seq.empty, orig.armIds), - labels = labels.cata(_.map(_.toDomain(orig.criterion.id)), Seq.empty, orig.labels) - ) - - private def applyTo(orig: Criterion): Criterion = Criterion( - id = orig.id, - meta = meta.cata(identity, "{}", orig.meta), - text = text.orElse(orig.text), - isCompound = isCompound.getOrElse(orig.isCompound), - trialId = orig.trialId - ) -} - -object ApiUpdateCriterion { - - private val reads: Reads[ApiUpdateCriterion] = ( - (JsPath \ "meta") - .readTristate(Reads { x => - JsSuccess(Json.stringify(x)) - }) - .map { - case Tristate.Present("{}") => Tristate.Absent - case x => x - } and - (JsPath \ "arms").readTristate(seqJsonFormat[Long]) and - (JsPath \ "text").readNullable[String] and - (JsPath \ "isCompound").readNullable[Boolean] and - (JsPath \ "labels").readTristate(seqJsonFormat[ApiCriterionLabel]) - )(ApiUpdateCriterion.apply _) - - private val writes: Writes[ApiUpdateCriterion] = ( - (JsPath \ "meta").writeTristate(Writes[String](Json.parse)) and - (JsPath \ "arms").writeTristate(seqJsonFormat[Long]) and - (JsPath \ "text").writeNullable[String] and - (JsPath \ "isCompound").writeNullable[Boolean] and - (JsPath \ "labels").writeTristate(seqJsonFormat[ApiCriterionLabel]) - )(unlift(ApiUpdateCriterion.unapply)) - - implicit val format: Format[ApiUpdateCriterion] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala deleted file mode 100644 index 1869ff3..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocument.scala +++ /dev/null @@ -1,107 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.document - -import java.time.{LocalDate, ZoneId, ZonedDateTime} -import xyz.driver.pdsuicommon.domain.{LongId, StringId, TextJson} -import xyz.driver.pdsuicommon.json.JsonSerializer - -import xyz.driver.pdsuidomain.entities._ -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.json.JsonSerializer - -final case class ApiDocument(id: Long, - recordId: Long, - physician: Option[String], - lastUpdate: ZonedDateTime, - typeId: Option[Long], - startDate: Option[LocalDate], - endDate: Option[LocalDate], - provider: Option[String], - providerTypeId: Option[Long], - requiredType: Option[String], - status: Option[String], - previousStatus: Option[String], - assignee: Option[String], - previousAssignee: Option[String], - lastActiveUser: Option[String], - meta: Option[String]) { - - private def extractStatus(status: String): Document.Status = - Document.Status.fromString(status).getOrElse(throw new NoSuchElementException(s"Status $status unknown")) - - private def extractRequiredType(tpe: String): Document.RequiredType = - Document.RequiredType.fromString(tpe).getOrElse(throw new NoSuchElementException(s"RequitedType $tpe unknown")) - - def toDomain = Document( - id = LongId(this.id), - status = extractStatus(this.status.getOrElse("")), - previousStatus = previousStatus.map(extractStatus), - assignee = this.assignee.map(StringId(_)), - previousAssignee = this.previousAssignee.map(StringId(_)), - lastActiveUserId = this.lastActiveUser.map(StringId(_)), - recordId = LongId(this.recordId), - physician = this.physician, - typeId = this.typeId.map(LongId(_)), - providerName = this.provider, - providerTypeId = this.providerTypeId.map(LongId(_)), - requiredType = this.requiredType.map(extractRequiredType), - meta = this.meta.map(x => TextJson(JsonSerializer.deserialize[Document.Meta](x))), - startDate = this.startDate, - endDate = this.endDate, - lastUpdate = this.lastUpdate.toLocalDateTime() - ) - -} - -object ApiDocument { - - private val statusFormat = Format( - Reads.StringReads.filter(ValidationError("unknown status")) { x => - Document.Status.fromString(x).isDefined - }, - Writes.StringWrites - ) - - implicit val format: Format[ApiDocument] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "recordId").format[Long] and - (JsPath \ "physician").formatNullable[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "typeId").formatNullable[Long] and - (JsPath \ "startDate").formatNullable[LocalDate] and - (JsPath \ "endDate").formatNullable[LocalDate] and - (JsPath \ "provider").formatNullable[String] and - (JsPath \ "providerTypeId").formatNullable[Long] and - (JsPath \ "requiredType").formatNullable[String] and - (JsPath \ "status").formatNullable(statusFormat) and - (JsPath \ "previousStatus").formatNullable(statusFormat) and - (JsPath \ "assignee").formatNullable[String] and - (JsPath \ "previousAssignee").formatNullable[String] and - (JsPath \ "lastActiveUser").formatNullable[String] and - (JsPath \ "meta").formatNullable(Format(Reads { x => - JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) - )(ApiDocument.apply, unlift(ApiDocument.unapply)) - - def fromDomain(document: Document): ApiDocument = { - ApiDocument( - id = document.id.id, - recordId = document.recordId.id, - physician = document.physician, - lastUpdate = ZonedDateTime.of(document.lastUpdate, ZoneId.of("Z")), - typeId = document.typeId.map(_.id), - startDate = document.startDate, - endDate = document.endDate, - provider = document.providerName, - providerTypeId = document.providerTypeId.map(_.id), - requiredType = document.requiredType.map(Document.RequiredType.requiredTypeToString), - status = Option(Document.Status.statusToString(document.status)), - previousStatus = document.previousStatus.map(Document.Status.statusToString), - assignee = document.assignee.map(_.id), - previousAssignee = document.previousAssignee.map(_.id), - lastActiveUser = document.lastActiveUserId.map(_.id), - meta = document.meta.map(meta => JsonSerializer.serialize(meta.content)) - ) - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocumentType.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocumentType.scala deleted file mode 100644 index 8b4974f..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiDocumentType.scala +++ /dev/null @@ -1,28 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.document - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuidomain.entities.DocumentType - -final case class ApiDocumentType(id: Long, name: String) { - - def toDomain = DocumentType( - id = LongId(this.id), - name = this.name - ) - -} - -object ApiDocumentType { - - implicit val format: Format[ApiDocumentType] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] - )(ApiDocumentType.apply, unlift(ApiDocumentType.unapply)) - - def fromDomain(documentType: DocumentType) = ApiDocumentType( - id = documentType.id.id, - name = documentType.name - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala deleted file mode 100644 index eae0c62..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiPartialDocument.scala +++ /dev/null @@ -1,124 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.document - -import java.time.{LocalDate, LocalDateTime} - -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.data.validation._ -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, TextJson} -import xyz.driver.pdsuicommon.json.{JsonSerializer, JsonValidationException} -import xyz.driver.pdsuicommon.validation.{AdditionalConstraints, JsonValidationErrors} -import xyz.driver.pdsuidomain.entities.Document.Meta -import xyz.driver.pdsuidomain.entities._ - -import scala.collection.breakOut -import scala.util.Try - -final case class ApiPartialDocument(recordId: Option[Long], - physician: Option[String], - typeId: Tristate[Long], - startDate: Tristate[LocalDate], - endDate: Tristate[LocalDate], - provider: Tristate[String], - providerTypeId: Tristate[Long], - status: Option[String], - assignee: Tristate[String], - meta: Tristate[String]) { - - import xyz.driver.pdsuicommon.domain.User - - def applyTo(orig: Document): Document = Document( - id = orig.id, - status = status.flatMap(Document.Status.fromString).getOrElse(orig.status), - previousStatus = orig.previousStatus, - assignee = assignee.map(StringId[User]).cata(Some(_), None, orig.assignee), - previousAssignee = orig.previousAssignee, - lastActiveUserId = orig.lastActiveUserId, - recordId = recordId.map(LongId[MedicalRecord]).getOrElse(orig.recordId), - physician = physician.orElse(orig.physician), - typeId = typeId.map(LongId[DocumentType]).cata(Some(_), None, orig.typeId), - providerName = provider.cata(Some(_), None, orig.providerName), - providerTypeId = providerTypeId.map(LongId[ProviderType]).cata(Some(_), None, orig.providerTypeId), - requiredType = orig.requiredType, - meta = meta.cata(x => Some(TextJson(JsonSerializer.deserialize[Meta](x))), None, orig.meta), - startDate = startDate.cata(Some(_), None, orig.startDate), - endDate = endDate.cata(Some(_), None, orig.endDate), - lastUpdate = LocalDateTime.MIN // Should update internally in a business logic module - ) - - def toDomain: Try[Document] = Try { - val validation = Map(JsPath \ "recordId" -> AdditionalConstraints.optionNonEmptyConstraint(recordId)) - - val validationErrors: JsonValidationErrors = validation.collect({ - case (fieldName, e: Invalid) => (fieldName, e.errors) - })(breakOut) - - if (validationErrors.isEmpty) { - Document( - id = LongId(0), - recordId = recordId.map(LongId[MedicalRecord]).get, - status = Document.Status.New, - physician = physician, - typeId = typeId.map(LongId[DocumentType]).toOption, - startDate = startDate.toOption, - endDate = endDate.toOption, - providerName = provider.toOption, - providerTypeId = providerTypeId.map(LongId[ProviderType]).toOption, - requiredType = None, - meta = meta.map(x => TextJson(JsonSerializer.deserialize[Meta](x))).toOption, - previousStatus = None, - assignee = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.MIN - ) - } else { - throw new JsonValidationException(validationErrors) - } - } -} - -object ApiPartialDocument { - - private val reads: Reads[ApiPartialDocument] = ( - (JsPath \ "recordId").readNullable[Long] and - (JsPath \ "physician").readNullable[String] and - (JsPath \ "typeId").readTristate[Long] and - (JsPath \ "startDate").readTristate[LocalDate] and - (JsPath \ "endDate").readTristate[LocalDate] and - (JsPath \ "provider").readTristate[String] and - (JsPath \ "providerTypeId").readTristate[Long] and - (JsPath \ "status").readNullable[String]( - Reads - .of[String] - .filter(ValidationError("unknown status"))( - Document.Status.fromString(_).isDefined - )) and - (JsPath \ "assignee").readTristate[String] and - (JsPath \ "meta") - .readTristate(Reads { x => - JsSuccess(Json.stringify(x)) - }) - .map { - case Tristate.Present("{}") => Tristate.Absent - case x => x - } - )(ApiPartialDocument.apply _) - - private val writes: Writes[ApiPartialDocument] = ( - (JsPath \ "recordId").writeNullable[Long] and - (JsPath \ "physician").writeNullable[String] and - (JsPath \ "typeId").writeTristate[Long] and - (JsPath \ "startDate").writeTristate[LocalDate] and - (JsPath \ "endDate").writeTristate[LocalDate] and - (JsPath \ "provider").writeTristate[String] and - (JsPath \ "providerTypeId").writeTristate[Long] and - (JsPath \ "status").writeNullable[String] and - (JsPath \ "assignee").writeTristate[String] and - (JsPath \ "meta").writeTristate(Writes[String](Json.parse)) - )(unlift(ApiPartialDocument.unapply)) - - implicit val format: Format[ApiPartialDocument] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiProviderType.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiProviderType.scala deleted file mode 100644 index c0eddad..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/document/ApiProviderType.scala +++ /dev/null @@ -1,28 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.document - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuidomain.entities.ProviderType - -final case class ApiProviderType(id: Long, name: String) { - - def toDomain = ProviderType( - id = LongId(this.id), - name = this.name - ) - -} - -object ApiProviderType { - - implicit val format: Format[ApiProviderType] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] - )(ApiProviderType.apply, unlift(ApiProviderType.unapply)) - - def fromDomain(providerType: ProviderType) = ApiProviderType( - id = providerType.id.id, - name = providerType.name - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documenthistory/ApiDocumentHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documenthistory/ApiDocumentHistory.scala deleted file mode 100644 index 5aae774..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documenthistory/ApiDocumentHistory.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.documenthistory - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.json.{Format, Json} -import xyz.driver.pdsuidomain.entities.DocumentHistory - -final case class ApiDocumentHistory(id: Long, - executor: String, - documentId: Long, - state: String, - action: String, - created: ZonedDateTime) - -object ApiDocumentHistory { - implicit val format: Format[ApiDocumentHistory] = - Json.format[ApiDocumentHistory] - - def fromDomain(x: DocumentHistory) = ApiDocumentHistory( - id = x.id.id, - executor = x.executor.id, - documentId = x.documentId.id, - state = DocumentHistory.State.stateToString(x.state), - action = DocumentHistory.Action.actionToString(x.action), - created = ZonedDateTime.of(x.created, ZoneId.of("Z")) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiDocumentIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiDocumentIssue.scala deleted file mode 100644 index f157bb2..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiDocumentIssue.scala +++ /dev/null @@ -1,40 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.documentissue - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuidomain.entities.DocumentIssue - -final case class ApiDocumentIssue(id: Long, - startPage: Option[Double], - endPage: Option[Double], - text: String, - lastUpdate: ZonedDateTime, - userId: String, - isDraft: Boolean, - archiveRequired: Boolean) - -object ApiDocumentIssue { - implicit val format: Format[ApiDocumentIssue] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "startPage").formatNullable[Double] and - (JsPath \ "endPage").formatNullable[Double] and - (JsPath \ "text").format[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "userId").format[String] and - (JsPath \ "isDraft").format[Boolean] and - (JsPath \ "archiveRequired").format[Boolean] - )(ApiDocumentIssue.apply, unlift(ApiDocumentIssue.unapply)) - - def fromDomain(x: DocumentIssue) = ApiDocumentIssue( - id = x.id.id, - startPage = x.startPage, - endPage = x.endPage, - text = x.text, - lastUpdate = ZonedDateTime.of(x.lastUpdate, ZoneId.of("Z")), - userId = x.userId.id, - isDraft = x.isDraft, - archiveRequired = x.archiveRequired - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiPartialDocumentIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiPartialDocumentIssue.scala deleted file mode 100644 index c29b703..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/documentissue/ApiPartialDocumentIssue.scala +++ /dev/null @@ -1,42 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.documentissue - -import java.time.LocalDateTime - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuidomain.entities.{Document, DocumentIssue} - -final case class ApiPartialDocumentIssue(startPage: Option[Double], - endPage: Option[Double], - text: String, - archiveRequired: Boolean) { - def applyTo(x: DocumentIssue): DocumentIssue = x.copy( - startPage = startPage, - endPage = endPage, - text = text, - archiveRequired = archiveRequired - ) - - def toDomain(userId: StringId[User], documentId: LongId[Document]) = - DocumentIssue( - id = LongId(0), - userId = userId, - documentId = documentId, - startPage = startPage, - endPage = endPage, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text, - archiveRequired = false - ) -} - -object ApiPartialDocumentIssue { - implicit val format: Format[ApiPartialDocumentIssue] = ( - (JsPath \ "startPage").formatNullable[Double] and - (JsPath \ "endPage").formatNullable[Double] and - (JsPath \ "text").format[String] and - (JsPath \ "archiveRequired").format[Boolean] - )(ApiPartialDocumentIssue.apply, unlift(ApiPartialDocumentIssue.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/evidence/ApiPatientLabelEvidence.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/evidence/ApiPatientLabelEvidence.scala deleted file mode 100644 index e0f23e3..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/evidence/ApiPatientLabelEvidence.scala +++ /dev/null @@ -1,34 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.evidence - -import java.time.LocalDate - -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.FuzzyValue -import xyz.driver.pdsuidomain.entities.PatientLabelEvidenceView - -final case class ApiPatientLabelEvidence(id: Long, - value: String, - evidenceText: String, - documentId: Option[Long], - evidenceId: Option[Long], - reportId: Option[String], - documentType: String, - date: LocalDate, - providerType: String) - -object ApiPatientLabelEvidence { - - implicit val format: Format[ApiPatientLabelEvidence] = Json.format - - def fromDomain(x: PatientLabelEvidenceView) = ApiPatientLabelEvidence( - id = x.id.id, - value = FuzzyValue.valueToString(x.value), - evidenceText = x.evidenceText, - documentId = x.documentId.map(_.id), - evidenceId = x.evidenceId.map(_.id), - reportId = x.reportId.map(_.toString), - documentType = x.documentType, - date = x.date.get, - providerType = x.providerType - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportPatientLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportPatientLabel.scala deleted file mode 100644 index 0ef1c68..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportPatientLabel.scala +++ /dev/null @@ -1,28 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.export - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuidomain.entities.export.patient.ExportPatientLabel - -final case class ApiExportPatientLabel(id: String, evidences: List[ApiExportPatientLabelEvidence]) { - - def toDomain = ExportPatientLabel( - id = LongId(this.id.toLong), - evidences = this.evidences.map(_.toDomain) - ) - -} - -object ApiExportPatientLabel { - - implicit val format: Format[ApiExportPatientLabel] = ( - (JsPath \ "labelId").format[String] and - (JsPath \ "evidence").format[List[ApiExportPatientLabelEvidence]] - )(ApiExportPatientLabel.apply, unlift(ApiExportPatientLabel.unapply)) - - def fromDomain(label: ExportPatientLabel) = ApiExportPatientLabel( - id = label.id.toString, - evidences = label.evidences.map(ApiExportPatientLabelEvidence.fromDomain) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportPatientLabelEvidence.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportPatientLabelEvidence.scala deleted file mode 100644 index d141762..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportPatientLabelEvidence.scala +++ /dev/null @@ -1,38 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.export - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId} -import xyz.driver.pdsuidomain.entities.export.patient.ExportPatientLabelEvidence - -final case class ApiExportPatientLabelEvidence(evidenceId: String, - labelValue: String, - evidenceText: String, - document: ApiExportPatientLabelEvidenceDocument) { - - def toDomain = ExportPatientLabelEvidence( - id = LongId(this.evidenceId.toLong), - value = FuzzyValue.fromString - .applyOrElse(this.labelValue, (s: String) => throw new NoSuchElementException(s"Unknown fuzzy value $s")), - evidenceText = this.evidenceText, - document = this.document.toDomain - ) - -} - -object ApiExportPatientLabelEvidence { - - implicit val format: Format[ApiExportPatientLabelEvidence] = ( - (JsPath \ "evidenceId").format[String] and - (JsPath \ "labelValue").format[String](Writes[String](x => JsString(x.toUpperCase))) and - (JsPath \ "evidenceText").format[String] and - (JsPath \ "document").format[ApiExportPatientLabelEvidenceDocument] - )(ApiExportPatientLabelEvidence.apply, unlift(ApiExportPatientLabelEvidence.unapply)) - - def fromDomain(evidence: ExportPatientLabelEvidence) = ApiExportPatientLabelEvidence( - evidenceId = evidence.id.toString, - labelValue = FuzzyValue.valueToString(evidence.value), - evidenceText = evidence.evidenceText, - document = ApiExportPatientLabelEvidenceDocument.fromDomain(evidence.document) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportPatientLabelEvidenceDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportPatientLabelEvidenceDocument.scala deleted file mode 100644 index 6999301..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportPatientLabelEvidenceDocument.scala +++ /dev/null @@ -1,46 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.export - -import java.time.LocalDate -import java.util.UUID - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuidomain.entities.RecordRequestId -import xyz.driver.pdsuidomain.entities.export.patient.ExportPatientLabelEvidenceDocument - -final case class ApiExportPatientLabelEvidenceDocument(documentId: String, - requestId: String, - documentType: String, - providerType: String, - date: LocalDate) { - - def toDomain = ExportPatientLabelEvidenceDocument( - documentId = LongId(this.documentId.toLong), - requestId = RecordRequestId(UUID.fromString(this.requestId)), - documentType = this.documentType, - providerType = this.providerType, - date = this.date - ) - -} - -object ApiExportPatientLabelEvidenceDocument { - - implicit val format: Format[ApiExportPatientLabelEvidenceDocument] = ( - (JsPath \ "documentId").format[String] and - (JsPath \ "requestId").format[String] and - (JsPath \ "documentType").format[String] and - (JsPath \ "providerType").format[String] and - (JsPath \ "date").format[LocalDate] - )(ApiExportPatientLabelEvidenceDocument.apply, unlift(ApiExportPatientLabelEvidenceDocument.unapply)) - - def fromDomain(document: ExportPatientLabelEvidenceDocument) = - ApiExportPatientLabelEvidenceDocument( - documentId = document.documentId.toString, - requestId = document.requestId.toString, - documentType = document.documentType, - providerType = document.providerType, - date = document.date - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportPatientWithLabels.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportPatientWithLabels.scala deleted file mode 100644 index fc9bab7..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportPatientWithLabels.scala +++ /dev/null @@ -1,31 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.export - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuidomain.entities.export.patient.ExportPatientWithLabels - -final case class ApiExportPatientWithLabels(patientId: String, labelVersion: Long, labels: List[ApiExportPatientLabel]) { - - def toDomain = ExportPatientWithLabels( - patientId = UuidId(this.patientId), - labelVersion = this.labelVersion, - labels = this.labels.map(_.toDomain) - ) - -} - -object ApiExportPatientWithLabels { - - implicit val format: Format[ApiExportPatientWithLabels] = ( - (JsPath \ "patientId").format[String] and - (JsPath \ "labelVersion").format[Long] and - (JsPath \ "labels").format[List[ApiExportPatientLabel]] - )(ApiExportPatientWithLabels.apply, unlift(ApiExportPatientWithLabels.unapply)) - - def fromDomain(patient: ExportPatientWithLabels) = ApiExportPatientWithLabels( - patientId = patient.patientId.toString, - labelVersion = patient.labelVersion, - labels = patient.labels.map(ApiExportPatientLabel.fromDomain) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportTrialArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportTrialArm.scala deleted file mode 100644 index ea96f58..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportTrialArm.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.export - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuidomain.entities.Arm -import xyz.driver.pdsuidomain.entities.export.trial.ExportTrialArm - -final case class ApiExportTrialArm(armId: String, armName: String) { - - def toDomain: ExportTrialArm = { - ExportTrialArm(LongId[Arm](armId.toLong), armName) - } -} - -object ApiExportTrialArm { - - implicit val format: Format[ApiExportTrialArm] = ( - (JsPath \ "armId").format[String] and - (JsPath \ "armName").format[String] - )(ApiExportTrialArm.apply, unlift(ApiExportTrialArm.unapply)) - - def fromDomain(arm: ExportTrialArm) = ApiExportTrialArm( - armId = arm.armId.toString, - armName = arm.armName - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportTrialLabelCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportTrialLabelCriterion.scala deleted file mode 100644 index df1ebb4..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportTrialLabelCriterion.scala +++ /dev/null @@ -1,55 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.export - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId} -import xyz.driver.pdsuidomain.entities.export.trial.ExportTrialLabelCriterion -import xyz.driver.pdsuidomain.entities.{Arm, Criterion, Label} - -final case class ApiExportTrialLabelCriterion(value: String, - labelId: String, - criterionId: String, - criterionText: String, - armIds: List[String], - isCompound: Boolean, - isDefining: Boolean) { - - def toDomain: ExportTrialLabelCriterion = { - ExportTrialLabelCriterion( - LongId[Criterion](criterionId.toLong), - FuzzyValue.fromString.lift(value).map(_ == FuzzyValue.Yes), - LongId[Label](labelId.toLong), - armIds.map(armId => LongId[Arm](armId.toLong)).toSet, - criterionText, - isCompound, - isDefining - ) - } -} - -object ApiExportTrialLabelCriterion { - - implicit val format: Format[ApiExportTrialLabelCriterion] = ( - (JsPath \ "value").format[String](Writes[String](x => JsString(x.toUpperCase))) and - (JsPath \ "labelId").format[String] and - (JsPath \ "criterionId").format[String] and - (JsPath \ "criterionText").format[String] and - (JsPath \ "armIds").format[List[String]] and - (JsPath \ "isCompound").format[Boolean] and - (JsPath \ "isDefining").format[Boolean] - )(ApiExportTrialLabelCriterion.apply, unlift(ApiExportTrialLabelCriterion.unapply)) - - def fromDomain(x: ExportTrialLabelCriterion) = ApiExportTrialLabelCriterion( - value = x.value - .map { x => - FuzzyValue.valueToString(FuzzyValue.fromBoolean(x)) - } - .getOrElse("Unknown"), - labelId = x.labelId.toString, - criterionId = x.criterionId.toString, - criterionText = x.criteria, - armIds = x.armIds.map(_.toString).toList, - isCompound = x.isCompound, - isDefining = x.isDefining - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportTrialWithLabels.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportTrialWithLabels.scala deleted file mode 100644 index e383a1f..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/export/ApiExportTrialWithLabels.scala +++ /dev/null @@ -1,53 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.export - -import java.time.{Instant, ZoneId} - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuicommon.domain.{StringId, UuidId} -import xyz.driver.pdsuidomain.entities.Trial -import xyz.driver.pdsuidomain.entities.export.trial.ExportTrialWithLabels - -final case class ApiExportTrialWithLabels(nctId: String, - trialId: String, - condition: String, - lastReviewed: Long, - labelVersion: Long, - arms: List[ApiExportTrialArm], - criteria: List[ApiExportTrialLabelCriterion]) { - - def toDomain: ExportTrialWithLabels = { - ExportTrialWithLabels( - StringId[Trial](nctId), - UuidId[Trial](trialId), - condition, - lastReviewed = Instant.ofEpochMilli(lastReviewed).atZone(ZoneId.of("Z")).toLocalDateTime, - labelVersion, - arms.map(_.toDomain), - criteria.map(_.toDomain) - ) - } -} - -object ApiExportTrialWithLabels { - - implicit val format: Format[ApiExportTrialWithLabels] = ( - (JsPath \ "nctId").format[String] and - (JsPath \ "trialId").format[String] and - (JsPath \ "disease").format[String] and - (JsPath \ "lastReviewed").format[Long] and - (JsPath \ "labelVersion").format[Long] and - (JsPath \ "arms").format[List[ApiExportTrialArm]] and - (JsPath \ "criteria").format[List[ApiExportTrialLabelCriterion]] - )(ApiExportTrialWithLabels.apply, unlift(ApiExportTrialWithLabels.unapply)) - - def fromDomain(x: ExportTrialWithLabels) = ApiExportTrialWithLabels( - nctId = x.nctId.id, - trialId = x.trialId.toString, - condition = x.condition, - lastReviewed = x.lastReviewed.atZone(ZoneId.of("Z")).toEpochSecond, - labelVersion = x.labelVersion, - arms = x.arms.map(ApiExportTrialArm.fromDomain), - criteria = x.criteria.map(ApiExportTrialLabelCriterion.fromDomain) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiExtractedData.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiExtractedData.scala deleted file mode 100644 index 4182c8d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiExtractedData.scala +++ /dev/null @@ -1,64 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.extracteddata - -import xyz.driver.pdsuicommon.domain.{LongId, TextJson} -import xyz.driver.pdsuidomain.entities.ExtractedData -import xyz.driver.pdsuidomain.formats.json.label.ApiExtractedDataLabel -import play.api.libs.json._ -import play.api.data.validation._ -import play.api.libs.functional.syntax._ -import xyz.driver.pdsuicommon.json.JsonSerializer -import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData - -// The specification: https://driverinc.atlassian.net/wiki/pages/viewpage.action?pageId=33423387 -// Note, that there is "Extracted data object or Temporary extracted data object" in specification -// ApiExtractedData represents both types -final case class ApiExtractedData(id: Long, - documentId: Long, - keywordId: Option[Long], - evidence: Option[String], - meta: Option[String], - // An empty list and no-existent list are different cases - labels: Option[List[ApiExtractedDataLabel]]) { - - def toDomain = RichExtractedData( - extractedData = ExtractedData( - id = LongId(this.id), - documentId = LongId(this.documentId), - keywordId = this.keywordId.map(LongId(_)), - evidenceText = this.evidence, - meta = this.meta.map(x => TextJson(JsonSerializer.deserialize[ExtractedData.Meta](x))) - ), - labels = labels.getOrElse(List.empty).map(_.toDomain()) - ) - -} - -object ApiExtractedData { - - implicit val format: Format[ApiExtractedData] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "documentId").format[Long] and - (JsPath \ "keywordId").formatNullable[Long] and - (JsPath \ "evidence").formatNullable[String] and - (JsPath \ "meta").formatNullable[String] and - (JsPath \ "labels").formatNullable[List[ApiExtractedDataLabel]]( - Format( - Reads - .of[List[ApiExtractedDataLabel]] - .filter(ValidationError("empty labels"))({ - case x if x.nonEmpty => true - case _ => false - }), - Writes.of[List[ApiExtractedDataLabel]] - )) - )(ApiExtractedData.apply, unlift(ApiExtractedData.unapply)) - - def fromDomain(extractedDataWithLabels: RichExtractedData) = ApiExtractedData( - id = extractedDataWithLabels.extractedData.id.id, - documentId = extractedDataWithLabels.extractedData.documentId.id, - keywordId = extractedDataWithLabels.extractedData.keywordId.map(_.id), - evidence = extractedDataWithLabels.extractedData.evidenceText, - meta = extractedDataWithLabels.extractedData.meta.map(x => JsonSerializer.serialize(x.content)), - labels = Option(extractedDataWithLabels.labels.map(ApiExtractedDataLabel.fromDomain)) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiPartialExtractedData.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiPartialExtractedData.scala deleted file mode 100644 index cfd55fd..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiPartialExtractedData.scala +++ /dev/null @@ -1,80 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.extracteddata - -import xyz.driver.pdsuicommon.domain.{LongId, TextJson} -import xyz.driver.pdsuidomain.entities.ExtractedData.Meta -import xyz.driver.pdsuidomain.entities._ -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.data.validation._ -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.json.{JsonSerializer, JsonValidationException} -import xyz.driver.pdsuicommon.validation.{AdditionalConstraints, JsonValidationErrors} -import xyz.driver.pdsuidomain.formats.json.label.ApiExtractedDataLabel -import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData - -import scala.collection._ - -final case class ApiPartialExtractedData(documentId: Option[Long], - keywordId: Option[Long], - evidence: Tristate[String], - meta: Tristate[String], - labels: Tristate[List[ApiExtractedDataLabel]]) { - - def applyTo(orig: RichExtractedData): RichExtractedData = RichExtractedData( - extractedData = applyTo(orig.extractedData), - labels = labels.cata(_.map(_.toDomain(orig.extractedData.id)), List.empty, orig.labels) - ) - - private def applyTo(orig: ExtractedData): ExtractedData = ExtractedData( - id = orig.id, - documentId = orig.documentId, - keywordId = keywordId.map(LongId[Keyword]).orElse(orig.keywordId), - evidenceText = evidence.cata(Some(_), None, orig.evidenceText), - meta = meta.map(x => TextJson(JsonSerializer.deserialize[Meta](x))).cata(Some(_), None, orig.meta) - ) - - def toDomain: RichExtractedData = { - val validation = Map( - JsPath \ "documentId" -> AdditionalConstraints.optionNonEmptyConstraint(documentId) - ) - - val validationErrors: JsonValidationErrors = validation.collect({ - case (fieldName, e: Invalid) => (fieldName, e.errors) - })(breakOut) - - if (validationErrors.isEmpty) { - val extractedData = ExtractedData( - documentId = documentId.map(LongId[Document]).get, - keywordId = keywordId.map(LongId[Keyword]), - evidenceText = evidence.toOption, - meta = meta.map(x => TextJson(JsonSerializer.deserialize[Meta](x))).toOption - ) - val labelList = labels.map(_.map(_.toDomain())) - RichExtractedData(extractedData, labelList.getOrElse(List.empty)) - } else { - throw new JsonValidationException(validationErrors) - } - } -} - -object ApiPartialExtractedData { - - private val reads: Reads[ApiPartialExtractedData] = ( - (JsPath \ "documentId").readNullable[Long] and - (JsPath \ "keywordId").readNullable[Long] and - (JsPath \ "evidence").readTristate[String] and - (JsPath \ "meta").readTristate[String] and - (JsPath \ "labels").readTristate[List[ApiExtractedDataLabel]] - )(ApiPartialExtractedData.apply _) - - private val writes: Writes[ApiPartialExtractedData] = ( - (JsPath \ "documentId").writeNullable[Long] and - (JsPath \ "keywordId").writeNullable[Long] and - (JsPath \ "evidence").writeTristate[String] and - (JsPath \ "meta").writeTristate[String] and - (JsPath \ "labels").writeTristate[List[ApiExtractedDataLabel]] - )(unlift(ApiPartialExtractedData.unapply)) - - implicit val format: Format[ApiPartialExtractedData] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/hypothesis/ApiHypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/hypothesis/ApiHypothesis.scala deleted file mode 100644 index bf18a60..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/hypothesis/ApiHypothesis.scala +++ /dev/null @@ -1,35 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.hypothesis - -import java.util.UUID - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuidomain.entities.Hypothesis - -final case class ApiHypothesis(id: UUID, name: String, treatmentType: String, description: String) { - - def toDomain = Hypothesis( - id = UuidId[Hypothesis](id), - name = name, - treatmentType = treatmentType, - description = description - ) -} - -object ApiHypothesis { - - implicit val format: Format[ApiHypothesis] = ( - (JsPath \ "id").format[UUID] and - (JsPath \ "name").format[String] and - (JsPath \ "treatmentType").format[String] and - (JsPath \ "description").format[String] - )(ApiHypothesis.apply, unlift(ApiHypothesis.unapply)) - - def fromDomain(hypothesis: Hypothesis) = ApiHypothesis( - id = hypothesis.id.id, - name = hypothesis.name, - treatmentType = hypothesis.treatmentType, - description = hypothesis.description - ) -} 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 deleted file mode 100644 index 39acbde..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala +++ /dev/null @@ -1,72 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.intervention - -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{Intervention, InterventionArm, InterventionWithArms} -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} - -final case class ApiIntervention(id: Long, - name: String, - typeId: Option[Long], - description: String, - isActive: Boolean, - arms: List[Long], - trialId: String, - originalName: String, - originalDescription: String, - originalType: Option[String]) { - - def toDomain = { - val intervention = Intervention( - id = LongId(this.id), - trialId = StringId(this.trialId), - name = this.name, - originalName = this.originalName, - typeId = this.typeId.map(id => LongId(id)), - originalType = this.originalType.map(id => id.toString), - description = this.description, - originalDescription = this.originalDescription, - isActive = this.isActive - ) - - InterventionWithArms(intervention, this.arms.map { armId => - InterventionArm(LongId(armId), intervention.id) - }) - - } - -} - -object ApiIntervention { - - implicit val format: Format[ApiIntervention] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] and - (JsPath \ "typeId").formatNullable[Long] and - (JsPath \ "description").format[String] and - (JsPath \ "isActive").format[Boolean] and - (JsPath \ "arms").format[List[Long]] and - (JsPath \ "trialId").format[String] and - (JsPath \ "originalName").format[String] and - (JsPath \ "originalDescription").format[String] and - (JsPath \ "originalType").formatNullable[String] - )(ApiIntervention.apply, unlift(ApiIntervention.unapply)) - - def fromDomain(interventionWithArms: InterventionWithArms): ApiIntervention = { - import interventionWithArms.intervention - import interventionWithArms.arms - - ApiIntervention( - id = intervention.id.id, - name = intervention.name, - typeId = intervention.typeId.map(_.id), - description = intervention.description, - isActive = intervention.isActive, - arms = arms.map(_.armId.id), - trialId = intervention.trialId.id, - originalName = intervention.originalName, - originalDescription = intervention.originalDescription, - 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 deleted file mode 100644 index ebef225..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiInterventionType.scala +++ /dev/null @@ -1,24 +0,0 @@ -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 - -final case class ApiInterventionType(id: Long, name: String) { - - def toDomain = InterventionType(id = LongId[InterventionType](id), name = name) -} - -object ApiInterventionType { - - implicit val format: Format[ApiInterventionType] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] - )(ApiInterventionType.apply, unlift(ApiInterventionType.unapply)) - - def fromDomain(interventionType: InterventionType) = ApiInterventionType( - id = interventionType.id.id, - name = interventionType.name - ) -} 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 deleted file mode 100644 index f67ba6b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiPartialIntervention.scala +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.intervention - -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuidomain.entities.{InterventionArm, InterventionWithArms} -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ApiPartialIntervention(typeId: Option[Long], - description: Option[String], - isActive: Option[Boolean], - 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))) - orig.copy( - intervention = origIntervention.copy( - typeId = typeId.map(LongId(_)).orElse(origIntervention.typeId), - description = description.getOrElse(origIntervention.description), - isActive = isActive.getOrElse(origIntervention.isActive) - ), - arms = draftArmList.getOrElse(orig.arms) - ) - } -} - -object ApiPartialIntervention { - - private val reads: Reads[ApiPartialIntervention] = ( - (JsPath \ "typeId").readNullable[Long] and - (JsPath \ "description").readNullable[String] and - (JsPath \ "isActive").readNullable[Boolean] and - (JsPath \ "arms").readNullable[List[Long]] - )(ApiPartialIntervention.apply _) - - private val writes: Writes[ApiPartialIntervention] = ( - (JsPath \ "typeId").writeNullable[Long] and - (JsPath \ "description").writeNullable[String] and - (JsPath \ "isActive").writeNullable[Boolean] and - (JsPath \ "arms").writeNullable[List[Long]] - )(unlift(ApiPartialIntervention.unapply)) - - implicit val format: Format[ApiPartialIntervention] = Format(reads, writes) -} 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 deleted file mode 100644 index 7a65af8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiCriterionLabel.scala +++ /dev/null @@ -1,53 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.label - -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId} -import xyz.driver.pdsuidomain.entities.{Category, Criterion, CriterionLabel, Label} -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -/** - * @param value Yes|No - */ -final case class ApiCriterionLabel(labelId: Option[Long], - categoryId: Option[Long], - value: Option[String], - isDefining: Boolean) { - - def toDomain(criterionId: LongId[Criterion]) = CriterionLabel( - id = LongId(0L), - labelId = labelId.map(LongId[Label]), - criterionId = criterionId, - categoryId = categoryId.map(LongId[Category]), - value = value.map { - case "Yes" => true - case "No" => false - }, - isDefining = isDefining - ) -} - -object ApiCriterionLabel { - - def fromDomain(x: CriterionLabel) = ApiCriterionLabel( - labelId = x.labelId.map(_.id), - categoryId = x.categoryId.map(_.id), - value = x.value.map { x => - FuzzyValue.valueToString(FuzzyValue.fromBoolean(x)) - }, - isDefining = x.isDefining - ) - - implicit val format: Format[ApiCriterionLabel] = ( - (JsPath \ "labelId").formatNullable[Long] and - (JsPath \ "categoryId").formatNullable[Long] and - (JsPath \ "value").formatNullable[String]( - Format(Reads - .of[String] - .filter(ValidationError("unknown value"))({ x => - x == "Yes" || x == "No" - }), - Writes.of[String])) and - (JsPath \ "isDefining").format[Boolean] - )(ApiCriterionLabel.apply, unlift(ApiCriterionLabel.unapply)) -} 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 deleted file mode 100644 index cb45025..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/label/ApiExtractedDataLabel.scala +++ /dev/null @@ -1,40 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.label - -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId} -import xyz.driver.pdsuidomain.entities.{Category, ExtractedData, ExtractedDataLabel, Label} -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ApiExtractedDataLabel(id: Option[Long], categoryId: Option[Long], value: Option[String]) { - - def toDomain(dataId: LongId[ExtractedData] = LongId(0)) = ExtractedDataLabel( - id = LongId(0), - dataId = dataId, - labelId = id.map(LongId[Label]), - categoryId = categoryId.map(LongId[Category]), - value = value.map(FuzzyValue.fromString) - ) -} - -object ApiExtractedDataLabel { - - implicit val format: Format[ApiExtractedDataLabel] = ( - (JsPath \ "id").formatNullable[Long] and - (JsPath \ "categoryId").formatNullable[Long] and - (JsPath \ "value").formatNullable[String]( - Format(Reads - .of[String] - .filter(ValidationError("unknown value"))({ - case x if FuzzyValue.fromString.isDefinedAt(x) => true - case _ => false - }), - Writes.of[String])) - )(ApiExtractedDataLabel.apply, unlift(ApiExtractedDataLabel.unapply)) - - def fromDomain(dataLabel: ExtractedDataLabel) = ApiExtractedDataLabel( - id = dataLabel.labelId.map(_.id), - categoryId = dataLabel.categoryId.map(_.id), - value = dataLabel.value.map(FuzzyValue.valueToString) - ) -} 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/message/ApiMessage.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiMessage.scala deleted file mode 100644 index 425eeac..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiMessage.scala +++ /dev/null @@ -1,79 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.message - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.Message - -final case class ApiMessage(id: Long, - text: String, - lastUpdate: ZonedDateTime, - userId: String, - isDraft: Boolean, - recordId: Option[Long], - documentId: Option[Long], - patientId: Option[String], - trialId: Option[String], - startPage: Option[Double], - endPage: Option[Double], - evidence: Option[String], - archiveRequired: Option[Boolean], - meta: Option[String]) { - - def toDomain = Message( - id = LongId(this.id), - text = this.text, - lastUpdate = this.lastUpdate.toLocalDateTime(), - userId = StringId(this.userId), - isDraft = this.isDraft, - recordId = this.recordId.map(id => LongId(id)), - documentId = this.documentId.map(id => LongId(id)), - patientId = this.patientId.map(id => UuidId(id)), - trialId = this.trialId.map(id => StringId(id)), - startPage = this.startPage, - endPage = this.endPage, - evidence = this.evidence, - archiveRequired = this.archiveRequired, - meta = this.meta - ) - -} - -object ApiMessage { - - def fromDomain(domain: Message) = ApiMessage( - id = domain.id.id, - text = domain.text, - lastUpdate = ZonedDateTime.of(domain.lastUpdate, ZoneId.of("Z")), - userId = domain.userId.id, - isDraft = domain.isDraft, - recordId = domain.recordId.map(_.id), - documentId = domain.documentId.map(_.id), - patientId = domain.patientId.map(_.toString), - trialId = domain.trialId.map(_.toString), - startPage = domain.startPage, - endPage = domain.endPage, - evidence = domain.evidence, - archiveRequired = domain.archiveRequired, - meta = domain.meta - ) - - implicit val format: Format[ApiMessage] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "text").format[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "userId").format[String] and - (JsPath \ "isDraft").format[Boolean] and - (JsPath \ "recordId").formatNullable[Long] and - (JsPath \ "documentId").formatNullable[Long] and - (JsPath \ "patientId").formatNullable[String] and - (JsPath \ "trialId").formatNullable[String] and - (JsPath \ "startPage").formatNullable[Double] and - (JsPath \ "endPage").formatNullable[Double] and - (JsPath \ "evidence").formatNullable[String] and - (JsPath \ "archiveRequired").formatNullable[Boolean] and - (JsPath \ "meta").formatNullable[String] - )(ApiMessage.apply, unlift(ApiMessage.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiPartialMessage.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiPartialMessage.scala deleted file mode 100644 index a2656f2..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiPartialMessage.scala +++ /dev/null @@ -1,82 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.message - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.domain._ -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuidomain.entities.Message - -final case class ApiPartialMessage(text: Option[String], - recordId: Option[Long], - documentId: Option[Long], - patientId: Option[String], - trialId: Option[String], - startPage: Option[Double], - endPage: Option[Double], - evidence: Option[String], - archiveRequired: Option[Boolean], - meta: Option[String]) { - - def toDomain(userId: StringId[User]) = Message( - id = LongId(0), - text = text.getOrElse(""), - userId = userId, - isDraft = true, - recordId = recordId.map(LongId(_)), - documentId = documentId.map(LongId(_)), - patientId = patientId.map(UuidId(_)), - trialId = trialId.map(StringId(_)), - startPage = startPage, - endPage = endPage, - evidence = evidence, - archiveRequired = archiveRequired, - meta = meta, - lastUpdate = LocalDateTime.MIN - ) - - def applyTo(orig: Message): Message = { - orig.copy( - text = text.getOrElse(""), - recordId = recordId.map(LongId(_)), - documentId = documentId.map(LongId(_)), - patientId = patientId.map(UuidId(_)), - trialId = trialId.map(StringId(_)), - startPage = startPage, - endPage = endPage, - evidence = evidence, - archiveRequired = archiveRequired, - meta = meta, - lastUpdate = LocalDateTime.MIN - ) - } -} - -object ApiPartialMessage { - - implicit val format: Format[ApiPartialMessage] = ( - (JsPath \ "text").formatNullable[String] and - (JsPath \ "recordId").formatNullable[Long] and - (JsPath \ "documentId").formatNullable[Long] and - (JsPath \ "patientId").formatNullable[String] and - (JsPath \ "trialId").formatNullable[String] and - (JsPath \ "startPage").formatNullable[Double] and - (JsPath \ "endPage").formatNullable[Double] and - (JsPath \ "evidence").formatNullable[String] and - (JsPath \ "archiveRequired").formatNullable[Boolean] and - (JsPath \ "meta").formatNullable[String] - )(ApiPartialMessage.apply, unlift(ApiPartialMessage.unapply)) - - def fromDomain(domain: Message) = ApiPartialMessage( - text = Some(domain.text), - recordId = domain.recordId.map(_.id), - documentId = domain.documentId.map(_.id), - patientId = domain.patientId.map(_.toString), - trialId = domain.trialId.map(_.toString), - startPage = domain.startPage, - endPage = domain.endPage, - evidence = domain.evidence, - archiveRequired = domain.archiveRequired, - meta = domain.meta - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordCreateRequest.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordCreateRequest.scala deleted file mode 100644 index 5c12415..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordCreateRequest.scala +++ /dev/null @@ -1,9 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.password - -import play.api.libs.json.{Format, Json} - -final case class PasswordCreateRequest(password: String, key: String) - -object PasswordCreateRequest { - implicit val format: Format[PasswordCreateRequest] = Json.format[PasswordCreateRequest] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordUpdateRequest.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordUpdateRequest.scala deleted file mode 100644 index 07851ea..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/password/PasswordUpdateRequest.scala +++ /dev/null @@ -1,9 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.password - -import play.api.libs.json.{Format, Json} - -final case class PasswordUpdateRequest(password: String, oldPassword: String) - -object PasswordUpdateRequest { - implicit val format: Format[PasswordUpdateRequest] = Json.format[PasswordUpdateRequest] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/ApiPatient.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/ApiPatient.scala deleted file mode 100644 index db430ae..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/ApiPatient.scala +++ /dev/null @@ -1,73 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient - -import java.time.{LocalDate, ZoneId, ZonedDateTime} -import java.util.UUID - -import xyz.driver.pdsuicommon.domain.{StringId, UuidId} -import xyz.driver.pdsuidomain.entities.{Patient, PatientOrderId} -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} - -final case class ApiPatient(id: String, - status: String, - name: String, - dob: LocalDate, - assignee: Option[String], - previousStatus: Option[String], - previousAssignee: Option[String], - lastActiveUser: Option[String], - lastUpdate: ZonedDateTime, - condition: String, - orderId: UUID) { - - private def extractStatus(status: String): Patient.Status = - PatientStatus.statusFromString - .applyOrElse(status, (s: String) => throw new NoSuchElementException(s"Unknown status $s")) - - def toDomain = Patient( - id = UuidId(this.id), - status = extractStatus(this.status), - name = this.name, - dob = this.dob, - assignee = this.assignee.map(StringId(_)), - previousStatus = this.previousStatus.map(extractStatus), - previousAssignee = this.previousAssignee.map(StringId(_)), - lastActiveUserId = this.lastActiveUser.map(StringId(_)), - isUpdateRequired = false, - condition = this.condition, - orderId = PatientOrderId(this.orderId), - lastUpdate = this.lastUpdate.toLocalDateTime - ) - -} - -object ApiPatient { - - implicit val format: Format[ApiPatient] = ( - (JsPath \ "id").format[String] and - (JsPath \ "status").format[String] and - (JsPath \ "name").format[String] and - (JsPath \ "dob").format[LocalDate] and - (JsPath \ "assignee").formatNullable[String] and - (JsPath \ "previousStatus").formatNullable[String] and - (JsPath \ "previousAssignee").formatNullable[String] and - (JsPath \ "lastActiveUser").formatNullable[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "condition").format[String] and - (JsPath \ "orderId").format[UUID] - )(ApiPatient.apply, unlift(ApiPatient.unapply)) - - def fromDomain(patient: Patient) = ApiPatient( - id = patient.id.toString, - status = PatientStatus.statusToString(patient.status), - name = patient.name, - dob = patient.dob, - assignee = patient.assignee.map(_.id), - previousStatus = patient.previousStatus.map(PatientStatus.statusToString), - previousAssignee = patient.previousAssignee.map(_.id), - lastActiveUser = patient.lastActiveUserId.map(_.id), - lastUpdate = ZonedDateTime.of(patient.lastUpdate, ZoneId.of("Z")), - condition = patient.condition, - orderId = patient.orderId.id - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/PatientStatus.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/PatientStatus.scala deleted file mode 100644 index a23a1de..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/PatientStatus.scala +++ /dev/null @@ -1,24 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient - -import xyz.driver.pdsuidomain.entities.Patient.Status - -object PatientStatus { - - val statusFromString: PartialFunction[String, Status] = { - case "New" => Status.New - case "Verified" => Status.Verified - case "Reviewed" => Status.Reviewed - case "Curated" => Status.Curated - case "Flagged" => Status.Flagged - case "Done" => Status.Done - } - - def statusToString(x: Status): String = x match { - case Status.New => "New" - case Status.Verified => "Verified" - case Status.Reviewed => "Reviewed" - case Status.Curated => "Curated" - case Status.Flagged => "Flagged" - case Status.Done => "Done" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPartialPatientEligibleTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPartialPatientEligibleTrial.scala deleted file mode 100644 index 03ff275..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPartialPatientEligibleTrial.scala +++ /dev/null @@ -1,18 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.eligible - -import xyz.driver.pdsuidomain.entities.PatientTrialArmGroupView -import play.api.libs.json.{Format, Json} - -final case class ApiPartialPatientEligibleTrial(isVerified: Option[Boolean]) { - - def applyTo(orig: PatientTrialArmGroupView): PatientTrialArmGroupView = { - orig.copy( - isVerified = isVerified.getOrElse(orig.isVerified) - ) - } -} - -object ApiPartialPatientEligibleTrial { - - implicit val format: Format[ApiPartialPatientEligibleTrial] = Json.format -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPatientEligibleTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPatientEligibleTrial.scala deleted file mode 100644 index 4136715..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/eligible/ApiPatientEligibleTrial.scala +++ /dev/null @@ -1,51 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.eligible - -import java.util.UUID - -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.FuzzyValue -import xyz.driver.pdsuidomain.services.PatientEligibleTrialService.RichPatientEligibleTrial - -final case class ApiPatientEligibleTrial(id: Long, - patientId: String, - trialId: String, - trialTitle: String, - arms: List[String], - hypothesisId: UUID, - verifiedEligibilityStatus: Option[String], - isVerified: Boolean) - -object ApiPatientEligibleTrial { - - implicit val apiEligibleTrialJsonFormat: Format[ApiPatientEligibleTrial] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "patientId").format[String] and - (JsPath \ "trialId").format[String] and - (JsPath \ "trialTitle").format[String] and - (JsPath \ "arms").format[List[String]] and - (JsPath \ "hypothesisId").format[UUID] and - (JsPath \ "verifiedEligibilityStatus").formatNullable[String](Format( - Reads - .of[String] - .filter(ValidationError("unknown eligibility status"))({ - case x if FuzzyValue.fromString.isDefinedAt(x) => true - case _ => false - }), - Writes.of[String] - )) and - (JsPath \ "isVerified").format[Boolean] - )(ApiPatientEligibleTrial.apply, unlift(ApiPatientEligibleTrial.unapply)) - - def fromDomain(eligibleTrialWithTrial: RichPatientEligibleTrial) = ApiPatientEligibleTrial( - id = eligibleTrialWithTrial.group.id.id, - patientId = eligibleTrialWithTrial.group.patientId.toString, - trialId = eligibleTrialWithTrial.group.trialId.id, - trialTitle = eligibleTrialWithTrial.trial.title, - arms = eligibleTrialWithTrial.arms.map(_.armName), - hypothesisId = eligibleTrialWithTrial.group.hypothesisId.id, - eligibleTrialWithTrial.group.verifiedEligibilityStatus.map(FuzzyValue.valueToString), - eligibleTrialWithTrial.group.isVerified - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPartialPatientHypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPartialPatientHypothesis.scala deleted file mode 100644 index 0858ce1..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPartialPatientHypothesis.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.hypothesis - -import xyz.driver.pdsuidomain.entities.PatientHypothesis -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ApiPartialPatientHypothesis(rationale: Tristate[String]) { - - def applyTo(orig: PatientHypothesis): PatientHypothesis = { - orig.copy( - rationale = rationale.cata(Some(_), None, orig.rationale) - ) - } -} - -object ApiPartialPatientHypothesis { - - implicit val reads: Reads[ApiPartialPatientHypothesis] = - (__ \ "rationale").readTristate[String].map(x => ApiPartialPatientHypothesis(x)) - - implicit val writes: Writes[ApiPartialPatientHypothesis] = - (__ \ "rationale").writeTristate[String].contramap(_.rationale) - - implicit val format: Format[ApiPartialPatientHypothesis] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPatientHypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPatientHypothesis.scala deleted file mode 100644 index 584ff72..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/hypothesis/ApiPatientHypothesis.scala +++ /dev/null @@ -1,35 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.hypothesis - -import java.util.UUID - -import xyz.driver.pdsuidomain.entities.PatientHypothesis -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ApiPatientHypothesis(id: UUID, - patientId: String, - hypothesisId: UUID, - matchedTrials: Long, - rationale: Option[String], - isRationaleRequired: Boolean) - -object ApiPatientHypothesis { - - implicit val apiPatientHypothesisJsonFormat: Format[ApiPatientHypothesis] = ( - (JsPath \ "id").format[UUID] and - (JsPath \ "patientId").format[String] and - (JsPath \ "hypothesisId").format[UUID] and - (JsPath \ "matchedTrials").format[Long] and - (JsPath \ "rationale").formatNullable[String] and - (JsPath \ "isRationaleRequired").format[Boolean] - )(ApiPatientHypothesis.apply, unlift(ApiPatientHypothesis.unapply)) - - def fromDomain(patientHypothesis: PatientHypothesis, isRationaleRequired: Boolean) = ApiPatientHypothesis( - id = patientHypothesis.id.id, - patientId = patientHypothesis.patientId.toString, - hypothesisId = patientHypothesis.hypothesisId.id, - matchedTrials = patientHypothesis.matchedTrials, - rationale = patientHypothesis.rationale, - isRationaleRequired = isRationaleRequired - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPartialPatientLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPartialPatientLabel.scala deleted file mode 100644 index 91d0a0e..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPartialPatientLabel.scala +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.label - -import xyz.driver.pdsuidomain.entities.PatientLabel -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.FuzzyValue - -final case class ApiPartialPatientLabel(primaryValue: Option[String], verifiedPrimaryValue: Tristate[String]) { - - def applyTo(orig: PatientLabel): PatientLabel = { - orig.copy( - primaryValue = primaryValue.map(FuzzyValue.fromString).orElse(orig.primaryValue), - verifiedPrimaryValue = - verifiedPrimaryValue.cata(x => Some(FuzzyValue.fromString(x)), None, orig.verifiedPrimaryValue) - ) - } -} - -object ApiPartialPatientLabel { - - implicit val format: Format[ApiPartialPatientLabel] = ( - (JsPath \ "primaryValue").formatNullable[String]( - Format(Reads - .of[String] - .filter(ValidationError("unknown primary value"))({ - case x if FuzzyValue.fromString.isDefinedAt(x) => true - case _ => false - }), - Writes.of[String])) and - (JsPath \ "verifiedPrimaryValue").formatTristate[String]( - Format( - Reads - .of[String] - .filter(ValidationError("unknown verified primary value"))({ - case x if FuzzyValue.fromString.isDefinedAt(x) => true - case _ => false - }), - Writes.of[String] - )) - )(ApiPartialPatientLabel.apply, unlift(ApiPartialPatientLabel.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabel.scala deleted file mode 100644 index fc8687b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabel.scala +++ /dev/null @@ -1,47 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.label - -import xyz.driver.pdsuidomain.entities.PatientLabel -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.FuzzyValue - -final case class ApiPatientLabel(id: Long, - labelId: Long, - primaryValue: Option[String], - verifiedPrimaryValue: Option[String], - score: Int, - isImplicitMatch: Boolean, - isVisible: Boolean, - isVerified: Boolean) - -object ApiPatientLabel { - - implicit val apiPatientLabelJsonFormat: Format[ApiPatientLabel] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "labelId").format[Long] and - (JsPath \ "primaryValue").formatNullable[String](Format(Reads.of[String].filter(ValidationError("unknown value"))({ - case x if FuzzyValue.fromString.isDefinedAt(x) => true - case _ => false - }), Writes.of[String])) and - (JsPath \ "verifiedPrimaryValue").formatNullable[String](Format(Reads.of[String].filter(ValidationError("unknown value"))({ - case x if FuzzyValue.fromString.isDefinedAt(x) => true - case _ => false - }), Writes.of[String])) and - (JsPath \ "score").format[Int] and - (JsPath \ "isImplicitMatch").format[Boolean] and - (JsPath \ "isVisible").format[Boolean] and - (JsPath \ "isVerified").format[Boolean] - ) (ApiPatientLabel.apply, unlift(ApiPatientLabel.unapply)) - - def fromDomain(patientLabel: PatientLabel, isVerified: Boolean): ApiPatientLabel = ApiPatientLabel( - id = patientLabel.id.id, - labelId = patientLabel.labelId.id, - primaryValue = patientLabel.primaryValue.map(FuzzyValue.valueToString), - verifiedPrimaryValue = patientLabel.verifiedPrimaryValue.map(FuzzyValue.valueToString), - score = patientLabel.score, - isImplicitMatch = patientLabel.isImplicitMatch, - isVisible = patientLabel.isVisible, - isVerified = isVerified - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabelDefiningCriteria.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabelDefiningCriteria.scala deleted file mode 100644 index ae64c33..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/label/ApiPatientLabelDefiningCriteria.scala +++ /dev/null @@ -1,29 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.label - -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.FuzzyValue -import xyz.driver.pdsuidomain.entities.PatientLabel - -final case class ApiPatientLabelDefiningCriteria(labelId: Long, value: Option[String]) - -object ApiPatientLabelDefiningCriteria { - - implicit val format: Format[ApiPatientLabelDefiningCriteria] = ( - (JsPath \ "labelId").format[Long] and - (JsPath \ "value").formatNullable[String]( - Format(Reads - .of[String] - .filter(ValidationError("unknown value"))({ - case x if FuzzyValue.fromString.isDefinedAt(x) => true - case _ => false - }), - Writes.of[String])) - )(ApiPatientLabelDefiningCriteria.apply, unlift(ApiPatientLabelDefiningCriteria.unapply)) - - def fromDomain(x: PatientLabel) = ApiPatientLabelDefiningCriteria( - labelId = x.labelId.id, - value = x.verifiedPrimaryValue.map(FuzzyValue.valueToString) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterion.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterion.scala deleted file mode 100644 index 399bc7d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterion.scala +++ /dev/null @@ -1,47 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.trial - -import xyz.driver.pdsuidomain.entities.PatientCriterion -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath, Reads, Writes} -import xyz.driver.pdsuicommon.domain.FuzzyValue - -final case class ApiPartialPatientCriterion(eligibilityStatus: Option[String], - verifiedEligibilityStatus: Tristate[String]) { - - def applyTo(orig: PatientCriterion): PatientCriterion = { - orig.copy( - eligibilityStatus = eligibilityStatus.map(FuzzyValue.fromString).orElse(orig.eligibilityStatus), - verifiedEligibilityStatus = - verifiedEligibilityStatus.cata(x => Some(FuzzyValue.fromString(x)), None, orig.verifiedEligibilityStatus) - ) - } -} - -object ApiPartialPatientCriterion { - - implicit val format: Format[ApiPartialPatientCriterion] = ( - (JsPath \ "eligibilityStatus").formatNullable[String]( - Format( - Reads - .of[String] - .filter(ValidationError("unknown eligibility status"))({ - case x if FuzzyValue.fromString.isDefinedAt(x) => true - case _ => false - }), - Writes.of[String] - )) and - (JsPath \ "verifiedEligibilityStatus").formatTristate[String]( - Format( - Reads - .of[String] - .filter(ValidationError("unknown verified eligibility status"))({ - case x if FuzzyValue.fromString.isDefinedAt(x) => true - case _ => false - }), - Writes.of[String] - )) - )(ApiPartialPatientCriterion.apply, unlift(ApiPartialPatientCriterion.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterionList.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterionList.scala deleted file mode 100644 index 4b08970..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPartialPatientCriterionList.scala +++ /dev/null @@ -1,36 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patient.trial - -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId} -import xyz.driver.pdsuidomain.entities.PatientCriterion -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath, Reads, Writes} -import xyz.driver.pdsuidomain.services.PatientCriterionService.DraftPatientCriterion - -final case class ApiPartialPatientCriterionList(id: Long, - eligibilityStatus: Option[String], - isVerified: Option[Boolean]) { - - def toDomain: DraftPatientCriterion = DraftPatientCriterion( - id = LongId[PatientCriterion](id), - eligibilityStatus = eligibilityStatus.map(FuzzyValue.fromString), - isVerified = isVerified - ) -} - -object ApiPartialPatientCriterionList { - - implicit val format: Format[ApiPartialPatientCriterionList] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "eligibilityStatus").formatNullable[String](Format( - Reads - .of[String] - .filter(ValidationError("unknown eligibility status"))({ - case x if FuzzyValue.fromString.isDefinedAt(x) => true - case _ => false - }), - Writes.of[String] - )) and - (JsPath \ "isVerified").formatNullable[Boolean] - )(ApiPartialPatientCriterionList.apply, unlift(ApiPartialPatientCriterionList.unapply)) -} 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 deleted file mode 100644 index 75347f4..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patient/trial/ApiPatientCriterion.scala +++ /dev/null @@ -1,74 +0,0 @@ -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 play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath, Reads, Writes} - -final case class ApiPatientCriterion(id: Long, - labelId: Long, - nctId: String, - criterionId: Long, - criterionText: String, - criterionValue: Option[String], - criterionIsDefining: Boolean, - criterionIsCompound: Boolean, - arms: List[String], - eligibilityStatus: Option[String], - verifiedEligibilityStatus: Option[String], - isVerified: Boolean, - isVisible: Boolean, - lastUpdate: ZonedDateTime) - -object ApiPatientCriterion { - - implicit val format: Format[ApiPatientCriterion] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "labelId").format[Long] and - (JsPath \ "nctId").format[String] and - (JsPath \ "criterionId").format[Long] and - (JsPath \ "criterionText").format[String] and - (JsPath \ "criterionValue").formatNullable[String](Format(Reads.of[String].filter(ValidationError("unknown value"))({ x => - x == "Yes" || x == "No" - }), Writes.of[String])) and - (JsPath \ "criterionIsDefining").format[Boolean] and - (JsPath \ "criterionIsCompound").format[Boolean] and - (JsPath \ "arms").format[List[String]] and - (JsPath \ "eligibilityStatus").formatNullable[String](Format(Reads.of[String].filter(ValidationError("unknown status"))({ - case x if FuzzyValue.fromString.isDefinedAt(x) => true - case _ => false - }), Writes.of[String])) and - (JsPath \ "verifiedEligibilityStatus").formatNullable[String](Format( - Reads.of[String].filter(ValidationError("unknown status"))({ - case x if FuzzyValue.fromString.isDefinedAt(x) => true - case _ => false - }), Writes.of[String])) and - (JsPath \ "isVerified").format[Boolean] and - (JsPath \ "isVisible").format[Boolean] and - (JsPath \ "lastUpdate").format[ZonedDateTime] - ) (ApiPatientCriterion.apply, unlift(ApiPatientCriterion.unapply)) - - def fromDomain(patientCriterion: PatientCriterion, - labelId: LongId[Label], - arms: List[PatientCriterionArm]) = ApiPatientCriterion( - id = patientCriterion.id.id, - labelId = labelId.id, - nctId = patientCriterion.nctId.id, - criterionId = patientCriterion.criterionId.id, - criterionText = patientCriterion.criterionText, - criterionValue = patientCriterion.criterionValue.map { x => - FuzzyValue.valueToString(FuzzyValue.fromBoolean(x)) - }, - criterionIsDefining = patientCriterion.criterionIsDefining, - criterionIsCompound = patientCriterion.criterionValue.isEmpty, - arms = arms.map(_.armName), - eligibilityStatus = patientCriterion.eligibilityStatus.map(FuzzyValue.valueToString), - verifiedEligibilityStatus = patientCriterion.verifiedEligibilityStatus.map(FuzzyValue.valueToString), - isVerified = patientCriterion.isVerified, - isVisible = patientCriterion.isVisible, - lastUpdate = ZonedDateTime.of(patientCriterion.lastUpdate, ZoneId.of("Z")) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthistory/ApiPatientHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthistory/ApiPatientHistory.scala deleted file mode 100644 index cdcd510..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patienthistory/ApiPatientHistory.scala +++ /dev/null @@ -1,28 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patienthistory - -import java.time.{ZoneId, ZonedDateTime} -import java.util.UUID - -import play.api.libs.json.{Format, Json} -import xyz.driver.pdsuidomain.entities.PatientHistory - -final case class ApiPatientHistory(id: Long, - executor: String, - patientId: UUID, - state: String, - action: String, - created: ZonedDateTime) - -object ApiPatientHistory { - implicit val format: Format[ApiPatientHistory] = - Json.format[ApiPatientHistory] - - def fromDomain(x: PatientHistory) = ApiPatientHistory( - id = x.id.id, - executor = x.executor.id, - patientId = x.patientId.id, - state = PatientHistory.State.stateToString(x.state), - action = PatientHistory.Action.actionToString(x.action), - created = ZonedDateTime.of(x.created, ZoneId.of("Z")) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPartialPatientIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPartialPatientIssue.scala deleted file mode 100644 index eadd1f8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPartialPatientIssue.scala +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patientissue - -import java.time.LocalDateTime - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities.{Patient, PatientIssue} - -final case class ApiPartialPatientIssue(text: String, archiveRequired: Boolean) { - def applyTo(x: PatientIssue): PatientIssue = x.copy( - text = text, - archiveRequired = archiveRequired - ) - - def toDomain(userId: StringId[User], patientId: UuidId[Patient]) = - PatientIssue( - id = LongId(0), - userId = userId, - patientId = patientId, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text, - archiveRequired = false - ) -} - -object ApiPartialPatientIssue { - implicit val format: Format[ApiPartialPatientIssue] = ( - (JsPath \ "text").format[String] and - (JsPath \ "archiveRequired").format[Boolean] - )(ApiPartialPatientIssue.apply, unlift(ApiPartialPatientIssue.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPatientIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPatientIssue.scala deleted file mode 100644 index d1a216c..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/patientissue/ApiPatientIssue.scala +++ /dev/null @@ -1,34 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.patientissue - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuidomain.entities.PatientIssue - -final case class ApiPatientIssue(id: Long, - text: String, - lastUpdate: ZonedDateTime, - userId: String, - isDraft: Boolean, - archiveRequired: Boolean) - -object ApiPatientIssue { - implicit val format: Format[ApiPatientIssue] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "text").format[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "userId").format[String] and - (JsPath \ "isDraft").format[Boolean] and - (JsPath \ "archiveRequired").format[Boolean] - )(ApiPatientIssue.apply, unlift(ApiPatientIssue.unapply)) - - def fromDomain(x: PatientIssue) = ApiPatientIssue( - id = x.id.id, - text = x.text, - lastUpdate = ZonedDateTime.of(x.lastUpdate, ZoneId.of("Z")), - userId = x.userId.id, - isDraft = x.isDraft, - archiveRequired = x.archiveRequired - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/queue/ApiQueueUploadItem.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/queue/ApiQueueUploadItem.scala deleted file mode 100644 index cd76670..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/queue/ApiQueueUploadItem.scala +++ /dev/null @@ -1,38 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.queue - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue -import play.api.libs.json.{Format, Json} - -final case class ApiQueueUploadItem(kind: String, - tag: String, - created: LocalDateTime, - attempts: Int, - nextAttempt: LocalDateTime, - completed: Boolean) { - def toDomain = BridgeUploadQueue.Item( - kind = kind, - tag = tag, - created = created, - attempts = attempts, - nextAttempt = nextAttempt, - completed = true, - dependencyKind = None, - dependencyTag = None - ) -} - -object ApiQueueUploadItem { - - def fromDomain(domain: BridgeUploadQueue.Item) = ApiQueueUploadItem( - kind = domain.kind, - tag = domain.tag, - created = domain.created, - attempts = domain.attempts, - nextAttempt = domain.nextAttempt, - completed = domain.completed - ) - - implicit val format: Format[ApiQueueUploadItem] = Json.format[ApiQueueUploadItem] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiCreateRecord.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiCreateRecord.scala deleted file mode 100644 index 2e5943e..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiCreateRecord.scala +++ /dev/null @@ -1,34 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.record - -import java.time.LocalDateTime -import java.util.UUID - -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities._ -import play.api.libs.json._ - -final case class ApiCreateRecord(disease: String, patientId: String, requestId: UUID) { - - def toDomain = MedicalRecord( - id = LongId(0), - status = MedicalRecord.Status.New, - previousStatus = None, - assignee = None, - previousAssignee = None, - lastActiveUserId = None, - patientId = UuidId(patientId), - requestId = RecordRequestId(requestId), - disease = disease, - caseId = None, - physician = None, - meta = None, - predictedMeta = None, - predictedDocuments = None, - lastUpdate = LocalDateTime.now() - ) -} - -object ApiCreateRecord { - - implicit val format: Format[ApiCreateRecord] = Json.format[ApiCreateRecord] -} 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 deleted file mode 100644 index b255892..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiRecord.scala +++ /dev/null @@ -1,100 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.record - -import java.time.{ZoneId, ZonedDateTime} -import java.util.UUID - -import xyz.driver.pdsuidomain.entities.CaseId -import xyz.driver.pdsuidomain.entities.MedicalRecord -import xyz.driver.pdsuidomain.entities.MedicalRecord.Status -import xyz.driver.pdsuidomain.entities.RecordRequestId -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -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 statusFormat = Format( - Reads.StringReads.filter(ValidationError("unknown status")) { - case x if MedicalRecordStatus.statusFromString.isDefinedAt(x) => true - case _ => false - }, - Writes.StringWrites - ) - - implicit val format: Format[ApiRecord] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "patientId").format[String] and - (JsPath \ "caseId").formatNullable[String] and - (JsPath \ "disease").format[String] and - (JsPath \ "physician").formatNullable[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "status").format(statusFormat) and - (JsPath \ "previousStatus").formatNullable(statusFormat) and - (JsPath \ "assignee").formatNullable[String] and - (JsPath \ "previousAssignee").formatNullable[String] and - (JsPath \ "lastActiveUser").formatNullable[String] and - (JsPath \ "requestId").format[UUID] and - (JsPath \ "meta").format(Format(Reads { x => - JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) - )(ApiRecord.apply, unlift(ApiRecord.unapply)) - - def fromDomain(record: MedicalRecord) = ApiRecord( - id = record.id.id, - patientId = record.patientId.toString, - caseId = record.caseId.map(_.id), - disease = record.disease, - physician = record.physician, - lastUpdate = ZonedDateTime.of(record.lastUpdate, ZoneId.of("Z")), - status = MedicalRecordStatus.statusToString(record.status), - previousStatus = record.previousStatus.map(MedicalRecordStatus.statusToString), - assignee = record.assignee.map(_.id), - previousAssignee = record.previousAssignee.map(_.id), - lastActiveUser = record.lastActiveUserId.map(_.id), - requestId = record.requestId.id, - meta = record.meta.map(x => JsonSerializer.serialize(x.content)).getOrElse("[]") - ) -} 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 deleted file mode 100644 index 47bc493..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/ApiUpdateRecord.scala +++ /dev/null @@ -1,52 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.record - -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{StringId, TextJson, User} -import xyz.driver.pdsuicommon.json.JsonSerializer -import xyz.driver.pdsuidomain.entities.MedicalRecord.Meta -import xyz.driver.pdsuidomain.entities._ - -final case class ApiUpdateRecord(status: Option[String], assignee: Tristate[String], meta: Tristate[String]) { - - def applyTo(orig: MedicalRecord): MedicalRecord = { - orig.copy( - status = status.map(MedicalRecordStatus.statusFromString).getOrElse(orig.status), - assignee = assignee.map(StringId[User]).cata(Some(_), None, orig.assignee), - meta = meta.cata(x => Some(TextJson(JsonSerializer.deserialize[List[Meta]](x))), None, orig.meta) - ) - } -} - -object ApiUpdateRecord { - - private val reads: Reads[ApiUpdateRecord] = ( - (JsPath \ "status").readNullable[String]( - Reads - .of[String] - .filter(ValidationError("unknown status"))({ - case x if MedicalRecordStatus.statusFromString.isDefinedAt(x) => true - case _ => false - })) and - (JsPath \ "assignee").readTristate[String] and - (JsPath \ "meta") - .readTristate(Reads { x => - JsSuccess(Json.stringify(x)) - }) - .map { - case Tristate.Present("{}") => Tristate.Absent - case x => x - } - )(ApiUpdateRecord.apply _) - - private val writes: Writes[ApiUpdateRecord] = ( - (JsPath \ "status").writeNullable[String] and - (JsPath \ "assignee").writeTristate[String] and - (JsPath \ "meta").writeTristate(Writes[String](Json.parse)) - )(unlift(ApiUpdateRecord.unapply)) - - implicit val format: Format[ApiUpdateRecord] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/MedicalRecordStatus.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/MedicalRecordStatus.scala deleted file mode 100644 index a77b76b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/record/MedicalRecordStatus.scala +++ /dev/null @@ -1,34 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.record - -import xyz.driver.pdsuidomain.entities.MedicalRecord.Status - -object MedicalRecordStatus { - - val statusFromString: PartialFunction[String, Status] = { - case "Unprocessed" => Status.Unprocessed - case "PreCleaning" => Status.PreCleaning - case "New" => Status.New - case "Cleaned" => Status.Cleaned - case "PreOrganized" => Status.PreOrganized - case "PreOrganizing" => Status.PreOrganizing - case "Reviewed" => Status.Reviewed - case "Organized" => Status.Organized - case "Done" => Status.Done - case "Flagged" => Status.Flagged - case "Archived" => Status.Archived - } - - def statusToString(x: Status): String = x match { - case Status.Unprocessed => "Unprocessed" - case Status.PreCleaning => "PreCleaning" - case Status.New => "New" - case Status.Cleaned => "Cleaned" - case Status.PreOrganized => "PreOrganized" - case Status.PreOrganizing => "PreOrganizing" - case Status.Reviewed => "Reviewed" - case Status.Organized => "Organized" - case Status.Done => "Done" - case Status.Flagged => "Flagged" - case Status.Archived => "Archived" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordhistory/ApiRecordHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordhistory/ApiRecordHistory.scala deleted file mode 100644 index c55a78f..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordhistory/ApiRecordHistory.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.recordhistory - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.json.{Format, Json} -import xyz.driver.pdsuidomain.entities.MedicalRecordHistory - -final case class ApiRecordHistory(id: Long, - executor: String, - recordId: Long, - state: String, - action: String, - created: ZonedDateTime) - -object ApiRecordHistory { - implicit val format: Format[ApiRecordHistory] = - Json.format[ApiRecordHistory] - - def fromDomain(x: MedicalRecordHistory) = ApiRecordHistory( - id = x.id.id, - executor = x.executor.id, - recordId = x.recordId.id, - state = MedicalRecordHistory.State.stateToString(x.state), - action = MedicalRecordHistory.Action.actionToString(x.action), - created = ZonedDateTime.of(x.created, ZoneId.of("Z")) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiPartialRecordIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiPartialRecordIssue.scala deleted file mode 100644 index 890ad69..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiPartialRecordIssue.scala +++ /dev/null @@ -1,42 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.recordissue - -import java.time.LocalDateTime - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuidomain.entities.{MedicalRecord, MedicalRecordIssue} - -final case class ApiPartialRecordIssue(startPage: Option[Double], - endPage: Option[Double], - text: String, - archiveRequired: Boolean) { - def applyTo(x: MedicalRecordIssue): MedicalRecordIssue = x.copy( - startPage = startPage, - endPage = endPage, - text = text, - archiveRequired = archiveRequired - ) - - def toDomain(userId: StringId[User], recordId: LongId[MedicalRecord]) = - MedicalRecordIssue( - id = LongId(0), - userId = userId, - recordId = recordId, - startPage = startPage, - endPage = endPage, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text, - archiveRequired = false - ) -} - -object ApiPartialRecordIssue { - implicit val format: Format[ApiPartialRecordIssue] = ( - (JsPath \ "startPage").formatNullable[Double] and - (JsPath \ "endPage").formatNullable[Double] and - (JsPath \ "text").format[String] and - (JsPath \ "archiveRequired").format[Boolean] - )(ApiPartialRecordIssue.apply, unlift(ApiPartialRecordIssue.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiRecordIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiRecordIssue.scala deleted file mode 100644 index 45bc469..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/recordissue/ApiRecordIssue.scala +++ /dev/null @@ -1,40 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.recordissue - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuidomain.entities.MedicalRecordIssue - -final case class ApiRecordIssue(id: Long, - startPage: Option[Double], - endPage: Option[Double], - text: String, - lastUpdate: ZonedDateTime, - userId: String, - isDraft: Boolean, - archiveRequired: Boolean) - -object ApiRecordIssue { - implicit val format: Format[ApiRecordIssue] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "startPage").formatNullable[Double] and - (JsPath \ "endPage").formatNullable[Double] and - (JsPath \ "text").format[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "userId").format[String] and - (JsPath \ "isDraft").format[Boolean] and - (JsPath \ "archiveRequired").format[Boolean] - )(ApiRecordIssue.apply, unlift(ApiRecordIssue.unapply)) - - def fromDomain(x: MedicalRecordIssue) = ApiRecordIssue( - id = x.id.id, - startPage = x.startPage, - endPage = x.endPage, - text = x.text, - lastUpdate = ZonedDateTime.of(x.lastUpdate, ZoneId.of("Z")), - userId = x.userId.id, - isDraft = x.isDraft, - archiveRequired = x.archiveRequired - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionRequest.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionRequest.scala deleted file mode 100644 index fbe9689..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionRequest.scala +++ /dev/null @@ -1,12 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.session - -import xyz.driver.pdsuicommon.domain.Email -import play.api.libs.json._ -import xyz.driver.pdsuicommon.json.Serialization._ - -final case class NewSessionRequest(email: Email, password: String) - -object NewSessionRequest { - - implicit val format: Format[NewSessionRequest] = Json.format[NewSessionRequest] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionResponse.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionResponse.scala deleted file mode 100644 index 55e05b1..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/session/NewSessionResponse.scala +++ /dev/null @@ -1,11 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.session - -import play.api.libs.json.Json -import xyz.driver.pdsuidomain.formats.json.user.ApiUser - -final case class NewSessionResponse(token: String, user: ApiUser) - -object NewSessionResponse { - - implicit val format = Json.format[NewSessionResponse] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/arm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/arm.scala deleted file mode 100644 index 39af1c3..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/arm.scala +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities._ - -object arm { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToArm(json: JsValue, orig: Arm): Arm = json match { - case JsObject(fields) => - val name = fields - .get("name") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"Arm json object does not contain `name` field: $json")) - orig.copy(name = name) - - case _ => deserializationError(s"Expected Json Object as partial Arm, but got $json") - } - - def armFormat: RootJsonFormat[Arm] = new RootJsonFormat[Arm] { - override def write(obj: Arm): JsValue = - JsObject( - "id" -> obj.id.toJson, - "name" -> obj.name.toJson, - "originalName" -> obj.originalName.toJson, - "trialId" -> obj.trialId.toJson - ) - - override def read(json: JsValue): Arm = json.asJsObject.getFields("trialId", "name") match { - case Seq(trialId, name) => - Arm( - id = LongId(0), - name = name.convertTo[String], - trialId = trialId.convertTo[StringId[Trial]], - originalName = name.convertTo[String] - ) - - case _ => deserializationError(s"Expected Json Object as Arm, but got $json") - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/bridgeuploadqueue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/bridgeuploadqueue.scala deleted file mode 100644 index 77fb4d2..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/bridgeuploadqueue.scala +++ /dev/null @@ -1,68 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue.Item - -object bridgeuploadqueue { - import DefaultJsonProtocol._ - import common._ - - implicit val queueUploadItemFormat: RootJsonFormat[BridgeUploadQueue.Item] = new RootJsonFormat[Item] { - override def write(obj: Item) = - JsObject( - "kind" -> obj.kind.toJson, - "tag" -> obj.tag.toJson, - "created" -> obj.created.toJson, - "attempts" -> obj.attempts.toJson, - "nextAttempt" -> obj.nextAttempt.toJson, - "completed" -> obj.completed.toJson - ) - - override def read(json: JsValue): Item = json match { - case JsObject(fields) => - val kind = fields - .get("kind") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"BridgeUploadQueue.Item json object does not contain `kind` field: $json")) - - val tag = fields - .get("tag") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"BridgeUploadQueue.Item json object does not contain `tag` field: $json")) - - val created = fields - .get("created") - .map(_.convertTo[LocalDateTime]) - .getOrElse( - deserializationError(s"BridgeUploadQueue.Item json object does not contain `created` field: $json")) - - val attempts = fields - .get("attempts") - .map(_.convertTo[Int]) - .getOrElse( - deserializationError(s"BridgeUploadQueue.Item json object does not contain `attempts` field: $json")) - - val nextAttempt = fields - .get("nextAttempt") - .map(_.convertTo[LocalDateTime]) - .getOrElse( - deserializationError(s"BridgeUploadQueue.Item json object does not contain `nextAttempt` field: $json")) - - BridgeUploadQueue.Item( - kind = kind, - tag = tag, - created = created, - attempts = attempts, - nextAttempt = nextAttempt, - completed = true, - dependencyKind = None, - dependencyTag = None - ) - - case _ => deserializationError(s"Expected Json Object as BridgeUploadQueue.Item, but got $json") - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/common.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/common.scala deleted file mode 100644 index dbd0a43..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/common.scala +++ /dev/null @@ -1,74 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.{LocalDate, LocalDateTime, ZoneId, ZonedDateTime} - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, StringId, UuidId} - -object common { - - implicit def longIdFormat[T] = new RootJsonFormat[LongId[T]] { - override def write(id: LongId[T]): JsNumber = JsNumber(id.id) - override def read(json: JsValue): LongId[T] = json match { - case JsNumber(value) => LongId(value.toLong) - case _ => deserializationError(s"Expected number as LongId, but got $json") - } - } - - implicit def stringIdFormat[T] = new RootJsonFormat[StringId[T]] { - override def write(id: StringId[T]): JsString = JsString(id.toString) - override def read(json: JsValue): StringId[T] = json match { - case JsString(value) => StringId(value) - case _ => deserializationError(s"Expected string as StringId, but got $json") - } - } - - implicit def uuidIdFormat[T] = new RootJsonFormat[UuidId[T]] { - override def write(id: UuidId[T]): JsString = JsString(id.toString) - override def read(json: JsValue): UuidId[T] = json match { - case JsString(value) => UuidId(value) - case _ => deserializationError(s"Expected string as UuidId, but got $json") - } - } - - implicit def dateTimeFormat = new RootJsonFormat[LocalDateTime] { - override def write(date: LocalDateTime): JsString = JsString(ZonedDateTime.of(date, ZoneId.of("Z")).toString) - override def read(json: JsValue): LocalDateTime = json match { - case JsString(value) => ZonedDateTime.parse(value).toLocalDateTime - case _ => deserializationError(s"Expected date as LocalDateTime, but got $json") - } - } - - implicit def zonedDateTimeFormat = new RootJsonFormat[ZonedDateTime] { - override def write(date: ZonedDateTime): JsString = JsString(date.toString) - override def read(json: JsValue): ZonedDateTime = json match { - case JsString(value) => ZonedDateTime.parse(value) - case _ => deserializationError(s"Expected date as ZonedDateTime, but got $json") - } - } - - implicit def dateFormat = new RootJsonFormat[LocalDate] { - override def write(date: LocalDate): JsString = JsString(date.toString) - override def read(json: JsValue): LocalDate = json match { - case JsString(value) => LocalDate.parse(value) - case _ => deserializationError(s"Expected date as LocalDate, but got $json") - } - } - - implicit def fuzzyValueFormat: RootJsonFormat[FuzzyValue] = new RootJsonFormat[FuzzyValue] { - override def write(value: FuzzyValue): JsString = JsString(FuzzyValue.valueToString(value)) - override def read(json: JsValue): FuzzyValue = json match { - case JsString(value) => FuzzyValue.fromString(value) - case _ => deserializationError(s"Expected value as FuzzyValue, but got $json") - } - } - - implicit val integerFormat: RootJsonFormat[Integer] = new RootJsonFormat[Integer] { - override def write(obj: Integer): JsNumber = JsNumber(obj.intValue()) - override def read(json: JsValue): Integer = json match { - case JsNumber(value) => value.toInt - case _ => deserializationError(s"Expected number as Integer, but got $json") - } - } - -} 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 deleted file mode 100644 index 732bcad..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/criterion.scala +++ /dev/null @@ -1,158 +0,0 @@ -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") - } - - def applyUpdateToCriterion(json: JsValue, orig: RichCriterion): RichCriterion = json match { - case JsObject(fields) => - val text = fields - .get("text") - .map(_.convertTo[String]) - - val isCompound = fields - .get("isCompound") - .exists(_.convertTo[Boolean]) - - val meta = fields - .get("meta") - .map(_.convertTo[Option[String]].getOrElse("{}")) - .getOrElse(orig.criterion.meta) - - val arms = fields - .get("arms") - .map(_.convertTo[Option[List[LongId[Arm]]]].getOrElse(List.empty[LongId[Arm]])) - .getOrElse(orig.armIds) - - val labels = fields - .get("labels") - .map(_.convertTo[Option[List[JsValue]]].getOrElse(List.empty[JsValue])) - .map(_.map(l => jsValueToCriterionLabel(l, orig.criterion.id))) - .getOrElse(orig.labels) - - orig.copy( - criterion = orig.criterion.copy( - meta = meta, - text = text, - isCompound = isCompound - ), - armIds = arms, - labels = labels - ) - - case _ => deserializationError(s"Expected Json Object as partial Criterion, 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 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, LongId(0)))) - .getOrElse(List.empty[CriterionLabel]) - - RichCriterion( - criterion = Criterion( - id = LongId(0), - trialId = trialId, - text = text, - isCompound = isCompound, - meta = meta - ), - armIds = arms, - labels = labels - ) - - case _ => deserializationError(s"Expected Json Object as Criterion, but got $json") - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala deleted file mode 100644 index baf1b4e..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/document.scala +++ /dev/null @@ -1,164 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.{LocalDate, LocalDateTime} - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuicommon.domain.{LongId, TextJson} -import xyz.driver.pdsuidomain.entities._ - -object document { - import DefaultJsonProtocol._ - import Document._ - import common._ - - implicit val documentStatusFormat = new EnumJsonFormat[Status]( - "New" -> Status.New, - "Organized" -> Status.Organized, - "Extracted" -> Status.Extracted, - "Done" -> Status.Done, - "Flagged" -> Status.Flagged, - "Archived" -> Status.Archived - ) - - implicit val requiredTypeFormat = new EnumJsonFormat[RequiredType]( - "OPN" -> RequiredType.OPN, - "PN" -> RequiredType.PN - ) - - implicit val documentMetaFormat: RootJsonFormat[Meta] = jsonFormat3(Meta.apply) - - implicit val fullDocumentMetaFormat = new RootJsonFormat[TextJson[Meta]] { - override def write(obj: TextJson[Meta]): JsValue = obj.content.toJson - override def read(json: JsValue) = TextJson(documentMetaFormat.read(json)) - } - - def applyUpdateToDocument(json: JsValue, orig: Document): Document = json match { - case JsObject(fields) => - val physician = fields - .get("physician") - .map(_.convertTo[String]) - - val typeId = fields - .get("typeId") - .map(_.convertTo[Option[LongId[DocumentType]]]) - .getOrElse(orig.typeId) - - val provider = fields - .get("provider") - .map(_.convertTo[Option[String]]) - .getOrElse(orig.providerName) - - val providerTypeId = fields - .get("providerTypeId") - .map(_.convertTo[Option[LongId[ProviderType]]]) - .getOrElse(orig.providerTypeId) - - val meta = fields - .get("meta") - .map(_.convertTo[Option[TextJson[Meta]]]) - .getOrElse(orig.meta) - - val startDate = fields - .get("startDate") - .map(_.convertTo[Option[LocalDate]]) - .getOrElse(orig.startDate) - - val endDate = fields - .get("endDate") - .map(_.convertTo[Option[LocalDate]]) - .getOrElse(orig.endDate) - - orig.copy( - physician = physician.orElse(orig.physician), - typeId = typeId, - providerName = provider, - providerTypeId = providerTypeId, - meta = meta, - startDate = startDate, - endDate = endDate - ) - - case _ => deserializationError(s"Expected Json Object as partial Document, but got $json") - } - - implicit val documentFormat: RootJsonFormat[Document] = new RootJsonFormat[Document] { - override def write(document: Document): JsValue = - JsObject( - "id" -> document.id.id.toJson, - "recordId" -> document.recordId.toJson, - "physician" -> document.physician.toJson, - "typeId" -> document.typeId.toJson, - "provider" -> document.providerName.toJson, - "providerTypeId" -> document.providerTypeId.toJson, - "requiredType" -> document.requiredType.toJson, - "startDate" -> document.startDate.toJson, - "endDate" -> document.endDate.toJson, - "status" -> document.status.toJson, - "previousStatus" -> document.previousStatus.toJson, - "assignee" -> document.assignee.toJson, - "previousAssignee" -> document.previousAssignee.toJson, - "meta" -> document.meta.toJson, - "lastActiveUser" -> document.lastActiveUserId.toJson, - "lastUpdate" -> document.lastUpdate.toJson - ) - - override def read(json: JsValue): Document = json match { - case JsObject(fields) => - val recordId = fields - .get("recordId") - .map(_.convertTo[LongId[MedicalRecord]]) - .getOrElse(deserializationError(s"Document create json object does not contain `recordId` field: $json")) - - val physician = fields - .get("physician") - .map(_.convertTo[String]) - - val typeId = fields - .get("typeId") - .map(_.convertTo[LongId[DocumentType]]) - - val provider = fields - .get("provider") - .map(_.convertTo[String]) - - val providerTypeId = fields - .get("providerTypeId") - .map(_.convertTo[LongId[ProviderType]]) - - val meta = fields - .get("meta") - .map(_.convertTo[TextJson[Meta]]) - - val startDate = fields - .get("startDate") - .map(_.convertTo[LocalDate]) - - val endDate = fields - .get("endDate") - .map(_.convertTo[LocalDate]) - - Document( - id = LongId(0), - recordId = recordId, - status = Document.Status.New, - physician = physician, - typeId = typeId, - startDate = startDate, - endDate = endDate, - providerName = provider, - providerTypeId = providerTypeId, - requiredType = None, - meta = meta, - previousStatus = None, - assignee = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.MIN - ) - - case _ => deserializationError(s"Expected Json Object as Document, but got $json") - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documenthistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documenthistory.scala deleted file mode 100644 index 419c252..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documenthistory.scala +++ /dev/null @@ -1,29 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuidomain.entities._ - -object documenthistory { - import DefaultJsonProtocol._ - import common._ - import DocumentHistory._ - - implicit val documentStateFormat = new EnumJsonFormat[State]( - "Extract" -> State.Extract, - "Review" -> State.Review, - "Flag" -> State.Flag - ) - - implicit val documentActionFormat = new EnumJsonFormat[Action]( - "Start" -> Action.Start, - "Submit" -> Action.Submit, - "Unassign" -> Action.Unassign, - "Resolve" -> Action.Resolve, - "Flag" -> Action.Flag, - "Archive" -> Action.Archive - ) - - implicit val documentHistoryFormat: RootJsonFormat[DocumentHistory] = jsonFormat6(DocumentHistory.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documentissue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documentissue.scala deleted file mode 100644 index 28b2a5e..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/documentissue.scala +++ /dev/null @@ -1,77 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuidomain.entities._ - -object documentissue { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToDocumentIssue(json: JsValue, orig: DocumentIssue): DocumentIssue = json match { - case JsObject(fields) => - val text = fields - .get("text") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"DocumentIssue json object does not contain `text` field: $json")) - - val archiveRequired = fields - .get("archiveRequired") - .map(_.convertTo[Boolean]) - .getOrElse(deserializationError(s"DocumentIssue json object does not contain `archiveRequired` field: $json")) - - val startPage = fields.get("startPage").map(_.convertTo[Double]) - val endPage = fields.get("endPage").map(_.convertTo[Double]) - - orig.copy( - text = text, - archiveRequired = archiveRequired, - startPage = startPage, - endPage = endPage - ) - - case _ => deserializationError(s"Expected Json Object as partial DocumentIssue, but got $json") - - } - - def jsValueToDocumentIssue(json: JsValue, documentId: LongId[Document], userId: StringId[User]): DocumentIssue = - json match { - case JsObject(fields) => - val text = fields - .get("text") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"DocumentIssue json object does not contain `text` field: $json")) - - val startPage = fields.get("startPage").map(_.convertTo[Double]) - val endPage = fields.get("endPage").map(_.convertTo[Double]) - DocumentIssue( - id = LongId(0), - userId = userId, - documentId = documentId, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text, - archiveRequired = false, - startPage = startPage, - endPage = endPage - ) - - case _ => deserializationError(s"Expected Json Object as DocumentIssue, but got $json") - } - - implicit val documentIssueWriter = new JsonWriter[DocumentIssue] { - override def write(obj: DocumentIssue) = JsObject( - "id" -> obj.id.toJson, - "startPage" -> obj.startPage.toJson, - "endPage" -> obj.endPage.toJson, - "text" -> obj.text.toJson, - "lastUpdate" -> obj.lastUpdate.toJson, - "userId" -> obj.userId.toJson, - "isDraft" -> obj.isDraft.toJson, - "archiveRequired" -> obj.archiveRequired.toJson - ) - } - -} 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 deleted file mode 100644 index 20b6ed0..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/export.scala +++ /dev/null @@ -1,78 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuidomain.entities.export.patient._ -import xyz.driver.pdsuidomain.entities.export.trial.{ExportTrialArm, ExportTrialLabelCriterion, ExportTrialWithLabels} - -object export { - import DefaultJsonProtocol._ - import common._ - import record._ - - 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 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 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 trialArmFormat: RootJsonFormat[ExportTrialArm] = jsonFormat2(ExportTrialArm.apply) - - implicit val trialLabelCriterionWriter: JsonWriter[ExportTrialLabelCriterion] = - new JsonWriter[ExportTrialLabelCriterion] { - override def write(obj: ExportTrialLabelCriterion): JsValue = - JsObject( - "value" -> obj.value - .map { - case true => "Yes" - case false => "No" - } - .getOrElse("Unknown") - .toJson, - "labelId" -> obj.labelId.toJson, - "criterionId" -> obj.criterionId.toJson, - "criterionText" -> obj.criteria.toJson, - "armIds" -> obj.armIds.toJson, - "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 - ) - } - -} 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 deleted file mode 100644 index 42473bc..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/extracteddata.scala +++ /dev/null @@ -1,148 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, TextJson} -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData - -object extracteddata { - import DefaultJsonProtocol._ - import common._ - import ExtractedData._ - - implicit val metaKeywordFormat: RootJsonFormat[Meta.Keyword] = jsonFormat4(Meta.Keyword) - implicit val metaTextLayerPositionFormat: RootJsonFormat[Meta.TextLayerPosition] = jsonFormat3( - Meta.TextLayerPosition) - implicit val metaEvidenceFormat: RootJsonFormat[Meta.Evidence] = jsonFormat3(Meta.Evidence) - - implicit val extractedDataMetaFormat: RootJsonFormat[Meta] = jsonFormat2(Meta.apply) - implicit val fullExtractedDataMetaFormat = new RootJsonFormat[TextJson[Meta]] { - override def write(obj: TextJson[Meta]): JsValue = obj.content.toJson - override def read(json: JsValue): TextJson[Meta] = TextJson(extractedDataMetaFormat.read(json)) - } - - implicit val extractedDataLabelWriter: JsonWriter[ExtractedDataLabel] = new JsonWriter[ExtractedDataLabel] { - override def write(label: ExtractedDataLabel): JsObject = { - JsObject( - "id" -> label.labelId.toJson, - "categoryId" -> label.categoryId.toJson, - "value" -> label.value.toJson - ) - } - } - - def applyLabelsForExtractedData(json: JsValue, dataId: LongId[ExtractedData]): ExtractedDataLabel = json match { - case JsObject(fields) => - val labelId = fields - .get("id") - .map(_.convertTo[LongId[Label]]) - - val categoryId = fields - .get("categoryId") - .map(_.convertTo[LongId[Category]]) - - val value = fields - .get("value") - .map(_.convertTo[FuzzyValue]) - - ExtractedDataLabel( - id = LongId(0), - dataId = dataId, - labelId = labelId, - categoryId = categoryId, - value = value - ) - - case _ => deserializationError(s"Expected Json Object as ExtractedDataLabel, but got $json") - } - - def applyUpdateToExtractedData(json: JsValue, orig: RichExtractedData): RichExtractedData = json match { - case JsObject(fields) => - val keywordId = fields - .get("keywordId") - .map(_.convertTo[Option[LongId[Keyword]]]) - .getOrElse(orig.extractedData.keywordId) - - val evidence = fields - .get("evidence") - .map(_.convertTo[Option[String]]) - .getOrElse(orig.extractedData.evidenceText) - - val meta = fields - .get("meta") - .map(_.convertTo[Option[TextJson[Meta]]]) - .getOrElse(orig.extractedData.meta) - - val labels = fields - .get("labels") - .map( - _.convertTo[Option[List[JsValue]]] - .getOrElse(List.empty[JsValue]) - .map(l => applyLabelsForExtractedData(l, orig.extractedData.id))) - .getOrElse(orig.labels) - - val extractedData = orig.extractedData.copy( - keywordId = keywordId, - evidenceText = evidence, - meta = meta - ) - - orig.copy( - extractedData = extractedData, - labels = labels - ) - - case _ => deserializationError(s"Expected Json Object as partial ExtractedData, but got $json") - } - - implicit val extractedDataFormat: RootJsonFormat[RichExtractedData] = new RootJsonFormat[RichExtractedData] { - override def write(richData: RichExtractedData): JsValue = - JsObject( - "id" -> richData.extractedData.id.id.toJson, - "documentId" -> richData.extractedData.documentId.toJson, - "keywordId" -> richData.extractedData.keywordId.toJson, - "evidence" -> richData.extractedData.evidenceText.toJson, - "meta" -> richData.extractedData.meta.toJson, - "labels" -> richData.labels.map(_.toJson).toJson - ) - - override def read(json: JsValue): RichExtractedData = json match { - case JsObject(fields) => - val documentId = fields - .get("documentId") - .map(_.convertTo[LongId[Document]]) - .getOrElse( - deserializationError(s"ExtractedData create json object does not contain `documentId` field: $json")) - - val keywordId = fields - .get("keywordId") - .map(_.convertTo[LongId[Keyword]]) - - val evidence = fields - .get("evidence") - .map(_.convertTo[String]) - - val meta = fields - .get("meta") - .map(_.convertTo[TextJson[Meta]]) - - val labels = fields - .get("labels") - .map(_.convertTo[List[JsValue]]) - .getOrElse(List.empty[JsValue]) - .map(l => applyLabelsForExtractedData(l, LongId(0))) - - val extractedData = ExtractedData( - documentId = documentId, - keywordId = keywordId, - evidenceText = evidence, - meta = meta - ) - - RichExtractedData(extractedData, labels) - - case _ => deserializationError(s"Expected Json Object as ExtractedData, but got $json") - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/hypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/hypothesis.scala deleted file mode 100644 index c05ff23..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/hypothesis.scala +++ /dev/null @@ -1,12 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuidomain.entities._ - -object hypothesis { - import DefaultJsonProtocol._ - import common._ - - implicit val hypothesisFormat: RootJsonFormat[Hypothesis] = jsonFormat4(Hypothesis.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 deleted file mode 100644 index a8ce950..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/intervention.scala +++ /dev/null @@ -1,60 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuidomain.entities._ - -object intervention { - import DefaultJsonProtocol._ - import common._ - - implicit val interventionWriter: JsonWriter[InterventionWithArms] = new JsonWriter[InterventionWithArms] { - override def write(obj: InterventionWithArms) = - JsObject( - "id" -> obj.intervention.id.toJson, - "name" -> obj.intervention.name.toJson, - "typeId" -> obj.intervention.typeId.toJson, - "description" -> obj.intervention.description.toJson, - "isActive" -> obj.intervention.isActive.toJson, - "arms" -> obj.arms.map(_.armId).toJson, - "trialId" -> obj.intervention.trialId.toJson, - "originalName" -> obj.intervention.originalName.toJson, - "originalDescription" -> obj.intervention.originalDescription.toJson, - "originalType" -> obj.intervention.originalType.toJson - ) - } - - def applyUpdateToInterventionWithArms(json: JsValue, orig: InterventionWithArms): InterventionWithArms = json match { - case JsObject(fields) => - val typeId = fields - .get("typeId") - .map(_.convertTo[LongId[InterventionType]]) - - val description = fields - .get("description") - .map(_.convertTo[String]) - - val isActive = fields - .get("isActive") - .map(_.convertTo[Boolean]) - - val origIntervention = orig.intervention - val arms = fields - .get("arms") - .map(_.convertTo[List[LongId[Arm]]].map(x => InterventionArm(x, orig.intervention.id))) - - orig.copy( - intervention = origIntervention.copy( - typeId = typeId.orElse(origIntervention.typeId), - description = description.getOrElse(origIntervention.description), - isActive = isActive.getOrElse(origIntervention.isActive) - ), - arms = arms.getOrElse(orig.arms) - ) - - case _ => deserializationError(s"Expected Json Object as partial Intervention, but got $json") - } - - implicit val interventionTypeFormat: RootJsonFormat[InterventionType] = jsonFormat2(InterventionType.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patient.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patient.scala deleted file mode 100644 index 724c391..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patient.scala +++ /dev/null @@ -1,46 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuidomain.entities._ - -object patient { - import DefaultJsonProtocol._ - import common._ - import Patient._ - - implicit val patientStatusFormat = new EnumJsonFormat[Status]( - "New" -> Status.New, - "Verified" -> Status.Verified, - "Reviewed" -> Status.Reviewed, - "Curated" -> Status.Curated, - "Done" -> Status.Done, - "Flagged" -> Status.Flagged - ) - - implicit val patientOrderIdFormat = new RootJsonFormat[PatientOrderId] { - override def write(orderId: PatientOrderId): JsString = JsString(orderId.toString) - override def read(json: JsValue): PatientOrderId = json match { - case JsString(value) => PatientOrderId(value) - case _ => deserializationError(s"Expected string as PatientOrderId, but got $json") - } - } - - implicit val patientWriter: JsonWriter[Patient] = new JsonWriter[Patient] { - override def write(patient: Patient): JsValue = - JsObject( - "id" -> patient.id.toJson, - "status" -> patient.status.toJson, - "name" -> patient.name.toJson, - "dob" -> patient.dob.toJson, - "assignee" -> patient.assignee.toJson, - "previousStatus" -> patient.previousStatus.toJson, - "previousAssignee" -> patient.previousAssignee.toJson, - "lastActiveUser" -> patient.lastActiveUserId.toJson, - "lastUpdate" -> patient.lastUpdate.toJson, - "condition" -> patient.condition.toJson, - "orderId" -> patient.orderId.toJson - ) - } - -} 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 deleted file mode 100644 index 53e927d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientcriterion.scala +++ /dev/null @@ -1,68 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId} -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.services.PatientCriterionService.DraftPatientCriterion - -object patientcriterion { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToPatientCriterion(json: JsValue, orig: PatientCriterion): PatientCriterion = json match { - case JsObject(fields) => - val eligibilityStatus = if (fields.contains("eligibilityStatus")) { - fields - .get("eligibilityStatus") - .map(_.convertTo[FuzzyValue]) - } else orig.eligibilityStatus - - val verifiedEligibilityStatus = if (fields.contains("verifiedEligibilityStatus")) { - fields - .get("verifiedEligibilityStatus") - .map(_.convertTo[FuzzyValue]) - } else orig.verifiedEligibilityStatus - - orig.copy( - eligibilityStatus = eligibilityStatus, - verifiedEligibilityStatus = verifiedEligibilityStatus - ) - - case _ => deserializationError(s"Expected Json Object as partial PatientCriterion, but got $json") - } - - implicit val draftPatientCriterionFormat: RootJsonFormat[DraftPatientCriterion] = jsonFormat3( - DraftPatientCriterion.apply) - implicit val draftPatientCriterionListReader = new JsonReader[List[DraftPatientCriterion]] { - override def read(json: JsValue) = json.convertTo[List[JsValue]].map(_.convertTo[DraftPatientCriterion]) - } - - implicit val patientCriterionWriter: JsonWriter[(PatientCriterion, LongId[Label], List[PatientCriterionArm])] = - new JsonWriter[(PatientCriterion, LongId[Label], List[PatientCriterionArm])] { - override def write(obj: (PatientCriterion, LongId[Label], List[PatientCriterionArm])): JsValue = { - val criterion = obj._1 - val labelId = obj._2 - val arms = obj._3 - JsObject( - "id" -> criterion.id.toJson, - "labelId" -> labelId.toJson, - "nctId" -> criterion.nctId.toJson, - "criterionId" -> criterion.criterionId.toJson, - "criterionText" -> criterion.criterionText.toJson, - "criterionValue" -> criterion.criterionValue.map { - case true => "Yes" - case false => "No" - }.toJson, - "criterionIsDefining" -> criterion.criterionIsDefining.toJson, - "criterionIsCompound" -> criterion.criterionValue.isEmpty.toJson, - "arms" -> arms.map(_.armName).toJson, - "eligibilityStatus" -> criterion.eligibilityStatus.toJson, - "verifiedEligibilityStatus" -> criterion.verifiedEligibilityStatus.toJson, - "isVerified" -> criterion.isVerified.toJson, - "isVisible" -> criterion.isVisible.toJson, - "lastUpdate" -> criterion.lastUpdate.toJson - ) - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientdefiningcriteria.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientdefiningcriteria.scala deleted file mode 100644 index b97570a..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientdefiningcriteria.scala +++ /dev/null @@ -1,18 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuidomain.entities.PatientLabel - -object patientdefiningcriteria { - import DefaultJsonProtocol._ - import common._ - - implicit val patientLabelDefiningCriteriaWriter: JsonWriter[PatientLabel] = new JsonWriter[PatientLabel] { - override def write(obj: PatientLabel) = - JsObject( - "id" -> obj.id.toJson, - "value" -> obj.verifiedPrimaryValue.toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienteligibletrial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienteligibletrial.scala deleted file mode 100644 index 894e453..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienteligibletrial.scala +++ /dev/null @@ -1,39 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.services.PatientEligibleTrialService.RichPatientEligibleTrial - -object patienteligibletrial { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToTrialArmGroup(json: JsValue, orig: PatientTrialArmGroupView): PatientTrialArmGroupView = - json match { - case JsObject(fields) => - val isVerified = fields - .get("isVerified") - .map(_.convertTo[Boolean]) - .getOrElse(orig.isVerified) - - orig.copy(isVerified = isVerified) - - case _ => deserializationError(s"Expected Json Object as partial PatientTrialArmGroupView, but got $json") - } - - implicit val patientEligibleTrialWriter: JsonWriter[RichPatientEligibleTrial] = - new JsonWriter[RichPatientEligibleTrial] { - override def write(obj: RichPatientEligibleTrial) = - JsObject( - "id" -> obj.group.id.toJson, - "patientId" -> obj.group.patientId.toJson, - "trialId" -> obj.group.trialId.toJson, - "trialTitle" -> obj.trial.title.toJson, - "arms" -> obj.arms.map(_.armName).toJson, - "hypothesisId" -> obj.trial.hypothesisId.toJson, - "verifiedEligibilityStatus" -> obj.group.verifiedEligibilityStatus.toJson, - "isVerified" -> obj.group.isVerified.toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthistory.scala deleted file mode 100644 index da7a664..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthistory.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuidomain.entities._ - -object patienthistory { - import DefaultJsonProtocol._ - import common._ - import PatientHistory._ - - implicit val patientStateFormat = new EnumJsonFormat[State]( - "Verify" -> State.Verify, - "Curate" -> State.Curate, - "Review" -> State.Review, - "Flag" -> State.Flag - ) - - implicit val patientActionFormat = new EnumJsonFormat[Action]( - "Start" -> Action.Start, - "Submit" -> Action.Submit, - "Unassign" -> Action.Unassign, - "Resolve" -> Action.Resolve, - "Flag" -> Action.Flag, - "Archive" -> Action.Archive - ) - - implicit val patientHistoryFormat: RootJsonFormat[PatientHistory] = jsonFormat6(PatientHistory.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthypothesis.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthypothesis.scala deleted file mode 100644 index 4f2783c..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patienthypothesis.scala +++ /dev/null @@ -1,37 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuidomain.entities._ - -object patienthypothesis { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToPatientHypothesis(json: JsValue, orig: PatientHypothesis): PatientHypothesis = json match { - case JsObject(fields) => - val rationale = if (fields.contains("rationale")) { - fields.get("rationale").map(_.convertTo[String]) - } else orig.rationale - - orig.copy(rationale = rationale) - - case _ => deserializationError(s"Expected Json Object as partial PatientHypothesis, but got $json") - } - - implicit val patientHypothesisWriter: JsonWriter[(PatientHypothesis, Boolean)] = - new JsonWriter[(PatientHypothesis, Boolean)] { - override def write(obj: (PatientHypothesis, Boolean)): JsValue = { - val patientHypothesis = obj._1 - val isRationaleRequired = obj._2 - JsObject( - "id" -> patientHypothesis.id.toJson, - "patientId" -> patientHypothesis.patientId.toJson, - "hypothesisId" -> patientHypothesis.hypothesisId.toJson, - "matchedTrials" -> patientHypothesis.matchedTrials.toJson, - "rationale" -> patientHypothesis.rationale.toJson, - "isRationaleRequired" -> isRationaleRequired.toJson - ) - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientissue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientissue.scala deleted file mode 100644 index 7d35bd1..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientissue.scala +++ /dev/null @@ -1,54 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User, UuidId} -import xyz.driver.pdsuidomain.entities._ - -object patientissue { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToPatientIssue(json: JsValue, orig: PatientIssue): PatientIssue = { - json.asJsObject.getFields("text", "archiveRequired") match { - case Seq(text, archiveRequired) => - orig.copy( - text = text.convertTo[String], - archiveRequired = archiveRequired.convertTo[Boolean] - ) - - case _ => deserializationError(s"Expected Json Object as partial PatientIssue, but got $json") - } - } - - def jsValueToPatientIssue(json: JsValue, patientId: UuidId[Patient], userId: StringId[User]): PatientIssue = { - json.asJsObject.getFields("text") match { - case Seq(text) => - PatientIssue( - id = LongId(0), - userId = userId, - patientId = patientId, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text.convertTo[String], - archiveRequired = false - ) - - case _ => deserializationError(s"Expected Json Object as PatientIssue, but got $json") - } - - } - - implicit val patientIssueWriter = new JsonWriter[PatientIssue] { - override def write(obj: PatientIssue) = JsObject( - "id" -> obj.id.toJson, - "text" -> obj.text.toJson, - "lastUpdate" -> obj.lastUpdate.toJson, - "userId" -> obj.userId.toJson, - "isDraft" -> obj.isDraft.toJson, - "archiveRequired" -> obj.archiveRequired.toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientlabel.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientlabel.scala deleted file mode 100644 index 3b52833..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/patientlabel.scala +++ /dev/null @@ -1,64 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuicommon.domain.FuzzyValue -import xyz.driver.pdsuidomain.entities._ - -object patientlabel { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToPatientLabel(json: JsValue, orig: PatientLabel): PatientLabel = json match { - case JsObject(fields) => - val primaryValue = fields - .get("primaryValue") - .map(_.convertTo[Option[FuzzyValue]]) - .getOrElse(orig.primaryValue) - - val verifiedPrimaryValue = fields - .get("verifiedPrimaryValue") - .map(_.convertTo[Option[FuzzyValue]]) - .getOrElse(orig.verifiedPrimaryValue) - - orig.copy( - primaryValue = primaryValue, - verifiedPrimaryValue = verifiedPrimaryValue - ) - - case _ => deserializationError(s"Expected Json Object as PatientLabel, but got $json") - } - - implicit val patientLabelWriter: JsonWriter[(PatientLabel, Boolean)] = new JsonWriter[(PatientLabel, Boolean)] { - override def write(obj: (PatientLabel, Boolean)): JsValue = { - val patientLabel = obj._1 - val isVerified = obj._2 - JsObject( - "id" -> patientLabel.id.toJson, - "labelId" -> patientLabel.labelId.toJson, - "primaryValue" -> patientLabel.primaryValue.toJson, - "verifiedPrimaryValue" -> patientLabel.verifiedPrimaryValue.toJson, - "score" -> patientLabel.score.toJson, - "isImplicitMatch" -> patientLabel.isImplicitMatch.toJson, - "isVisible" -> patientLabel.isVisible.toJson, - "isVerified" -> isVerified.toJson - ) - } - } - - implicit val patientLabelEvidenceWriter: JsonWriter[PatientLabelEvidenceView] = - new JsonWriter[PatientLabelEvidenceView] { - override def write(evidence: PatientLabelEvidenceView): JsValue = - JsObject( - "id" -> evidence.id.toJson, - "value" -> evidence.value.toJson, - "evidenceText" -> evidence.evidenceText.toJson, - "documentId" -> evidence.documentId.toJson, - "evidenceId" -> evidence.evidenceId.toJson, - "reportId" -> evidence.reportId.toJson, - "documentType" -> evidence.documentType.toJson, - "date" -> evidence.date.toJson, - "providerType" -> evidence.providerType.toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala deleted file mode 100644 index e378dbd..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/record.scala +++ /dev/null @@ -1,237 +0,0 @@ -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.MedicalRecord.Meta._ -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 duplicateMetaFormat: RootJsonFormat[Duplicate] = new RootJsonFormat[Duplicate] { - override def write(obj: Duplicate) = - JsObject( - "type" -> "duplicate".toJson, - "predicted" -> obj.predicted.toJson, - "startPage" -> obj.startPage.toJson, - "endPage" -> obj.endPage.toJson, - "startOriginalPage" -> obj.startOriginalPage.toJson, - "endOriginalPage" -> obj.endOriginalPage.toJson - ) - - override def read(json: JsValue): Duplicate = json match { - case JsObject(fields) => - val predicted = fields - .get("predicted") - .map(_.convertTo[Boolean]) - - val startPage = fields - .get("startPage") - .map(_.convertTo[Double]) - .getOrElse(deserializationError(s"Duplicate meta json object does not contain `startPage` field: $json")) - - val endPage = fields - .get("endPage") - .map(_.convertTo[Double]) - .getOrElse(deserializationError(s"Duplicate meta json object does not contain `endPage` field: $json")) - - val startOriginalPage = fields - .get("startOriginalPage") - .map(_.convertTo[Double]) - .getOrElse( - deserializationError(s"Duplicate meta json object does not contain `startOriginalPage` field: $json")) - - val endOriginalPage = fields - .get("endOriginalPage") - .map(_.convertTo[Double]) - - Duplicate( - predicted = predicted, - startPage = startPage, - endPage = endPage, - startOriginalPage = startOriginalPage, - endOriginalPage = endOriginalPage - ) - - case _ => deserializationError(s"Expected JsObject as Duplicate meta of medical record, but got $json") - } - } - - implicit val reorderMetaFormat: RootJsonFormat[Reorder] = new RootJsonFormat[Reorder] { - override def write(obj: Reorder) = - JsObject( - "type" -> "reorder".toJson, - "predicted" -> obj.predicted.toJson, - "items" -> obj.items.toJson - ) - - override def read(json: JsValue): Reorder = json match { - case JsObject(fields) => - val predicted = fields - .get("predicted") - .map(_.convertTo[Boolean]) - - val items = fields - .get("items") - .map(_.convertTo[Seq[Int]]) - .getOrElse(deserializationError(s"Reorder meta json object does not contain `items` field: $json")) - - Reorder( - predicted = predicted, - items = items - ) - - case _ => deserializationError(s"Expected JsObject as Reorder meta of medical record, but got $json") - } - } - - implicit val rotateMetaFormat: RootJsonFormat[Rotation] = new RootJsonFormat[Rotation] { - override def write(obj: Rotation) = - JsObject( - "type" -> "rotation".toJson, - "predicted" -> obj.predicted.toJson, - "items" -> obj.items.toJson - ) - - override def read(json: JsValue): Rotation = json match { - case JsObject(fields) => - val predicted = fields - .get("predicted") - .map(_.convertTo[Boolean]) - - val items = fields - .get("items") - .map(_.convertTo[Map[String, Int]]) - .getOrElse(deserializationError(s"Rotation meta json object does not contain `items` field: $json")) - - Rotation( - predicted = predicted, - items = items - ) - - case _ => deserializationError(s"Expected JsObject as Rotation meta of medical record, but got $json") - } - } - - implicit val recordMetaTypeFormat: GadtJsonFormat[MedicalRecord.Meta] = { - GadtJsonFormat.create[Meta]("type")({ case m => m.metaType }) { - case "duplicate" => duplicateMetaFormat - case "reorder" => reorderMetaFormat - case "rotation" => rotateMetaFormat - } - } - - 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 = fields - .get("meta") - .map(_.convertTo[Option[TextJson[List[Meta]]]]) - .getOrElse(orig.meta) - orig.copy(meta = meta) - - case _ => deserializationError(s"Expected Json Object as partial MedicalRecord, but got $json") - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordhistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordhistory.scala deleted file mode 100644 index bd14d43..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordhistory.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuidomain.entities._ - -object recordhistory { - import DefaultJsonProtocol._ - import common._ - import MedicalRecordHistory._ - - implicit val recordStateFormat = new EnumJsonFormat[State]( - "Clean" -> State.Clean, - "Organize" -> State.Organize, - "Review" -> State.Review, - "Flag" -> State.Flag - ) - - implicit val recordActionFormat = new EnumJsonFormat[Action]( - "Start" -> Action.Start, - "Submit" -> Action.Submit, - "Unassign" -> Action.Unassign, - "Resolve" -> Action.Resolve, - "Flag" -> Action.Flag, - "Archive" -> Action.Archive - ) - - implicit val recordHistoryFormat: RootJsonFormat[MedicalRecordHistory] = jsonFormat6(MedicalRecordHistory.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordissue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordissue.scala deleted file mode 100644 index 4ae04d0..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/recordissue.scala +++ /dev/null @@ -1,79 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuidomain.entities._ - -object recordissue { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToRecordIssue(json: JsValue, orig: MedicalRecordIssue): MedicalRecordIssue = json match { - case JsObject(fields) => - val text = fields - .get("text") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"MedicalRecordIssue json object does not contain `text` field: $json")) - - val archiveRequired = fields - .get("archiveRequired") - .map(_.convertTo[Boolean]) - .getOrElse( - deserializationError(s"MedicalRecordIssue json object does not contain `archiveRequired` field: $json")) - - val startPage = fields.get("startPage").map(_.convertTo[Double]) - val endPage = fields.get("endPage").map(_.convertTo[Double]) - - orig.copy( - text = text, - archiveRequired = archiveRequired, - startPage = startPage, - endPage = endPage - ) - - case _ => deserializationError(s"Expected Json Object as partial MedicalRecordIssue, but got $json") - - } - - def jsValueToRecordIssue(json: JsValue, - recordId: LongId[MedicalRecord], - userId: StringId[User]): MedicalRecordIssue = json match { - case JsObject(fields) => - val text = fields - .get("text") - .map(_.convertTo[String]) - .getOrElse(deserializationError(s"MedicalRecordIssue json object does not contain `text` field: $json")) - - val startPage = fields.get("startPage").map(_.convertTo[Double]) - val endPage = fields.get("endPage").map(_.convertTo[Double]) - MedicalRecordIssue( - id = LongId(0), - userId = userId, - recordId = recordId, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text, - archiveRequired = false, - startPage = startPage, - endPage = endPage - ) - - case _ => deserializationError(s"Expected Json Object as MedicalRecordIssue, but got $json") - } - - implicit val recordIssueWriter = new JsonWriter[MedicalRecordIssue] { - override def write(obj: MedicalRecordIssue) = JsObject( - "id" -> obj.id.toJson, - "startPage" -> obj.startPage.toJson, - "endPage" -> obj.endPage.toJson, - "text" -> obj.text.toJson, - "lastUpdate" -> obj.lastUpdate.toJson, - "userId" -> obj.userId.toJson, - "isDraft" -> obj.isDraft.toJson, - "archiveRequired" -> obj.archiveRequired.toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/studydesign.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/studydesign.scala deleted file mode 100644 index e801666..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/studydesign.scala +++ /dev/null @@ -1,12 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.pdsuidomain.entities._ - -object studydesign { - import DefaultJsonProtocol._ - import common._ - - implicit val studyDesignFormat: RootJsonFormat[StudyDesign] = jsonFormat2(StudyDesign.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trial.scala deleted file mode 100644 index c1751bf..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trial.scala +++ /dev/null @@ -1,90 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.{ZoneId, ZonedDateTime} - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuicommon.domain.{LongId, UuidId} -import xyz.driver.pdsuidomain.entities._ - -object trial { - import DefaultJsonProtocol._ - import common._ - import Trial._ - - implicit val trialStatusFormat = new EnumJsonFormat[Status]( - "New" -> Status.New, - "ReviewSummary" -> Status.ReviewSummary, - "Summarized" -> Status.Summarized, - "PendingUpdate" -> Status.PendingUpdate, - "Update" -> Status.Update, - "ReviewCriteria" -> Status.ReviewCriteria, - "Done" -> Status.Done, - "Flagged" -> Status.Flagged, - "Archived" -> Status.Archived - ) - - implicit val conditionFormat = new EnumJsonFormat[Condition]( - "Breast" -> Condition.Breast, - "Lung" -> Condition.Lung, - "Prostate" -> Condition.Prostate - ) - - implicit val trialWriter: JsonWriter[Trial] = new JsonWriter[Trial] { - override def write(obj: Trial) = - JsObject( - "id" -> obj.id.toJson, - "externalid" -> obj.externalId.toJson, - "lastUpdate" -> ZonedDateTime.of(obj.lastUpdate, ZoneId.of("Z")).toJson, - "status" -> obj.status.toJson, - "assignee" -> obj.assignee.toJson, - "previousStatus" -> obj.previousStatus.toJson, - "previousAssignee" -> obj.previousAssignee.toJson, - "lastActiveUser" -> obj.lastActiveUserId.toJson, - "condition" -> obj.condition.toJson, - "phase" -> obj.phase.toJson, - "hypothesisId" -> obj.hypothesisId.toJson, - "studyDesignId" -> obj.studyDesignId.toJson, - "originalStudyDesignId" -> obj.originalStudyDesign.toJson, - "isPartner" -> obj.isPartner.toJson, - "overview" -> obj.overview.toJson, - "overviewTemplate" -> obj.overviewTemplate.toJson, - "isUpdated" -> obj.isUpdated.toJson, - "title" -> obj.title.toJson, - "originalTitle" -> obj.originalTitle.toJson - ) - } - - def applyUpdateToTrial(json: JsValue, orig: Trial): Trial = json match { - case JsObject(fields) => - val hypothesisId = fields - .get("hypothesisId") - .map(_.convertTo[Option[UuidId[Hypothesis]]]) - .getOrElse(orig.hypothesisId) - - val studyDesignId = fields - .get("studyDesignId") - .map(_.convertTo[Option[LongId[StudyDesign]]]) - .getOrElse(orig.studyDesignId) - - val overview = fields - .get("overview") - .map(_.convertTo[Option[String]]) - .getOrElse(orig.overview) - - val title = fields - .get("title") - .map(_.convertTo[Option[String]].getOrElse("")) - .getOrElse(orig.title) - - orig.copy( - hypothesisId = hypothesisId, - studyDesignId = studyDesignId, - overview = overview, - title = title - ) - - case _ => deserializationError(s"Expected Json Object as Trial, but got $json") - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialhistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialhistory.scala deleted file mode 100644 index 844c5f5..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialhistory.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import xyz.driver.core.json.EnumJsonFormat -import xyz.driver.pdsuidomain.entities._ - -object trialhistory { - import DefaultJsonProtocol._ - import common._ - import TrialHistory._ - - implicit val trialStateFormat = new EnumJsonFormat[State]( - "Summarize" -> State.Summarize, - "Criteriarize" -> State.Criteriarize, - "Review" -> State.Review, - "Flag" -> State.Flag - ) - - implicit val trialActionFormat = new EnumJsonFormat[Action]( - "Start" -> Action.Start, - "Submit" -> Action.Submit, - "Unassign" -> Action.Unassign, - "Resolve" -> Action.Resolve, - "Flag" -> Action.Flag, - "Archive" -> Action.Archive - ) - - implicit val trialHistoryFormat: RootJsonFormat[TrialHistory] = jsonFormat6(TrialHistory.apply) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialissue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialissue.scala deleted file mode 100644 index 572f44d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/trialissue.scala +++ /dev/null @@ -1,60 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuidomain.entities._ - -object trialissue { - import DefaultJsonProtocol._ - import common._ - - def applyUpdateToTrialIssue(json: JsValue, orig: TrialIssue): TrialIssue = { - json.asJsObject.getFields("text", "evidence", "archiveRequired", "meta") match { - case Seq(text, evidence, archiveRequired, meta) => - orig.copy( - text = text.convertTo[String], - evidence = evidence.convertTo[String], - archiveRequired = archiveRequired.convertTo[Boolean], - meta = meta.convertTo[String] - ) - - case _ => deserializationError(s"Expected Json Object as partial TrialIssue, but got $json") - } - } - - def jsValueToTrialIssue(json: JsValue, trialId: StringId[Trial], userId: StringId[User]): TrialIssue = { - json.asJsObject.getFields("text", "evidence", "meta") match { - case Seq(text, evidence, meta) => - TrialIssue( - id = LongId(0), - userId = userId, - trialId = trialId, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text.convertTo[String], - evidence = evidence.convertTo[String], - archiveRequired = false, - meta = meta.convertTo[String] - ) - - case _ => deserializationError(s"Expected Json Object as TrialIssue, but got $json") - } - - } - - implicit val trialIssueWriter = new JsonWriter[TrialIssue] { - override def write(obj: TrialIssue) = JsObject( - "id" -> obj.id.toJson, - "text" -> obj.text.toJson, - "lastUpdate" -> obj.lastUpdate.toJson, - "userId" -> obj.userId.toJson, - "isDraft" -> obj.isDraft.toJson, - "evidence" -> obj.evidence.toJson, - "archiveRequired" -> obj.archiveRequired.toJson, - "meta" -> obj.meta.toJson - ) - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign/ApiStudyDesign.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign/ApiStudyDesign.scala deleted file mode 100644 index 1e9a226..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/studydesign/ApiStudyDesign.scala +++ /dev/null @@ -1,24 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.studydesign - -import xyz.driver.pdsuidomain.entities.StudyDesign -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuicommon.domain.LongId - -final case class ApiStudyDesign(id: Long, name: String) { - - def toDomain = StudyDesign(id = LongId[StudyDesign](id), name = name) -} - -object ApiStudyDesign { - - implicit val format: Format[ApiStudyDesign] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "name").format[String] - )(ApiStudyDesign.apply, unlift(ApiStudyDesign.unapply)) - - def fromDomain(studyDesign: StudyDesign) = ApiStudyDesign( - id = studyDesign.id.id, - name = studyDesign.name - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiPartialTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiPartialTrial.scala deleted file mode 100644 index f89f181..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiPartialTrial.scala +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.trial - -import java.util.UUID - -import xyz.driver.pdsuicommon.domain.{LongId, UuidId} -import xyz.driver.pdsuidomain.entities.Trial -import org.davidbild.tristate.Tristate -import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ApiPartialTrial(hypothesisId: Tristate[UUID], - studyDesignId: Tristate[Long], - overview: Tristate[String], - title: Tristate[String]) { - - def applyTo(orig: Trial): Trial = { - orig.copy( - hypothesisId = hypothesisId.map(UuidId(_)).cata(Some(_), None, orig.hypothesisId), - studyDesignId = studyDesignId.map(LongId(_)).cata(Some(_), None, orig.studyDesignId), - overview = overview.cata(Some(_), None, orig.overview), - title = title.cata(Some(_).getOrElse(""), "", orig.title) - ) - } -} - -object ApiPartialTrial { - - private val reads: Reads[ApiPartialTrial] = ( - (JsPath \ "hypothesisId").readTristate[UUID] and - (JsPath \ "studyDesignId").readTristate[Long] and - (JsPath \ "overview").readTristate[String] and - (JsPath \ "title").readTristate[String] - )(ApiPartialTrial.apply _) - - private val writes: Writes[ApiPartialTrial] = ( - (JsPath \ "hypothesisId").writeTristate[UUID] and - (JsPath \ "studyDesignId").writeTristate[Long] and - (JsPath \ "overview").writeTristate[String] and - (JsPath \ "title").writeTristate[String] - )(unlift(ApiPartialTrial.unapply)) - - implicit val format: Format[ApiPartialTrial] = Format(reads, writes) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiTrial.scala deleted file mode 100644 index 1b4ac64..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiTrial.scala +++ /dev/null @@ -1,104 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.trial - -import java.time.{ZoneId, ZonedDateTime} -import java.util.UUID -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} - -import xyz.driver.pdsuidomain.entities.Trial -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -final case class ApiTrial(id: String, - externalId: UUID, - lastUpdate: ZonedDateTime, - status: String, - assignee: Option[String], - previousStatus: Option[String], - previousAssignee: Option[String], - lastActiveUser: Option[String], - condition: String, - phase: String, - hypothesisId: Option[UUID], - studyDesignId: Option[Long], - originalStudyDesign: Option[String], - isPartner: Boolean, - overview: Option[String], - overviewTemplate: String, - isUpdated: Boolean, - title: String, - originalTitle: String) { - - def toDomain = Trial( - id = StringId(this.id), - externalId = UuidId(this.externalId), - status = TrialStatus.statusFromString(this.status), - assignee = this.assignee.map(id => StringId(id)), - previousStatus = this.previousStatus.map(s => TrialStatus.statusFromString(s)), - previousAssignee = this.previousAssignee.map(id => StringId(id)), - lastActiveUserId = this.lastActiveUser.map(id => StringId(id)), - lastUpdate = this.lastUpdate.toLocalDateTime, - condition = Trial.Condition - .fromString(this.condition) - .getOrElse( - throw new NoSuchElementException(s"unknown condition ${this.condition}") - ), - phase = this.phase, - hypothesisId = this.hypothesisId.map(id => UuidId(id)), - studyDesignId = this.studyDesignId.map(id => LongId(id)), - originalStudyDesign = this.originalStudyDesign, - isPartner = this.isPartner, - overview = this.overview, - overviewTemplate = this.overviewTemplate, - isUpdated = this.isUpdated, - title = this.title, - originalTitle = this.originalTitle - ) - -} - -object ApiTrial { - - implicit val format: Format[ApiTrial] = ( - (JsPath \ "id").format[String] and - (JsPath \ "externalid").format[UUID] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "status").format[String] and - (JsPath \ "assignee").formatNullable[String] and - (JsPath \ "previousStatus").formatNullable[String] and - (JsPath \ "previousAssignee").formatNullable[String] and - (JsPath \ "lastActiveUser").formatNullable[String] and - (JsPath \ "condition").format[String] and - (JsPath \ "phase").format[String] and - (JsPath \ "hypothesisId").formatNullable[UUID] and - (JsPath \ "studyDesignId").formatNullable[Long] and - (JsPath \ "originalStudyDesignId").formatNullable[String] and - (JsPath \ "isPartner").format[Boolean] and - (JsPath \ "overview").formatNullable[String] and - (JsPath \ "overviewTemplate").format[String] and - (JsPath \ "isUpdated").format[Boolean] and - (JsPath \ "title").format[String] and - (JsPath \ "originalTitle").format[String] - )(ApiTrial.apply, unlift(ApiTrial.unapply)) - - def fromDomain(trial: Trial): ApiTrial = ApiTrial( - id = trial.id.id, - externalId = trial.externalId.id, - status = TrialStatus.statusToString(trial.status), - assignee = trial.assignee.map(_.id), - previousStatus = trial.previousStatus.map(TrialStatus.statusToString), - previousAssignee = trial.previousAssignee.map(_.id), - lastActiveUser = trial.lastActiveUserId.map(_.id), - lastUpdate = ZonedDateTime.of(trial.lastUpdate, ZoneId.of("Z")), - condition = trial.condition.toString, - phase = trial.phase, - hypothesisId = trial.hypothesisId.map(_.id), - studyDesignId = trial.studyDesignId.map(_.id), - originalStudyDesign = trial.originalStudyDesign, - isPartner = trial.isPartner, - overview = trial.overview, - overviewTemplate = trial.overviewTemplate, - isUpdated = trial.isUpdated, - title = trial.title, - originalTitle = trial.originalTitle - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/TrialStatus.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/TrialStatus.scala deleted file mode 100644 index a5b557b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/TrialStatus.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.trial - -import xyz.driver.pdsuidomain.entities.Trial.Status - -object TrialStatus { - - val statusFromString: PartialFunction[String, Status] = { - case "New" => Status.New - case "ReviewSummary" => Status.ReviewSummary - case "Summarized" => Status.Summarized - case "PendingUpdate" => Status.PendingUpdate - case "Update" => Status.Update - case "ReviewCriteria" => Status.ReviewCriteria - case "Done" => Status.Done - case "Flagged" => Status.Flagged - case "Archived" => Status.Archived - } - - def statusToString(x: Status): String = x match { - case Status.New => "New" - case Status.ReviewSummary => "ReviewSummary" - case Status.Summarized => "Summarized" - case Status.PendingUpdate => "PendingUpdate" - case Status.Update => "Update" - case Status.ReviewCriteria => "ReviewCriteria" - case Status.Done => "Done" - case Status.Flagged => "Flagged" - case Status.Archived => "Archived" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialhistory/ApiTrialHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialhistory/ApiTrialHistory.scala deleted file mode 100644 index 38faeb8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialhistory/ApiTrialHistory.scala +++ /dev/null @@ -1,26 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.trialhistory - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.json.{Format, Json} -import xyz.driver.pdsuidomain.entities.TrialHistory - -final case class ApiTrialHistory(id: Long, - executor: String, - trialId: String, - state: String, - action: String, - created: ZonedDateTime) - -object ApiTrialHistory { - implicit val format: Format[ApiTrialHistory] = Json.format[ApiTrialHistory] - - def fromDomain(x: TrialHistory) = ApiTrialHistory( - id = x.id.id, - executor = x.executor.id, - trialId = x.trialId.id, - state = TrialHistory.State.stateToString(x.state), - action = TrialHistory.Action.actionToString(x.action), - created = ZonedDateTime.of(x.created, ZoneId.of("Z")) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiPartialTrialIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiPartialTrialIssue.scala deleted file mode 100644 index fc31371..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiPartialTrialIssue.scala +++ /dev/null @@ -1,40 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.trialissue - -import java.time.LocalDateTime - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain.{LongId, StringId, User} -import xyz.driver.pdsuidomain.entities.{Trial, TrialIssue} - -final case class ApiPartialTrialIssue(text: String, evidence: String, archiveRequired: Boolean, meta: String) { - def applyTo(x: TrialIssue): TrialIssue = x.copy( - text = text, - evidence = evidence, - archiveRequired = archiveRequired, - meta = meta - ) - - def toDomain(userId: StringId[User], trialId: StringId[Trial]) = TrialIssue( - id = LongId(0), - userId = userId, - trialId = trialId, - lastUpdate = LocalDateTime.MIN, - isDraft = true, - text = text, - evidence = evidence, - archiveRequired = false, - meta = meta - ) -} - -object ApiPartialTrialIssue { - implicit val format: Format[ApiPartialTrialIssue] = ( - (JsPath \ "text").format[String] and - (JsPath \ "evidence").format[String] and - (JsPath \ "archiveRequired").format[Boolean] and - (JsPath \ "meta").format[String](Format(Reads { x => - JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) - )(ApiPartialTrialIssue.apply, unlift(ApiPartialTrialIssue.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiTrialIssue.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiTrialIssue.scala deleted file mode 100644 index c9475c6..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trialissue/ApiTrialIssue.scala +++ /dev/null @@ -1,60 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.trialissue - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities.TrialIssue - -final case class ApiTrialIssue(id: Long, - trialId: String, - text: String, - lastUpdate: ZonedDateTime, - userId: String, - isDraft: Boolean, - evidence: String, - archiveRequired: Boolean, - meta: String) { - - def toDomain = TrialIssue( - id = LongId(this.id), - trialId = StringId(this.trialId), - text = this.text, - userId = StringId(this.userId), - lastUpdate = this.lastUpdate.toLocalDateTime, - isDraft = this.isDraft, - evidence = this.evidence, - archiveRequired = this.archiveRequired, - meta = this.meta - ) - -} - -object ApiTrialIssue { - implicit val format: Format[ApiTrialIssue] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "trialId").format[String] and - (JsPath \ "text").format[String] and - (JsPath \ "lastUpdate").format[ZonedDateTime] and - (JsPath \ "userId").format[String] and - (JsPath \ "isDraft").format[Boolean] and - (JsPath \ "evidence").format[String] and - (JsPath \ "archiveRequired").format[Boolean] and - (JsPath \ "meta").format[String](Format(Reads { x => - JsSuccess(Json.stringify(x)) - }, Writes[String](Json.parse))) - )(ApiTrialIssue.apply, unlift(ApiTrialIssue.unapply)) - - def fromDomain(x: TrialIssue) = ApiTrialIssue( - id = x.id.id, - trialId = x.trialId.id, - text = x.text, - lastUpdate = ZonedDateTime.of(x.lastUpdate, ZoneId.of("Z")), - userId = x.userId.id, - isDraft = x.isDraft, - evidence = x.evidence, - archiveRequired = x.archiveRequired, - meta = x.meta - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala deleted file mode 100644 index cf20d32..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala +++ /dev/null @@ -1,76 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.user - -import java.util.UUID - -import xyz.driver.pdsuicommon.domain._ -import play.api.data.validation._ -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -import scala.collection._ -import scala.util.Try -import xyz.driver.pdsuicommon.json.JsonValidationException -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import xyz.driver.pdsuicommon.validation.{AdditionalConstraints, JsonValidationErrors} - -final case class ApiPartialUser(email: Option[String], name: Option[String], roles: Option[Seq[String]]) { - - def applyTo(orig: User): Try[User] = Try { - val validation = Map( - JsPath \ "name" -> AdditionalConstraints.optionNonEmptyConstraint(name) - ) - - val validationErrors: JsonValidationErrors = validation.collect({ - case (fieldName, e: Invalid) => (fieldName, e.errors) - })(breakOut) - - if (validationErrors.isEmpty) { - orig.copy(name = name.get) - } else { - throw new JsonValidationException(validationErrors) - } - } - - def toDomain(id: StringId[User] = StringId(UUID.randomUUID().toString)): Try[User] = Try { - val validation = Map( - JsPath \ "email" -> AdditionalConstraints.optionNonEmptyConstraint(email), - JsPath \ "name" -> AdditionalConstraints.optionNonEmptyConstraint(name), - JsPath \ "roles" -> AdditionalConstraints.optionNonEmptyConstraint(roles) - ) - - val validationErrors: JsonValidationErrors = validation.collect({ - case (fieldName, e: Invalid) => (fieldName, e.errors) - })(breakOut) - - if (validationErrors.isEmpty) { - val userEmail = email.map(x => Email(x.toLowerCase)).get - User( - id = id, - email = userEmail, - name = name.get, - roles = roles.toSeq.flatMap(_.map(UserRole.roleFromString)).toSet, - latestActivity = None, - deleted = None - ) - } else { - throw new JsonValidationException(validationErrors) - } - } -} - -object ApiPartialUser { - - implicit val format: Format[ApiPartialUser] = ( - (JsPath \ "email").formatNullable[String](Format(Reads.email, Writes.StringWrites)) and - (JsPath \ "name").formatNullable[String]( - Format( - Reads.filterNot[String](ValidationError("Username is too long (max length is 255 chars)", 255))( - _.length > 255), - Writes.StringWrites - )) and - (JsPath \ "roles").formatNullable[Seq[String]]( - Format(seqJsonFormat[String].filter(ValidationError("unknown roles"))( - _.forall(UserRole.roleFromString.isDefinedAt)), - Writes.of[Seq[String]])) - )(ApiPartialUser.apply, unlift(ApiPartialUser.unapply)) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiUser.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiUser.scala deleted file mode 100644 index c21edd1..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiUser.scala +++ /dev/null @@ -1,39 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.user - -import java.time.{ZoneId, ZonedDateTime} - -import xyz.driver.pdsuicommon.domain.User -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import play.api.data.validation.ValidationError -import play.api.libs.functional.syntax._ -import play.api.libs.json._ - -import scala.collection.Seq - -final case class ApiUser(id: String, - email: String, - name: String, - roles: Seq[String], - latestActivity: Option[ZonedDateTime]) - -object ApiUser { - - implicit val format: Format[ApiUser] = ( - (JsPath \ "id").format[String] and - (JsPath \ "email").format[String](Reads.email) and - (JsPath \ "name").format[String] and - (JsPath \ "roles").format( - Format( - seqJsonFormat[String].filter(ValidationError("unknown role"))(_.forall(UserRole.roleFromString.isDefinedAt)), - Writes.of[Seq[String]])) and - (JsPath \ "latestActivity").formatNullable[ZonedDateTime] - )(ApiUser.apply, unlift(ApiUser.unapply)) - - def fromDomain(user: User) = ApiUser( - user.id.id, - user.email.value, - user.name, - user.roles.map(UserRole.roleToString).toSeq, - user.latestActivity.map(ZonedDateTime.of(_, ZoneId.of("Z"))) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/UserRole.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/UserRole.scala deleted file mode 100644 index 412a969..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/UserRole.scala +++ /dev/null @@ -1,37 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.user - -import xyz.driver.pdsuicommon.domain.User.Role - -object UserRole { - - val roleFromString: PartialFunction[String, Role] = { - case "Cleaner" => Role.RecordCleaner - case "Organizer" => Role.RecordOrganizer - case "Extractor" => Role.DocumentExtractor - case "RecordAdmin" => Role.RecordAdmin - case "TrialSummarizer" => Role.TrialSummarizer - case "CriteriaCurator" => Role.CriteriaCurator - case "TrialAdmin" => Role.TrialAdmin - case "EligibilityVerifier" => Role.EligibilityVerifier - case "TreatmentMatchingAdmin" => Role.TreatmentMatchingAdmin - case "RoutesCurator" => Role.RoutesCurator - case "SystemUser" => Role.SystemUser - case "ResearchOncologist" => Role.ResearchOncologist - // No Mixed at this time - } - - def roleToString(x: Role): String = x match { - case Role.RecordCleaner => "Cleaner" - case Role.RecordOrganizer => "Organizer" - case Role.DocumentExtractor => "Extractor" - case Role.RecordAdmin => "RecordAdmin" - case Role.TrialSummarizer => "TrialSummarizer" - case Role.CriteriaCurator => "CriteriaCurator" - case Role.TrialAdmin => "TrialAdmin" - case Role.EligibilityVerifier => "EligibilityVerifier" - case Role.TreatmentMatchingAdmin => "TreatmentMatchingAdmin" - case Role.RoutesCurator => "RoutesCurator" - case Role.SystemUser => "SystemUser" - case Role.ResearchOncologist => "ResearchOncologist" - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/userhistory/ApiUserHistory.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/userhistory/ApiUserHistory.scala deleted file mode 100644 index 127337f..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/userhistory/ApiUserHistory.scala +++ /dev/null @@ -1,43 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.userhistory - -import java.time.{ZoneId, ZonedDateTime} - -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, JsPath} -import xyz.driver.pdsuidomain.entities.UserHistory - -final case class ApiUserHistory(id: Long, - executor: String, - recordId: Option[Long], - documentId: Option[Long], - trialId: Option[String], - patientId: Option[String], - state: String, - action: String, - created: ZonedDateTime) - -object ApiUserHistory { - implicit val format: Format[ApiUserHistory] = ( - (JsPath \ "id").format[Long] and - (JsPath \ "executor").format[String] and - (JsPath \ "recordId").formatNullable[Long] and - (JsPath \ "documentId").formatNullable[Long] and - (JsPath \ "trialId").formatNullable[String] and - (JsPath \ "patientId").formatNullable[String] and - (JsPath \ "state").format[String] and - (JsPath \ "action").format[String] and - (JsPath \ "created").format[ZonedDateTime] - )(ApiUserHistory.apply, unlift(ApiUserHistory.unapply)) - - def fromDomain(x: UserHistory) = ApiUserHistory( - id = x.id.id, - executor = x.executor.id, - recordId = x.recordId.map(_.id), - documentId = x.documentId.map(_.id), - trialId = x.trialId.map(_.id), - patientId = x.patientId.map(_.id.toString), - state = UserHistory.State.stateToString(x.state), - action = UserHistory.Action.actionToString(x.action), - created = ZonedDateTime.of(x.created, ZoneId.of("Z")) - ) -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala deleted file mode 100644 index 1f907c8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala +++ /dev/null @@ -1,124 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.Arm - -import scala.concurrent.Future - -object ArmService { - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - trait DefaultNotFoundError { - def userMessage: String = "Arm not found" - } - - sealed trait GetByIdReply - object GetByIdReply { - - final case class Entity(x: Arm) extends GetByIdReply - - type Error = GetByIdReply with DomainError - - case object NotFoundError extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) - extends GetByIdReply with DomainError - } - - sealed trait GetListReply - object GetListReply { - type Error = GetListReply with DomainError - - final case class EntityList(xs: Seq[Arm], totalFound: Int) extends GetListReply - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait UpdateReply - object UpdateReply { - - final case class Updated(updated: Arm) extends UpdateReply - - type Error = UpdateReply with DomainError - - case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - - final case class AlreadyExistsError(x: Arm) extends UpdateReply with DomainError { - val userMessage = s"The arm with such name of trial already exists." - } - - implicit def toPhiString(reply: UpdateReply): PhiString = reply match { - case Updated(x) => phi"Updated($x)" - case x: Error => DomainError.toPhiString(x) - } - } - - sealed trait CreateReply - object CreateReply { - final case class Created(x: Arm) extends CreateReply - - type Error = CreateReply with DomainError - - case object AuthorizationError - extends CreateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends CreateReply with DomainError - - final case class AlreadyExistsError(x: Arm) extends CreateReply with DomainError { - val userMessage = s"The arm with this name of trial already exists." - } - - implicit def toPhiString(reply: CreateReply): PhiString = reply match { - case Created(x) => phi"Created($x)" - case x: Error => DomainError.toPhiString(x) - } - } - - sealed trait DeleteReply - object DeleteReply { - case object Deleted extends DeleteReply - - type Error = DeleteReply with DomainError - - case object NotFoundError extends DeleteReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends DeleteReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends DeleteReply with DomainError - } -} - -trait ArmService { - - import ArmService._ - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def getById(armId: LongId[Arm])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def create(draftArm: Arm)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] - - def update(origArm: Arm, draftArm: Arm)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def delete(id: LongId[Arm])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/CriterionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/CriterionService.scala deleted file mode 100644 index fd9268b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/CriterionService.scala +++ /dev/null @@ -1,120 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities._ - -import scala.concurrent.Future - -object CriterionService { - - trait DefaultNotFoundError { - def userMessage: String = "Criterion not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - final case class RichCriterion(criterion: Criterion, armIds: Seq[LongId[Arm]], labels: Seq[CriterionLabel]) - object RichCriterion { - implicit def toPhiString(x: RichCriterion): PhiString = { - import x._ - phi"RichCriterion(criterion=$criterion, armIds=$armIds, labels=$labels)" - } - } - - sealed trait CreateReply - object CreateReply { - type Error = CreateReply with DomainError - - final case class Created(x: RichCriterion) extends CreateReply - - case object AuthorizationError - extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String) extends CreateReply with DomainError - } - - sealed trait GetByIdReply - object GetByIdReply { - final case class Entity(x: RichCriterion) extends GetByIdReply - - type Error = GetByIdReply with DomainError - - case object NotFoundError extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) - extends GetByIdReply with DomainError - - implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { - case x: DomainError => phi"GetByIdReply.Error($x)" - case Entity(x) => phi"GetByIdReply.Entity($x)" - } - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[RichCriterion], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListReply - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - - final case class Updated(updated: RichCriterion) extends UpdateReply - - case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - } - - sealed trait DeleteReply - object DeleteReply { - case object Deleted extends DeleteReply - - type Error = DeleteReply with DomainError - - case object NotFoundError extends DeleteReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends DeleteReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends DeleteReply with DomainError - } -} - -trait CriterionService { - - import CriterionService._ - - def create(draftRichCriterion: RichCriterion)( - implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] - - def getById(id: LongId[Criterion])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def update(origRichCriterion: RichCriterion, draftRichCriterion: RichCriterion)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def delete(id: LongId[Criterion])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentHistoryService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentHistoryService.scala deleted file mode 100644 index 2d9679d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentHistoryService.scala +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.{Document, DocumentHistory} - -import scala.concurrent.Future - -object DocumentHistoryService { - - trait DefaultNotFoundError { - def userMessage: String = "Document history not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[DocumentHistory], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListReply - - final case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - -} - -trait DocumentHistoryService { - - import DocumentHistoryService._ - - def getListByDocumentId(id: LongId[Document], - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentIssueService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentIssueService.scala deleted file mode 100644 index 4315352..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentIssueService.scala +++ /dev/null @@ -1,93 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.{Document, DocumentIssue} - -import scala.concurrent.Future - -object DocumentIssueService { - - trait DefaultNotFoundError { - def userMessage: String = "DocumentIssue not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait CreateReply - object CreateReply { - type Error = CreateReply with DomainError - final case class Created(x: DocumentIssue) extends CreateReply - case object AuthorizationError - extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends CreateReply with DomainError - } - - sealed trait GetByIdReply - object GetByIdReply { - type Error = GetByIdReply with DomainError - final case class Entity(x: DocumentIssue) extends GetByIdReply - case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait GetListByDocumentIdReply - object GetListByDocumentIdReply { - type Error = GetListByDocumentIdReply with DomainError - final case class EntityList(xs: Seq[DocumentIssue], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListByDocumentIdReply - case object NotFoundError extends GetListByDocumentIdReply with DomainError.NotFoundError with DefaultNotFoundError - case object AuthorizationError - extends GetListByDocumentIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - final case class Updated(updated: DocumentIssue) extends UpdateReply - case object AuthorizationError - extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - } - - sealed trait DeleteReply - object DeleteReply { - type Error = DeleteReply with DomainError - case object Deleted extends DeleteReply - case object AuthorizationError - extends DeleteReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case object NotFoundError extends DeleteReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends DeleteReply with DomainError - } -} - -trait DocumentIssueService { - - import DocumentIssueService._ - - def create(draft: DocumentIssue)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] - - def getById(documentId: LongId[Document], id: LongId[DocumentIssue])( - implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getListByDocumentId(documentId: LongId[Document], - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListByDocumentIdReply] - - def update(orig: DocumentIssue, draft: DocumentIssue)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def delete(documentId: LongId[Document], id: LongId[DocumentIssue])( - implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala deleted file mode 100644 index 9338a59..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala +++ /dev/null @@ -1,136 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities._ - -import scala.concurrent.Future - -object DocumentService { - - trait DefaultNotFoundError { - def userMessage: String = "Can not find the document" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait GetByIdReply - object GetByIdReply { - final case class Entity(x: Document) extends GetByIdReply - - type Error = GetByIdReply with DomainError - - case object NotFoundError extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) - extends GetByIdReply with DomainError - - implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { - case x: DomainError => phi"GetByIdReply.Error($x)" - case Entity(x) => phi"GetByIdReply.Entity($x)" - } - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[Document], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListReply - - type Error = GetListReply with DomainError - - case object AuthorizationError - extends GetListReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends GetListReply with DomainError - } - - sealed trait CreateReply - object CreateReply { - final case class Created(x: Document) extends CreateReply - - type Error = CreateReply with DomainError - - case object NotFoundError extends CreateReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends CreateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends CreateReply with DomainError - } - - sealed trait UpdateReply - object UpdateReply { - final case class Updated(updated: Document) extends UpdateReply - - type Error = UpdateReply with DomainError - - case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - - implicit def toPhiString(reply: UpdateReply): PhiString = reply match { - case Updated(x) => phi"Updated($x)" - case x: Error => DomainError.toPhiString(x) - } - } - - sealed trait DeleteReply - object DeleteReply { - case object Deleted extends DeleteReply - - type Error = DeleteReply with DomainError - - case object NotFoundError extends DeleteReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends DeleteReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends DeleteReply with DomainError - } -} - -trait DocumentService { - - import DocumentService._ - - def getById(id: LongId[Document])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def create(draftDocument: Document)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] - - def update(orig: Document, draft: Document)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def delete(id: LongId[Document])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] - - def start(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def submit(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def restart(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def flag(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def resolve(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def unassign(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def archive(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentTypeService.scala deleted file mode 100644 index 0f1bf76..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentTypeService.scala +++ /dev/null @@ -1,25 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.Sorting -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.DocumentType -import xyz.driver.pdsuidomain.services.DocumentTypeService.GetListReply - -import scala.concurrent.Future - -object DocumentTypeService { - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[DocumentType], totalFound: Int) extends GetListReply - case object AuthorizationError extends GetListReply with DomainError.AuthorizationError { - def userMessage: String = "Access denied" - } - } -} - -trait DocumentTypeService { - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ExtractedDataService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ExtractedDataService.scala deleted file mode 100644 index 9bcd921..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/ExtractedDataService.scala +++ /dev/null @@ -1,123 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.{LongId, UuidId} -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.entities.export.patient.ExportPatientWithLabels - -import scala.concurrent.Future - -object ExtractedDataService { - - trait DefaultNotFoundError { - def userMessage: String = "Extracted data hasn't been found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - final case class RichExtractedData(extractedData: ExtractedData, labels: List[ExtractedDataLabel]) - - object RichExtractedData { - implicit def toPhiString(x: RichExtractedData): PhiString = { - import x._ - phi"RichExtractedData(extractedData=$extractedData, labels=$labels)" - } - } - - sealed trait GetByIdReply - object GetByIdReply { - type Error = GetByIdReply with DomainError - final case class Entity(x: RichExtractedData) extends GetByIdReply - - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - case object NotFoundError extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError - - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[RichExtractedData], totalFound: Int) extends GetListReply - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait GetPatientLabelsReply - object GetPatientLabelsReply { - type Error = GetPatientLabelsReply with DomainError - - final case class Entity(x: ExportPatientWithLabels) extends GetPatientLabelsReply - - case object NotFoundError extends GetPatientLabelsReply with DomainError.NotFoundError { - def userMessage: String = "Patient not found" - } - } - - sealed trait CreateReply - object CreateReply { - type Error = CreateReply with DomainError - final case class Created(x: RichExtractedData) extends CreateReply - - case object AuthorizationError - extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String) extends CreateReply with DomainError - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - final case class Updated(updated: RichExtractedData) extends UpdateReply - - case object AuthorizationError - extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError - - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - } - - sealed trait DeleteReply - object DeleteReply { - type Error = DeleteReply with DomainError - case object Deleted extends DeleteReply - - case object AuthorizationError - extends DeleteReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - case object NotFoundError extends DeleteReply with DefaultNotFoundError with DomainError.NotFoundError - - final case class CommonError(userMessage: String) extends DeleteReply with DomainError - } -} - -trait ExtractedDataService { - - import ExtractedDataService._ - - def getById(id: LongId[ExtractedData])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getPatientLabels(id: UuidId[Patient])( - implicit requestContext: AuthenticatedRequestContext): Future[GetPatientLabelsReply] - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def create(draftRichExtractedData: RichExtractedData)( - implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] - - def update(origRichExtractedData: RichExtractedData, draftRichExtractedData: RichExtractedData)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def delete(id: LongId[ExtractedData])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/HypothesisService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/HypothesisService.scala deleted file mode 100644 index 52cd6c8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/HypothesisService.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.Sorting -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.Hypothesis - -import scala.concurrent.Future - -object HypothesisService { - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[Hypothesis], totalFound: Int) extends GetListReply - - case object AuthorizationError extends GetListReply with DomainError.AuthorizationError { - def userMessage: String = "Access denied" - } - } -} - -trait HypothesisService { - - import HypothesisService._ - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/InterventionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/InterventionService.scala deleted file mode 100644 index 439e456..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/InterventionService.scala +++ /dev/null @@ -1,79 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities._ - -import scala.concurrent.Future - -object InterventionService { - - trait DefaultNotFoundError { - def userMessage: String = "Intervention not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[InterventionWithArms], totalFound: Int) extends GetListReply - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait GetByIdReply - object GetByIdReply { - final case class Entity(x: InterventionWithArms) extends GetByIdReply - - type Error = GetByIdReply with DomainError - - case object NotFoundError extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) - extends GetByIdReply with DomainError - - implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { - case x: DomainError => phi"GetByIdReply.Error($x)" - case Entity(x) => phi"GetByIdReply.Entity($x)" - } - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - - final case class Updated(updated: InterventionWithArms) extends UpdateReply - - case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - } - -} - -trait InterventionService { - - import InterventionService._ - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def getById(id: LongId[Intervention])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def update(origIntervention: InterventionWithArms, draftIntervention: InterventionWithArms)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/InterventionTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/InterventionTypeService.scala deleted file mode 100644 index 298a92d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/InterventionTypeService.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.Sorting -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.InterventionType - -import scala.concurrent.Future - -object InterventionTypeService { - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[InterventionType], totalFound: Int) extends GetListReply - - case object AuthorizationError extends GetListReply with DomainError.AuthorizationError { - def userMessage: String = "Access denied" - } - } -} - -trait InterventionTypeService { - - import InterventionTypeService._ - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordHistoryService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordHistoryService.scala deleted file mode 100644 index f8fe3be..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordHistoryService.scala +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.{MedicalRecord, MedicalRecordHistory} - -import scala.concurrent.Future - -object MedicalRecordHistoryService { - - trait DefaultNotFoundError { - def userMessage: String = "Medical record history not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[MedicalRecordHistory], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListReply - - final case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - -} - -trait MedicalRecordHistoryService { - - import MedicalRecordHistoryService._ - - def getListByRecordId(id: LongId[MedicalRecord], - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordIssueService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordIssueService.scala deleted file mode 100644 index 723bdfa..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordIssueService.scala +++ /dev/null @@ -1,93 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.{MedicalRecord, MedicalRecordIssue} - -import scala.concurrent.Future - -object MedicalRecordIssueService { - - trait DefaultNotFoundError { - def userMessage: String = "MedicalRecordIssue not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait CreateReply - object CreateReply { - type Error = CreateReply with DomainError - final case class Created(x: MedicalRecordIssue) extends CreateReply - case object AuthorizationError - extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends CreateReply with DomainError - } - - sealed trait GetByIdReply - object GetByIdReply { - type Error = GetByIdReply with DomainError - final case class Entity(x: MedicalRecordIssue) extends GetByIdReply - case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait GetListByRecordIdReply - object GetListByRecordIdReply { - type Error = GetListByRecordIdReply with DomainError - final case class EntityList(xs: Seq[MedicalRecordIssue], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListByRecordIdReply - case object NotFoundError extends GetListByRecordIdReply with DomainError.NotFoundError with DefaultNotFoundError - case object AuthorizationError - extends GetListByRecordIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - final case class Updated(updated: MedicalRecordIssue) extends UpdateReply - case object AuthorizationError - extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - } - - sealed trait DeleteReply - object DeleteReply { - type Error = DeleteReply with DomainError - case object Deleted extends DeleteReply - case object AuthorizationError - extends DeleteReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case object NotFoundError extends DeleteReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends DeleteReply with DomainError - } -} - -trait MedicalRecordIssueService { - - import MedicalRecordIssueService._ - - def create(draft: MedicalRecordIssue)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] - - def getById(recordId: LongId[MedicalRecord], id: LongId[MedicalRecordIssue])( - implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getListByRecordId(recordId: LongId[MedicalRecord], - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListByRecordIdReply] - - def update(orig: MedicalRecordIssue, draft: MedicalRecordIssue)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def delete(recordId: LongId[MedicalRecord], id: LongId[MedicalRecordIssue])( - implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordService.scala deleted file mode 100644 index 7a0502b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordService.scala +++ /dev/null @@ -1,112 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import akka.NotUsed -import akka.stream.scaladsl.Source -import akka.util.ByteString -import java.time.LocalDateTime -import xyz.driver.pdsuicommon.auth.{AnonymousRequestContext, AuthenticatedRequestContext} -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.error._ -import xyz.driver.pdsuidomain.entities.MedicalRecord.PdfSource -import xyz.driver.pdsuidomain.entities._ - -import scala.concurrent.Future - -object MedicalRecordService { - - type PdfSourceFetcher = (String, String) => Future[PdfSource] - - trait DefaultNotFoundError { - def userMessage: String = "Medical record hasn't been found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait GetByIdReply - object GetByIdReply { - final case class Entity(x: MedicalRecord) extends GetByIdReply - - type Error = GetByIdReply with DomainError - - case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[MedicalRecord], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListReply - - type Error = GetListReply with DomainError - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - case object NotFoundError extends GetListReply with DomainError.NotFoundError { - def userMessage: String = "Patient wasn't found" - } - } - - sealed trait CreateReply - object CreateReply { - final case class Created(x: MedicalRecord) extends CreateReply - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - - final case class Updated(updated: MedicalRecord) extends UpdateReply - - case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - } - - final case class Settings(pdfSourceBucket: String) -} - -trait MedicalRecordService { - - import MedicalRecordService._ - - def getById(recordId: LongId[MedicalRecord])( - implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getPdfSource(recordId: LongId[MedicalRecord])( - implicit requestContext: AuthenticatedRequestContext): Future[Source[ByteString, NotUsed]] - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def create(draft: MedicalRecord)(implicit requestContext: AnonymousRequestContext): Future[CreateReply] - - def update(origRecord: MedicalRecord, draftRecord: MedicalRecord)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def start(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def submit(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def restart(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def flag(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def resolve(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def unassign(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def archive(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala deleted file mode 100644 index 6718f26..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala +++ /dev/null @@ -1,88 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.Message - -import scala.concurrent.Future - -object MessageService { - - trait DefaultNotFoundError { - def userMessage: String = "Message not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait CreateReply - object CreateReply { - type Error = CreateReply with DomainError - final case class Created(x: Message) extends CreateReply - case object AuthorizationError - extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends CreateReply with DomainError - } - - sealed trait GetByIdReply - object GetByIdReply { - type Error = GetByIdReply with DomainError - final case class Entity(x: Message) extends GetByIdReply - case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait GetListReply - object GetListReply { - type Error = GetListReply with DomainError - final case class EntityList(xs: Seq[Message], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListReply - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - final case class Updated(updated: Message) extends UpdateReply - case object AuthorizationError - extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - } - - sealed trait DeleteReply - object DeleteReply { - type Error = DeleteReply with DomainError - case object Deleted extends DeleteReply - case object AuthorizationError - extends DeleteReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case object NotFoundError extends DeleteReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends DeleteReply with DomainError - } -} - -trait MessageService { - - import MessageService._ - - def create(draftMessage: Message)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] - - def getById(messageId: LongId[Message])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def update(origMessage: Message, draftMessage: Message)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def delete(messageId: LongId[Message])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala deleted file mode 100644 index 9ff3879..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala +++ /dev/null @@ -1,118 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities._ - -import scala.concurrent.Future - -object PatientCriterionService { - - final case class DraftPatientCriterion(id: LongId[PatientCriterion], - eligibilityStatus: Option[FuzzyValue], - isVerified: Option[Boolean]) { - def applyTo(orig: PatientCriterion) = { - orig.copy( - eligibilityStatus = eligibilityStatus.orElse(orig.eligibilityStatus), - isVerified = isVerified.getOrElse(orig.isVerified) - ) - } - } - - trait DefaultPatientNotFoundError { - def userMessage: String = "Patient not found" - } - - trait DefaultNotFoundError { - def userMessage: String = "Patient criterion not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait GetListReply - object GetListReply { - type Error = GetListReply with DomainError - - final case class EntityList(xs: Seq[(PatientCriterion, LongId[Label], List[PatientCriterionArm])], - totalFound: Int, - lastUpdate: Option[LocalDateTime]) - extends GetListReply - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - case object PatientNotFoundError - extends GetListReply with DomainError.NotFoundError with DefaultPatientNotFoundError - - final case class CommonError(userMessage: String) extends GetListReply with DomainError - - } - - sealed trait GetByIdReply - object GetByIdReply { - type Error = GetByIdReply with DomainError - - final case class Entity(x: PatientCriterion, labelId: LongId[Label], armList: List[PatientCriterionArm]) - extends GetByIdReply - - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - - case object PatientNotFoundError - extends GetByIdReply with DomainError.NotFoundError with DefaultPatientNotFoundError - - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - - implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { - case x: DomainError => phi"GetByIdReply.Error($x)" - case Entity(x, labelId, armList) => phi"GetByIdReply.Entity(entity=$x, labelId=$labelId, armList=$armList)" - } - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - - final case class Updated(x: PatientCriterion, labelId: LongId[Label], armList: List[PatientCriterionArm]) - extends UpdateReply - - case object UpdatedList extends UpdateReply - - case object AuthorizationError - extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - case object PatientNotFoundError - extends UpdateReply with DomainError.NotFoundError with DefaultPatientNotFoundError - - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - } -} - -trait PatientCriterionService { - - import PatientCriterionService._ - - def getAll(patientId: UuidId[Patient], - origFilter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def getById(patientId: UuidId[Patient], id: LongId[PatientCriterion])( - implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def updateList(patientId: UuidId[Patient], draftEntities: List[DraftPatientCriterion])( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def update(origEntity: PatientCriterion, draftEntity: PatientCriterion, patientId: UuidId[Patient])( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala deleted file mode 100644 index 2c17f74..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala +++ /dev/null @@ -1,132 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.{LongId, UuidId} -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.{Trial, _} - -import scala.concurrent.Future - -object PatientEligibleTrialService { - - trait DefaultNotFoundError { - def userMessage: String = "Patient eligible trial not found" - } - - trait DefaultPatientNotFoundError { - def userMessage: String = "Patient not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - final case class RichPatientEligibleTrial(trial: Trial, - group: PatientTrialArmGroupView, - arms: List[PatientCriterionArm]) - - object RichPatientEligibleTrial { - implicit def toPhiString(x: RichPatientEligibleTrial): PhiString = { - phi"RichPatientEligibleTrial(group=${x.group}, trial=${x.trial}, arms=${x.arms})" - } - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[RichPatientEligibleTrial], totalFound: Int) extends GetListReply - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - case object PatientNotFoundError - extends GetListReply with DefaultPatientNotFoundError with DomainError.NotFoundError - - final case class CommonError(userMessage: String) extends GetListReply with DomainError - } - - sealed trait GetByIdReply - object GetByIdReply { - final case class Entity(x: RichPatientEligibleTrial) extends GetByIdReply - - type Error = GetByIdReply with DomainError - - case object NotFoundError extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError - - case object PatientNotFoundError - extends GetByIdReply with DefaultPatientNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - - implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { - case x: DomainError => phi"GetByIdReply.Error($x)" - case Entity(x) => phi"GetByIdReply.Entity($x)" - } - } - - sealed trait GetCriterionListOfGroupReply - object GetCriterionListOfGroupReply { - final case class EntityList(xs: Seq[(PatientCriterion, LongId[Label], List[PatientCriterionArm])], totalFound: Int) - extends GetCriterionListOfGroupReply - - type Error = GetCriterionListOfGroupReply with DomainError - - case object AuthorizationError - extends GetCriterionListOfGroupReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - case object NotFoundError - extends GetCriterionListOfGroupReply with DefaultNotFoundError with DomainError.NotFoundError - - case object PatientNotFoundError - extends GetCriterionListOfGroupReply with DefaultPatientNotFoundError with DomainError.NotFoundError - - final case class CommonError(userMessage: String) extends GetCriterionListOfGroupReply with DomainError - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - - final case class Updated(updated: RichPatientEligibleTrial) extends UpdateReply - - case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError - - case object PatientNotFoundError - extends UpdateReply with DefaultPatientNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - - implicit def toPhiString(reply: UpdateReply): PhiString = reply match { - case Updated(x) => phi"Updated($x)" - case x: Error => DomainError.toPhiString(x) - } - } -} - -trait PatientEligibleTrialService { - - import PatientEligibleTrialService._ - - def getAll(patientId: UuidId[Patient], - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def getById(patientId: UuidId[Patient], id: LongId[PatientTrialArmGroup])( - implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getCriterionListByGroupId(patientId: UuidId[Patient], id: LongId[PatientTrialArmGroup])( - implicit requestContext: AuthenticatedRequestContext): Future[GetCriterionListOfGroupReply] - - def update(origEligibleTrialWithTrial: RichPatientEligibleTrial, - draftPatientTrialArmGroup: PatientTrialArmGroupView)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientHistoryService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientHistoryService.scala deleted file mode 100644 index 855eddc..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientHistoryService.scala +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.{Patient, PatientHistory} - -import scala.concurrent.Future - -object PatientHistoryService { - - trait DefaultNotFoundError { - def userMessage: String = "Patient history not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[PatientHistory], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListReply - - final case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - -} - -trait PatientHistoryService { - - import PatientHistoryService._ - - def getListByPatientId(id: UuidId[Patient], - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala deleted file mode 100644 index f782cab..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala +++ /dev/null @@ -1,99 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.{Hypothesis, Patient, PatientHypothesis} - -import scala.concurrent.Future - -object PatientHypothesisService { - - trait DefaultNotFoundError { - def userMessage: String = "Patient hypothesis not found" - } - - trait DefaultPatientNotFoundError { - def userMessage: String = "Patient not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[(PatientHypothesis, Boolean)], totalFound: Int) extends GetListReply - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - case object PatientNotFoundError - extends GetListReply with DefaultPatientNotFoundError with DomainError.NotFoundError - - final case class CommonError(userMessage: String) extends GetListReply with DomainError - } - - sealed trait GetByIdReply - object GetByIdReply { - final case class Entity(x: PatientHypothesis, isRequired: Boolean) extends GetByIdReply - - type Error = GetByIdReply with DomainError - - case object NotFoundError extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError - - case object PatientNotFoundError - extends GetByIdReply with DefaultPatientNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - - implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { - case x: DomainError => phi"GetByIdReply.Error($x)" - case Entity(x, isRequired) => phi"GetByIdReply.Entity($x, $isRequired)" - } - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - - final case class Updated(updated: PatientHypothesis) extends UpdateReply - - case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError - - case object PatientNotFoundError - extends UpdateReply with DefaultPatientNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - - implicit def toPhiString(reply: UpdateReply): PhiString = reply match { - case Updated(x) => phi"Updated($x)" - case x: Error => DomainError.toPhiString(x) - } - } -} - -trait PatientHypothesisService { - - import PatientHypothesisService._ - - def getAll(patientId: UuidId[Patient], - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def getById(patientId: UuidId[Patient], hypothesisId: UuidId[Hypothesis])( - implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def update(origPatientHypothesis: PatientHypothesis, draftPatientHypothesis: PatientHypothesis)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientIssueService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientIssueService.scala deleted file mode 100644 index b53301d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientIssueService.scala +++ /dev/null @@ -1,93 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.{LongId, UuidId} -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.{Patient, PatientIssue} - -import scala.concurrent.Future - -object PatientIssueService { - - trait DefaultNotFoundError { - def userMessage: String = "PatientIssue not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait CreateReply - object CreateReply { - type Error = CreateReply with DomainError - final case class Created(x: PatientIssue) extends CreateReply - case object AuthorizationError - extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends CreateReply with DomainError - } - - sealed trait GetByIdReply - object GetByIdReply { - type Error = GetByIdReply with DomainError - final case class Entity(x: PatientIssue) extends GetByIdReply - case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait GetListByPatientIdReply - object GetListByPatientIdReply { - type Error = GetListByPatientIdReply with DomainError - final case class EntityList(xs: Seq[PatientIssue], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListByPatientIdReply - case object NotFoundError extends GetListByPatientIdReply with DomainError.NotFoundError with DefaultNotFoundError - case object AuthorizationError - extends GetListByPatientIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - final case class Updated(updated: PatientIssue) extends UpdateReply - case object AuthorizationError - extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - } - - sealed trait DeleteReply - object DeleteReply { - type Error = DeleteReply with DomainError - case object Deleted extends DeleteReply - case object AuthorizationError - extends DeleteReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case object NotFoundError extends DeleteReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends DeleteReply with DomainError - } -} - -trait PatientIssueService { - - import PatientIssueService._ - - def create(draft: PatientIssue)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] - - def getById(patientId: UuidId[Patient], id: LongId[PatientIssue])( - implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getListByPatientId(patientId: UuidId[Patient], - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListByPatientIdReply] - - def update(orig: PatientIssue, draft: PatientIssue)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def delete(patientId: UuidId[Patient], id: LongId[PatientIssue])( - implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala deleted file mode 100644 index 56e2e3d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala +++ /dev/null @@ -1,64 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain.{LongId, UuidId} -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities._ - -import scala.concurrent.Future - -object PatientLabelEvidenceService { - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - trait DefaultPatientNotFoundError { - def userMessage: String = "Patient not found" - } - - sealed trait GetByIdReply - object GetByIdReply { - final case class Entity(x: PatientLabelEvidenceView) extends GetByIdReply - - type Error = GetByIdReply with DomainError - - final case class NotFoundError(userMessage: String) extends GetByIdReply with DomainError.NotFoundError - - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[PatientLabelEvidenceView], totalFound: Int) extends GetListReply - - type Error = GetListReply with DomainError - - case object PatientNotFoundError - extends GetListReply with DefaultPatientNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String) extends GetListReply with DomainError - } -} - -trait PatientLabelEvidenceService { - - import PatientLabelEvidenceService._ - - def getById(patientId: UuidId[Patient], labelId: LongId[Label], id: LongId[PatientLabelEvidence])( - implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getAll(patientId: UuidId[Patient], - labelId: LongId[Label], - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala deleted file mode 100644 index 71b8bd4..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala +++ /dev/null @@ -1,117 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities._ - -import scala.concurrent.Future - -object PatientLabelService { - - trait DefaultNotFoundError { - def userMessage: String = "Patient label not found" - } - - trait DefaultPatientNotFoundError { - def userMessage: String = "Patient not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[(PatientLabel, Boolean)], totalFound: Int) extends GetListReply - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - case object PatientNotFoundError - extends GetListReply with DefaultPatientNotFoundError with DomainError.NotFoundError - - final case class CommonError(userMessage: String) extends GetListReply with DomainError - } - - sealed trait GetDefiningCriteriaListReply - object GetDefiningCriteriaListReply { - final case class EntityList(xs: Seq[PatientLabel], totalFound: Int) extends GetDefiningCriteriaListReply - - case object AuthorizationError - extends GetDefiningCriteriaListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - case object PatientNotFoundError - extends GetDefiningCriteriaListReply with DefaultPatientNotFoundError with DomainError.NotFoundError - - final case class CommonError(userMessage: String) extends GetDefiningCriteriaListReply with DomainError - } - - sealed trait GetByLabelIdReply - object GetByLabelIdReply { - final case class Entity(x: PatientLabel, isVerified: Boolean) extends GetByLabelIdReply - - type Error = GetByLabelIdReply with DomainError - - case object NotFoundError extends GetByLabelIdReply with DefaultNotFoundError with DomainError.NotFoundError - - case object PatientNotFoundError - extends GetByLabelIdReply with DefaultPatientNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends GetByLabelIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String) extends GetByLabelIdReply with DomainError - - implicit def toPhiString(reply: GetByLabelIdReply): PhiString = reply match { - case x: DomainError => phi"GetByIdReply.Error($x)" - case Entity(x, y) => phi"GetByIdReply.Entity($x, $y)" - } - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - - final case class Updated(updated: PatientLabel, isVerified: Boolean) extends UpdateReply - - case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError - - case object PatientNotFoundError - extends UpdateReply with DefaultPatientNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - - implicit def toPhiString(reply: UpdateReply): PhiString = reply match { - case Updated(x, y) => phi"Updated($x, $y)" - case x: Error => DomainError.toPhiString(x) - } - } -} - -trait PatientLabelService { - - import PatientLabelService._ - - def getAll(patientId: UuidId[Patient], - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def getDefiningCriteriaList(patientId: UuidId[Patient], - hypothesisId: UuidId[Hypothesis], - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetDefiningCriteriaListReply] - - def getByLabelIdOfPatient(patientId: UuidId[Patient], labelId: LongId[Label])( - implicit requestContext: AuthenticatedRequestContext): Future[GetByLabelIdReply] - - def update(origPatientLabel: PatientLabel, draftPatientLabel: PatientLabel)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientService.scala deleted file mode 100644 index ce70934..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientService.scala +++ /dev/null @@ -1,95 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities._ - -import scala.concurrent.Future - -object PatientService { - - trait DefaultNotFoundError { - def userMessage: String = "Patient not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[Patient], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListReply - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait GetByIdReply - object GetByIdReply { - final case class Entity(x: Patient) extends GetByIdReply - - type Error = GetByIdReply with DomainError - - case object NotFoundError extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) - extends GetByIdReply with DomainError - - implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { - case x: DomainError => phi"GetByIdReply.Error($x)" - case Entity(x) => phi"GetByIdReply.Entity($x)" - } - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - - final case class Updated(updated: Patient) extends UpdateReply - - case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - - implicit def toPhiString(reply: UpdateReply): PhiString = reply match { - case Updated(x) => phi"Updated($x)" - case x: Error => DomainError.toPhiString(x) - } - } -} - -trait PatientService { - - import PatientService._ - - def getById(id: UuidId[Patient])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def unassign(origPatient: Patient)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def start(origPatient: Patient)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def submit(origPatient: Patient)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def restart(origPatient: Patient)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def flag(origPatient: Patient)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def resolve(origPatient: Patient)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ProviderTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ProviderTypeService.scala deleted file mode 100644 index cad17a4..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/ProviderTypeService.scala +++ /dev/null @@ -1,26 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.Sorting -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.ProviderType - -import scala.concurrent.Future - -object ProviderTypeService { - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[ProviderType], totalFound: Int) extends GetListReply - case object AuthorizationError extends GetListReply with DomainError.AuthorizationError { - def userMessage: String = "Access denied" - } - } -} - -trait ProviderTypeService { - - import ProviderTypeService._ - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/QueueUploadService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/QueueUploadService.scala deleted file mode 100644 index 340733d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/QueueUploadService.scala +++ /dev/null @@ -1,76 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.error.DomainError - -import scala.concurrent.Future - -object QueueUploadService { - trait DefaultNotFoundError { - def userMessage: String = "Message not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait CreateReply - object CreateReply { - type Error = CreateReply with DomainError - - final case class Created(x: BridgeUploadQueue.Item) extends CreateReply - case object AuthorizationError - extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends CreateReply with DomainError - } - - sealed trait GetByIdReply - object GetByIdReply { - type Error = GetByIdReply with DomainError - - final case class Entity(x: BridgeUploadQueue.Item) extends GetByIdReply - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - } - - sealed trait GetListReply - object GetListReply { - type Error = GetListReply with DomainError - - final case class EntityList(xs: Seq[BridgeUploadQueue.Item], totalFound: Int) extends GetListReply - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait ResetReply - object ResetReply { - type Error = ResetReply with DomainError - - final case class Updated(updated: BridgeUploadQueue.Item) extends ResetReply - case object AuthorizationError extends ResetReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case object NotFoundError extends ResetReply with DefaultNotFoundError with DomainError.NotFoundError - final case class CommonError(userMessage: String) extends ResetReply with DomainError - } -} - -trait QueueUploadService { - - import QueueUploadService._ - - def create(kind: String, tag: String)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] - - def getById(kind: String, tag: String)(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def reset(kind: String, tag: String)(implicit requestContext: AuthenticatedRequestContext): Future[ResetReply] - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ScrapedTrialsService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ScrapedTrialsService.scala deleted file mode 100644 index 233495e..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/ScrapedTrialsService.scala +++ /dev/null @@ -1,53 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.ScrapedTrial - -import scala.concurrent.Future - -object ScrapedTrialsService { - - sealed trait GetRawTrialReply - object GetRawTrialReply { - type Error = GetRawTrialReply with DomainError - - final case class TrialRawEntity(rawTrial: ScrapedTrial) extends GetRawTrialReply - - case object NotFoundError extends GetRawTrialReply with DomainError.NotFoundError { - override def userMessage: String = "Raw clinical trial not found" - } - } - - sealed trait GetRawTrialOptReply - object GetRawTrialOptReply { - final case class TrialRawEntity(rawTrial: Option[ScrapedTrial]) extends GetRawTrialOptReply - } - - sealed trait GetAllRawTrialsExceptReply - object GetAllRawTrialsExceptReply { - final case class MultipleRawTrials(rawTrials: Seq[ScrapedTrial]) extends GetAllRawTrialsExceptReply - } - - sealed trait GetHtmlForReply - object GetHtmlForReply { - type TrialHtmlMap = Map[String, String] - - /** - * @param trialHtmlMap nctId -> html - */ - final case class HtmlMap(trialHtmlMap: TrialHtmlMap) extends GetHtmlForReply - } -} - -trait ScrapedTrialsService { - - import ScrapedTrialsService._ - - def getRawTrial(nctId: String): Future[GetRawTrialReply] - - def getRawTrialOpt(nctId: String): Future[GetRawTrialOptReply] - - def getAllRawTrialsExcept(nctIds: Seq[String], limit: Int): Future[GetAllRawTrialsExceptReply] - - def getHtmlFor(nctIds: Set[String]): Future[GetHtmlForReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/StudyDesignService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/StudyDesignService.scala deleted file mode 100644 index e98c1ec..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/StudyDesignService.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.Sorting -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.StudyDesign - -import scala.concurrent.Future - -object StudyDesignService { - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[StudyDesign], totalFound: Int) extends GetListReply - - case object AuthorizationError extends GetListReply with DomainError.AuthorizationError { - def userMessage: String = "Access denied" - } - } -} - -trait StudyDesignService { - - import StudyDesignService._ - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/TrialHistoryService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/TrialHistoryService.scala deleted file mode 100644 index bcf1c53..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/TrialHistoryService.scala +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.StringId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.{Trial, TrialHistory} - -import scala.concurrent.Future - -object TrialHistoryService { - - trait DefaultNotFoundError { - def userMessage: String = "Trial not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[TrialHistory], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListReply - - final case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - -} - -trait TrialHistoryService { - - import TrialHistoryService._ - - def getListByTrialId(id: StringId[Trial], - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/TrialIssueService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/TrialIssueService.scala deleted file mode 100644 index 726feda..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/TrialIssueService.scala +++ /dev/null @@ -1,93 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.{Trial, TrialIssue} - -import scala.concurrent.Future - -object TrialIssueService { - - trait DefaultNotFoundError { - def userMessage: String = "TrialIssue not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait CreateReply - object CreateReply { - type Error = CreateReply with DomainError - final case class Created(x: TrialIssue) extends CreateReply - case object AuthorizationError - extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends CreateReply with DomainError - } - - sealed trait GetByIdReply - object GetByIdReply { - type Error = GetByIdReply with DomainError - final case class Entity(x: TrialIssue) extends GetByIdReply - case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends GetByIdReply with DomainError - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait GetListByTrialIdReply - object GetListByTrialIdReply { - type Error = GetListByTrialIdReply with DomainError - final case class EntityList(xs: Seq[TrialIssue], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListByTrialIdReply - case object NotFoundError extends GetListByTrialIdReply with DomainError.NotFoundError with DefaultNotFoundError - case object AuthorizationError - extends GetListByTrialIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - final case class Updated(updated: TrialIssue) extends UpdateReply - case object AuthorizationError - extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - } - - sealed trait DeleteReply - object DeleteReply { - type Error = DeleteReply with DomainError - case object Deleted extends DeleteReply - case object AuthorizationError - extends DeleteReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case object NotFoundError extends DeleteReply with DomainError.NotFoundError with DefaultNotFoundError - final case class CommonError(userMessage: String) extends DeleteReply with DomainError - } -} - -trait TrialIssueService { - - import TrialIssueService._ - - def create(draft: TrialIssue)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] - - def getById(trialId: StringId[Trial], id: LongId[TrialIssue])( - implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getListByTrialId(trialId: StringId[Trial], - filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListByTrialIdReply] - - def update(orig: TrialIssue, draft: TrialIssue)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def delete(trialId: StringId[Trial], id: LongId[TrialIssue])( - implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/TrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/TrialService.scala deleted file mode 100644 index 5bd99a8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/TrialService.scala +++ /dev/null @@ -1,125 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import java.time.LocalDateTime - -import akka.NotUsed -import akka.stream.scaladsl.Source -import akka.util.ByteString -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain.StringId -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuicommon.logging._ -import xyz.driver.pdsuidomain.entities.Trial -import xyz.driver.pdsuidomain.entities.export.trial.ExportTrialWithLabels - -import scala.concurrent.Future - -object TrialService { - - trait DefaultNotFoundError { - def userMessage: String = "Trial not found" - } - - trait DefaultAccessDeniedError { - def userMessage: String = "Access denied" - } - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[Trial], totalFound: Int, lastUpdate: Option[LocalDateTime]) - extends GetListReply - - case object AuthorizationError - extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait GetByIdReply - object GetByIdReply { - final case class Entity(x: Trial) extends GetByIdReply - - type Error = GetByIdReply with DomainError - - case object NotFoundError extends GetByIdReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - - final case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) - extends GetByIdReply with DomainError - - implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { - case x: DomainError => phi"GetByIdReply.Error($x)" - case Entity(x) => phi"GetByIdReply.Entity($x)" - } - } - - sealed trait GetTrialWithLabelsReply - object GetTrialWithLabelsReply { - type Error = GetTrialWithLabelsReply with DomainError - - final case class Entity(x: ExportTrialWithLabels) extends GetTrialWithLabelsReply - - case object NotFoundError extends GetTrialWithLabelsReply with DomainError.NotFoundError { - def userMessage: String = "Trial not found" - } - - case object AuthorizationError - extends GetTrialWithLabelsReply with DomainError.AuthorizationError with DefaultAccessDeniedError - } - - sealed trait UpdateReply - object UpdateReply { - type Error = UpdateReply with DomainError - - final case class Updated(updated: Trial) extends UpdateReply - - case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError - - case object AuthorizationError - extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - - final case class CommonError(userMessage: String) extends UpdateReply with DomainError - - implicit def toPhiString(reply: UpdateReply): PhiString = reply match { - case Updated(x) => phi"Updated($x)" - case x: Error => DomainError.toPhiString(x) - } - } -} - -trait TrialService { - - import TrialService._ - - def getById(id: StringId[Trial])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] - - def getTrialWithLabels(trialId: StringId[Trial], condition: String)( - implicit requestContext: AuthenticatedRequestContext): Future[GetTrialWithLabelsReply] - - def getPdfSource(trialId: StringId[Trial])( - implicit requestContext: AuthenticatedRequestContext): Future[Source[ByteString, NotUsed]] - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] - - def update(origTrial: Trial, draftTrial: Trial)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def start(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def submit(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def restart(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def flag(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def resolve(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def archive(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - - def unassign(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala deleted file mode 100644 index a29e041..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.driver.pdsuidomain.services - -import xyz.driver.pdsuicommon.auth.AuthenticatedRequestContext -import xyz.driver.pdsuicommon.db.{Pagination, SearchFilterExpr, Sorting} -import xyz.driver.pdsuicommon.error.DomainError -import xyz.driver.pdsuidomain.entities.UserHistory - -import scala.concurrent.Future - -object UserHistoryService { - - sealed trait GetListReply - object GetListReply { - final case class EntityList(xs: Seq[UserHistory], totalFound: Int) extends GetListReply - - case object AuthorizationError extends GetListReply with DomainError.AuthorizationError { - def userMessage: String = "Access denied" - } - } -} - -trait UserHistoryService { - - import UserHistoryService._ - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/fake/FakeTrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/fake/FakeTrialService.scala deleted file mode 100644 index 3793c1f..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/fake/FakeTrialService.scala +++ /dev/null @@ -1,109 +0,0 @@ -package xyz.driver.pdsuidomain.services.fake - -import java.time.LocalDateTime - -import akka.NotUsed -import akka.stream.scaladsl.Source -import akka.util.ByteString -import xyz.driver.core.generators -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.export.trial.{ExportTrialArm, ExportTrialLabelCriterion, ExportTrialWithLabels} -import xyz.driver.pdsuidomain.services.TrialService - -import scala.concurrent.Future - -class FakeTrialService extends TrialService { - - import TrialService._ - - private val trial = Trial( - id = StringId(""), - externalId = UuidId(), - status = Trial.Status.New, - assignee = None, - previousStatus = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.now(), - condition = Trial.Condition.Breast, - phase = "", - hypothesisId = None, - studyDesignId = None, - originalStudyDesign = None, - isPartner = false, - overview = None, - overviewTemplate = "", - isUpdated = false, - title = "", - originalTitle = "" - ) - - def getById(id: StringId[Trial])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = - Future.successful( - GetByIdReply.Entity(trial) - ) - - def getPdfSource(trialId: StringId[Trial])( - implicit requestContext: AuthenticatedRequestContext): Future[Source[ByteString, NotUsed]] = - Future.failed(new NotImplementedError("fake pdf download is not implemented")) - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = - Future.successful(GetListReply.EntityList(Seq(trial), 1, None)) - - override def getTrialWithLabels(trialId: StringId[Trial], condition: String)( - implicit requestContext: AuthenticatedRequestContext): Future[GetTrialWithLabelsReply] = { - Future.successful( - GetTrialWithLabelsReply.Entity(ExportTrialWithLabels( - StringId[Trial]("NCT" + generators.nextInt(999999).toString), - UuidId[Trial](generators.nextUuid()), - generators.oneOf("adenocarcinoma", "breast", "prostate"), - LocalDateTime.now(), - labelVersion = 1L, - generators.listOf(new ExportTrialArm( - LongId[Arm](generators.nextInt(999999).toLong), - generators.nextName().value - )), - generators.listOf(new ExportTrialLabelCriterion( - LongId[Criterion](generators.nextInt(999999).toLong), - generators.nextOption(generators.nextBoolean()), - LongId[Label](generators.nextInt(999999).toLong), - generators.setOf(LongId[Arm](generators.nextInt(999999).toLong)), - generators.nextName().value, - generators.nextBoolean(), - generators.nextBoolean() - )) - ))) - } - - def update(origTrial: Trial, draftTrial: Trial)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - Future.successful(UpdateReply.Updated(draftTrial)) - - def start(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - update(origTrial, origTrial) - - def submit(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - update(origTrial, origTrial) - - def restart(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - update(origTrial, origTrial) - - def flag(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - update(origTrial, origTrial) - - def resolve(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - update(origTrial, origTrial) - - def archive(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - update(origTrial, origTrial) - - def unassign(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - update(origTrial, origTrial) - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala deleted file mode 100644 index 2b4e858..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala +++ /dev/null @@ -1,81 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.marshalling.Marshal -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest.{Pagination => _, _} -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.arm.ApiArm -import xyz.driver.pdsuidomain.services.ArmService - -class RestArmService(transport: ServiceTransport, baseUri: Uri)(implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends ArmService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.ArmService._ - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest( - HttpMethods.GET, - endpointUri(baseUri, "/v1/arm", filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiArm]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) - } - } - - def getById(armId: LongId[Arm])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/arm/$armId")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiArm](response) - } yield { - GetByIdReply.Entity(reply.toDomain) - } - } - - def create(draftArm: Arm)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = { - for { - entity <- Marshal(ApiArm.fromDomain(draftArm)).to[RequestEntity] - request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/arm")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiArm](response) - } yield { - CreateReply.Created(reply.toDomain) - } - } - - def update(origArm: Arm, draftArm: Arm)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - val id = origArm.id - val request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/arm/$id")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiArm](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - - def delete(id: LongId[Arm])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] = { - val request = HttpRequest(HttpMethods.DELETE, endpointUri(baseUri, s"/v1/arm/$id")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - _ <- apiResponse[HttpEntity](response) - } yield { - DeleteReply.Deleted - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala deleted file mode 100644 index f0f4de8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala +++ /dev/null @@ -1,86 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.marshalling.Marshal -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest.{Pagination => _, _} -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.services.CriterionService - -class RestCriterionService(transport: ServiceTransport, baseUri: Uri)( - implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends CriterionService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.formats.json.criterion.ApiCriterion - import xyz.driver.pdsuidomain.services.CriterionService._ - - def create(draftRichCriterion: RichCriterion)( - implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = { - for { - entity <- Marshal(ApiCriterion.fromDomain(draftRichCriterion)).to[RequestEntity] - request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/criterion")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiCriterion](response) - } yield { - CreateReply.Created(reply.toDomain) - } - } - - def getById(id: LongId[Criterion])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/criterion/$id")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiCriterion](response) - } yield { - GetByIdReply.Entity(reply.toDomain) - } - } - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest(HttpMethods.GET, - endpointUri(baseUri, - s"/v1/criterion", - filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiCriterion]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate) - } - } - - def update(origRichCriterion: RichCriterion, draftRichCriterion: RichCriterion)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - val id = origRichCriterion.criterion.id - for { - entity <- Marshal(ApiCriterion.fromDomain(draftRichCriterion)).to[RequestEntity] - request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/criterion/$id")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiCriterion](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - - def delete(id: LongId[Criterion])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] = { - val request = HttpRequest(HttpMethods.DELETE, endpointUri(baseUri, s"/v1/criterion/$id")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - _ <- apiResponse[HttpEntity](response) - } yield { - DeleteReply.Deleted - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentService.scala deleted file mode 100644 index 68fdde1..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentService.scala +++ /dev/null @@ -1,111 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.marshalling.Marshal -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest.{Pagination => _, _} -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.document.ApiDocument -import xyz.driver.pdsuidomain.services.DocumentService - -class RestDocumentService(transport: ServiceTransport, baseUri: Uri)(implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends DocumentService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.DocumentService._ - - def getById(id: LongId[Document])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/document/$id")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiDocument](response) - } yield { - GetByIdReply.Entity(reply.toDomain) - } - } - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - - val request = HttpRequest(HttpMethods.GET, - endpointUri(baseUri, - "/v1/document", - filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiDocument]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate) - } - } - - def create(draftDocument: Document)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = { - for { - entity <- Marshal(ApiDocument.fromDomain(draftDocument)).to[RequestEntity] - request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/document")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiDocument](response) - } yield { - CreateReply.Created(reply.toDomain) - } - } - - def update(orig: Document, draft: Document)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - for { - entity <- Marshal(ApiDocument.fromDomain(draft)).to[RequestEntity] - request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/document/${orig.id}")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiDocument](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - - def delete(id: LongId[Document])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] = { - val request = HttpRequest(HttpMethods.DELETE, endpointUri(baseUri, s"/v1/document/$id")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - _ <- apiResponse[HttpEntity](response) - } yield { - DeleteReply.Deleted - } - } - - private def editAction(orig: Document, action: String)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - val id = orig.id.toString - val request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, s"/v1/document/$id/$action")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiDocument](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - - def start(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "start") - def submit(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "submit") - def restart(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "restart") - def flag(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "flag") - def resolve(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "resolve") - def unassign(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "unassign") - def archive(orig: Document)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "archive") - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentTypeService.scala deleted file mode 100644 index caa0042..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestDocumentTypeService.scala +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest.{Pagination => _, _} -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.services.DocumentTypeService -import xyz.driver.pdsuidomain.formats.json.document.ApiDocumentType - -class RestDocumentTypeService(transport: ServiceTransport, baseUri: Uri)( - implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends DocumentTypeService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.DocumentTypeService._ - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/document-type", sortingQuery(sorting))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiDocumentType]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) - } - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestExtractedDataService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestExtractedDataService.scala deleted file mode 100644 index 53b9f38..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestExtractedDataService.scala +++ /dev/null @@ -1,97 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.marshalling.Marshal -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest.{Pagination => _, _} -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.export.ApiExportPatientWithLabels -import xyz.driver.pdsuidomain.formats.json.extracteddata.ApiExtractedData -import xyz.driver.pdsuidomain.services.ExtractedDataService - -class RestExtractedDataService(transport: ServiceTransport, baseUri: Uri)( - implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends ExtractedDataService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.ExtractedDataService._ - - def getById(id: LongId[ExtractedData])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/extracted-data/$id")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiExtractedData](response) - } yield { - GetByIdReply.Entity(reply.toDomain) - } - } - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest(HttpMethods.GET, - endpointUri(baseUri, - "/v1/extracted-data", - filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiExtractedData]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) - } - } - - def create(draftRichExtractedData: RichExtractedData)( - implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = { - for { - entity <- Marshal(ApiExtractedData.fromDomain(draftRichExtractedData)).to[RequestEntity] - request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/extracted-data")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiExtractedData](response) - } yield { - CreateReply.Created(reply.toDomain) - } - } - def update(origRichExtractedData: RichExtractedData, draftRichExtractedData: RichExtractedData)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - val id = origRichExtractedData.extractedData.id - for { - entity <- Marshal(ApiExtractedData.fromDomain(draftRichExtractedData)).to[RequestEntity] - request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/extracted-data/$id")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiExtractedData](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - - def delete(id: LongId[ExtractedData])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] = { - val request = HttpRequest(HttpMethods.DELETE, endpointUri(baseUri, s"/v1/export-data/$id")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - _ <- apiResponse[HttpEntity](response) - } yield { - DeleteReply.Deleted - } - } - - def getPatientLabels(id: UuidId[Patient])( - implicit requestContext: AuthenticatedRequestContext): Future[GetPatientLabelsReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/export/patient/$id")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiExportPatientWithLabels](response) - } yield { - GetPatientLabelsReply.Entity(reply.toDomain) - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala deleted file mode 100644 index 0ff29ef..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala +++ /dev/null @@ -1,128 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} -import akka.http.scaladsl.model.{HttpResponse, ResponseEntity, StatusCodes, Uri} -import akka.http.scaladsl.unmarshalling.{Unmarshal, Unmarshaller} -import akka.stream.Materializer -import xyz.driver.core.rest.{ContextHeaders, ServiceRequestContext} -import xyz.driver.pdsuicommon.auth.{AnonymousRequestContext, AuthenticatedRequestContext} -import xyz.driver.pdsuicommon.db.{ - Pagination, - SearchFilterBinaryOperation, - SearchFilterExpr, - SearchFilterNAryOperation, - Sorting, - SortingOrder -} -import xyz.driver.pdsuicommon.error._ - -trait RestHelper { - - implicit protected val materializer: Materializer - implicit protected val exec: ExecutionContext - - protected def endpointUri(baseUri: Uri, path: String) = - baseUri.withPath(Uri.Path(path)) - - protected def endpointUri(baseUri: Uri, path: String, query: Seq[(String, String)]) = - baseUri.withPath(Uri.Path(path)).withQuery(Uri.Query(query: _*)) - - def sortingQuery(sorting: Option[Sorting]): Seq[(String, String)] = { - def dimensionQuery(dimension: Sorting.Dimension) = { - val ord = dimension.order match { - case SortingOrder.Ascending => "" - case SortingOrder.Descending => "-" - } - s"$ord${dimension.name}" - } - - sorting match { - case None => Seq.empty - case Some(dimension: Sorting.Dimension) => Seq("sort" -> dimensionQuery(dimension)) - case Some(Sorting.Sequential(dimensions)) => Seq("sort" -> dimensions.map(dimensionQuery).mkString(",")) - } - } - - def filterQuery(expr: SearchFilterExpr): Seq[(String, String)] = { - def opToString(op: SearchFilterBinaryOperation) = op match { - case SearchFilterBinaryOperation.Eq => "eq" - case SearchFilterBinaryOperation.NotEq => "ne" - case SearchFilterBinaryOperation.Like => "like" - case SearchFilterBinaryOperation.Gt => "gt" - case SearchFilterBinaryOperation.GtEq => "ge" - case SearchFilterBinaryOperation.Lt => "lt" - case SearchFilterBinaryOperation.LtEq => "le" - } - - def exprToQuery(expr: SearchFilterExpr): Seq[(String, String)] = expr match { - case SearchFilterExpr.Empty => Seq.empty - case SearchFilterExpr.Atom.Binary(dimension, op, value) => - Seq("filters" -> s"${dimension.name} ${opToString(op)} $value") - case SearchFilterExpr.Atom.NAry(dimension, SearchFilterNAryOperation.In, values) => - Seq("filters" -> s"${dimension.name} in ${values.mkString(",")}") - case SearchFilterExpr.Intersection(ops) => - ops.flatMap(op => exprToQuery(op)) - case expr => sys.error(s"No parser available for filter expression $expr.") - } - - exprToQuery(expr) - } - - def paginationQuery(pagination: Option[Pagination]): Seq[(String, String)] = pagination match { - case None => Seq.empty - case Some(pp) => - Seq( - "pageNumber" -> pp.pageNumber.toString, - "pageSize" -> pp.pageSize.toString - ) - } - - /** Utility method to parse responses from records-acquisition-server. - * - * Non-2xx HTTP error codes will be cause the returned future to fail with a corresponding - * `DomainException`. - * @tparam ApiReply The type of the serialized reply object, contained in the HTTP entity - * @param response The HTTP response to parse. - * @param unmarshaller An unmarshaller that converts a successful response to an api reply. - */ - def apiResponse[ApiReply](response: HttpResponse)( - implicit unmarshaller: Unmarshaller[ResponseEntity, ApiReply]): Future[ApiReply] = { - - def extractErrorMessage(response: HttpResponse): Future[String] = { - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - Unmarshal(response.entity) - .to[ErrorsResponse] - .transform( - response => response.errors.map(_.message).mkString(", "), - ex => new DomainException("Response has invalid format", ex) - ) - } - - if (response.status.isSuccess) { - Unmarshal(response.entity).to[ApiReply] - } else { - extractErrorMessage(response).flatMap { message => - Future.failed(response.status match { - case StatusCodes.Unauthorized => new AuthenticationException(message) - case StatusCodes.Forbidden => new AuthorizationException(message) - case StatusCodes.NotFound => new NotFoundException(message) - case other => - new DomainException(s"Unhandled domain error for HTTP status ${other.value}. ${message}") - }) - } - } - } - - implicit def toServiceRequestContext(requestContext: AnonymousRequestContext): ServiceRequestContext = { - val auth: Map[String, String] = requestContext match { - case ctx: AuthenticatedRequestContext => - Map( - ContextHeaders.AuthenticationTokenHeader -> ctx.authToken, - ContextHeaders.TrackingIdHeader -> ctx.requestId.value - ) - case _ => - Map() - } - new ServiceRequestContext(contextHeaders = auth, trackingId = requestContext.requestId.value) - } -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHypothesisService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHypothesisService.scala deleted file mode 100644 index 1b8c943..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHypothesisService.scala +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest._ -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.hypothesis.ApiHypothesis -import xyz.driver.pdsuidomain.services.HypothesisService - -class RestHypothesisService(transport: ServiceTransport, baseUri: Uri)( - implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends HypothesisService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.HypothesisService._ - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/hypothesis", sortingQuery(sorting))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiHypothesis]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala deleted file mode 100644 index e593c3b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala +++ /dev/null @@ -1,64 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.marshalling.Marshal -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest.{Pagination => _, _} -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.intervention.ApiIntervention -import xyz.driver.pdsuidomain.services.InterventionService - -class RestInterventionService(transport: ServiceTransport, baseUri: Uri)( - implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends InterventionService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.InterventionService._ - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest(HttpMethods.GET, - endpointUri(baseUri, - "/v1/intervention", - filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiIntervention]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) - } - } - - def getById(id: LongId[Intervention])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/intervention/$id")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiIntervention](response) - } yield { - GetByIdReply.Entity(reply.toDomain) - } - } - - def update(origIntervention: InterventionWithArms, draftIntervention: InterventionWithArms)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - val id = origIntervention.intervention.id - for { - entity <- Marshal(ApiIntervention.fromDomain(draftIntervention)).to[RequestEntity] - request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/intervention/$id")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiIntervention](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala deleted file mode 100644 index 87f32ec..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala +++ /dev/null @@ -1,36 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest._ -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuidomain.formats.json.intervention.ApiInterventionType -import xyz.driver.pdsuidomain.services.InterventionTypeService - -class RestInterventionTypeService(transport: ServiceTransport, baseUri: Uri)( - implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends InterventionTypeService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.formats.json.ListResponse - import xyz.driver.pdsuidomain.services.InterventionTypeService._ - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/intervention-type", sortingQuery(sorting))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiInterventionType]](response) - } yield { - { - val domain = reply.items.map(_.toDomain) - GetListReply.EntityList(domain.toList, reply.meta.itemsCount) - } - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMedicalRecordService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMedicalRecordService.scala deleted file mode 100644 index f2b0f2d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMedicalRecordService.scala +++ /dev/null @@ -1,119 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import akka.NotUsed -import akka.stream.scaladsl.Source -import akka.util.ByteString -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.marshalling.Marshal -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest.{Pagination => _, _} -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.record.ApiRecord -import xyz.driver.pdsuidomain.services.MedicalRecordService - -class RestMedicalRecordService(transport: ServiceTransport, baseUri: Uri)( - implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends MedicalRecordService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.MedicalRecordService._ - - def getById(recordId: LongId[MedicalRecord])( - implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/record/$recordId")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiRecord](response) - } yield { - GetByIdReply.Entity(reply.toDomain) - } - } - - def getPdfSource(recordId: LongId[MedicalRecord])( - implicit requestContext: AuthenticatedRequestContext): Future[Source[ByteString, NotUsed]] = { - - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/record/${recordId}/source")) - - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[HttpEntity](response) - } yield { - reply.dataBytes.mapMaterializedValue(_ => NotUsed) - } - } - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - - val request = HttpRequest( - HttpMethods.GET, - endpointUri(baseUri, "/v1/record", filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiRecord]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate) - } - } - - def create(draftRecord: MedicalRecord)(implicit requestContext: AnonymousRequestContext): Future[CreateReply] = { - for { - entity <- Marshal(ApiRecord.fromDomain(draftRecord)).to[RequestEntity] - request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/record")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiRecord](response) - } yield { - CreateReply.Created(reply.toDomain) - } - } - - def update(origRecord: MedicalRecord, draftRecord: MedicalRecord)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - val id = origRecord.id.toString - for { - entity <- Marshal(ApiRecord.fromDomain(draftRecord)).to[RequestEntity] - request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/record/$id")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiRecord](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - - private def editAction(orig: MedicalRecord, action: String)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - val id = orig.id.toString - val request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, s"/v1/record/$id/$action")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiRecord](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - - def start(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "start") - def submit(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "submit") - def restart(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "restart") - def flag(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "flag") - def resolve(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "resolve") - def unassign(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "unassign") - def archive(orig: MedicalRecord)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(orig, "archive") - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala deleted file mode 100644 index e133825..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala +++ /dev/null @@ -1,87 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.marshalling.Marshal -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest.{Pagination => _, _} -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.message.ApiMessage -import xyz.driver.pdsuidomain.services.MessageService - -class RestMessageService(transport: ServiceTransport, baseUri: Uri)(implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends MessageService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.MessageService._ - - def create(draftMessage: Message)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = { - for { - entity <- Marshal(ApiMessage.fromDomain(draftMessage)).to[RequestEntity] - request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/message")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiMessage](response) - } yield { - CreateReply.Created(reply.toDomain) - } - } - - def getById(messageId: LongId[Message])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { - import xyz.driver.pdsuicommon.db.SearchFilterBinaryOperation._ - import xyz.driver.pdsuicommon.db.SearchFilterExpr._ - val filter = Atom.Binary("id", Eq, messageId) - getAll(filter).map({ - case GetListReply.EntityList(messages, _, _) if messages.isEmpty => - GetByIdReply.NotFoundError - case GetListReply.EntityList(messages, _, _) => - GetByIdReply.Entity(messages.head) - case GetListReply.AuthorizationError => - GetByIdReply.AuthorizationError - }) - } - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest( - HttpMethods.GET, - endpointUri(baseUri, "/v1/message", filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiMessage]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate) - } - } - - def update(origMessage: Message, draftMessage: Message)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - for { - entity <- Marshal(ApiMessage.fromDomain(draftMessage)).to[RequestEntity] - id = origMessage.id.id - request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/message/$id")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiMessage](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - - def delete(messageId: LongId[Message])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] = { - val request = HttpRequest(HttpMethods.DELETE, endpointUri(baseUri, s"/v1/message/${messageId.id}")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - _ <- apiResponse[HttpEntity](response) - } yield { - DeleteReply.Deleted - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestPatientService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestPatientService.scala deleted file mode 100644 index b9cbec8..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestPatientService.scala +++ /dev/null @@ -1,72 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest.{Pagination => _, _} -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.patient.ApiPatient -import xyz.driver.pdsuidomain.services.PatientService - -class RestPatientService(transport: ServiceTransport, baseUri: Uri)(implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends PatientService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.PatientService._ - - def getById(id: UuidId[Patient])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/patient/$id")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiPatient](response) - } yield { - GetByIdReply.Entity(reply.toDomain) - } - } - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest( - HttpMethods.GET, - endpointUri(baseUri, "/v1/patient", filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiPatient]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate) - } - } - - private def editAction(orig: Patient, action: String)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - val id = orig.id.toString - val request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, s"/v1/patient/$id/$action")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiPatient](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - - def unassign(origPatient: Patient)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(origPatient, "unassign") - def start(origPatient: Patient)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(origPatient, "start") - def submit(origPatient: Patient)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(origPatient, "submit") - def restart(origPatient: Patient)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(origPatient, "restart") - def flag(origPatient: Patient)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(origPatient, "flag") - def resolve(origPatient: Patient)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - editAction(origPatient, "resolve") -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestProviderTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestProviderTypeService.scala deleted file mode 100644 index f82ec40..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestProviderTypeService.scala +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest.{Pagination => _, _} -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.services.ProviderTypeService -import xyz.driver.pdsuidomain.formats.json.document.ApiProviderType - -class RestProviderTypeService(transport: ServiceTransport, baseUri: Uri)( - implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends ProviderTypeService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.ProviderTypeService._ - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/provider-type", sortingQuery(sorting))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiProviderType]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala deleted file mode 100644 index 98b397d..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala +++ /dev/null @@ -1,33 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} - -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest._ -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.studydesign.ApiStudyDesign -import xyz.driver.pdsuidomain.services.StudyDesignService - -class RestStudyDesignService(transport: ServiceTransport, baseUri: Uri)( - implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends StudyDesignService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.StudyDesignService._ - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/study-design", sortingQuery(sorting))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiStudyDesign]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount) - } - } - -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala deleted file mode 100644 index f826b98..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala +++ /dev/null @@ -1,113 +0,0 @@ -package xyz.driver.pdsuidomain.services.rest - -import scala.concurrent.{ExecutionContext, Future} -import akka.NotUsed -import akka.stream.scaladsl.Source -import akka.util.ByteString -import akka.http.scaladsl.marshalling.Marshal -import akka.http.scaladsl.model._ -import akka.stream.Materializer -import xyz.driver.core.rest.{Pagination => _, _} -import xyz.driver.pdsuicommon.auth._ -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.ListResponse -import xyz.driver.pdsuidomain.formats.json.export.ApiExportTrialWithLabels -import xyz.driver.pdsuidomain.formats.json.trial.ApiTrial -import xyz.driver.pdsuidomain.services.TrialService - -class RestTrialService(transport: ServiceTransport, baseUri: Uri)(implicit protected val materializer: Materializer, - protected val exec: ExecutionContext) - extends TrialService with RestHelper { - - import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ - import xyz.driver.pdsuidomain.services.TrialService._ - - def getById(id: StringId[Trial])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/trial/$id")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiTrial](response) - } yield { - GetByIdReply.Entity(reply.toDomain) - } - } - - def getTrialWithLabels(trialId: StringId[Trial], condition: String)( - implicit requestContext: AuthenticatedRequestContext): Future[GetTrialWithLabelsReply] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/export/trial/$trialId")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiExportTrialWithLabels](response) - } yield { - GetTrialWithLabelsReply.Entity(reply.toDomain) - } - } - - def getPdfSource(trialId: StringId[Trial])( - implicit requestContext: AuthenticatedRequestContext): Future[Source[ByteString, NotUsed]] = { - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/trial/${trialId}/source")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[HttpEntity](response) - } yield { - reply.dataBytes.mapMaterializedValue(_ => NotUsed) - } - } - - def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty, - sorting: Option[Sorting] = None, - pagination: Option[Pagination] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = { - val request = HttpRequest( - HttpMethods.GET, - endpointUri(baseUri, "/v1/trial", filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination))) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ListResponse[ApiTrial]](response) - } yield { - GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate) - } - } - - def update(origTrial: Trial, draftTrial: Trial)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - val id = origTrial.id.id - for { - entity <- Marshal(ApiTrial.fromDomain(draftTrial)).to[RequestEntity] - request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/trial/$id")).withEntity(entity) - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiTrial](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - - private def singleAction(origTrial: Trial, action: String)( - implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = { - val id = origTrial.id.id - val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/trial/$id/$action")) - for { - response <- transport.sendRequestGetResponse(requestContext)(request) - reply <- apiResponse[ApiTrial](response) - } yield { - UpdateReply.Updated(reply.toDomain) - } - } - - def start(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - singleAction(origTrial, "start") - def submit(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - singleAction(origTrial, "submit") - def restart(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - singleAction(origTrial, "restart") - def flag(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - singleAction(origTrial, "flag") - def resolve(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - singleAction(origTrial, "resolve") - def archive(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - singleAction(origTrial, "archive") - def unassign(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = - singleAction(origTrial, "unassign") -} diff --git a/src/main/scala/xyz/driver/restquery/db/SlickPostgresQueryBuilder.scala b/src/main/scala/xyz/driver/restquery/db/SlickPostgresQueryBuilder.scala new file mode 100644 index 0000000..0b3fece --- /dev/null +++ b/src/main/scala/xyz/driver/restquery/db/SlickPostgresQueryBuilder.scala @@ -0,0 +1,118 @@ +package xyz.driver.restquery.db + +import java.time.{LocalDateTime, ZoneOffset} + +import org.slf4j.LoggerFactory +import slick.jdbc.{GetResult, JdbcProfile} +import xyz.driver.core.database.SlickDal +import xyz.driver.restquery.query.{Pagination, SearchFilterExpr, Sorting} + +import scala.collection.breakOut +import scala.concurrent.ExecutionContext + +object SlickPostgresQueryBuilder { + private val logger = LoggerFactory.getLogger(this.getClass) + + import xyz.driver.restquery.db.SlickQueryBuilder._ + + def apply[T]( + databaseName: String, + tableName: String, + lastUpdateFieldName: Option[String], + nullableFields: Set[String], + links: Set[SlickTableLink], + runner: Runner[T], + countRunner: CountRunner)( + implicit sqlContext: SlickDal, + profile: JdbcProfile, + getResult: GetResult[T], + ec: ExecutionContext): SlickPostgresQueryBuilder[T] = { + val parameters = SlickPostgresQueryBuilderParameters( + databaseName = databaseName, + tableData = TableData(tableName, lastUpdateFieldName, nullableFields), + links = links.map(x => x.foreignTableName -> x)(breakOut) + ) + new SlickPostgresQueryBuilder[T](parameters)(runner, countRunner) + } + + def apply[T]( + databaseName: String, + tableName: String, + lastUpdateFieldName: Option[String], + nullableFields: Set[String], + links: Set[SlickTableLink])( + implicit sqlContext: SlickDal, + profile: JdbcProfile, + getResult: GetResult[T], + ec: ExecutionContext): SlickPostgresQueryBuilder[T] = { + apply[T](databaseName, tableName, SlickQueryBuilderParameters.AllFields, lastUpdateFieldName, nullableFields, links) + } + + def apply[T]( + databaseName: String, + tableName: String, + fields: Set[String], + lastUpdateFieldName: Option[String], + nullableFields: Set[String], + links: Set[SlickTableLink])( + implicit sqlContext: SlickDal, + profile: JdbcProfile, + getResult: GetResult[T], + ec: ExecutionContext): SlickPostgresQueryBuilder[T] = { + + val runner: Runner[T] = { parameters => + val sql = parameters.toSql(countQuery = false, fields = fields).as[T] + logger.debug(s"Built an SQL query: $sql") + sqlContext.execute(sql) + } + + val countRunner: CountRunner = { parameters => + implicit val getCountResult: GetResult[(Int, Option[LocalDateTime])] = GetResult({ r => + val count = r.rs.getInt(1) + val lastUpdate = if (parameters.tableData.lastUpdateFieldName.isDefined) { + Option(r.rs.getTimestamp(2)).map(timestampToLocalDateTime) + } else None + (count, lastUpdate) + }) + val sql = parameters.toSql(countQuery = true).as[(Int, Option[LocalDateTime])] + logger.debug(s"Built an SQL query returning count: $sql") + sqlContext.execute(sql).map(_.head) + } + + apply[T]( + databaseName = databaseName, + tableName = tableName, + lastUpdateFieldName = lastUpdateFieldName, + nullableFields = nullableFields, + links = links, + runner = runner, + countRunner = countRunner + ) + } + + def timestampToLocalDateTime(timestamp: java.sql.Timestamp): LocalDateTime = { + LocalDateTime.ofInstant(timestamp.toInstant, ZoneOffset.UTC) + } +} + +class SlickPostgresQueryBuilder[T](parameters: SlickPostgresQueryBuilderParameters)( + implicit runner: SlickQueryBuilder.Runner[T], + countRunner: SlickQueryBuilder.CountRunner) + extends SlickQueryBuilder[T](parameters) { + + def withFilter(newFilter: SearchFilterExpr): SlickQueryBuilder[T] = { + new SlickPostgresQueryBuilder[T](parameters.copy(filter = newFilter)) + } + + def withSorting(newSorting: Sorting): SlickQueryBuilder[T] = { + new SlickPostgresQueryBuilder[T](parameters.copy(sorting = newSorting)) + } + + def withPagination(newPagination: Pagination): SlickQueryBuilder[T] = { + new SlickPostgresQueryBuilder[T](parameters.copy(pagination = Some(newPagination))) + } + + def resetPagination: SlickQueryBuilder[T] = { + new SlickPostgresQueryBuilder[T](parameters.copy(pagination = None)) + } +} diff --git a/src/main/scala/xyz/driver/restquery/db/SlickQueryBuilder.scala b/src/main/scala/xyz/driver/restquery/db/SlickQueryBuilder.scala new file mode 100644 index 0000000..67ce9f4 --- /dev/null +++ b/src/main/scala/xyz/driver/restquery/db/SlickQueryBuilder.scala @@ -0,0 +1,138 @@ +package xyz.driver.restquery.db + +import java.sql.{JDBCType, PreparedStatement} +import java.time.LocalDateTime + +import slick.jdbc.{JdbcProfile, PositionedParameters, SQLActionBuilder, SetParameter} +import xyz.driver.restquery.query._ + +import scala.concurrent.{ExecutionContext, Future} + +object SlickQueryBuilder { + + type Runner[T] = SlickQueryBuilderParameters => Future[Seq[T]] + + type CountResult = Future[(Int, Option[LocalDateTime])] + + type CountRunner = SlickQueryBuilderParameters => CountResult + + /** + * Binder for PreparedStatement + */ + type Binder = PreparedStatement => PreparedStatement + + final case class TableData( + tableName: String, + lastUpdateFieldName: Option[String] = None, + nullableFields: Set[String] = Set.empty) + + val AllFields = Set("*") + + implicit class SQLActionBuilderConcat(a: SQLActionBuilder) { + def concat(b: SQLActionBuilder): SQLActionBuilder = { + SQLActionBuilder(a.queryParts ++ b.queryParts, (p: Unit, pp: PositionedParameters) => { + a.unitPConv.apply(p, pp) + b.unitPConv.apply(p, pp) + }) + } + } + + implicit object SetQueryParameter extends SetParameter[AnyRef] { + def apply(v: AnyRef, pp: PositionedParameters) = { + pp.setObject(v, JDBCType.BINARY.getVendorTypeNumber) + } + } +} + +final case class SlickTableLink(keyColumnName: String, foreignTableName: String, foreignKeyColumnName: String) + +final case class SlickPostgresQueryBuilderParameters( + databaseName: String, + tableData: SlickQueryBuilder.TableData, + links: Map[String, SlickTableLink] = Map.empty, + filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Sorting = Sorting.Empty, + pagination: Option[Pagination] = None) + extends SlickQueryBuilderParameters { + + def limitToSql()(implicit profile: JdbcProfile): SQLActionBuilder = { + import profile.api._ + pagination.map { pagination => + val startFrom = (pagination.pageNumber - 1) * pagination.pageSize + sql"limit #${pagination.pageSize} OFFSET #$startFrom" + } getOrElse (sql"") + } + + val qs = """"""" + +} + +/** + * @param links Links to another tables grouped by foreignTableName + */ +final case class SlickMysqlQueryBuilderParameters( + databaseName: String, + tableData: SlickQueryBuilder.TableData, + links: Map[String, SlickTableLink] = Map.empty, + filter: SearchFilterExpr = SearchFilterExpr.Empty, + sorting: Sorting = Sorting.Empty, + pagination: Option[Pagination] = None) + extends SlickQueryBuilderParameters { + + def limitToSql()(implicit profile: JdbcProfile): SQLActionBuilder = { + import profile.api._ + pagination + .map { pagination => + val startFrom = (pagination.pageNumber - 1) * pagination.pageSize + sql"limit #$startFrom, #${pagination.pageSize}" + } + .getOrElse(sql"") + } + + val qs = """`""" + +} + +abstract class SlickQueryBuilder[T](val parameters: SlickQueryBuilderParameters)( + implicit runner: SlickQueryBuilder.Runner[T], + countRunner: SlickQueryBuilder.CountRunner) { + + def run()(implicit ec: ExecutionContext): Future[Seq[T]] = runner(parameters) + + def runCount()(implicit ec: ExecutionContext): SlickQueryBuilder.CountResult = countRunner(parameters) + + /** + * Runs the query and returns total found rows without considering of pagination. + */ + def runWithCount()(implicit ec: ExecutionContext): Future[(Seq[T], Int, Option[LocalDateTime])] = { + for { + all <- run + (total, lastUpdate) <- runCount + } yield (all, total, lastUpdate) + } + + def withFilter(newFilter: SearchFilterExpr): SlickQueryBuilder[T] + + def withFilter(filter: Option[SearchFilterExpr]): SlickQueryBuilder[T] = { + filter.fold(this)(withFilter) + } + + def resetFilter: SlickQueryBuilder[T] = withFilter(SearchFilterExpr.Empty) + + def withSorting(newSorting: Sorting): SlickQueryBuilder[T] + + def withSorting(sorting: Option[Sorting]): SlickQueryBuilder[T] = { + sorting.fold(this)(withSorting) + } + + def resetSorting: SlickQueryBuilder[T] = withSorting(Sorting.Empty) + + def withPagination(newPagination: Pagination): SlickQueryBuilder[T] + + def withPagination(pagination: Option[Pagination]): SlickQueryBuilder[T] = { + pagination.fold(this)(withPagination) + } + + def resetPagination: SlickQueryBuilder[T] + +} diff --git a/src/main/scala/xyz/driver/restquery/db/SlickQueryBuilderParameters.scala b/src/main/scala/xyz/driver/restquery/db/SlickQueryBuilderParameters.scala new file mode 100644 index 0000000..d4d1761 --- /dev/null +++ b/src/main/scala/xyz/driver/restquery/db/SlickQueryBuilderParameters.scala @@ -0,0 +1,245 @@ +package xyz.driver.restquery.db + +import java.sql.PreparedStatement + +import slick.jdbc.{JdbcProfile, SQLActionBuilder} +import xyz.driver.restquery.query.Sorting.{Dimension, Sequential} +import xyz.driver.restquery.query.SortingOrder.{Ascending, Descending} +import xyz.driver.restquery.query._ + +object SlickQueryBuilderParameters { + val AllFields = Set("*") +} + +trait SlickQueryBuilderParameters { + import SlickQueryBuilder._ + + def databaseName: String + def tableData: SlickQueryBuilder.TableData + def links: Map[String, SlickTableLink] + def filter: SearchFilterExpr + def sorting: Sorting + def pagination: Option[Pagination] + + def qs: String + + def findLink(tableName: String): SlickTableLink = links.get(tableName) match { + case None => throw new IllegalArgumentException(s"Cannot find a link for `$tableName`") + case Some(link) => link + } + + def toSql(countQuery: Boolean = false)(implicit profile: JdbcProfile): SQLActionBuilder = { + toSql(countQuery, SlickQueryBuilderParameters.AllFields) + } + + def toSql(countQuery: Boolean, fields: Set[String])(implicit profile: JdbcProfile): SQLActionBuilder = { + import profile.api._ + val escapedTableName = s"""$qs$databaseName$qs.$qs${tableData.tableName}$qs""" + val fieldsSql: String = if (countQuery) { + val suffix: String = tableData.lastUpdateFieldName match { + case Some(lastUpdateField) => s", max($escapedTableName.$qs$lastUpdateField$qs)" + case None => "" + } + s"count(*) $suffix" + } else { + if (fields == SlickQueryBuilderParameters.AllFields) { + s"$escapedTableName.*" + } else { + fields + .map { field => + s"$escapedTableName.$qs$field$qs" + } + .mkString(", ") + } + } + val where = filterToSql(escapedTableName, filter) + val orderBy = sortingToSql(escapedTableName, sorting) + + val limitSql = limitToSql() + + val sql = sql"""select #$fieldsSql from #$escapedTableName""" + + val filtersTableLinks: Seq[SlickTableLink] = { + import SearchFilterExpr._ + def aux(expr: SearchFilterExpr): Seq[SlickTableLink] = expr match { + case Atom.TableName(tableName) => List(findLink(tableName)) + case Intersection(xs) => xs.flatMap(aux) + case Union(xs) => xs.flatMap(aux) + case _ => Nil + } + aux(filter) + } + + val sortingTableLinks: Seq[SlickTableLink] = Sorting.collect(sorting) { + case Dimension(Some(foreignTableName), _, _) => findLink(foreignTableName) + } + + // Combine links from sorting and filter without duplicates + val foreignTableLinks = (filtersTableLinks ++ sortingTableLinks).distinct + + def fkSql(fkLinksSql: SQLActionBuilder, tableLinks: Seq[SlickTableLink]): SQLActionBuilder = { + if (tableLinks.nonEmpty) { + tableLinks.head match { + case SlickTableLink(keyColumnName, foreignTableName, foreignKeyColumnName) => + val escapedForeignTableName = s"$qs$databaseName$qs.$qs$foreignTableName$qs" + val join = sql""" inner join #$escapedForeignTableName + on #$escapedTableName.#$qs#$keyColumnName#$qs=#$escapedForeignTableName.#$qs#$foreignKeyColumnName#$qs""" + fkSql(fkLinksSql concat join, tableLinks.tail) + } + } else fkLinksSql + } + val foreignTableLinksSql = fkSql(sql"", foreignTableLinks) + + val whereSql = if (where.queryParts.size > 1) { + sql" where " concat where + } else sql"" + + val orderSql = if (orderBy.nonEmpty && !countQuery) { + sql" order by #$orderBy" + } else sql"" + + val limSql = if (limitSql.queryParts.size > 1 && !countQuery) { + sql" " concat limitSql + } else sql"" + + sql concat foreignTableLinksSql concat whereSql concat orderSql concat limSql + } + + /** + * Converts filter expression to SQL expression. + * + * @return Returns SQL string and list of values for binding in prepared statement. + */ + protected def filterToSql(escapedTableName: String, filter: SearchFilterExpr)( + implicit profile: JdbcProfile): SQLActionBuilder = { + import SearchFilterBinaryOperation._ + import SearchFilterExpr._ + import profile.api._ + + def isNull(string: AnyRef) = Option(string).isEmpty || string.toString.toLowerCase == "null" + + def escapeDimension(dimension: SearchFilterExpr.Dimension) = { + s"${dimension.tableName.map(t => s"$qs$databaseName$qs.$qs$t$qs").getOrElse(escapedTableName)}.$qs${dimension.name}$qs" + } + + def filterToSqlMultiple(operands: Seq[SearchFilterExpr]) = operands.collect { + case x if !SearchFilterExpr.isEmpty(x) => filterToSql(escapedTableName, x) + } + + def multipleSqlToAction( + first: Boolean, + op: String, + conditions: Seq[SQLActionBuilder], + sql: SQLActionBuilder): SQLActionBuilder = { + if (conditions.nonEmpty) { + val condition = conditions.head + if (first) { + multipleSqlToAction(first = false, op, conditions.tail, condition) + } else { + multipleSqlToAction(first = false, op, conditions.tail, sql concat sql" #${op} " concat condition) + } + } else sql + } + + def concatenateParameters(sql: SQLActionBuilder, first: Boolean, tail: Seq[AnyRef]): SQLActionBuilder = { + if (tail.nonEmpty) { + if (!first) { + concatenateParameters(sql concat sql""",${tail.head}""", first = false, tail.tail) + } else { + concatenateParameters(sql"""(${tail.head}""", first = false, tail.tail) + } + } else sql concat sql")" + } + + filter match { + case x if isEmpty(x) => + sql"" + + case AllowAll => + sql"1=1" + + case DenyAll => + sql"1=0" + + case Atom.Binary(dimension, Eq, value) if isNull(value) => + sql"#${escapeDimension(dimension)} is NULL" + + case Atom.Binary(dimension, NotEq, value) if isNull(value) => + sql"#${escapeDimension(dimension)} is not NULL" + + case Atom.Binary(dimension, NotEq, value) if tableData.nullableFields.contains(dimension.name) => + // In MySQL NULL <> Any === NULL + // So, to handle NotEq for nullable fields we need to use more complex SQL expression. + // http://dev.mysql.com/doc/refman/5.7/en/working-with-null.html + val escapedColumn = escapeDimension(dimension) + sql"(#${escapedColumn} is null or #${escapedColumn} != $value)" + + case Atom.Binary(dimension, op, value) => + val operator = op match { + case Eq => sql"=" + case NotEq => sql"!=" + case Like => sql" like " + case Gt => sql">" + case GtEq => sql">=" + case Lt => sql"<" + case LtEq => sql"<=" + } + sql"#${escapeDimension(dimension)}" concat operator concat sql"""$value""" + + case Atom.NAry(dimension, op, values) => + val sqlOp = op match { + case SearchFilterNAryOperation.In => sql" in " + case SearchFilterNAryOperation.NotIn => sql" not in " + } + + if (values.nonEmpty) { + val formattedValues = concatenateParameters(sql"", first = true, values) + sql"#${escapeDimension(dimension)}" concat sqlOp concat formattedValues + } else { + sql"1=0" + } + + case Intersection(operands) => + val filter = multipleSqlToAction(first = true, "and", filterToSqlMultiple(operands), sql"") + sql"(" concat filter concat sql")" + + case Union(operands) => + val filter = multipleSqlToAction(first = true, "or", filterToSqlMultiple(operands), sql"") + sql"(" concat filter concat sql")" + } + } + + protected def limitToSql()(implicit profile: JdbcProfile): SQLActionBuilder + + /** + * @param escapedMainTableName Should be escaped + */ + protected def sortingToSql(escapedMainTableName: String, sorting: Sorting)(implicit profile: JdbcProfile): String = { + sorting match { + case Dimension(optSortingTableName, field, order) => + val sortingTableName = + optSortingTableName.map(x => s"$qs$databaseName$qs.$qs$x$qs").getOrElse(escapedMainTableName) + val fullName = s"$sortingTableName.$qs$field$qs" + + s"$fullName ${orderToSql(order)}" + + case Sequential(xs) => + xs.map(sortingToSql(escapedMainTableName, _)).mkString(", ") + } + } + + protected def orderToSql(x: SortingOrder): String = x match { + case Ascending => "asc" + case Descending => "desc" + } + + protected def binder(bindings: List[AnyRef])(bind: PreparedStatement): PreparedStatement = { + bindings.zipWithIndex.foreach { + case (binding, index) => + bind.setObject(index + 1, binding) + } + + bind + } + +} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/Pagination.scala b/src/main/scala/xyz/driver/restquery/query/Pagination.scala index 92689dd..b899d1b 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/db/Pagination.scala +++ b/src/main/scala/xyz/driver/restquery/query/Pagination.scala @@ -1,6 +1,4 @@ -package xyz.driver.pdsuicommon.db - -import xyz.driver.pdsuicommon.logging._ +package xyz.driver.restquery.query /** * @param pageNumber Starts with 1 @@ -11,9 +9,4 @@ object Pagination { // @see https://driverinc.atlassian.net/wiki/display/RA/REST+API+Specification#RESTAPISpecification-CommonRequestQueryParametersForWebServices val Default = Pagination(pageSize = 100, pageNumber = 1) - - implicit def toPhiString(x: Pagination): PhiString = { - import x._ - phi"Pagination(pageSize=${Unsafe(pageSize)}, pageNumber=${Unsafe(pageNumber)})" - } } diff --git a/src/main/scala/xyz/driver/restquery/query/SearchFilterBinaryOperation.scala b/src/main/scala/xyz/driver/restquery/query/SearchFilterBinaryOperation.scala new file mode 100644 index 0000000..30d210c --- /dev/null +++ b/src/main/scala/xyz/driver/restquery/query/SearchFilterBinaryOperation.scala @@ -0,0 +1,15 @@ +package xyz.driver.restquery.query + +sealed trait SearchFilterBinaryOperation + +object SearchFilterBinaryOperation { + + case object Eq extends SearchFilterBinaryOperation + case object NotEq extends SearchFilterBinaryOperation + case object Like extends SearchFilterBinaryOperation + case object Gt extends SearchFilterBinaryOperation + case object GtEq extends SearchFilterBinaryOperation + case object Lt extends SearchFilterBinaryOperation + case object LtEq extends SearchFilterBinaryOperation + +} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/SearchFilterExpr.scala b/src/main/scala/xyz/driver/restquery/query/SearchFilterExpr.scala index 0577921..8cbf685 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/db/SearchFilterExpr.scala +++ b/src/main/scala/xyz/driver/restquery/query/SearchFilterExpr.scala @@ -1,6 +1,4 @@ -package xyz.driver.pdsuicommon.db - -import xyz.driver.pdsuicommon.logging._ +package xyz.driver.restquery.query sealed trait SearchFilterExpr { def find(p: SearchFilterExpr => Boolean): Option[SearchFilterExpr] @@ -9,7 +7,7 @@ sealed trait SearchFilterExpr { object SearchFilterExpr { - val Empty = Intersection.Empty + val Empty: Intersection = Intersection.Empty val Forbid = Atom.Binary( dimension = Dimension(None, "true"), op = SearchFilterBinaryOperation.Eq, @@ -22,8 +20,7 @@ object SearchFilterExpr { sealed trait Atom extends SearchFilterExpr { override def find(p: SearchFilterExpr => Boolean): Option[SearchFilterExpr] = { - if (p(this)) Some(this) - else None + Some(this).filter(p) } override def replace(f: PartialFunction[SearchFilterExpr, SearchFilterExpr]): SearchFilterExpr = { @@ -132,8 +129,7 @@ object SearchFilterExpr { case object AllowAll extends SearchFilterExpr { override def find(p: SearchFilterExpr => Boolean): Option[SearchFilterExpr] = { - if (p(this)) Some(this) - else None + Some(this).filter(p) } override def replace(f: PartialFunction[SearchFilterExpr, SearchFilterExpr]): SearchFilterExpr = { @@ -144,8 +140,7 @@ object SearchFilterExpr { case object DenyAll extends SearchFilterExpr { override def find(p: SearchFilterExpr => Boolean): Option[SearchFilterExpr] = { - if (p(this)) Some(this) - else None + Some(this).filter(p) } override def replace(f: PartialFunction[SearchFilterExpr, SearchFilterExpr]): SearchFilterExpr = { @@ -173,36 +168,6 @@ object SearchFilterExpr { } } } - } - // There is no case, when this is unsafe. At this time. - implicit def toPhiString(x: SearchFilterExpr): PhiString = { - if (isEmpty(x)) Unsafe("SearchFilterExpr.Empty") - else Unsafe(x.toString) - } - -} - -sealed trait SearchFilterBinaryOperation - -object SearchFilterBinaryOperation { - - case object Eq extends SearchFilterBinaryOperation - case object NotEq extends SearchFilterBinaryOperation - case object Like extends SearchFilterBinaryOperation - case object Gt extends SearchFilterBinaryOperation - case object GtEq extends SearchFilterBinaryOperation - case object Lt extends SearchFilterBinaryOperation - case object LtEq extends SearchFilterBinaryOperation - -} - -sealed trait SearchFilterNAryOperation - -object SearchFilterNAryOperation { - - case object In extends SearchFilterNAryOperation - case object NotIn extends SearchFilterNAryOperation - } diff --git a/src/main/scala/xyz/driver/restquery/query/SearchFilterNAryOperation.scala b/src/main/scala/xyz/driver/restquery/query/SearchFilterNAryOperation.scala new file mode 100644 index 0000000..a388597 --- /dev/null +++ b/src/main/scala/xyz/driver/restquery/query/SearchFilterNAryOperation.scala @@ -0,0 +1,10 @@ +package xyz.driver.restquery.query + +sealed trait SearchFilterNAryOperation + +object SearchFilterNAryOperation { + + case object In extends SearchFilterNAryOperation + case object NotIn extends SearchFilterNAryOperation + +} diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/Sorting.scala b/src/main/scala/xyz/driver/restquery/query/Sorting.scala index a2c5a75..af0066b 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/db/Sorting.scala +++ b/src/main/scala/xyz/driver/restquery/query/Sorting.scala @@ -1,6 +1,4 @@ -package xyz.driver.pdsuicommon.db - -import xyz.driver.pdsuicommon.logging._ +package xyz.driver.restquery.query import scala.collection.generic.CanBuildFrom @@ -40,22 +38,19 @@ object Sorting { def filter(sorting: Sorting, p: Dimension => Boolean): Seq[Dimension] = sorting match { case x: Dimension if p(x) => Seq(x) - case x: Dimension => Seq.empty + case _: Dimension => Seq.empty case Sequential(xs) => xs.filter(p) } def collect[B, That](sorting: Sorting)(f: PartialFunction[Dimension, B])( - implicit bf: CanBuildFrom[Seq[Dimension], B, That]): That = sorting match { + implicit bf: CanBuildFrom[Seq[Dimension], B, That]): That = sorting match { case x: Dimension if f.isDefinedAt(x) => val r = bf.apply() r += f(x) r.result() - case x: Dimension => bf.apply().result() + case _: Dimension => bf.apply().result() case Sequential(xs) => xs.collect(f) } - // Contains dimensions and ordering only, thus it is safe. - implicit def toPhiString(x: Sorting): PhiString = Unsafe(x.toString) - } diff --git a/src/main/scala/xyz/driver/restquery/rest/Directives.scala b/src/main/scala/xyz/driver/restquery/rest/Directives.scala new file mode 100644 index 0000000..a8dcb3b --- /dev/null +++ b/src/main/scala/xyz/driver/restquery/rest/Directives.scala @@ -0,0 +1,46 @@ +package xyz.driver.restquery.rest + +import akka.http.scaladsl.server.Directives._ +import akka.http.scaladsl.server._ +import xyz.driver.restquery.query.{SearchFilterExpr, _} +import xyz.driver.restquery.rest.parsers._ + +import scala.util._ + +trait Directives { + + val paginated: Directive1[Pagination] = parameterSeq.flatMap { params => + PaginationParser.parse(params) match { + case Success(pagination) => provide(pagination) + case Failure(ex) => + reject(ValidationRejection("invalid pagination parameter", Some(ex))) + } + } + + def sorted(validDimensions: Set[String] = Set.empty): Directive1[Sorting] = parameterSeq.flatMap { params => + SortingParser.parse(validDimensions, params) match { + case Success(sorting) => provide(sorting) + case Failure(ex) => + reject(ValidationRejection("invalid sorting parameter", Some(ex))) + } + } + + val dimensioned: Directive1[Dimensions] = parameterSeq.flatMap { params => + DimensionsParser.tryParse(params) match { + case Success(dims) => provide(dims) + case Failure(ex) => + reject(ValidationRejection("invalid dimension parameter", Some(ex))) + } + } + + val searchFiltered: Directive1[SearchFilterExpr] = parameterSeq.flatMap { params => + SearchFilterParser.parse(params) match { + case Success(sorting) => provide(sorting) + case Failure(ex) => + reject(ValidationRejection("invalid filter parameter", Some(ex))) + } + } + +} + +object Directives extends Directives diff --git a/src/main/scala/xyz/driver/pdsuicommon/parsers/DimensionsParser.scala b/src/main/scala/xyz/driver/restquery/rest/parsers/DimensionsParser.scala index 17c09ed..3472e40 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/parsers/DimensionsParser.scala +++ b/src/main/scala/xyz/driver/restquery/rest/parsers/DimensionsParser.scala @@ -1,4 +1,4 @@ -package xyz.driver.pdsuicommon.parsers +package xyz.driver.restquery.rest.parsers import scala.util.{Failure, Success, Try} diff --git a/src/main/scala/xyz/driver/pdsuicommon/parsers/PaginationParser.scala b/src/main/scala/xyz/driver/restquery/rest/parsers/PaginationParser.scala index b59b1a5..6d8aaf8 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/parsers/PaginationParser.scala +++ b/src/main/scala/xyz/driver/restquery/rest/parsers/PaginationParser.scala @@ -1,17 +1,11 @@ -package xyz.driver.pdsuicommon.parsers +package xyz.driver.restquery.rest.parsers + +import xyz.driver.restquery.query.Pagination -import xyz.driver.pdsuicommon.db._ import scala.util._ object PaginationParser { - @deprecated("play-akka transition", "0") - def parse(query: Map[String, Seq[String]]): Try[Pagination] = - parse(query.toSeq.flatMap { - case (key, values) => - values.map(value => key -> value) - }) - def parse(query: Seq[(String, String)]): Try[Pagination] = { val IntString = """(\d+)""".r def validate(field: String, default: Int) = query.collectFirst { case (`field`, size) => size } match { @@ -22,8 +16,9 @@ object PaginationParser { } Try { - Pagination(validate("pageSize", Pagination.Default.pageSize), - validate("pageNumber", Pagination.Default.pageNumber)) + Pagination( + validate("pageSize", Pagination.Default.pageSize), + validate("pageNumber", Pagination.Default.pageNumber)) } } } diff --git a/src/main/scala/xyz/driver/pdsuicommon/parsers/ParseQueryArgException.scala b/src/main/scala/xyz/driver/restquery/rest/parsers/ParseQueryArgException.scala index 64b3d2e..456329e 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/parsers/ParseQueryArgException.scala +++ b/src/main/scala/xyz/driver/restquery/rest/parsers/ParseQueryArgException.scala @@ -1,3 +1,3 @@ -package xyz.driver.pdsuicommon.parsers +package xyz.driver.restquery.rest.parsers class ParseQueryArgException(val errors: (String, String)*) extends Exception(errors.mkString(",")) diff --git a/src/main/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParser.scala b/src/main/scala/xyz/driver/restquery/rest/parsers/SearchFilterParser.scala index 768e5f5..52a31bf 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParser.scala +++ b/src/main/scala/xyz/driver/restquery/rest/parsers/SearchFilterParser.scala @@ -1,10 +1,12 @@ -package xyz.driver.pdsuicommon.parsers +package xyz.driver.restquery.rest.parsers + +import java.util.UUID -import xyz.driver.pdsuicommon.utils.Implicits.{toCharOps, toStringOps} import fastparse.all._ import fastparse.core.Parsed -import fastparse.parsers.Intrinsics.CharPred -import xyz.driver.pdsuicommon.db.{SearchFilterBinaryOperation, SearchFilterExpr, SearchFilterNAryOperation} +import xyz.driver.restquery.query.{SearchFilterBinaryOperation, SearchFilterExpr, SearchFilterNAryOperation} +import xyz.driver.restquery.utils.Utils +import xyz.driver.restquery.utils.Utils._ import scala.util.Try @@ -12,10 +14,12 @@ import scala.util.Try object SearchFilterParser { private object BinaryAtomFromTuple { - def unapply(input: (SearchFilterExpr.Dimension, (String, String))): Option[SearchFilterExpr.Atom.Binary] = { + def unapply(input: (SearchFilterExpr.Dimension, (String, Any))): Option[SearchFilterExpr.Atom.Binary] = { val (dimensionName, (strOperation, value)) = input + val updatedValue = trimIfString(value) + parseOperation(strOperation.toLowerCase).map { op => - SearchFilterExpr.Atom.Binary(dimensionName, op, value.safeTrim) + SearchFilterExpr.Atom.Binary(dimensionName, op, updatedValue.asInstanceOf[AnyRef]) } } } @@ -24,17 +28,26 @@ 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 => Utils.safeTrim(s) + case a => a + } + private val operationsMapping = { - import xyz.driver.pdsuicommon.db.SearchFilterBinaryOperation._ + import xyz.driver.restquery.query.SearchFilterBinaryOperation._ Map[String, SearchFilterBinaryOperation]( "eq" -> Eq, @@ -49,14 +62,15 @@ object SearchFilterParser { private def parseOperation(x: String): Option[SearchFilterBinaryOperation] = operationsMapping.get(x) - private val whitespaceParser = P(CharPred(_.isSafeWhitespace)) + private val whitespaceParser = P(CharPred(Utils.isSafeWhitespace)) val dimensionParser: Parser[SearchFilterExpr.Dimension] = { val identParser = P( CharPred(c => c.isLetterOrDigit) - .rep(min = 1)).!.map(SearchFilterExpr.Dimension(None, _)) + .rep(min = 1)).!.map(s => SearchFilterExpr.Dimension(None, toSnakeCase(s))) val pathParser = P(identParser.! ~ "." ~ identParser.!) map { - case (left, right) => SearchFilterExpr.Dimension(Some(left), right) + case (left, right) => + SearchFilterExpr.Dimension(Some(toSnakeCase(left)), toSnakeCase(right)) } P(pathParser | identParser) } @@ -66,7 +80,7 @@ object SearchFilterParser { } private val numericOperatorParser: Parser[String] = { - P((IgnoreCase("gt") | IgnoreCase("lt")) ~ IgnoreCase("eq").?).! + P(IgnoreCase("eq") | IgnoreCase("noteq") | ((IgnoreCase("gt") | IgnoreCase("lt")) ~ IgnoreCase("eq").?)).! } private val naryOperatorParser: Parser[String] = P(IgnoreCase("in")).! @@ -76,10 +90,8 @@ object SearchFilterParser { case _ => true } - // Exclude Unicode "digits" - private val digitsParser: Parser[String] = P(CharIn('0' to '9').rep(min = 1).!) + private val digitsParser: Parser[String] = P(CharIn('0' to '9').rep(min = 1).!) // Exclude Unicode "digits" - // @TODO Make complex checking here private val numberParser: Parser[String] = P(isPositiveParser ~ digitsParser.! ~ ("." ~ digitsParser).!.?).map { case (false, intPart, Some(fracPart)) => s"-$intPart.${fracPart.tail}" case (false, intPart, None) => s"-$intPart" @@ -89,19 +101,35 @@ object SearchFilterParser { private val nAryValueParser: Parser[String] = P(CharPred(_ != ',').rep(min = 1).!) + private val longParser: Parser[Long] = P(CharIn('0' to '9').rep(min = 1).!.map(_.toLong)) + + private val booleanParser: Parser[Boolean] = + P((IgnoreCase("true") | IgnoreCase("false")).!.map(_.toBoolean)) + + private val hexDigit: Parser[String] = P((CharIn('a' to 'f') | CharIn('A' to 'F') | CharIn('0' to '9')).!) + + private val uuidParser: Parser[UUID] = + P( + hexDigit.rep(8).! ~ "-" ~ hexDigit.rep(4).! ~ "-" ~ hexDigit.rep(4).! ~ "-" ~ hexDigit.rep(4).! ~ "-" ~ hexDigit + .rep(12) + .!).map { + case (group1, group2, group3, group4, group5) => UUID.fromString(s"$group1-$group2-$group3-$group4-$group5") + } + private val binaryAtomParser: Parser[SearchFilterExpr.Atom.Binary] = P( - dimensionParser ~ whitespaceParser ~ ( - (commonOperatorParser.! ~/ whitespaceParser ~/ AnyChar.rep(min = 1).!) - | (numericOperatorParser.! ~/ whitespaceParser ~/ numberParser.!) - ) ~ End + dimensionParser ~ whitespaceParser ~ + ((numericOperatorParser.! ~ whitespaceParser ~ (longParser | numberParser.!) ~ End) | + (commonOperatorParser.! ~ whitespaceParser ~ (uuidParser | booleanParser | AnyChar.rep(min = 1).!) ~ End)) ).map { case BinaryAtomFromTuple(atom) => atom } private val nAryAtomParser: Parser[SearchFilterExpr.Atom.NAry] = P( dimensionParser ~ whitespaceParser ~ ( - naryOperatorParser ~/ whitespaceParser ~/ nAryValueParser.!.rep(min = 1, sep = ",") - ) ~ End + naryOperatorParser ~ whitespaceParser ~ + ((longParser.rep(min = 1, sep = ",") ~ End) | (booleanParser.rep(min = 1, sep = ",") ~ End) | + (nAryValueParser.!.rep(min = 1, sep = ",") ~ End)) + ) ).map { case NAryAtomFromTuple(atom) => atom } @@ -121,14 +149,14 @@ object SearchFilterParser { case head :: Nil => atomParser.parse(head) match { - case Parsed.Success(x, _) => x - case e: Parsed.Failure => throw new ParseQueryArgException("filters" -> formatFailure(1, e)) + case Parsed.Success(x, _) => x + case e: Parsed.Failure[_, _] => throw new ParseQueryArgException("filters" -> formatFailure(1, e)) } case xs => val parsed = xs.map(x => atomParser.parse(x)) val failures: Seq[String] = parsed.zipWithIndex.collect { - case (e: Parsed.Failure, index) => formatFailure(index, e) + case (e: Parsed.Failure[_, _], index) => formatFailure(index, e) } if (failures.isEmpty) { @@ -143,8 +171,8 @@ object SearchFilterParser { } } - private def formatFailure(sectionIndex: Int, e: Parsed.Failure): String = { - s"section $sectionIndex: ${ParseError.msg(e.extra.input, e.extra.traced.expected, e.index)}" + private def formatFailure(sectionIndex: Int, e: Parsed.Failure[_, _]): String = { + s"section $sectionIndex: ${fastparse.core.ParseError.msg(e.extra.input, e.extra.traced.expected, e.index)}" } } diff --git a/src/main/scala/xyz/driver/pdsuicommon/parsers/SortingParser.scala b/src/main/scala/xyz/driver/restquery/rest/parsers/SortingParser.scala index c1c332f..fce18d1 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/parsers/SortingParser.scala +++ b/src/main/scala/xyz/driver/restquery/rest/parsers/SortingParser.scala @@ -1,8 +1,9 @@ -package xyz.driver.pdsuicommon.parsers +package xyz.driver.restquery.rest.parsers -import xyz.driver.pdsuicommon.db.{Sorting, SortingOrder} import fastparse.all._ import fastparse.core.Parsed +import xyz.driver.restquery.query.{Sorting, SortingOrder} +import xyz.driver.restquery.utils.Utils._ import scala.util.Try @@ -18,8 +19,12 @@ object SortingParser { case (sortingOrder, field) => val prefixedFields = field.split("\\.", 2) prefixedFields.size match { - case 1 => Sorting.Dimension(None, field, sortingOrder) - case 2 => Sorting.Dimension(Some(prefixedFields.head), prefixedFields.last, sortingOrder) + case 1 => Sorting.Dimension(None, toSnakeCase(field), sortingOrder) + case 2 => + Sorting.Dimension( + Some(prefixedFields.head).map(toSnakeCase), + toSnakeCase(prefixedFields.last), + sortingOrder) } } } @@ -45,7 +50,7 @@ object SortingParser { val parser = sequentialSortingParser(validDimensions.toSeq) parser.parse(rawSorting) match { case Parsed.Success(x, _) => x - case e: Parsed.Failure => + case e: Parsed.Failure[_, _] => throw new ParseQueryArgException("sort" -> formatFailure(e)) } @@ -53,8 +58,8 @@ object SortingParser { } } - private def formatFailure(e: Parsed.Failure): String = { - ParseError.msg(e.extra.input, e.extra.traced.expected, e.index) + private def formatFailure(e: Parsed.Failure[_, _]): String = { + fastparse.core.ParseError.msg(e.extra.input, e.extra.traced.expected, e.index) } } diff --git a/src/main/scala/xyz/driver/restquery/utils/Utils.scala b/src/main/scala/xyz/driver/restquery/utils/Utils.scala new file mode 100644 index 0000000..827f2a0 --- /dev/null +++ b/src/main/scala/xyz/driver/restquery/utils/Utils.scala @@ -0,0 +1,78 @@ +package xyz.driver.restquery.utils + +import java.time.LocalDateTime +import java.util.regex.{Matcher, Pattern} + +object Utils { + + implicit val localDateTimeOrdering: Ordering[LocalDateTime] = Ordering.fromLessThan(_ isBefore _) + + /** + * Hack to avoid scala compiler bug with getSimpleName + * @see https://issues.scala-lang.org/browse/SI-2034 + */ + def getClassSimpleName(klass: Class[_]): String = { + try { + klass.getSimpleName + } catch { + case _: InternalError => + val fullName = klass.getName.stripSuffix("$") + val fullClassName = fullName.substring(fullName.lastIndexOf(".") + 1) + fullClassName.substring(fullClassName.lastIndexOf("$") + 1) + } + } + + def toSnakeCase(str: String): String = + str + .replaceAll("([A-Z]+)([A-Z][a-z])", "$1_$2") + .replaceAll("([a-z\\d])([A-Z])", "$1_$2") + .toLowerCase + + def toCamelCase(str: String): String = { + val sb = new StringBuffer() + def loop(m: Matcher): Unit = if (m.find()) { + m.appendReplacement(sb, m.group(1).toUpperCase()) + loop(m) + } + val m: Matcher = Pattern.compile("_(.)").matcher(str) + loop(m) + m.appendTail(sb) + sb.toString + } + + object Whitespace { + private val Table: String = + "\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000" + + "\u2029\u000B\u3000\u2008\u2003\u205F\u3000\u1680" + + "\u0009\u0020\u2006\u2001\u202F\u00A0\u000C\u2009" + + "\u3000\u2004\u3000\u3000\u2028\n\u2007\u3000" + + private val Multiplier: Int = 1682554634 + private val Shift: Int = Integer.numberOfLeadingZeros(Table.length - 1) + + def matches(c: Char): Boolean = Table.charAt((Multiplier * c) >>> Shift) == c + } + + def isSafeWhitespace(char: Char): Boolean = Whitespace.matches(char) + + // From Guava + def isSafeControl(char: Char): Boolean = + char <= '\u001f' || (char >= '\u007f' && char <= '\u009f') + + def safeTrim(string: String): String = { + def shouldKeep(c: Char): Boolean = !isSafeControl(c) && !isSafeWhitespace(c) + + if (string.isEmpty) { + "" + } else { + val start = string.indexWhere(shouldKeep) + val end = string.lastIndexWhere(shouldKeep) + + if (start >= 0 && end >= 0) { + string.substring(start, end + 1) + } else { + "" + } + } + } +} diff --git a/src/test/scala/xyz/driver/pdsuicommon/BaseSuite.scala b/src/test/scala/xyz/driver/pdsuicommon/BaseSuite.scala deleted file mode 100644 index 7c9d8c4..0000000 --- a/src/test/scala/xyz/driver/pdsuicommon/BaseSuite.scala +++ /dev/null @@ -1,35 +0,0 @@ -package xyz.driver.pdsuicommon - -import java.time.{LocalDateTime, ZoneId} - -import org.scalatest.FreeSpecLike -import org.scalatest.concurrent.ScalaFutures -import org.scalatest.time.{Millis, Span} -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.error.UnexpectedFilterException -import xyz.driver.pdsuicommon.utils.DiffUtils - -trait BaseSuite extends FreeSpecLike with DiffUtils with ScalaFutures { - - implicit val defaultPatience = PatienceConfig(timeout = Span(1000, Millis), interval = Span(20, Millis)) - implicit val sqlContext = new MockMySqlContext() - - def sampleUser(role: User.Role, email: String = "test@example.com", password: String = "123") = User( - id = StringId("2001"), - email = Email(email), - name = "Test", - roles = Set(role), - latestActivity = Some(LocalDateTime.now(ZoneId.of("Z"))), - deleted = None - ) - - def createMockQueryBuilder[T](isExpectedFilter: SearchFilterExpr => Boolean): MysqlQueryBuilder[T] = { - MockQueryBuilder[T] { - case (filter, _, _) if isExpectedFilter(filter) => Seq.empty - case (filter, _, _) => throw new UnexpectedFilterException(s"Filter is unexpected: $filter") - } { - case _ => (0, Option.empty[LocalDateTime]) - } - } -} diff --git a/src/test/scala/xyz/driver/pdsuicommon/Mocks.scala b/src/test/scala/xyz/driver/pdsuicommon/Mocks.scala deleted file mode 100644 index 51d39e5..0000000 --- a/src/test/scala/xyz/driver/pdsuicommon/Mocks.scala +++ /dev/null @@ -1,88 +0,0 @@ -package xyz.driver.pdsuicommon - -import java.io.{Closeable, PrintWriter} -import java.net.URL -import java.sql.Connection -import java.util.logging.Logger -import javax.sql.DataSource - -import com.typesafe.config.ConfigFactory -import xyz.driver.pdsuicommon.db._ -import xyz.driver.pdsuicommon.http.HttpFetcher - -import scala.concurrent.Future - -class MockDataSource extends DataSource with Closeable { - override def getConnection: Connection = throw new NotImplementedError("MockDataSource.getConnection") - override def getConnection(username: String, password: String): Connection = { - throw new NotImplementedError(s"MockDataSource.getConnection($username, $password)") - } - override def close(): Unit = throw new NotImplementedError("MockDataSource.close") - override def setLogWriter(out: PrintWriter): Unit = throw new NotImplementedError("MockDataSource.setLogWriter") - override def getLoginTimeout: Int = throw new NotImplementedError("MockDataSource.getLoginTimeout") - override def setLoginTimeout(seconds: Int): Unit = throw new NotImplementedError("MockDataSource.setLoginTimeout") - override def getParentLogger: Logger = throw new NotImplementedError("MockDataSource.getParentLogger") - override def getLogWriter: PrintWriter = throw new NotImplementedError("MockDataSource.getLogWriter") - override def unwrap[T](iface: Class[T]): T = throw new NotImplementedError("MockDataSource.unwrap") - override def isWrapperFor(iface: Class[_]): Boolean = throw new NotImplementedError("MockDataSource.isWrapperFor") -} - -object MockMySqlContext { - - val Settings = MySqlContext.Settings( - credentials = MySqlContext.DbCredentials( - user = "test", - password = "test", - host = "localhost", - port = 3248, - dbName = "test", - dbCreateFlag = false, - dbContext = "test", - connectionParams = "", - url = "" - ), - connection = ConfigFactory.empty(), - threadPoolSize = 10 - ) -} - -class MockMySqlContext() extends MySqlContext(new MockDataSource, MockMySqlContext.Settings) { - override protected def withConnection[T](f: Connection => T): Nothing = { - throw new NotImplementedError("MockSqlContext.withConnection") - } -} - -class MockFactory()(implicit val sqlContext: MySqlContext) { - val MockHttpFetcher: HttpFetcher = { (url: URL) => - Future.successful(Array.empty[Byte]) - } -} - -object MockQueryBuilder { - - type MockRunnerIn = (SearchFilterExpr, Sorting, Option[Pagination]) - type MockRunnerOut[T] = Seq[T] - type MockCountRunnerOut = QueryBuilder.CountResult - - def apply[T](matcher: PartialFunction[MockRunnerIn, MockRunnerOut[T]])( - countMatcher: PartialFunction[MockRunnerIn, MockCountRunnerOut])( - implicit context: MySqlContext): MysqlQueryBuilder[T] = { - - val runner: QueryBuilder.Runner[T] = { parameters => - matcher((parameters.filter, parameters.sorting, parameters.pagination)) - } - - val countRunner: QueryBuilder.CountRunner = { parameters => - countMatcher((parameters.filter, parameters.sorting, parameters.pagination)) - } - - MysqlQueryBuilder[T]( - tableName = "", - lastUpdateFieldName = Option.empty[String], - nullableFields = Set.empty[String], - links = Set.empty[TableLink], - runner = runner, - countRunner = countRunner - ) - } -} diff --git a/src/test/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapterSuite.scala b/src/test/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapterSuite.scala deleted file mode 100644 index 8b38316..0000000 --- a/src/test/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapterSuite.scala +++ /dev/null @@ -1,285 +0,0 @@ -package xyz.driver.pdsuicommon.concurrent - -import java.util.concurrent.ThreadLocalRandom - -import xyz.driver.pdsuicommon.BaseSuite -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueueRepositoryAdapter.Strategy -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueueRepositoryAdapter.Strategy.{OnAttempt, OnComplete} -import xyz.driver.pdsuicommon.db.{FakeDbIo, MysqlQueryBuilder} -import xyz.driver.pdsuicommon.db.repositories.BridgeUploadQueueRepository - -import scala.concurrent.Future -import scala.concurrent.duration.DurationInt - -class BridgeUploadQueueRepositoryAdapterSuite extends BaseSuite { - - // IDEA have some issue here with imports - private implicit val executionContext = scala.concurrent.ExecutionContext.global - - "Strategy" - { - "LimitExponential" - { - "on" - { - val strategy = Strategy.LimitExponential( - startInterval = 10.seconds, - intervalFactor = 1.4, - maxInterval = 50.seconds, - onComplete = OnComplete.Delete - ) - - "a new interval should be greater than the previous one if the limit not reached" in { - val previous = strategy.on(1) - val current = strategy.on(2) - - (previous, current) match { - case (OnAttempt.Continue(a), OnAttempt.Continue(b)) => assert(a < b) - case x => fail(s"Unexpected result: $x") - } - } - - "should limit intervals" in { - assert(strategy.on(20) == OnAttempt.Continue(strategy.maxInterval)) - } - - "should not fail, if there is many attempts" in { - assert(strategy.on(1000) == OnAttempt.Continue(strategy.maxInterval)) - } - } - } - } - - "complete" - { - "onComplete == mark" - { - "should update the item" in { - var done = false - val item = defaultItem - - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - - override def delete(kind: String, tag: String): Unit = throw new IllegalStateException("Impossible call") - - override def update(entity: EntityT): EntityT = { - assert(entity.kind == item.kind, "repository.delete, kind") - assert(entity.tag == item.tag, "repository.delete, tag") - done = true - entity - } - - override def getById(kind: String, tag: String): Option[EntityT] = Some(item) - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = Strategy.Stop(OnComplete.Mark), - repository = repository, - dbIo = FakeDbIo - ) - - assert(adapter.complete(item.kind, item.tag).isReadyWithin(100.millis)) - assert(done) - } - } - - "onComplete == delete" - { - "should delete the item" in { - var done = false - val item = defaultItem - - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - - override def delete(kind: String, tag: String): Unit = { - assert(kind == item.kind, "repository.delete, kind") - assert(tag == item.tag, "repository.delete, tag") - done = true - } - override def update(entity: EntityT): EntityT = throw new IllegalStateException("Impossible call") - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = Strategy.Stop(OnComplete.Delete), - repository = repository, - dbIo = FakeDbIo - ) - - assert(adapter.complete(item.kind, item.tag).isReadyWithin(100.millis)) - assert(done) - } - } - } - - "tryRetry" - { - - "when all attempts are not out" - { - - val defaultStrategy = Strategy.Constant(10.seconds) - - "should return an updated item" in { - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - - override def update(draft: EntityT): EntityT = draft - override def delete(kind: String, tag: String): Unit = throw new IllegalAccessError(s"kind=$kind, tag=$tag") - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = defaultStrategy, - repository = repository, - dbIo = FakeDbIo - ) - - val item = defaultItem - val r = adapter.tryRetry(item).futureValue - assert(r.isDefined) - assert(!r.contains(item)) - } - - "should update an item with increased attempts" in { - val item = defaultItem - - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - - override def update(draft: EntityT): EntityT = { - assert(draft.attempts === (item.attempts + 1), "repository.add") - draft - } - override def delete(kind: String, tag: String): Unit = throw new IllegalAccessError(s"kind=$kind, tag=$tag") - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = defaultStrategy, - repository = repository, - dbIo = FakeDbIo - ) - - assert(adapter.tryRetry(item).isReadyWithin(100.millis)) - } - - "should remove an old item" in { - val item = defaultItem - - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - override def update(draft: EntityT): EntityT = draft - override def delete(kind: String, tag: String): Unit = { - assert(kind == item.kind, "repository.delete, kind") - assert(tag == item.tag, "repository.delete, kind") - } - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = defaultStrategy, - repository = repository, - dbIo = FakeDbIo - ) - - assert(adapter.tryRetry(item).isReadyWithin(100.millis)) - } - - "should update time of the next attempt" in { - val item = defaultItem - - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - - override def update(draft: EntityT): EntityT = { - assert(draft.nextAttempt.isAfter(item.nextAttempt), "repository.add") - draft - } - override def delete(kind: String, tag: String): Unit = throw new IllegalAccessError(s"kind=$kind, tag=$tag") - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = defaultStrategy, - repository = repository, - dbIo = FakeDbIo - ) - - assert(adapter.tryRetry(item).isReadyWithin(100.millis)) - } - - } - - "when all attempts are out" - { - - val defaultStrategy = Strategy.Stop() - - "should not return an item" in { - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - override def update(entity: EntityT): EntityT = fail("update should not be used!") - - override def delete(kind: String, tag: String): Unit = {} - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = defaultStrategy, - repository = repository, - dbIo = FakeDbIo - ) - - val r = adapter.tryRetry(defaultItem).futureValue - assert(r.isEmpty) - } - - "should complete the item" in { - var taskWasCompleted = false - val item = defaultItem - - val repository = new BridgeUploadQueueRepository { - override def add(draft: EntityT): EntityT = draft - override def getOne(kind: String): Option[EntityT] = fail("getOne should not be used!") - override def buildQuery: MysqlQueryBuilder[EntityT] = fail("buildQuery should not be used!") - override def getById(kind: String, tag: String): Option[EntityT] = fail("getById should not be used!") - override def update(entity: EntityT): EntityT = fail("update should not be used!") - - override def delete(kind: String, tag: String): Unit = {} - } - - val adapter = new BridgeUploadQueueRepositoryAdapter( - strategy = defaultStrategy, - repository = repository, - dbIo = FakeDbIo - ) { - override def complete(kind: String, tag: String): Future[Unit] = Future { - assert(kind == item.kind, "adapter.complete, kind") - assert(tag == item.tag, "adapter.complete, tag") - taskWasCompleted = true - } - } - - val r = adapter.tryRetry(item).futureValue - assert(r.isEmpty) - assert(taskWasCompleted) - } - - } - - } - - private def defaultItem = BridgeUploadQueue.Item( - "test", - ThreadLocalRandom.current().nextInt().toString - ) - -} diff --git a/src/test/scala/xyz/driver/pdsuicommon/db/QueryBuilderParametersSuite.scala b/src/test/scala/xyz/driver/pdsuicommon/db/QueryBuilderParametersSuite.scala deleted file mode 100644 index 2c23b92..0000000 --- a/src/test/scala/xyz/driver/pdsuicommon/db/QueryBuilderParametersSuite.scala +++ /dev/null @@ -1,310 +0,0 @@ -package xyz.driver.pdsuicommon.db - -import java.time.LocalDateTime - -import io.getquill.MysqlEscape -import org.scalatest.FreeSpecLike -import xyz.driver.pdsuicommon.db.QueryBuilder.TableData -import xyz.driver.pdsuicommon.domain._ - -class QueryBuilderParametersSuite extends FreeSpecLike { - - import SearchFilterBinaryOperation._ - import SearchFilterExpr.{Dimension => _, _} - import SearchFilterNAryOperation._ - import Sorting._ - import SortingOrder._ - - val tableName = "Entity" - - case class Entity(id: LongId[Entity], - name: String, - email: Email, - optionUser: Option[StringId[User]], - date: LocalDateTime, - optionDate: Option[LocalDateTime], - kindId: Long) - - def queryBuilderParameters = MysqlQueryBuilderParameters( - tableData = TableData( - tableName = tableName, - nullableFields = Set("optionUser", "optionDate") - ), - links = Map( - "Kind" -> TableLink("kindId", "Kind", "id"), - "User" -> TableLink("optionUser", "User", "id") - ) - ) - - val queryBasis = - s"""select `$tableName`.* - |from `$tableName`""".stripMargin.trim - - "toSql" - { - "should generate correct SQL query" - { - "with default parameters" in { - val (sql, _) = queryBuilderParameters.toSql(namingStrategy = MysqlEscape) - assert(sql == queryBasis) - } - - "with filtering: " - { - "single atom filter" in { - val (sql, _) = - queryBuilderParameters.copy(filter = Atom.Binary("name", Eq, "x")).toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |where `$tableName`.`name` = ?""".stripMargin) - } - - "single atom filter for optional field with NotEq operation" in { - val (sql, _) = queryBuilderParameters - .copy(filter = Atom.Binary("optionUser", NotEq, "x")) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |where (`$tableName`.`optionUser` is null or `$tableName`.`optionUser` != ?)""".stripMargin) - } - - "single atom filter for field with IN operation" in { - val (sql, _) = queryBuilderParameters - .copy(filter = Atom.NAry("date", In, Seq("x", "x", "x"))) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |where `$tableName`.`date` in (?, ?, ?)""".stripMargin) - } - - "multiple intersected filters" in { - val (sql, _) = queryBuilderParameters - .copy( - filter = Intersection( - Seq( - Atom.Binary("name", Gt, "x"), - Atom.Binary("optionDate", GtEq, "x") - ))) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |where (`$tableName`.`name` > ? and `$tableName`.`optionDate` >= ?)""".stripMargin) - } - - "multiple intersected nested filters" in { - val (sql, _) = queryBuilderParameters - .copy( - filter = Intersection( - Seq( - Atom.Binary("name", Gt, "x"), - Atom.Binary("optionDate", GtEq, "x"), - Intersection(Seq( - Atom.Binary("optionUser", Eq, "x"), - Atom.Binary("date", LtEq, "x") - )) - ))) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"$queryBasis\nwhere (`$tableName`.`name` > ? and `$tableName`.`optionDate` >= ?" + - s" and (`$tableName`.`optionUser` = ? and `$tableName`.`date` <= ?))") - } - - "multiple unionized filters" in { - val (sql, _) = queryBuilderParameters - .copy( - filter = Union( - Seq( - Atom.Binary("name", Gt, "x"), - Atom.Binary("optionDate", GtEq, "x") - ))) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |where (`$tableName`.`name` > ? or `$tableName`.`optionDate` >= ?)""".stripMargin.trim) - } - - "multiple unionized nested filters" in { - val (sql, _) = queryBuilderParameters - .copy( - filter = Union( - Seq( - Atom.Binary("name", Gt, "x"), - Atom.Binary("optionDate", GtEq, "x"), - Union(Seq( - Atom.Binary("optionUser", Eq, "x"), - Atom.Binary("date", LtEq, "x") - )) - ))) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |where (`$tableName`.`name` > ? or `$tableName`.`optionDate` >= ? or (`$tableName`.`optionUser` = ? or `$tableName`.`date` <= ?))""".stripMargin) - } - - "multiple unionized and intersected nested filters" in { - val (sql, _) = queryBuilderParameters - .copy(filter = Union(Seq( - Intersection(Seq( - Atom.Binary("name", Gt, "x"), - Atom.Binary("optionDate", GtEq, "x") - )), - Intersection(Seq( - Atom.Binary("optionUser", Eq, "x"), - Atom.Binary("date", LtEq, "x") - )) - ))) - .toSql(namingStrategy = MysqlEscape) - - assert( - sql == - s"$queryBasis\nwhere ((`$tableName`.`name` > ? and `$tableName`.`optionDate` >= ?) " + - s"or (`$tableName`.`optionUser` = ? and `$tableName`.`date` <= ?))") - } - - "single field from foreign table" in { - val (sql, _) = queryBuilderParameters - .copy(filter = Atom.Binary(SearchFilterExpr.Dimension(Some("Kind"), "name"), Eq, "x")) - .toSql(namingStrategy = MysqlEscape) - val pattern = - s"""select `$tableName`.* - |from `$tableName` - |inner join `Kind` on `Entity`.`kindId` = `Kind`.`id` - |where `Kind`.`name` = ?""".stripMargin - assert(sql == pattern) - } - } - - "with sorting:" - { - "single field sorting" in { - val (sql, _) = queryBuilderParameters - .copy(sorting = Dimension(None, "name", Ascending)) - .toSql(namingStrategy = MysqlEscape) - - assert( - sql == - s"""$queryBasis - |order by `$tableName`.`name` asc""".stripMargin) - } - - "single foreign sorting field" in { - val (sql, _) = queryBuilderParameters - .copy(sorting = Dimension(Some("Kind"), "name", Ascending)) - .toSql(namingStrategy = MysqlEscape) - - assert( - sql == - s"""select `$tableName`.* - |from `$tableName` - |inner join `Kind` on `Entity`.`kindId` = `Kind`.`id` - |order by `Kind`.`name` asc""".stripMargin) - } - - "multiple fields sorting" in { - val (sql, _) = queryBuilderParameters - .copy( - sorting = Sequential( - Seq( - Dimension(None, "name", Ascending), - Dimension(None, "date", Descending) - ))) - .toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |order by `$tableName`.`name` asc, `$tableName`.`date` desc""".stripMargin) - } - - "multiple foreign sorting field" in { - val (sql, _) = queryBuilderParameters - .copy( - sorting = Sequential( - Seq( - Dimension(Some("Kind"), "name", Ascending), - Dimension(Some("User"), "name", Descending) - ))) - .toSql(namingStrategy = MysqlEscape) - - assert( - sql == - s"""select `$tableName`.* - |from `$tableName` - |inner join `Kind` on `$tableName`.`kindId` = `Kind`.`id` - |inner join `User` on `$tableName`.`optionUser` = `User`.`id` - |order by `Kind`.`name` asc, `User`.`name` desc""".stripMargin) - } - - "multiple field sorting (including foreign tables)" in { - val (sql, _) = queryBuilderParameters - .copy( - sorting = Sequential( - Seq( - Dimension(Some("Kind"), "name", Ascending), - Dimension(None, "date", Descending) - ))) - .toSql(namingStrategy = MysqlEscape) - - assert( - sql == - s"""select `$tableName`.* - |from `$tableName` - |inner join `Kind` on `$tableName`.`kindId` = `Kind`.`id` - |order by `Kind`.`name` asc, `$tableName`.`date` desc""".stripMargin) - } - } - - "with pagination" in { - val (sql, _) = - queryBuilderParameters.copy(pagination = Some(Pagination(5, 3))).toSql(namingStrategy = MysqlEscape) - assert( - sql == - s"""$queryBasis - |limit 10, 5""".stripMargin) - } - - "combined" in { - val filter = Union( - Seq( - Intersection( - Seq( - Atom.Binary("name", Gt, "x"), - Atom.Binary("optionDate", GtEq, "x") - )), - Intersection( - Seq( - Atom.Binary("optionUser", Eq, "x"), - Atom.Binary("date", LtEq, "x") - )) - )) - val sorting = Sequential( - Seq( - Dimension(Some("Kind"), "name", Ascending), - Dimension(None, "name", Ascending), - Dimension(None, "date", Descending) - )) - - val (sql, _) = queryBuilderParameters - .copy( - filter = filter, - sorting = sorting, - pagination = Some(Pagination(5, 3)) - ) - .toSql(namingStrategy = MysqlEscape) - - assert( - sql == - s"""select `$tableName`.* - |from `$tableName` - |inner join `Kind` on `$tableName`.`kindId` = `Kind`.`id` - |where ((`$tableName`.`name` > ? and `$tableName`.`optionDate` >= ?) or (`$tableName`.`optionUser` = ? and `$tableName`.`date` <= ?)) - |order by `Kind`.`name` asc, `$tableName`.`name` asc, `$tableName`.`date` desc - |limit 10, 5""".stripMargin) - } - - } - } - -} diff --git a/src/test/scala/xyz/driver/pdsuicommon/error/UnexpectedFilterException.scala b/src/test/scala/xyz/driver/pdsuicommon/error/UnexpectedFilterException.scala deleted file mode 100644 index 567661a..0000000 --- a/src/test/scala/xyz/driver/pdsuicommon/error/UnexpectedFilterException.scala +++ /dev/null @@ -1,3 +0,0 @@ -package xyz.driver.pdsuicommon.error - -class UnexpectedFilterException(message: String) extends RuntimeException(message) diff --git a/src/test/scala/xyz/driver/pdsuicommon/logging/PhiStringContextSuite.scala b/src/test/scala/xyz/driver/pdsuicommon/logging/PhiStringContextSuite.scala deleted file mode 100644 index eb9d9b4..0000000 --- a/src/test/scala/xyz/driver/pdsuicommon/logging/PhiStringContextSuite.scala +++ /dev/null @@ -1,31 +0,0 @@ -package xyz.driver.pdsuicommon.logging - -import org.scalatest.FreeSpecLike - -class PhiStringContextSuite extends FreeSpecLike { - - class Foo(x: Int, y: String) { - val z: Boolean = true - } - - case class Bar(y: Boolean) - - implicit def fooToPhiString(foo: Foo): PhiString = new PhiString(s"Foo(z=${foo.z})") - - "should not compile if there is no PhiString implicit" in assertDoesNotCompile( - """val bar = Bar(true) - |phi"bar is $bar"""".stripMargin - ) - - "should compile if there is a PhiString implicit" in assertCompiles( - """val foo = new Foo(1, "test") - |println(phi"foo is $foo}")""".stripMargin - ) - - "should not contain private info" in { - val foo = new Foo(42, "test") - val result = phi"foo is $foo".text - assert(!result.contains("test")) - assert(!result.contains("42")) - } -} diff --git a/src/test/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParserSuite.scala b/src/test/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParserSuite.scala deleted file mode 100644 index 5cd2dc9..0000000 --- a/src/test/scala/xyz/driver/pdsuicommon/parsers/SearchFilterParserSuite.scala +++ /dev/null @@ -1,185 +0,0 @@ -package xyz.driver.pdsuicommon.parsers - -import xyz.driver.pdsuicommon.db.SearchFilterExpr.Dimension -import xyz.driver.pdsuicommon.db.{SearchFilterBinaryOperation, SearchFilterExpr, SearchFilterNAryOperation} -import xyz.driver.pdsuicommon.utils.Implicits.toStringOps -import xyz.driver.pdsuicommon.parsers.TestUtils._ -import fastparse.core.Parsed -import org.scalacheck.Arbitrary.arbitrary -import org.scalacheck.{Gen, Prop} -import org.scalatest.FreeSpecLike -import org.scalatest.prop.Checkers - -object SearchFilterParserSuite { - - class UnexpectedSearchFilterExprException(x: SearchFilterExpr) extends Exception(s"unexpected $x") - -} - -class SearchFilterParserSuite extends FreeSpecLike with Checkers { - - import SearchFilterParserSuite._ - - "parse" - { - "dimensions" - { - "with table name" in check { - val dimensionGen = { - for (left <- Gen.identifier; right <- Gen.identifier) - yield left -> right - } - Prop.forAllNoShrink(dimensionGen) { - case (left, right) => - val raw = s"$left.$right" - SearchFilterParser.dimensionParser.parse(raw) match { - case Parsed.Success(Dimension(Some(`left`), `right`), _) => true - case res => false - } - } - } - "just with field name" in check { - Prop.forAllNoShrink(Gen.identifier) { s => - SearchFilterParser.dimensionParser.parse(s) match { - case Parsed.Success(Dimension(None, `s`), _) => true - case _ => false - } - } - } - } - "atoms" - { - "binary" - { - "common operators" - { - "should be parsed with text values" in check { - import SearchFilterBinaryOperation._ - - val testQueryGen = queryGen( - dimensionGen = Gen.identifier, - opGen = commonBinaryOpsGen, - valueGen = nonEmptyString - ) - - Prop.forAllNoShrink(testQueryGen) { query => - SearchFilterParser.parse(Seq("filters" -> query)) - .map { - case SearchFilterExpr.Atom.Binary(_, Eq | NotEq | Like, _) => true - case x => throw new UnexpectedSearchFilterExprException(x) - } - .successProp - } - } - } - - "numeric operators" - { - "should not be parsed with text values" in check { - val testQueryGen = queryGen( - dimensionGen = Gen.identifier, - opGen = numericBinaryOpsGen, - valueGen = nonEmptyString.filter { s => !s.matches("^\\d+$") } - ) - - Prop.forAllNoShrink(testQueryGen) { query => - SearchFilterParser.parse(Seq("filters" -> query)).failureProp - } - } - } - - "all operators" - { - "should be parsed with numeric values" in check { - val testQueryGen = queryGen( - dimensionGen = Gen.identifier, - opGen = allBinaryOpsGen, - valueGen = numericBinaryAtomValuesGen - ) - - Prop.forAllNoShrink(testQueryGen) { query => - SearchFilterParser.parse(Seq("filters" -> query)) - .map { - case _: SearchFilterExpr.Atom.Binary => true - case x => throw new UnexpectedSearchFilterExprException(x) - } - .successProp - } - } - } - } - - "n-ary" - { - "in" in check { - val testQueryGen = queryGen( - dimensionGen = Gen.identifier, - opGen = Gen.const("in"), - valueGen = inValuesGen - ) - - Prop.forAllNoShrink(testQueryGen) { query => - SearchFilterParser.parse(Seq("filters" -> query)) - .map { - case SearchFilterExpr.Atom.NAry(_, SearchFilterNAryOperation.In, _) => true - case x => throw new UnexpectedSearchFilterExprException(x) - } - .successProp - } - } - } - } - - "intersections" - { - "should be parsed" in check { - val commonAtomsGen = queryGen( - dimensionGen = Gen.identifier, - opGen = commonBinaryOpsGen, - valueGen = nonEmptyString - ) - - val numericAtomsGen = queryGen( - dimensionGen = Gen.identifier, - opGen = numericBinaryOpsGen, - valueGen = numericBinaryAtomValuesGen - ) - - val allAtomsGen = Gen.oneOf(commonAtomsGen, numericAtomsGen) - val intersectionsGen = Gen.choose(1, 3).flatMap { size => - Gen.containerOfN[Seq, String](size, allAtomsGen) - } - - Prop.forAllNoShrink(intersectionsGen) { queries => - SearchFilterParser.parse(queries.map(query => "filters" -> query)).successProp - } - } - } - } - - private val CommonBinaryOps = Seq("eq", "noteq", "like") - private val NumericBinaryOps = Seq("gt", "gteq", "lt", "lteq") - - private val allBinaryOpsGen: Gen[String] = Gen.oneOf(CommonBinaryOps ++ NumericBinaryOps).flatMap(randomCapitalization) - private val commonBinaryOpsGen: Gen[String] = Gen.oneOf(CommonBinaryOps).flatMap(randomCapitalization) - private val numericBinaryOpsGen: Gen[String] = Gen.oneOf(NumericBinaryOps).flatMap(randomCapitalization) - - private val inValueCharsGen: Gen[Char] = arbitrary[Char].filter(_ != ',') - - private val nonEmptyString = arbitrary[String].filter { s => !s.safeTrim.isEmpty } - - private val numericBinaryAtomValuesGen: Gen[String] = arbitrary[BigInt].map(_.toString) - private val inValueGen: Gen[String] = { - Gen.nonEmptyContainerOf[Seq, Char](inValueCharsGen).map(_.mkString).filter(_.safeTrim.nonEmpty) - } - private val inValuesGen: Gen[String] = Gen.choose(1, 5).flatMap { size => - Gen.containerOfN[Seq, String](size, inValueGen).map(_.mkString(",")) - } - - private def queryGen(dimensionGen: Gen[String], opGen: Gen[String], valueGen: Gen[String]): Gen[String] = for { - dimension <- dimensionGen - op <- opGen - value <- valueGen - } yield s"$dimension $op $value" - - private def randomCapitalization(input: String): Gen[String] = { - Gen.containerOfN[Seq, Boolean](input.length, arbitrary[Boolean]).map { capitalize => - input.view.zip(capitalize).map { - case (currChar, true) => currChar.toUpper - case (currChar, false) => currChar - }.mkString - } - } - -} diff --git a/src/test/scala/xyz/driver/pdsuicommon/pdf/MockPdfRenderer.scala b/src/test/scala/xyz/driver/pdsuicommon/pdf/MockPdfRenderer.scala deleted file mode 100644 index 8dfd29c..0000000 --- a/src/test/scala/xyz/driver/pdsuicommon/pdf/MockPdfRenderer.scala +++ /dev/null @@ -1,25 +0,0 @@ -package xyz.driver.pdsuicommon.pdf - -import java.nio.file.{Path, Paths} - -import xyz.driver.pdsuicommon.logging._ - -object MockPdfRenderer extends PdfRenderer with PhiLogging { - - private lazy val defaultDocument: Path = { - val uri = getClass.getResource("/pdf/example.pdf").toURI - Paths.get(uri) - } - - override def render(html: String, documentName: String, force: Boolean = false): Path = { - logger.trace(phi"render(html, documentName=${Unsafe(documentName)})") - defaultDocument - } - - override def delete(documentName: String): Unit = { - logger.trace(phi"delete(${Unsafe(documentName)})") - } - - override def getPath(documentName: String): Path = defaultDocument - -} diff --git a/src/test/scala/xyz/driver/pdsuicommon/utils/DiffUtils.scala b/src/test/scala/xyz/driver/pdsuicommon/utils/DiffUtils.scala deleted file mode 100644 index 156cb08..0000000 --- a/src/test/scala/xyz/driver/pdsuicommon/utils/DiffUtils.scala +++ /dev/null @@ -1,68 +0,0 @@ -package xyz.driver.pdsuicommon.utils - -import java.net.URI -import java.time.{LocalDate, LocalDateTime} - -import ai.x.diff._ -import org.scalatest.Assertions -import xyz.driver.pdsuidomain.entities.{Document, ExtractedData, MedicalRecord} - -import scala.io.AnsiColor - -trait DiffUtils { this: Assertions => - - def assertIdentical[T: DiffShow](left: T, right: T): Unit = { - val diff = DiffShow.diff(left, right) - assert(diff.isIdentical, s"\n${AnsiColor.RESET}$diff") // reset red color - } - - implicit def localTimeDiffShow: DiffShow[LocalDateTime] = new DiffShow[LocalDateTime] { - def show(x: LocalDateTime): String = s"LocalTime($x)" - def diff(left: LocalDateTime, right: LocalDateTime): Comparison = { - if (left.isEqual(right)) Identical(show(left)) - else Different(showChange(left, right)) - } - } - - implicit def localDateDiffShow: DiffShow[LocalDate] = new DiffShow[LocalDate] { - def show(x: LocalDate): String = s"LocalDate($x)" - def diff(left: LocalDate, right: LocalDate): Comparison = { - if (left.isEqual(right)) Identical(show(left)) - else Different(showChange(left, right)) - } - } - - implicit def urlDiffShow: DiffShow[URI] = new DiffShow[URI] { - def show(x: URI): String = s"URI($x)" - def diff(left: URI, right: URI): Comparison = { - if (left.equals(right)) Identical(show(left)) - else Different(showChange(left, right)) - } - } - - implicit def metaDiffShow: DiffShow[MedicalRecord.Meta] = new DiffShow[MedicalRecord.Meta] { - def show(x: MedicalRecord.Meta): String = s"MedicalRecord.Meta($x)" - def diff(left: MedicalRecord.Meta, right: MedicalRecord.Meta): Comparison = { - if (left.equals(right)) Identical(show(left)) - else Different(showChange(left, right)) - } - } - - implicit def extractedDataMetaDiffShow: DiffShow[ExtractedData.Meta] = new DiffShow[ExtractedData.Meta] { - def show(x: ExtractedData.Meta): String = s"ExtractedData.Meta($x)" - def diff(left: ExtractedData.Meta, right: ExtractedData.Meta): Comparison = { - if (left.equals(right)) Identical(show(left)) - else Different(showChange(left, right)) - } - } - - implicit def documentDiffShow: DiffShow[Document] = new DiffShow[Document] { - def show(x: Document): String = s"Document($x)" - - def diff(left: Document, right: Document): Comparison = { - if (left == right) Identical(show(left)) - else Different(showChange(left, right)) - } - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/DocumentSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/DocumentSuite.scala deleted file mode 100644 index f851680..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/DocumentSuite.scala +++ /dev/null @@ -1,87 +0,0 @@ -package xyz.driver.pdsuidomain - -import java.time.{LocalDate, LocalDateTime} -import java.time.temporal.ChronoUnit - -import xyz.driver.pdsuicommon.BaseSuite -import xyz.driver.pdsuicommon.domain.{LongId, TextJson} -import xyz.driver.pdsuidomain.entities.Document - -class DocumentSuite extends BaseSuite { - - "validation" - { - "can't submit invalid data" - { - val base = sampleDocument - - val now = LocalDate.now() - val past1 = now.minus(2, ChronoUnit.DAYS) - val past2 = past1.plus(1, ChronoUnit.DAYS) - val future1 = now.plus(1, ChronoUnit.DAYS) - val future2 = future1.plus(1, ChronoUnit.DAYS) - - Seq( - "startDate should be non-empty" -> base.copy(startDate = None), - "startDate should be greater, than endDate" -> base.copy(startDate = Some(past2), endDate = Some(past1)), - "startDate and endDate should be in the past" -> base.copy(startDate = Some(future1), endDate = Some(future2)) - ).foreach { - case (title, orig) => - s"$title" in { - val r = Document.validator(orig) - assert(r.isLeft, s"should fail, but: ${r.right}") - } - } - } - } - - "getRequiredType" - { - "getOPNType" in { - val documentForOPNType = sampleDocument.copy( - typeId = Some(LongId(1L)), - providerTypeId = Some(LongId(1L)), - startDate = Some(LocalDate.now().minus(2, ChronoUnit.DAYS)) - ) - val r = documentForOPNType.getRequiredType("Outpatient Physician Note", "Medical Oncology") - assert(r.contains(Document.RequiredType.OPN), s"document should have the requiredType=OPN, but:$r") - } - - "getPNType" in { - val documentForPNType = sampleDocument.copy( - typeId = Some(LongId(6)) - ) - val r = documentForPNType.getRequiredType("Pathology Report", "") - assert(r.contains(Document.RequiredType.PN), s"document should have the requiredType=PN, but:$r") - } - "get None" in { - val document = sampleDocument.copy( - typeId = Some(LongId(1L)), - providerTypeId = Some(LongId(1L)), - startDate = Some(LocalDate.now().minus(7, ChronoUnit.MONTHS)) - ) - val r = document.getRequiredType("Outpatient Physician Note", "Medical Oncology") - assert(r.isEmpty, s"document should have the requiredType=None, but:$r") - } - } - - private def sampleDocument = { - val lastUpdate = LocalDateTime.now() - - Document( - id = LongId(2002), - status = Document.Status.New, - previousStatus = None, - assignee = None, - previousAssignee = None, - lastActiveUserId = None, - recordId = LongId(2003), - physician = None, - typeId = Some(LongId(123)), - providerName = Some("etst"), - providerTypeId = Some(LongId(123)), - requiredType = None, - startDate = Some(lastUpdate.toLocalDate.minusDays(2)), - endDate = None, - lastUpdate = lastUpdate, - meta = Some(TextJson(Document.Meta(None, 1.1, 2.2))) - ) - } -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ArmFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ArmFormatSuite.scala deleted file mode 100644 index e7d37a0..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ArmFormatSuite.scala +++ /dev/null @@ -1,36 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.Arm - -class ArmFormatSuite extends FlatSpec with Matchers { - import arm._ - - "Json format for Arm" should "read and write correct JSON" in { - val arm = Arm( - id = LongId(10), - trialId = StringId("NCT000001"), - name = "arm name", - originalName = "orig arm name" - ) - val writtenJson = armFormat.write(arm) - - writtenJson should be("""{"id":10,"trialId":"NCT000001","name":"arm name","originalName":"orig arm name"}""".parseJson) - - val createArmJson = """{"trialId":"NCT000001","name":"arm name"}""".parseJson - val parsedArm = armFormat.read(createArmJson) - val expectedCreatedArm = arm.copy( - id = LongId(0), - originalName = "arm name" - ) - parsedArm should be(expectedCreatedArm) - - val updateArmJson = """{"name":"new arm name"}""".parseJson - val expectedUpdatedArm = arm.copy(name = "new arm name") - val parsedUpdateArm = applyUpdateToArm(updateArmJson, arm) - parsedUpdateArm should be(expectedUpdatedArm) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/BridgeUploadQueueFormat.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/BridgeUploadQueueFormat.scala deleted file mode 100644 index 854f51f..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/BridgeUploadQueueFormat.scala +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue - -class BridgeUploadQueueFormat extends FlatSpec with Matchers { - import bridgeuploadqueue._ - - "Json format for BridgeUploadQueue.Item" should "read and write correct JSON" in { - val item = BridgeUploadQueue.Item( - kind = "kind", - tag = "tag", - created = LocalDateTime.parse("2017-08-10T18:00:00"), - attempts = 0, - nextAttempt = LocalDateTime.parse("2017-08-10T18:10:00"), - completed = false, - dependencyKind = Some("dependency king"), - dependencyTag = None - ) - val writtenJson = queueUploadItemFormat.write(item) - - writtenJson should be( - """{"kind":"kind","tag":"tag","created":"2017-08-10T18:00Z","attempts":0,"nextAttempt":"2017-08-10T18:10Z","completed":false}""".parseJson) - - val parsedItem = queueUploadItemFormat.read(writtenJson) - parsedItem should be(item.copy(dependencyKind = None, completed = true)) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/CriterionFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/CriterionFormatSuite.scala deleted file mode 100644 index d24c4c1..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/CriterionFormatSuite.scala +++ /dev/null @@ -1,68 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{Arm, Criterion, CriterionLabel} -import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion - -class CriterionFormatSuite extends FlatSpec with Matchers { - import criterion._ - - "Json format for Criterion" should "read and write correct JSON" in { - val criterion = Criterion( - id = LongId(10), - trialId = StringId("NCT000001"), - text = Some("text"), - isCompound = false, - meta = "{}" - ) - val labels = List( - CriterionLabel( - id = LongId(1L), - labelId = Some(LongId(101)), - criterionId = criterion.id, - categoryId = Some(LongId(3)), - value = Some(true), - isDefining = true - ), - CriterionLabel( - id = LongId(2L), - labelId = Some(LongId(102)), - criterionId = criterion.id, - categoryId = Some(LongId(3)), - value = Some(false), - isDefining = true - ) - ) - val arms = List(LongId[Arm](20), LongId[Arm](21), LongId[Arm](21)) - val richCriterion = RichCriterion( - criterion = criterion, - armIds = arms, - labels = labels - ) - val writtenJson = richCriterionFormat.write(richCriterion) - - writtenJson should be( - """{"text":"text","isCompound":false,"trialId":"NCT000001","arms":[20,21,21],"id":10,"meta":"{}", - "labels":[{"labelId":101,"categoryId":3,"value":"Yes","isDefining":true}, - {"labelId":102,"categoryId":3,"value":"No","isDefining":true}]}""".parseJson) - - val createCriterionJson = - """{"text":"text","isCompound":false,"trialId":"NCT000001", - "arms":[20,21,21],"meta":"{}","labels":[{"labelId":101,"categoryId":3,"value":"Yes","isDefining":true}, - {"labelId":102,"categoryId":3,"value":"No","isDefining":true}]}""".parseJson - val parsedRichCriterion = richCriterionFormat.read(createCriterionJson) - val expectedRichCriterion = richCriterion.copy( - criterion = criterion.copy(id = LongId(0)), - labels = labels.map(_.copy(id = LongId(0), criterionId = LongId(0))) - ) - parsedRichCriterion should be(expectedRichCriterion) - - val updateCriterionJson = """{"meta":null,"text":"new text","isCompound":true}""".parseJson - val expectedUpdatedCriterion = richCriterion.copy(criterion = criterion.copy(text = Some("new text"), isCompound = true, meta = "{}")) - val parsedUpdateCriterion = applyUpdateToCriterion(updateCriterionJson, richCriterion) - parsedUpdateCriterion should be(expectedUpdatedCriterion) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentFormatSuite.scala deleted file mode 100644 index 9394735..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentFormatSuite.scala +++ /dev/null @@ -1,74 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.{LocalDate, LocalDateTime} - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, TextJson} -import xyz.driver.pdsuidomain.entities.Document - -class DocumentFormatSuite extends FlatSpec with Matchers { - import document._ - - "Json format for Document" should "read and write correct JSON" in { - val orig = Document( - id = LongId(1), - status = Document.Status.New, - assignee = None, - previousStatus = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - recordId = LongId(101), - physician = Some("physician"), - typeId = Some(LongId(10)), - providerName = Some("provider 21"), - providerTypeId = Some(LongId(21)), - requiredType = Some(Document.RequiredType.OPN), - meta = None, - startDate = None, - endDate = None - ) - val writtenJson = documentFormat.write(orig) - - writtenJson should be ( - """{"id":1,"recordId":101,"physician":"physician","typeId":10,"provider":"provider 21","providerTypeId":21, - "requiredType":"OPN","startDate":null,"endDate":null,"status":"New","assignee":null,"previousStatus":null, - "previousAssignee":null,"lastActiveUser":null,"lastUpdate":"2017-08-10T18:00Z","meta":null}""".parseJson) - - val createDocumentJson = - """{"recordId":101,"physician":"physician","typeId":10,"provider":"provider 21","providerTypeId":21}""".parseJson - val expectedCreatedDocument = orig.copy( - id = LongId(0), - lastUpdate = LocalDateTime.MIN, - requiredType = None - ) - val parsedCreatedDocument = documentFormat.read(createDocumentJson) - parsedCreatedDocument should be(expectedCreatedDocument) - - val updateDocumentJson = - """{"startDate":"2017-08-10","endDate":"2018-08-10","meta":{"predicted":true,"startPage":1.0,"endPage":2.0}}""".parseJson - val expectedUpdatedDocument = orig.copy( - startDate = Some(LocalDate.parse("2017-08-10")), - endDate = Some(LocalDate.parse("2018-08-10")), - meta = Some(TextJson(Document.Meta(predicted = Some(true), startPage = 1.0, endPage = 2.0))) - ) - val parsedUpdatedDocument = applyUpdateToDocument(updateDocumentJson, orig) - parsedUpdatedDocument should be(expectedUpdatedDocument) - } - - "Json format for Document.Meta" should "read and write correct JSON" in { - val meta = Document.Meta(predicted = None, startPage = 1.0, endPage = 2.0) - val writtenJson = documentMetaFormat.write(meta) - writtenJson should be ("""{"startPage":1.0,"endPage":2.0}""".parseJson) - - val metaJsonWithoutPredicted = """{"startPage":1.0,"endPage":2.0}""".parseJson - val parsedMetaWithoutPredicted = documentMetaFormat.read(metaJsonWithoutPredicted) - parsedMetaWithoutPredicted should be(meta) - - val metaJsonWithPredicted = """{"predicted":true,"startPage":1.0,"endPage":2.0}""".parseJson - val parsedMetaWithPredicted = documentMetaFormat.read(metaJsonWithPredicted) - parsedMetaWithPredicted should be(meta.copy(predicted = Some(true))) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentHistoryFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentHistoryFormatSuite.scala deleted file mode 100644 index ddbda1d..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentHistoryFormatSuite.scala +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.DocumentHistory - -class DocumentHistoryFormatSuite extends FlatSpec with Matchers { - import documenthistory._ - - "Json format for DocumentHistory" should "read and write correct JSON" in { - val documentHistory = DocumentHistory( - id = LongId(10), - documentId = LongId(1), - executor = StringId("userId-001"), - state = DocumentHistory.State.Extract, - action = DocumentHistory.Action.Start, - created = LocalDateTime.parse("2017-08-10T18:00:00") - ) - val writtenJson = documentHistoryFormat.write(documentHistory) - - writtenJson should be( - """{"id":10,"executor":"userId-001","documentId":1,"state":"Extract", - "action":"Start","created":"2017-08-10T18:00Z"}""".parseJson) - - val parsedDocumentHistory = documentHistoryFormat.read(writtenJson) - parsedDocumentHistory should be(documentHistory) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentIssueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentIssueFormatSuite.scala deleted file mode 100644 index 1a8e3f0..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/DocumentIssueFormatSuite.scala +++ /dev/null @@ -1,47 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.DocumentIssue - -class DocumentIssueFormatSuite extends FlatSpec with Matchers { - import documentissue._ - - "Json format for DocumentIssue" should "read and write correct JSON" in { - val documentIssue = DocumentIssue( - id = LongId(10), - documentId = LongId(1), - userId = StringId("userId-001"), - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - isDraft = false, - text = "message text", - archiveRequired = false, - startPage = Some(1.0), - endPage = Some(2.0) - ) - val writtenJson = documentIssueWriter.write(documentIssue) - - writtenJson should be( - """{"id":10,"userId":"userId-001","lastUpdate":"2017-08-10T18:00Z","isDraft":false, - "text":"message text","archiveRequired":false,"startPage":1.0,"endPage":2.0}""".parseJson) - - val createDocumentIssueJson = """{"text":"message text","startPage":1.0,"endPage":2.0}""".parseJson - val expectedCreatedDocumentIssue = documentIssue.copy(id = LongId(0), lastUpdate = LocalDateTime.MIN, isDraft = true) - val parsedCreateDocumentIssue = jsValueToDocumentIssue(createDocumentIssueJson, LongId(1), StringId("userId-001")) - parsedCreateDocumentIssue should be(expectedCreatedDocumentIssue) - - val updateDocumentIssueJson = - """{"text":"new issue text","evidence":"issue evidence","archiveRequired":true,"startPage":1.0,"endPage":4.0}""".parseJson - val expectedUpdatedDocumentIssue = documentIssue.copy( - text = "new issue text", - archiveRequired = true, - endPage = Some(4.0) - ) - val parsedUpdateDocumentIssue = applyUpdateToDocumentIssue(updateDocumentIssueJson, documentIssue) - parsedUpdateDocumentIssue should be(expectedUpdatedDocumentIssue) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExportFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExportFormatSuite.scala deleted file mode 100644 index d0d4d1a..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExportFormatSuite.scala +++ /dev/null @@ -1,124 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.{LocalDate, LocalDateTime} -import java.util.UUID - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.RecordRequestId - -class ExportFormatSuite extends FlatSpec with Matchers { - import export._ - - "Json format for ExportPatientWithLabels" should "read and write correct JSON" in { - import xyz.driver.pdsuidomain.entities.export.patient._ - val document = ExportPatientLabelEvidenceDocument( - documentId = LongId(101), - requestId = RecordRequestId(UUID.fromString("7b54a75d-4197-4b27-9045-b9b6cb131be9")), - documentType = "document type", - providerType = "provider type", - date = LocalDate.parse("2017-08-10") - ) - val labels = List( - ExportPatientLabel( - id = LongId(1), - evidences = List( - ExportPatientLabelEvidence( - id = LongId(11), - value = FuzzyValue.Yes, - evidenceText = "evidence text 11", - document = document - ), - ExportPatientLabelEvidence( - id = LongId(12), - value = FuzzyValue.No, - evidenceText = "evidence text 12", - document = document - ) - ) - ), - ExportPatientLabel( - id = LongId(2), - evidences = List( - ExportPatientLabelEvidence( - id = LongId(12), - value = FuzzyValue.Yes, - evidenceText = "evidence text 12", - document = document - ), - ExportPatientLabelEvidence( - id = LongId(13), - value = FuzzyValue.Yes, - evidenceText = "evidence text 13", - document = document - ) - ) - ) - ) - val patientWithLabels = ExportPatientWithLabels( - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - labelVersion = 1L, - labels = labels - ) - - val writtenJson = patientWithLabelsWriter.write(patientWithLabels) - writtenJson should be( - """{"patientId":"748b5884-3528-4cb9-904b-7a8151d6e343","labelVersion":1,"labels":[{"labelId":1,"evidence":[{"evidenceId":11, - "labelValue":"Yes","evidenceText":"evidence text 11","document":{"documentId":101,"requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9", - "documentType":"document type","providerType":"provider type","date":"2017-08-10"}},{"evidenceId":12,"labelValue":"No", - "evidenceText":"evidence text 12","document":{"documentId":101,"requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9", - "documentType":"document type","providerType":"provider type","date":"2017-08-10"}}]}, - {"labelId":2,"evidence":[{"evidenceId":12,"labelValue":"Yes","evidenceText":"evidence text 12","document": - {"documentId":101,"requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9","documentType":"document type", - "providerType":"provider type","date":"2017-08-10"}},{"evidenceId":13,"labelValue":"Yes","evidenceText":"evidence text 13", - "document":{"documentId":101,"requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9","documentType":"document type", - "providerType":"provider type","date":"2017-08-10"}}]}]}""".parseJson) - } - - "Json format for ApiExportTrialWithLabels" should "read and write correct JSON" in { - import xyz.driver.pdsuidomain.entities.export.trial._ - val arms = List( - ExportTrialArm(armId = LongId(1), armName = "arm 1"), - ExportTrialArm(armId = LongId(2), armName = "arm 2") - ) - val criteriaList = List( - ExportTrialLabelCriterion( - criterionId = LongId(10), - value = Some(true), - labelId = LongId(21), - armIds = Set(LongId(1), LongId(2)), - criteria = "criteria 10 text", - isCompound = false, - isDefining = false - ), - ExportTrialLabelCriterion( - criterionId = LongId(11), - value = None, - labelId = LongId(21), - armIds = Set(LongId(2)), - criteria = "criteria 11 text", - isCompound = true, - isDefining = false - ) - ) - val trialWithLabels = ExportTrialWithLabels( - nctId = StringId("NCT000001"), - trialId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), - condition = "Breast", - lastReviewed = LocalDateTime.parse("2017-08-10T18:00:00"), - labelVersion = 1L, - arms = arms, - criteria = criteriaList - ) - - val writtenJson = trialWithLabelsWriter.write(trialWithLabels) - writtenJson should be( - """{"nctId":"NCT000001","trialId":"40892a07-c638-49d2-9795-1edfefbbcc7c","disease":"Breast","lastReviewed":"2017-08-10T18:00Z", - "labelVersion":1,"arms":[{"armId":1,"armName":"arm 1"},{"armId":2,"armName":"arm 2"}],"criteria":[ - {"value":"Yes","labelId":21,"criterionId":10,"criterionText":"criteria 10 text","armIds":[1,2],"isCompound":false,"isDefining":false}, - {"value":"Unknown","labelId":21,"criterionId":11,"criterionText":"criteria 11 text","armIds":[2],"isCompound":true,"isDefining":false}]}""".parseJson) - } - - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExtractedDataFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExtractedDataFormatSuite.scala deleted file mode 100644 index a4b8bab..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/ExtractedDataFormatSuite.scala +++ /dev/null @@ -1,95 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, TextJson} -import xyz.driver.pdsuidomain.entities.ExtractedData.Meta -import xyz.driver.pdsuidomain.entities.{ExtractedData, ExtractedDataLabel} -import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData - -class ExtractedDataFormatSuite extends FlatSpec with Matchers { - import extracteddata._ - - "Json format for ExtractedData" should "read and write correct JSON" in { - val extractedData = ExtractedData( - id = LongId(1), - documentId = LongId(101), - keywordId = Some(LongId(201)), - evidenceText = Some("evidence text"), - meta = None - ) - val extractedDataLabels = List( - ExtractedDataLabel( - id = LongId(1), - dataId = extractedData.id, - labelId = None, - categoryId = None, - value = Some(FuzzyValue.Yes) - ), - ExtractedDataLabel( - id = LongId(2), - dataId = extractedData.id, - labelId = Some(LongId(12)), - categoryId = Some(LongId(1)), - value = Some(FuzzyValue.No) - ) - ) - val origRichExtractedData = RichExtractedData( - extractedData = extractedData, - labels = extractedDataLabels - ) - val writtenJson = extractedDataFormat.write(origRichExtractedData) - - writtenJson should be ( - """{"id":1,"documentId":101,"keywordId":201,"evidence":"evidence text","meta":null, - "labels":[{"id":null,"categoryId":null,"value":"Yes"},{"id":12,"categoryId":1,"value":"No"}]}""".parseJson) - - val createExtractedDataJson = - """{"documentId":101,"keywordId":201,"evidence":"evidence text", - "labels":[{"value":"Yes"},{"id":12,"categoryId":1,"value":"No"}]}""".parseJson - val expectedCreatedExtractedData = origRichExtractedData.copy( - extractedData = extractedData.copy(id = LongId(0)), - labels = extractedDataLabels.map(_.copy(id = LongId(0), dataId = LongId(0))) - ) - val parsedCreatedExtractedData = extractedDataFormat.read(createExtractedDataJson) - parsedCreatedExtractedData should be(expectedCreatedExtractedData) - - val updateExtractedDataJson = - """{"evidence":"new evidence text","meta":{"keyword":{"page":1,"index":2,"sortIndex":"ASC"}, - "evidence":{"pageRatio":1.0,"start":{"page":1,"index":3,"offset":2},"end":{"page":2,"index":3,"offset":10}}}, - "labels":[{"id":20,"categoryId":1,"value":"Yes"},{"id":12,"categoryId":1,"value":"No"}]}""".parseJson - val updatedExtractedDataLabels = List( - ExtractedDataLabel( - id = LongId(0), - dataId = extractedData.id, - labelId = Some(LongId(20)), - categoryId = Some(LongId(1)), - value = Some(FuzzyValue.Yes) - ), - ExtractedDataLabel( - id = LongId(0), - dataId = extractedData.id, - labelId = Some(LongId(12)), - categoryId = Some(LongId(1)), - value = Some(FuzzyValue.No) - ) - ) - val expectedUpdatedExtractedData = origRichExtractedData.copy( - extractedData = extractedData.copy( - evidenceText = Some("new evidence text"), - meta = Some(TextJson(Meta( - keyword = Meta.Keyword(page = 1, pageRatio = None, index = 2, sortIndex = "ASC"), - evidence = Meta.Evidence( - pageRatio = 1.0, - start = Meta.TextLayerPosition(page = 1, index = 3, offset = 2), - end = Meta.TextLayerPosition(page = 2, index = 3, offset = 10) - ) - ))) - ), - labels = updatedExtractedDataLabels - ) - val parsedUpdatedExtractedData = applyUpdateToExtractedData(updateExtractedDataJson, origRichExtractedData) - parsedUpdatedExtractedData should be(expectedUpdatedExtractedData) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/HypothesisFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/HypothesisFormatSuite.scala deleted file mode 100644 index 306fb17..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/HypothesisFormatSuite.scala +++ /dev/null @@ -1,28 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuidomain.entities.Hypothesis - -class HypothesisFormatSuite extends FlatSpec with Matchers { - import hypothesis._ - - "Json format for Hypothesis" should "read and write correct JSON" in { - val hypothesis = Hypothesis( - id = UuidId("3b80b2e2-5372-4cf5-a342-6e4ebe10fafd"), - name = "hypothesis name", - treatmentType = "treatment type", - description = "descr" - ) - val writtenJson = hypothesisFormat.write(hypothesis) - - writtenJson should be( - """{"id":"3b80b2e2-5372-4cf5-a342-6e4ebe10fafd","name":"hypothesis name", - "treatmentType":"treatment type","description":"descr"}""".parseJson) - - val parsedHypothesis = hypothesisFormat.read(writtenJson) - parsedHypothesis should be(hypothesis) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/InterventionFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/InterventionFormatSuite.scala deleted file mode 100644 index 784a655..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/InterventionFormatSuite.scala +++ /dev/null @@ -1,63 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.{Intervention, InterventionArm, InterventionType, InterventionWithArms} - -class InterventionFormatSuite extends FlatSpec with Matchers { - import intervention._ - - "Json format for Intervention" should "read and write correct JSON" in { - val intervention = Intervention( - id = LongId(1), - trialId = StringId("NCT000001"), - name = "intervention name", - originalName = "orig name", - typeId = Some(LongId(10)), - originalType = Some("orig type"), - description = "", - originalDescription = "", - isActive = true - ) - val arms = List( - InterventionArm(interventionId = intervention.id, armId = LongId(20)), - InterventionArm(interventionId = intervention.id, armId = LongId(21)), - InterventionArm(interventionId = intervention.id, armId = LongId(22)) - ) - val orig = InterventionWithArms( - intervention = intervention, - arms = arms - ) - val writtenJson = interventionWriter.write(orig) - - writtenJson should be( - """{"id":1,"name":"intervention name","typeId":10,"description":"","isActive":true,"arms":[20,21,22], - "trialId":"NCT000001","originalName":"orig name","originalDescription":"","originalType":"orig type"}""".parseJson) - - val updateInterventionJson = """{"description":"descr","arms":[21,22]}""".parseJson - val expectedUpdatedIntervention = orig.copy( - intervention = intervention.copy(description = "descr"), - arms = List( - InterventionArm(interventionId = intervention.id, armId = LongId(21)), - InterventionArm(interventionId = intervention.id, armId = LongId(22)) - ) - ) - val parsedUpdateIntervention = applyUpdateToInterventionWithArms(updateInterventionJson, orig) - parsedUpdateIntervention should be(expectedUpdatedIntervention) - } - - "Json format for InterventionType" should "read and write correct JSON" in { - val interventionType = InterventionType( - id = LongId(10), - name = "type name" - ) - val writtenJson = interventionTypeFormat.write(interventionType) - - writtenJson should be("""{"id":10,"name":"type name"}""".parseJson) - - val parsedInterventionType = interventionTypeFormat.read(writtenJson) - parsedInterventionType should be(interventionType) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordFormatSuite.scala deleted file mode 100644 index 899e5c9..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordFormatSuite.scala +++ /dev/null @@ -1,77 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime -import java.util.UUID - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, TextJson, UuidId} -import xyz.driver.pdsuidomain.entities.{MedicalRecord, RecordRequestId} - -class MedicalRecordFormatSuite extends FlatSpec with Matchers { - import record._ - import MedicalRecord._ - - "Json format for MedicalRecord" should "read and write correct JSON" in { - val orig = MedicalRecord( - id = LongId(1), - status = Status.New, - assignee = None, - previousStatus = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - physician = Some("physician"), - meta = None, - predictedMeta = None, - predictedDocuments = None, - disease = "Breast", - requestId = RecordRequestId(UUID.fromString("7b54a75d-4197-4b27-9045-b9b6cb131be9")), - caseId = None, - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343") - ) - val writtenJson = recordFormat.write(orig) - - writtenJson should be ( - """{"id":1,"status":"New","assignee":null,"previousStatus":null,"previousAssignee":null,"lastActiveUser":null, - "lastUpdate":"2017-08-10T18:00Z","meta":[],"patientId":"748b5884-3528-4cb9-904b-7a8151d6e343","caseId":null, - "requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9","disease":"Breast","physician":"physician"}""".parseJson) - - val createRecordJson = - """{"disease":"Breast","patientId":"748b5884-3528-4cb9-904b-7a8151d6e343","requestId":"7b54a75d-4197-4b27-9045-b9b6cb131be9"}""".parseJson - val expectedCreatedRecord = MedicalRecord( - id = LongId(0), - status = MedicalRecord.Status.New, - previousStatus = None, - assignee = None, - previousAssignee = None, - lastActiveUserId = None, - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - requestId = RecordRequestId(UUID.fromString("7b54a75d-4197-4b27-9045-b9b6cb131be9")), - disease = "Breast", - caseId = None, - physician = None, - meta = None, - predictedMeta = None, - predictedDocuments = None, - lastUpdate = LocalDateTime.now() - ) - val parsedCreatedRecord = recordFormat.read(createRecordJson).copy(lastUpdate = expectedCreatedRecord.lastUpdate) - parsedCreatedRecord should be(expectedCreatedRecord) - - val updateRecordJson = - """{"meta":[{"type":"duplicate","predicted":true,"startPage":1.0,"endPage":2.0,"startOriginalPage":1.0}, - {"type":"reorder","items":[1,2]}, - {"type":"rotation","items":{"item1":1,"item2":2}}]}""".parseJson - val expectedUpdatedRecord = orig.copy( - meta = Some(TextJson(List( - Meta.Duplicate(predicted = Some(true), startPage = 1.0, endPage = 2.0, startOriginalPage = 1.0, endOriginalPage = None), - Meta.Reorder(predicted = None, items = Seq(1, 2)), - Meta.Rotation(predicted = None, items = Map("item1" -> 1, "item2" -> 2)) - ))) - ) - val parsedUpdatedRecord = applyUpdateToMedicalRecord(updateRecordJson, orig) - parsedUpdatedRecord should be(expectedUpdatedRecord) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordHistoryFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordHistoryFormatSuite.scala deleted file mode 100644 index 5cd6c8d..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordHistoryFormatSuite.scala +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.MedicalRecordHistory - -class MedicalRecordHistoryFormatSuite extends FlatSpec with Matchers { - import recordhistory._ - - "Json format for MedicalRecordHistory" should "read and write correct JSON" in { - val recordHistory = MedicalRecordHistory( - id = LongId(10), - recordId = LongId(1), - executor = StringId("userId-001"), - state = MedicalRecordHistory.State.Clean, - action = MedicalRecordHistory.Action.Start, - created = LocalDateTime.parse("2017-08-10T18:00:00") - ) - val writtenJson = recordHistoryFormat.write(recordHistory) - - writtenJson should be( - """{"id":10,"executor":"userId-001","recordId":1,"state":"Clean", - "action":"Start","created":"2017-08-10T18:00Z"}""".parseJson) - - val parsedRecordHistory = recordHistoryFormat.read(writtenJson) - parsedRecordHistory should be(recordHistory) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordIssueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordIssueFormatSuite.scala deleted file mode 100644 index 9b89c97..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/MedicalRecordIssueFormatSuite.scala +++ /dev/null @@ -1,47 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.MedicalRecordIssue - -class MedicalRecordIssueFormatSuite extends FlatSpec with Matchers { - import recordissue._ - - "Json format for MedicalRecordIssue" should "read and write correct JSON" in { - val recordIssue = MedicalRecordIssue( - id = LongId(10), - recordId = LongId(1), - userId = StringId("userId-001"), - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - isDraft = false, - text = "message text", - archiveRequired = false, - startPage = Some(1.0), - endPage = Some(2.0) - ) - val writtenJson = recordIssueWriter.write(recordIssue) - - writtenJson should be( - """{"id":10,"userId":"userId-001","lastUpdate":"2017-08-10T18:00Z","isDraft":false, - "text":"message text","archiveRequired":false,"startPage":1.0,"endPage":2.0}""".parseJson) - - val createRecordIssueJson = """{"text":"message text","startPage":1.0,"endPage":2.0}""".parseJson - val expectedCreatedRecordIssue = recordIssue.copy(id = LongId(0), lastUpdate = LocalDateTime.MIN, isDraft = true) - val parsedCreateRecordIssue = jsValueToRecordIssue(createRecordIssueJson, LongId(1), StringId("userId-001")) - parsedCreateRecordIssue should be(expectedCreatedRecordIssue) - - val updateRecordIssueJson = - """{"text":"new issue text","evidence":"issue evidence","archiveRequired":true,"startPage":1.0,"endPage":4.0}""".parseJson - val expectedUpdatedRecordIssue = recordIssue.copy( - text = "new issue text", - archiveRequired = true, - endPage = Some(4.0) - ) - val parsedUpdateRecordIssue = applyUpdateToRecordIssue(updateRecordIssueJson, recordIssue) - parsedUpdateRecordIssue should be(expectedUpdatedRecordIssue) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientCriterionFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientCriterionFormatSuite.scala deleted file mode 100644 index 0f5e4e2..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientCriterionFormatSuite.scala +++ /dev/null @@ -1,55 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, StringId} -import xyz.driver.pdsuidomain.entities.{PatientCriterion, PatientCriterionArm} -import xyz.driver.pdsuidomain.services.PatientCriterionService.DraftPatientCriterion - -class PatientCriterionFormatSuite extends FlatSpec with Matchers { - import patientcriterion._ - - "Json format for PatientCriterion" should "read and write correct JSON" in { - val orig = PatientCriterion( - id = LongId(1), - patientLabelId = LongId(1), - trialId = 0L, - nctId = StringId("NCT00001"), - criterionId = LongId(101), - criterionText = "criterion text", - criterionValue = Some(true), - criterionIsDefining = false, - eligibilityStatus = Some(FuzzyValue.Yes), - verifiedEligibilityStatus = None, - isVisible = true, - isVerified = true, - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00") - ) - val arms = List( - PatientCriterionArm(patientCriterionId = LongId(1), armId = LongId(31), armName = "arm 31"), - PatientCriterionArm(patientCriterionId = LongId(1), armId = LongId(32), armName = "arm 32") - ) - val writtenJson = patientCriterionWriter.write((orig, LongId(21), arms)) - - writtenJson should be ( - """{"id":1,"labelId":21,"nctId":"NCT00001","criterionId":101,"criterionText":"criterion text","criterionValue":"Yes", - "criterionIsDefining":false,"criterionIsCompound":false,"eligibilityStatus":"Yes","verifiedEligibilityStatus":null, - "isVisible":true,"isVerified":true,"lastUpdate":"2017-08-10T18:00Z","arms":["arm 31","arm 32"]}""".parseJson) - - val updatePatientCriterionJson = """{"verifiedEligibilityStatus":"No"}""".parseJson - val expectedUpdatedPatientCriterion = orig.copy(verifiedEligibilityStatus = Some(FuzzyValue.No)) - val parsedUpdatePatientCriterion = applyUpdateToPatientCriterion(updatePatientCriterionJson, orig) - parsedUpdatePatientCriterion should be(expectedUpdatedPatientCriterion) - - val updateBulkPatientCriterionJson = """[{"id":1,"eligibilityStatus":"No"},{"id":2,"isVerified":false}]""".parseJson - val expectedDraftPatientCriterionList = List( - DraftPatientCriterion(id = LongId(1), eligibilityStatus = Some(FuzzyValue.No), isVerified = None), - DraftPatientCriterion(id = LongId(2), eligibilityStatus = None, isVerified = Some(false)) - ) - val parsedDraftPatientCriterionList = draftPatientCriterionListReader.read(updateBulkPatientCriterionJson) - parsedDraftPatientCriterionList should be(expectedDraftPatientCriterionList) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientEligibleTrialFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientEligibleTrialFormatSuite.scala deleted file mode 100644 index ad54946..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientEligibleTrialFormatSuite.scala +++ /dev/null @@ -1,62 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.{PatientCriterionArm, PatientTrialArmGroupView, Trial} -import xyz.driver.pdsuidomain.services.PatientEligibleTrialService.RichPatientEligibleTrial - -class PatientEligibleTrialFormatSuite extends FlatSpec with Matchers { - import patienteligibletrial._ - - "Json format for PatientEligibleTrial" should "read and write correct JSON" in { - val trial = Trial( - id = StringId("NCT000001"), - externalId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), - status = Trial.Status.Done, - assignee = None, - previousStatus = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.parse("2017-08-10T18:16:19"), - condition = Trial.Condition.Breast, - phase = "", - hypothesisId = Some(UuidId("e76e2fc4-a29c-44fb-a81b-8856d06bb1d4")), - studyDesignId = Some(LongId(321)), - originalStudyDesign = None, - isPartner = false, - overview = None, - overviewTemplate = "", - isUpdated = false, - title = "trial title", - originalTitle = "orig trial title" - ) - val group = PatientTrialArmGroupView( - id = LongId(1), - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - trialId = StringId("NCT000001"), - hypothesisId = UuidId("e76e2fc4-a29c-44fb-a81b-8856d06bb1d4"), - eligibilityStatus = Some(FuzzyValue.Yes), - verifiedEligibilityStatus = Some(FuzzyValue.Yes), - isVerified = false - ) - val arms = List( - PatientCriterionArm(patientCriterionId = LongId(1), armId = LongId(31), armName = "arm 31"), - PatientCriterionArm(patientCriterionId = LongId(1), armId = LongId(32), armName = "arm 32") - ) - val orig = RichPatientEligibleTrial(trial, group, arms) - val writtenJson = patientEligibleTrialWriter.write(orig) - - writtenJson should be ( - """{"id":1,"patientId":"748b5884-3528-4cb9-904b-7a8151d6e343","trialId":"NCT000001","trialTitle":"trial title", - "hypothesisId":"e76e2fc4-a29c-44fb-a81b-8856d06bb1d4","verifiedEligibilityStatus":"Yes","isVerified":false,"arms":["arm 31","arm 32"]}""".parseJson) - - val updatePatientEligibleTrialJson = """{"isVerified":true}""".parseJson - val expectedUpdatedPatientTrialArmGroup = group.copy(isVerified = true) - val parsedUpdatePatientTrialArmGroup = applyUpdateToTrialArmGroup(updatePatientEligibleTrialJson, group) - parsedUpdatePatientTrialArmGroup should be(expectedUpdatedPatientTrialArmGroup) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientFormatSuite.scala deleted file mode 100644 index 2761d6a..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientFormatSuite.scala +++ /dev/null @@ -1,36 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.{LocalDate, LocalDateTime} - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuidomain.entities.{Patient, PatientOrderId} - -class PatientFormatSuite extends FlatSpec with Matchers { - import patient._ - - "Json format for Patient" should "read and write correct JSON" in { - val orig = Patient( - id = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - status = Patient.Status.New, - name = "John Doe", - dob = LocalDate.parse("1980-06-30"), - assignee = None, - previousStatus = None, - previousAssignee = None, - lastActiveUserId = None, - isUpdateRequired = false, - condition = "breast", - orderId = PatientOrderId("7b54a75d-4197-4b27-9045-b9b6cb131be9"), - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00") - ) - val writtenJson = patientWriter.write(orig) - - writtenJson should be ( - """{"id":"748b5884-3528-4cb9-904b-7a8151d6e343","dob":"1980-06-30","name":"John Doe","status":"New","assignee":null, - "previousStatus":null,"previousAssignee":null,"lastActiveUser":null,"lastUpdate":"2017-08-10T18:00Z", - "orderId":"7b54a75d-4197-4b27-9045-b9b6cb131be9","condition":"breast"}""".parseJson) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHistoryFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHistoryFormatSuite.scala deleted file mode 100644 index c6a5a9f..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHistoryFormatSuite.scala +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.PatientHistory - -class PatientHistoryFormatSuite extends FlatSpec with Matchers { - import patienthistory._ - - "Json format for PatientHistory" should "read and write correct JSON" in { - val patientHistory = PatientHistory( - id = LongId(10), - patientId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), - executor = StringId("userId-001"), - state = PatientHistory.State.Verify, - action = PatientHistory.Action.Start, - created = LocalDateTime.parse("2017-08-10T18:00:00") - ) - val writtenJson = patientHistoryFormat.write(patientHistory) - - writtenJson should be( - """{"id":10,"executor":"userId-001","patientId":"40892a07-c638-49d2-9795-1edfefbbcc7c","state":"Verify", - "action":"Start","created":"2017-08-10T18:00Z"}""".parseJson) - - val parsedPatientHistory = patientHistoryFormat.read(writtenJson) - parsedPatientHistory should be(patientHistory) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHypothesisFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHypothesisFormatSuite.scala deleted file mode 100644 index 2999cc1..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientHypothesisFormatSuite.scala +++ /dev/null @@ -1,31 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.UuidId -import xyz.driver.pdsuidomain.entities.PatientHypothesis - -class PatientHypothesisFormatSuite extends FlatSpec with Matchers { - import patienthypothesis._ - - "Json format for PatientHypothesis" should "read and write correct JSON" in { - val orig = PatientHypothesis( - id = UuidId("815d9715-1089-4775-b120-3afb983b9a97"), - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - hypothesisId = UuidId("e76e2fc4-a29c-44fb-a81b-8856d06bb1d4"), - rationale = None, - matchedTrials = 1 - ) - val writtenJson = patientHypothesisWriter.write((orig, true)) - - writtenJson should be ( - """{"id":"815d9715-1089-4775-b120-3afb983b9a97","patientId":"748b5884-3528-4cb9-904b-7a8151d6e343", - "hypothesisId":"e76e2fc4-a29c-44fb-a81b-8856d06bb1d4","rationale":null,"matchedTrials":1,"isRationaleRequired":true}""".parseJson) - - val updatePatientHypothesisJson = """{"rationale":"rationale"}""".parseJson - val expectedUpdatedPatientHypothesis = orig.copy(rationale = Some("rationale")) - val parsedUpdatePatientHypothesis = applyUpdateToPatientHypothesis(updatePatientHypothesisJson, orig) - parsedUpdatePatientHypothesis should be(expectedUpdatedPatientHypothesis) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientIssueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientIssueFormatSuite.scala deleted file mode 100644 index 1e2a11e..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientIssueFormatSuite.scala +++ /dev/null @@ -1,44 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.PatientIssue - -class PatientIssueFormatSuite extends FlatSpec with Matchers { - import patientissue._ - - "Json format for PatientIssue" should "read and write correct JSON" in { - val patientIssue = PatientIssue( - id = LongId(10), - patientId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), - userId = StringId("userId-001"), - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - isDraft = false, - text = "message text", - archiveRequired = false - ) - val writtenJson = patientIssueWriter.write(patientIssue) - - writtenJson should be( - """{"id":10,"userId":"userId-001","lastUpdate":"2017-08-10T18:00Z","isDraft":false, - "text":"message text","archiveRequired":false}""".parseJson) - - val createPatientIssueJson = """{"text":"message text"}""".parseJson - val expectedCreatedPatientIssue = patientIssue.copy(id = LongId(0), lastUpdate = LocalDateTime.MIN, isDraft = true) - val parsedCreatePatientIssue = jsValueToPatientIssue(createPatientIssueJson, UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), StringId("userId-001")) - parsedCreatePatientIssue should be(expectedCreatedPatientIssue) - - val updatePatientIssueJson = - """{"text":"new issue text","evidence":"issue evidence","archiveRequired":true}""".parseJson - val expectedUpdatedPatientIssue = patientIssue.copy( - text = "new issue text", - archiveRequired = true - ) - val parsedUpdatePatientIssue = applyUpdateToPatientIssue(updatePatientIssueJson, patientIssue) - parsedUpdatePatientIssue should be(expectedUpdatedPatientIssue) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientLabelFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientLabelFormatSuite.scala deleted file mode 100644 index e18239c..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/PatientLabelFormatSuite.scala +++ /dev/null @@ -1,76 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDate - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, UuidId} -import xyz.driver.pdsuidomain.entities.{PatientLabel, PatientLabelEvidenceView} - -class PatientLabelFormatSuite extends FlatSpec with Matchers { - - "Json format for PatientLabel" should "read and write correct JSON" in { - import patientlabel._ - val orig = PatientLabel( - id = LongId(1), - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - labelId = LongId(20), - primaryValue = Some(FuzzyValue.Yes), - verifiedPrimaryValue = None, - isVisible = true, - score = 1, - isImplicitMatch = false - ) - val writtenJson = patientLabelWriter.write((orig, true)) - - writtenJson should be ( - """{"id":1,"labelId":20,"primaryValue":"Yes","verifiedPrimaryValue":null,"isVisible":true,"isVerified":true, - "score":1,"isImplicitMatch":false}""".parseJson) - - val updatePatientLabelJson = """{"verifiedPrimaryValue":"No"}""".parseJson - val expectedUpdatedPatientLabel = orig.copy(verifiedPrimaryValue = Some(FuzzyValue.No)) - val parsedUpdatePatientLabel = applyUpdateToPatientLabel(updatePatientLabelJson, orig) - parsedUpdatePatientLabel should be(expectedUpdatedPatientLabel) - } - - "Json format for PatientLabelEvidence" should "read and write correct JSON" in { - import patientlabel._ - val orig = PatientLabelEvidenceView( - id = LongId(1), - value = FuzzyValue.Maybe, - evidenceText = "evidence text", - documentId = Some(LongId(21)), - evidenceId = Some(LongId(10)), - reportId = None, - documentType = "document type", - date = Some(LocalDate.parse("2017-08-10")), - providerType = "provider type", - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - labelId = LongId(20), - isImplicitMatch = false - ) - val writtenJson = patientLabelEvidenceWriter.write(orig) - - writtenJson should be ( - """{"id":1,"value":"Maybe","evidenceText":"evidence text","documentId":21,"evidenceId":10,"reportId":null, - "documentType":"document type","date":"2017-08-10","providerType":"provider type"}""".parseJson) - } - - "Json format for PatientLabelDefiningCriteria" should "read and write correct JSON" in { - import patientdefiningcriteria._ - val orig = PatientLabel( - id = LongId(1), - patientId = UuidId("748b5884-3528-4cb9-904b-7a8151d6e343"), - labelId = LongId(20), - primaryValue = Some(FuzzyValue.Yes), - verifiedPrimaryValue = Some(FuzzyValue.Yes), - isVisible = true, - score = 1, - isImplicitMatch = false - ) - val writtenJson = patientLabelDefiningCriteriaWriter.write(orig) - - writtenJson should be ("""{"id":1,"value":"Yes"}""".parseJson) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/StudyDesignFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/StudyDesignFormatSuite.scala deleted file mode 100644 index 9cf9b5f..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/StudyDesignFormatSuite.scala +++ /dev/null @@ -1,24 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.LongId -import xyz.driver.pdsuidomain.entities.StudyDesign - -class StudyDesignFormatSuite extends FlatSpec with Matchers { - import studydesign._ - - "Json format for StudyDesign" should "read and write correct JSON" in { - val studyDesign = StudyDesign( - id = LongId(10), - name = "study design name" - ) - val writtenJson = studyDesignFormat.write(studyDesign) - - writtenJson should be("""{"id":10,"name":"study design name"}""".parseJson) - - val parsedStudyDesign = studyDesignFormat.read(writtenJson) - parsedStudyDesign should be(studyDesign) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialFormatSuite.scala deleted file mode 100644 index 59cf779..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialFormatSuite.scala +++ /dev/null @@ -1,50 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} -import xyz.driver.pdsuidomain.entities.Trial - -class TrialFormatSuite extends FlatSpec with Matchers { - import trial._ - - "Json format for Trial" should "read and write correct JSON" in { - val orig = Trial( - id = StringId("NCT000001"), - externalId = UuidId("40892a07-c638-49d2-9795-1edfefbbcc7c"), - status = Trial.Status.New, - assignee = None, - previousStatus = None, - previousAssignee = None, - lastActiveUserId = None, - lastUpdate = LocalDateTime.parse("2017-08-10T18:16:19"), - condition = Trial.Condition.Breast, - phase = "", - hypothesisId = Some(UuidId("3b80b2e2-5372-4cf5-a342-6e4ebe10fafd")), - studyDesignId = Some(LongId(321)), - originalStudyDesign = None, - isPartner = false, - overview = None, - overviewTemplate = "", - isUpdated = false, - title = "trial title", - originalTitle = "orig trial title" - ) - val writtenJson = trialWriter.write(orig) - - writtenJson should be ( - """{"isPartner":false,"assignee":null,"lastUpdate":"2017-08-10T18:16:19Z","previousStatus":null, - "isUpdated":false,"overviewTemplate":"","phase":"","originalStudyDesignId":null, - "hypothesisId":"3b80b2e2-5372-4cf5-a342-6e4ebe10fafd","originalTitle":"orig trial title", - "studyDesignId":321,"lastActiveUser":null,"externalid":"40892a07-c638-49d2-9795-1edfefbbcc7c", - "id":"NCT000001","condition":"Breast","status":"New","overview":null,"previousAssignee":null,"title":"trial title"}""".parseJson) - - val updateTrialJson = """{"hypothesisId":null,"overview":"new overview"}""".parseJson - val expectedUpdatedTrial = orig.copy(hypothesisId = None, overview = Some("new overview")) - val parsedUpdateTrial = applyUpdateToTrial(updateTrialJson, orig) - parsedUpdateTrial should be(expectedUpdatedTrial) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialHistoryFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialHistoryFormatSuite.scala deleted file mode 100644 index dbb143c..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialHistoryFormatSuite.scala +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.TrialHistory - -class TrialHistoryFormatSuite extends FlatSpec with Matchers { - import trialhistory._ - - "Json format for TrialHistory" should "read and write correct JSON" in { - val trialHistory = TrialHistory( - id = LongId(10), - trialId = StringId("NCT000001"), - executor = StringId("userId-001"), - state = TrialHistory.State.Summarize, - action = TrialHistory.Action.Start, - created = LocalDateTime.parse("2017-08-10T18:00:00") - ) - val writtenJson = trialHistoryFormat.write(trialHistory) - - writtenJson should be( - """{"id":10,"executor":"userId-001","trialId":"NCT000001","state":"Summarize", - "action":"Start","created":"2017-08-10T18:00Z"}""".parseJson) - - val parsedTrialHistory = trialHistoryFormat.read(writtenJson) - parsedTrialHistory should be(trialHistory) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialIssueFormatSuite.scala b/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialIssueFormatSuite.scala deleted file mode 100644 index 02e14ba..0000000 --- a/src/test/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/TrialIssueFormatSuite.scala +++ /dev/null @@ -1,49 +0,0 @@ -package xyz.driver.pdsuidomain.formats.json.sprayformats - -import java.time.LocalDateTime - -import spray.json._ -import org.scalatest.{FlatSpec, Matchers} -import xyz.driver.pdsuicommon.domain.{LongId, StringId} -import xyz.driver.pdsuidomain.entities.TrialIssue - -class TrialIssueFormatSuite extends FlatSpec with Matchers { - import trialissue._ - - "Json format for TrialIssue" should "read and write correct JSON" in { - val trialIssue = TrialIssue( - id = LongId(10), - trialId = StringId("NCT000001"), - userId = StringId("userId-001"), - lastUpdate = LocalDateTime.parse("2017-08-10T18:00:00"), - isDraft = false, - text = "message text", - evidence = "evidence", - archiveRequired = false, - meta = "{}" - ) - val writtenJson = trialIssueWriter.write(trialIssue) - - writtenJson should be( - """{"id":10,"userId":"userId-001","lastUpdate":"2017-08-10T18:00Z","isDraft":false, - "text":"message text","evidence":"evidence","archiveRequired":false,"meta":"{}"}""".parseJson) - - val createTrialIssueJson = """{"text":"message text","evidence":"evidence","meta":"{}"}""".parseJson - val expectedCreatedTrialIssue = trialIssue.copy(id = LongId(0), lastUpdate = LocalDateTime.MIN, isDraft = true) - val parsedCreateTrialIssue = jsValueToTrialIssue(createTrialIssueJson, StringId("NCT000001"), StringId("userId-001")) - parsedCreateTrialIssue should be(expectedCreatedTrialIssue) - - val updateTrialIssueJson = - """{"text":"new issue text","evidence":"issue evidence","archiveRequired":true, - "meta":"{\"startPage\":1.0,\"endPage\":2.0}"}""".parseJson - val expectedUpdatedTrialIssue = trialIssue.copy( - text = "new issue text", - evidence = "issue evidence", - archiveRequired = true, - meta = """{"startPage":1.0,"endPage":2.0}""" - ) - val parsedUpdateTrialIssue = applyUpdateToTrialIssue(updateTrialIssueJson, trialIssue) - parsedUpdateTrialIssue should be(expectedUpdatedTrialIssue) - } - -} diff --git a/src/test/scala/xyz/driver/pdsuicommon/db/SearchFilterExprSuite.scala b/src/test/scala/xyz/driver/restquery/db/SearchFilterExprSuite.scala index 35c8d30..56ad545 100644 --- a/src/test/scala/xyz/driver/pdsuicommon/db/SearchFilterExprSuite.scala +++ b/src/test/scala/xyz/driver/restquery/db/SearchFilterExprSuite.scala @@ -1,6 +1,7 @@ -package xyz.driver.pdsuicommon.db +package xyz.driver.restquery.db import org.scalatest.{FreeSpecLike, MustMatchers} +import xyz.driver.restquery.query.{SearchFilterBinaryOperation, SearchFilterExpr, SearchFilterNAryOperation} class SearchFilterExprSuite extends FreeSpecLike with MustMatchers { diff --git a/src/test/scala/xyz/driver/pdsuicommon/parsers/PaginationParserSuite.scala b/src/test/scala/xyz/driver/restquery/rest/parsers/PaginationParserSuite.scala index 48fc99b..e806f85 100644 --- a/src/test/scala/xyz/driver/pdsuicommon/parsers/PaginationParserSuite.scala +++ b/src/test/scala/xyz/driver/restquery/rest/parsers/PaginationParserSuite.scala @@ -1,8 +1,8 @@ -package xyz.driver.pdsuicommon.parsers +package xyz.driver.restquery.rest.parsers -import xyz.driver.pdsuicommon.db.Pagination -import xyz.driver.pdsuicommon.parsers.TestUtils._ +import xyz.driver.restquery.rest.parsers.TestUtils._ import org.scalatest.{FreeSpecLike, MustMatchers} +import xyz.driver.restquery.query.Pagination import scala.util.{Failure, Try} @@ -11,36 +11,40 @@ class PaginationParserSuite extends FreeSpecLike with MustMatchers { "parse" - { "pageSize" - { "should parse positive value" in { - val pagination = PaginationParser.parse(Seq( - "pageSize" -> "10", - "pageNumber" -> "1" - )) + val pagination = PaginationParser.parse( + Seq( + "pageSize" -> "10", + "pageNumber" -> "1" + )) pagination must success pagination.get.pageSize mustBe 10 } "should return a default value if there is no one" in { - val pagination = PaginationParser.parse(Seq( - "pageNumber" -> "1" - )) + val pagination = PaginationParser.parse( + Seq( + "pageNumber" -> "1" + )) pagination must success pagination.get.pageSize mustBe 100 } "should return a error for zero value" in { - val pagination = PaginationParser.parse(Seq( - "pageSize" -> "0", - "pageNumber" -> "1" - )) + val pagination = PaginationParser.parse( + Seq( + "pageSize" -> "0", + "pageNumber" -> "1" + )) checkFailedValidationOnlyOn(pagination, "pageSize") } "should return a error for negative value" in { - val pagination = PaginationParser.parse(Seq( - "pageSize" -> "-10", - "pageNumber" -> "1" - )) + val pagination = PaginationParser.parse( + Seq( + "pageSize" -> "-10", + "pageNumber" -> "1" + )) checkFailedValidationOnlyOn(pagination, "pageSize") } @@ -48,36 +52,40 @@ class PaginationParserSuite extends FreeSpecLike with MustMatchers { "pageNumber" - { "should parse positive value" in { - val pagination = PaginationParser.parse(Seq( - "pageSize" -> "1", - "pageNumber" -> "1" - )) + val pagination = PaginationParser.parse( + Seq( + "pageSize" -> "1", + "pageNumber" -> "1" + )) pagination must success pagination.get.pageSize mustBe 1 } "should return a default value if there is no one" in { - val pagination = PaginationParser.parse(Seq( - "pageSize" -> "1" - )) + val pagination = PaginationParser.parse( + Seq( + "pageSize" -> "1" + )) pagination must success pagination.get.pageNumber mustBe 1 } "should return a error for zero value" in { - val pagination = PaginationParser.parse(Seq( - "pageSize" -> "1", - "pageNumber" -> "0" - )) + val pagination = PaginationParser.parse( + Seq( + "pageSize" -> "1", + "pageNumber" -> "0" + )) checkFailedValidationOnlyOn(pagination, "pageNumber") } "should return a error for negative value" in { - val pagination = PaginationParser.parse(Seq( - "pageSize" -> "1", - "pageNumber" -> "-1" - )) + val pagination = PaginationParser.parse( + Seq( + "pageSize" -> "1", + "pageNumber" -> "-1" + )) checkFailedValidationOnlyOn(pagination, "pageNumber") } diff --git a/src/test/scala/xyz/driver/restquery/rest/parsers/SearchFilterParserSuite.scala b/src/test/scala/xyz/driver/restquery/rest/parsers/SearchFilterParserSuite.scala new file mode 100644 index 0000000..e0a1696 --- /dev/null +++ b/src/test/scala/xyz/driver/restquery/rest/parsers/SearchFilterParserSuite.scala @@ -0,0 +1,261 @@ +package xyz.driver.restquery.rest.parsers + +import java.util.UUID + +import fastparse.core.Parsed +import org.scalacheck.Arbitrary.arbitrary +import org.scalacheck.{Gen, Prop} +import org.scalatest.FreeSpecLike +import org.scalatest.prop.Checkers +import xyz.driver.restquery.query.SearchFilterBinaryOperation.Eq +import xyz.driver.restquery.query.SearchFilterExpr.Dimension +import xyz.driver.restquery.query.SearchFilterNAryOperation.In +import xyz.driver.restquery.query.{SearchFilterExpr, SearchFilterNAryOperation} +import xyz.driver.restquery.rest.parsers.TestUtils._ +import xyz.driver.restquery.utils.Utils +import xyz.driver.restquery.utils.Utils._ + +import scala.util._ + +object SearchFilterParserSuite { + + class UnexpectedSearchFilterExprException(x: SearchFilterExpr) extends Exception(s"unexpected $x") + +} + +class SearchFilterParserSuite extends FreeSpecLike with Checkers { + + import SearchFilterParserSuite._ + + "parse" - { + "should convert column names to snake case" in { + import xyz.driver.restquery.query.SearchFilterBinaryOperation._ + + val filter = SearchFilterParser.parse( + Seq( + "filters" -> "status IN Summarized,ReviewCriteria,Flagged,Done", + "filters" -> "previousStatus NOTEQ New", + "filters" -> "previousStatus NOTEQ ReviewSummary" + )) + + assert( + filter === Success(SearchFilterExpr.Intersection(List( + SearchFilterExpr.Atom + .NAry(Dimension(None, "status"), In, Seq("Summarized", "ReviewCriteria", "Flagged", "Done")), + SearchFilterExpr.Atom.Binary(Dimension(None, "previous_status"), NotEq, "New"), + SearchFilterExpr.Atom.Binary(Dimension(None, "previous_status"), NotEq, "ReviewSummary") + )))) + } + "dimensions" - { + "with table name" in check { + val dimensionGen = { + for (left <- Gen.identifier; right <- Gen.identifier) + yield left -> right + } + Prop.forAllNoShrink(dimensionGen) { + case (left, right) => + val raw = s"$left.$right" + val l = toSnakeCase(left) + val r = toSnakeCase(right) + SearchFilterParser.dimensionParser.parse(raw) match { + case Parsed.Success(Dimension(Some(`l`), `r`), _) => true + case _ => false + } + } + } + "just with field name" in check { + Prop.forAllNoShrink(Gen.identifier) { s => + val databaseS = Utils.toSnakeCase(s) + SearchFilterParser.dimensionParser.parse(s) match { + case Parsed.Success(Dimension(None, `databaseS`), _) => true + case _ => false + } + } + } + } + "atoms" - { + "binary" - { + "common operators" - { + "should be parsed with text values" in check { + import xyz.driver.restquery.query.SearchFilterBinaryOperation._ + + val testQueryGen = queryGen( + dimensionGen = Gen.identifier, + opGen = commonBinaryOpsGen, + valueGen = nonEmptyString + ) + + Prop.forAllNoShrink(testQueryGen) { query => + SearchFilterParser + .parse(Seq("filters" -> query)) + .map { + case SearchFilterExpr.Atom.Binary(_, Eq | NotEq | Like, _) => true + case x => throw new UnexpectedSearchFilterExprException(x) + } + .successProp + } + } + } + + "numeric operators" - { + "should not be parsed with text values" in check { + val testQueryGen = queryGen( + dimensionGen = Gen.identifier, + opGen = numericBinaryOpsGen, + valueGen = nonEmptyString.filter { s => + !s.matches("^\\d+$") + } + ) + + Prop.forAllNoShrink(testQueryGen) { query => + SearchFilterParser.parse(Seq("filters" -> query)).failureProp + } + } + } + + "actual recordId" - { + "should not be parsed with numeric values" in { + val filter = SearchFilterParser.parse(Seq("filters" -> "recordId EQ 1")) + assert(filter === Success(SearchFilterExpr.Atom.Binary(Dimension(None, "record_id"), Eq, Long.box(1)))) + } + } + + "actual isVisible boolean" - { + "should not be parsed with boolean values" in { + val filter = SearchFilterParser.parse(Seq("filters" -> "isVisible EQ true")) + assert( + filter === Success(SearchFilterExpr.Atom.Binary(Dimension(None, "is_visible"), Eq, Boolean.box(true)))) + } + } + + "actual patientId uuid" - { + "should parse the full UUID as java.util.UUID type" in { + val filter = SearchFilterParser.parse(Seq("filters" -> "patientId EQ 4b4879f7-42b3-4b7c-a685-5c97d9e69e7c")) + assert( + filter === Success(SearchFilterExpr.Atom + .Binary(Dimension(None, "patient_id"), Eq, UUID.fromString("4b4879f7-42b3-4b7c-a685-5c97d9e69e7c")))) + } + } + + "all operators" - { + "should be parsed with numeric values" in check { + val testQueryGen = queryGen( + dimensionGen = Gen.identifier, + opGen = allBinaryOpsGen, + valueGen = numericBinaryAtomValuesGen + ) + + Prop.forAllNoShrink(testQueryGen) { query => + SearchFilterParser + .parse(Seq("filters" -> query)) + .map { + case _: SearchFilterExpr.Atom.Binary => true + case x => throw new UnexpectedSearchFilterExprException(x) + } + .successProp + } + } + } + } + + "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, + opGen = Gen.const("in"), + valueGen = inValuesGen + ) + + Prop.forAllNoShrink(testQueryGen) { query => + SearchFilterParser + .parse(Seq("filters" -> query)) + .map { + case SearchFilterExpr.Atom.NAry(_, SearchFilterNAryOperation.In, _) => true + case x => throw new UnexpectedSearchFilterExprException(x) + } + .successProp + } + } + } + } + + "intersections" - { + "should be parsed" in check { + val commonAtomsGen = queryGen( + dimensionGen = Gen.identifier, + opGen = commonBinaryOpsGen, + valueGen = nonEmptyString + ) + + val numericAtomsGen = queryGen( + dimensionGen = Gen.identifier, + opGen = numericBinaryOpsGen, + valueGen = numericBinaryAtomValuesGen + ) + + val allAtomsGen = Gen.oneOf(commonAtomsGen, numericAtomsGen) + val intersectionsGen = Gen.choose(1, 3).flatMap { size => + Gen.containerOfN[Seq, String](size, allAtomsGen) + } + + Prop.forAllNoShrink(intersectionsGen) { queries => + SearchFilterParser.parse(queries.map(query => "filters" -> query)).successProp + } + } + } + } + + private val CommonBinaryOps = Seq("eq", "noteq", "like") + private val NumericBinaryOps = Seq("gt", "gteq", "lt", "lteq") + + private val allBinaryOpsGen: Gen[String] = + Gen.oneOf(CommonBinaryOps ++ NumericBinaryOps).flatMap(randomCapitalization) + private val commonBinaryOpsGen: Gen[String] = Gen.oneOf(CommonBinaryOps).flatMap(randomCapitalization) + private val numericBinaryOpsGen: Gen[String] = Gen.oneOf(NumericBinaryOps).flatMap(randomCapitalization) + + private val inValueCharsGen: Gen[Char] = arbitrary[Char].filter(_ != ',') + + private val nonEmptyString = arbitrary[String].filter { s => + !Utils.safeTrim(s).isEmpty + } + + private val numericBinaryAtomValuesGen: Gen[String] = arbitrary[Long].map(_.toString) + private val inValueGen: Gen[String] = { + Gen.nonEmptyContainerOf[Seq, Char](inValueCharsGen).map(_.mkString).filter(s => Utils.safeTrim(s).nonEmpty) + } + private val inValuesGen: Gen[String] = Gen.choose(1, 5).flatMap { size => + Gen.containerOfN[Seq, String](size, inValueGen).map(_.mkString(",")) + } + + private def queryGen(dimensionGen: Gen[String], opGen: Gen[String], valueGen: Gen[String]): Gen[String] = + for { + dimension <- dimensionGen + op <- opGen + value <- valueGen + } yield s"$dimension $op $value" + + private def randomCapitalization(input: String): Gen[String] = { + Gen.containerOfN[Seq, Boolean](input.length, arbitrary[Boolean]).map { capitalize => + input.view + .zip(capitalize) + .map { + case (currChar, true) => currChar.toUpper + case (currChar, false) => currChar + } + .mkString + } + } + +} diff --git a/src/test/scala/xyz/driver/pdsuicommon/parsers/SortingParserSuite.scala b/src/test/scala/xyz/driver/restquery/rest/parsers/SortingParserSuite.scala index e46015c..a18ac1e 100644 --- a/src/test/scala/xyz/driver/pdsuicommon/parsers/SortingParserSuite.scala +++ b/src/test/scala/xyz/driver/restquery/rest/parsers/SortingParserSuite.scala @@ -1,6 +1,6 @@ -package xyz.driver.pdsuicommon.parsers +package xyz.driver.restquery.rest.parsers -import xyz.driver.pdsuicommon.parsers.TestUtils._ +import xyz.driver.restquery.rest.parsers.TestUtils._ import org.scalacheck.Arbitrary.arbitrary import org.scalacheck.{Gen, Prop} import org.scalatest.prop.Checkers @@ -12,7 +12,7 @@ class SortingParserSuite extends FreeSpecLike with MustMatchers with Checkers { "single dimension" - commonTests(singleSortingQueryGen) "multiple dimensions in one query" - commonTests(multipleSortingQueryGen) "multiple queries" in { - val r = SortingParser.parse(Set("foo", "bar"), Seq("sort" -> "foo", "sort" ->"bar")) + val r = SortingParser.parse(Set("foo", "bar"), Seq("sort" -> "foo", "sort" -> "bar")) r must failWith[ParseQueryArgException] } } @@ -21,7 +21,7 @@ class SortingParserSuite extends FreeSpecLike with MustMatchers with Checkers { "valid" in check { val inputGen: Gen[(Set[String], String)] = for { validDimensions <- dimensionsGen - sorting <- queryGen(validDimensions) + sorting <- queryGen(validDimensions) } yield (validDimensions, sorting) Prop.forAllNoShrink(inputGen) { @@ -33,7 +33,9 @@ class SortingParserSuite extends FreeSpecLike with MustMatchers with Checkers { "invalid" in check { val inputGen: Gen[(Set[String], String)] = for { validDimensions <- dimensionsGen - invalidDimensions <- dimensionsGen.filter { xs => xs.intersect(validDimensions).isEmpty } + invalidDimensions <- dimensionsGen.filter { xs => + xs.intersect(validDimensions).isEmpty + } sorting <- queryGen(invalidDimensions) } yield (validDimensions, sorting) @@ -46,12 +48,12 @@ class SortingParserSuite extends FreeSpecLike with MustMatchers with Checkers { private val dimensionsGen: Gen[Set[String]] = for { unPrefixedSize <- Gen.choose(0, 3) - prefixedSize <- Gen.choose(0, 3) + prefixedSize <- Gen.choose(0, 3) if (unPrefixedSize + prefixedSize) > 0 unPrefixedDimensions <- Gen.containerOfN[Set, String](unPrefixedSize, Gen.identifier) - prefixes <- Gen.containerOfN[Set, String](prefixedSize, Gen.identifier) + prefixes <- Gen.containerOfN[Set, String](prefixedSize, Gen.identifier) dimensions <- Gen.containerOfN[Set, String](prefixedSize, Gen.identifier) } yield { val prefixedDimensions = prefixes.zip(dimensions).map { @@ -62,30 +64,33 @@ class SortingParserSuite extends FreeSpecLike with MustMatchers with Checkers { private def multipleSortingQueryGen(validDimensions: Set[String]): Gen[String] = { val validDimensionsSeq = validDimensions.toSeq - val indexGen = Gen.oneOf(validDimensionsSeq.indices) + val indexGen = Gen.oneOf(validDimensionsSeq.indices) val multipleDimensionsGen = Gen.nonEmptyContainerOf[Set, Int](indexGen).filter(_.size >= 2).map { indices => indices.map(validDimensionsSeq.apply) } for { - dimensions <- multipleDimensionsGen + dimensions <- multipleDimensionsGen isAscending <- Gen.containerOfN[Seq, Boolean](dimensions.size, arbitrary[Boolean]) } yield { - isAscending.zip(dimensions) + isAscending + .zip(dimensions) .map { - case (true, dimension) => dimension + case (true, dimension) => dimension case (false, dimension) => "-" + dimension } .mkString(",") } } - private def singleSortingQueryGen(validDimensions: Set[String]): Gen[String] = for { - isAscending <- arbitrary[Boolean] - dimensions <- Gen.oneOf(validDimensions.toSeq) - } yield isAscending match { - case true => dimensions - case false => "-" + dimensions - } + private def singleSortingQueryGen(validDimensions: Set[String]): Gen[String] = + for { + isAscending <- arbitrary[Boolean] + dimensions <- Gen.oneOf(validDimensions.toSeq) + } yield + isAscending match { + case true => dimensions + case false => "-" + dimensions + } } diff --git a/src/test/scala/xyz/driver/pdsuicommon/parsers/TestUtils.scala b/src/test/scala/xyz/driver/restquery/rest/parsers/TestUtils.scala index 4892b95..22ce5a0 100644 --- a/src/test/scala/xyz/driver/pdsuicommon/parsers/TestUtils.scala +++ b/src/test/scala/xyz/driver/restquery/rest/parsers/TestUtils.scala @@ -1,9 +1,9 @@ -package xyz.driver.pdsuicommon.parsers +package xyz.driver.restquery.rest.parsers import org.scalacheck.Prop import org.scalacheck.Prop.BooleanOperators import org.scalatest.matchers.{MatchResult, Matcher} -import xyz.driver.pdsuicommon.utils.Utils +import xyz.driver.restquery.utils.Utils import scala.reflect.ClassTag import scala.util.{Failure, Success, Try} @@ -21,9 +21,10 @@ object TestUtils { MatchResult( left.isFailure && left.failed.get.getClass == ct.runtimeClass, left match { - case Success(x) => s"$left did not fail" - case Failure(e) => s"$left did fail with ${Utils.getClassSimpleName(e.getClass)}, " + - s"not ${Utils.getClassSimpleName(ct.runtimeClass)}" + case Success(_) => s"$left did not fail" + case Failure(e) => + s"$left did fail with ${Utils.getClassSimpleName(e.getClass)}, " + + s"not ${Utils.getClassSimpleName(ct.runtimeClass)}" }, left match { case Success(_) => s"$left failed with ${Utils.getClassSimpleName(ct.runtimeClass)}" @@ -33,7 +34,7 @@ object TestUtils { } } - def failWith[ThrowableT <:Throwable](implicit ct: ClassTag[ThrowableT]) = new FailWith[ThrowableT] + def failWith[ThrowableT <: Throwable](implicit ct: ClassTag[ThrowableT]) = new FailWith[ThrowableT] final implicit class TryPropOps(val self: Try[Any]) extends AnyVal { @@ -44,7 +45,7 @@ object TestUtils { def failureProp: Prop = self match { case Success(x) => false :| s"invalid: $x" - case Failure(e) => true + case Failure(_) => true } } diff --git a/src/test/scala/xyz/driver/pdsuicommon/utils/StringOpsSuite.scala b/src/test/scala/xyz/driver/restquery/utils/StringOpsSuite.scala index 9bd4382..97a432f 100644 --- a/src/test/scala/xyz/driver/pdsuicommon/utils/StringOpsSuite.scala +++ b/src/test/scala/xyz/driver/restquery/utils/StringOpsSuite.scala @@ -1,33 +1,32 @@ -package xyz.driver.pdsuicommon.utils +package xyz.driver.restquery.utils -import xyz.driver.pdsuicommon.utils.Implicits.toStringOps import org.scalatest.FreeSpecLike class StringOpsSuite extends FreeSpecLike { "safeTrim" - { "empty string" in { - assert("".safeTrim == "") + assert(Utils.safeTrim("") == "") } "string with whitespace symbols" in { - assert("\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000".safeTrim == "") + assert(Utils.safeTrim("\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000") == "") } "string with control symbols" in { - assert("\u001f\u007f\t\n".safeTrim == "") + assert(Utils.safeTrim("\u001f\u007f\t\n") == "") } "whitespaces and control symbols from the left side" in { - assert("\u001f\u2002\u007f\nfoo".safeTrim == "foo") + assert(Utils.safeTrim("\u001f\u2002\u007f\nfoo") == "foo") } "whitespaces and control symbols from the right side" in { - assert("foo\u001f\u2002\u007f\n".safeTrim == "foo") + assert(Utils.safeTrim("foo\u001f\u2002\u007f\n") == "foo") } "already trimmed string" in { - assert("foo".safeTrim == "foo") + assert(Utils.safeTrim("foo") == "foo") } } -}
\ No newline at end of file +} |