diff options
author | Jakob Odersky <jakob@driver.xyz> | 2017-07-05 19:02:13 -0700 |
---|---|---|
committer | Jakob Odersky <jakob@driver.xyz> | 2017-07-12 21:04:25 -0700 |
commit | f9ac0adf5c3bcfcde03bd3ea2bc2471b0d0f99fe (patch) | |
tree | 9e26568fe6598074a6de8815b465cbfc7ff69b7c /src/main/scala/xyz/driver/pdsuidomain/services | |
parent | 3d902b5197db861c30325c159dc10cfb211ae209 (diff) | |
download | rest-query-f9ac0adf5c3bcfcde03bd3ea2bc2471b0d0f99fe.tar.gz rest-query-f9ac0adf5c3bcfcde03bd3ea2bc2471b0d0f99fe.tar.bz2 rest-query-f9ac0adf5c3bcfcde03bd3ea2bc2471b0d0f99fe.zip |
Implement REST services for trial curation
Diffstat (limited to 'src/main/scala/xyz/driver/pdsuidomain/services')
38 files changed, 924 insertions, 240 deletions
diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala index 8c89505..1f907c8 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala @@ -22,7 +22,7 @@ object ArmService { sealed trait GetByIdReply object GetByIdReply { - case class Entity(x: Arm) extends GetByIdReply + final case class Entity(x: Arm) extends GetByIdReply type Error = GetByIdReply with DomainError @@ -31,7 +31,7 @@ object ArmService { case object AuthorizationError extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) + final case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) extends GetByIdReply with DomainError } @@ -39,7 +39,7 @@ object ArmService { object GetListReply { type Error = GetListReply with DomainError - case class EntityList(xs: Seq[Arm], totalFound: Int) extends GetListReply + final case class EntityList(xs: Seq[Arm], totalFound: Int) extends GetListReply case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -71,7 +71,7 @@ object ArmService { sealed trait CreateReply object CreateReply { - case class Created(x: Arm) extends CreateReply + final case class Created(x: Arm) extends CreateReply type Error = CreateReply with DomainError @@ -101,7 +101,7 @@ object ArmService { case object AuthorizationError extends DeleteReply with DefaultAccessDeniedError with DomainError.AuthorizationError - case class CommonError(userMessage: String) extends DeleteReply with DomainError + final case class CommonError(userMessage: String) extends DeleteReply with DomainError } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/CategoryService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/CategoryService.scala deleted file mode 100644 index f8d820b..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/CategoryService.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.CategoryWithLabels - -import scala.concurrent.Future - -object CategoryService { - sealed trait GetListReply - object GetListReply { - case class EntityList(xs: Seq[CategoryWithLabels], totalFound: Int) extends GetListReply - - case object AuthorizationError extends GetListReply with DomainError.AuthorizationError { - def userMessage: String = "Access denied" - } - } -} - -trait CategoryService { - - import CategoryService._ - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/CriterionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/CriterionService.scala index ffb7843..fd9268b 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/CriterionService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/CriterionService.scala @@ -21,7 +21,7 @@ object CriterionService { def userMessage: String = "Access denied" } - case class RichCriterion(criterion: Criterion, armIds: Seq[LongId[Arm]], labels: Seq[CriterionLabel]) + final case class RichCriterion(criterion: Criterion, armIds: Seq[LongId[Arm]], labels: Seq[CriterionLabel]) object RichCriterion { implicit def toPhiString(x: RichCriterion): PhiString = { import x._ @@ -33,17 +33,17 @@ object CriterionService { object CreateReply { type Error = CreateReply with DomainError - case class Created(x: RichCriterion) extends CreateReply + final case class Created(x: RichCriterion) extends CreateReply case object AuthorizationError extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends CreateReply with DomainError + final case class CommonError(userMessage: String) extends CreateReply with DomainError } sealed trait GetByIdReply object GetByIdReply { - case class Entity(x: RichCriterion) extends GetByIdReply + final case class Entity(x: RichCriterion) extends GetByIdReply type Error = GetByIdReply with DomainError @@ -52,7 +52,7 @@ object CriterionService { case object AuthorizationError extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) + final case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) extends GetByIdReply with DomainError implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { @@ -63,7 +63,7 @@ object CriterionService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[RichCriterion], totalFound: Int, lastUpdate: Option[LocalDateTime]) + final case class EntityList(xs: Seq[RichCriterion], totalFound: Int, lastUpdate: Option[LocalDateTime]) extends GetListReply case object AuthorizationError @@ -74,14 +74,14 @@ object CriterionService { object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(updated: RichCriterion) extends UpdateReply + 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 - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError } sealed trait DeleteReply @@ -95,7 +95,7 @@ object CriterionService { case object AuthorizationError extends DeleteReply with DefaultAccessDeniedError with DomainError.AuthorizationError - case class CommonError(userMessage: String) extends DeleteReply with DomainError + final case class CommonError(userMessage: String) extends DeleteReply with DomainError } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala index 2c01a7e..9338a59 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala @@ -23,7 +23,7 @@ object DocumentService { sealed trait GetByIdReply object GetByIdReply { - case class Entity(x: Document) extends GetByIdReply + final case class Entity(x: Document) extends GetByIdReply type Error = GetByIdReply with DomainError @@ -32,7 +32,7 @@ object DocumentService { case object AuthorizationError extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) + final case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) extends GetByIdReply with DomainError implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { @@ -43,19 +43,20 @@ object DocumentService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[Document], totalFound: Int, lastUpdate: Option[LocalDateTime]) extends 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 - case class CommonError(userMessage: String) extends GetListReply with DomainError + final case class CommonError(userMessage: String) extends GetListReply with DomainError } sealed trait CreateReply object CreateReply { - case class Created(x: Document) extends CreateReply + final case class Created(x: Document) extends CreateReply type Error = CreateReply with DomainError @@ -64,12 +65,12 @@ object DocumentService { case object AuthorizationError extends CreateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - case class CommonError(userMessage: String) extends CreateReply with DomainError + final case class CommonError(userMessage: String) extends CreateReply with DomainError } sealed trait UpdateReply object UpdateReply { - case class Updated(updated: Document) extends UpdateReply + final case class Updated(updated: Document) extends UpdateReply type Error = UpdateReply with DomainError @@ -78,7 +79,7 @@ object DocumentService { case object AuthorizationError extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError implicit def toPhiString(reply: UpdateReply): PhiString = reply match { case Updated(x) => phi"Updated($x)" @@ -97,7 +98,7 @@ object DocumentService { case object AuthorizationError extends DeleteReply with DefaultAccessDeniedError with DomainError.AuthorizationError - case class CommonError(userMessage: String) extends DeleteReply with DomainError + final case class CommonError(userMessage: String) extends DeleteReply with DomainError } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentTypeService.scala index 1268cbf..0f1bf76 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/DocumentTypeService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/DocumentTypeService.scala @@ -11,7 +11,7 @@ import scala.concurrent.Future object DocumentTypeService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[DocumentType], totalFound: Int) extends 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" } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ExportService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ExportService.scala index ddc927d..a313703 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/ExportService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/ExportService.scala @@ -18,7 +18,7 @@ object ExportService { object GetPatientReply { type Error = GetPatientReply with DomainError - case class Entity(x: ExportPatientWithLabels) extends GetPatientReply + final case class Entity(x: ExportPatientWithLabels) extends GetPatientReply case object NotFoundError extends GetPatientReply with DomainError.NotFoundError { def userMessage: String = "Patient not found" @@ -27,7 +27,7 @@ object ExportService { sealed trait GetTrialListReply object GetTrialListReply { - case class EntityList(xs: Seq[ExportTrial], totalFound: Int, lastUpdate: Option[LocalDateTime]) + final case class EntityList(xs: Seq[ExportTrial], totalFound: Int, lastUpdate: Option[LocalDateTime]) extends GetTrialListReply } @@ -35,7 +35,7 @@ object ExportService { object GetTrialReply { type Error = GetTrialReply with DomainError - case class Entity(x: ExportTrialWithLabels) extends GetTrialReply + final case class Entity(x: ExportTrialWithLabels) extends GetTrialReply case object NotFoundError extends GetTrialReply with DomainError.NotFoundError { def userMessage: String = "Trial not found" diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ExtractedDataService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ExtractedDataService.scala index 93cb3ea..afb994e 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/ExtractedDataService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/ExtractedDataService.scala @@ -19,7 +19,7 @@ object ExtractedDataService { def userMessage: String = "Access denied" } - case class RichExtractedData(extractedData: ExtractedData, labels: List[ExtractedDataLabel]) + final case class RichExtractedData(extractedData: ExtractedData, labels: List[ExtractedDataLabel]) object RichExtractedData { implicit def toPhiString(x: RichExtractedData): PhiString = { @@ -31,19 +31,19 @@ object ExtractedDataService { sealed trait GetByIdReply object GetByIdReply { type Error = GetByIdReply with DomainError - case class Entity(x: RichExtractedData) extends GetByIdReply + 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 - case class CommonError(userMessage: String) extends GetByIdReply with DomainError + final case class CommonError(userMessage: String) extends GetByIdReply with DomainError } sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[RichExtractedData], totalFound: Int) extends GetListReply + final case class EntityList(xs: Seq[RichExtractedData], totalFound: Int) extends GetListReply case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -52,25 +52,25 @@ object ExtractedDataService { sealed trait CreateReply object CreateReply { type Error = CreateReply with DomainError - case class Created(x: RichExtractedData) extends CreateReply + final case class Created(x: RichExtractedData) extends CreateReply case object AuthorizationError extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends CreateReply with DomainError + final case class CommonError(userMessage: String) extends CreateReply with DomainError } sealed trait UpdateReply object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(updated: RichExtractedData) extends UpdateReply + 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 - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError } sealed trait DeleteReply @@ -83,7 +83,7 @@ object ExtractedDataService { case object NotFoundError extends DeleteReply with DefaultNotFoundError with DomainError.NotFoundError - case class CommonError(userMessage: String) extends DeleteReply with DomainError + final case class CommonError(userMessage: String) extends DeleteReply with DomainError } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/HypothesisService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/HypothesisService.scala index 7fccf7f..52cd6c8 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/HypothesisService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/HypothesisService.scala @@ -10,7 +10,7 @@ import scala.concurrent.Future object HypothesisService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[Hypothesis], totalFound: Int) extends 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" diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/InterventionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/InterventionService.scala index a4b380f..439e456 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/InterventionService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/InterventionService.scala @@ -21,7 +21,7 @@ object InterventionService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[InterventionWithArms], totalFound: Int) extends GetListReply + final case class EntityList(xs: Seq[InterventionWithArms], totalFound: Int) extends GetListReply case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -29,7 +29,7 @@ object InterventionService { sealed trait GetByIdReply object GetByIdReply { - case class Entity(x: InterventionWithArms) extends GetByIdReply + final case class Entity(x: InterventionWithArms) extends GetByIdReply type Error = GetByIdReply with DomainError @@ -38,7 +38,7 @@ object InterventionService { case object AuthorizationError extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) + final case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) extends GetByIdReply with DomainError implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { @@ -51,14 +51,14 @@ object InterventionService { object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(updated: InterventionWithArms) extends UpdateReply + 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 - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/InterventionTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/InterventionTypeService.scala index 5805655..298a92d 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/InterventionTypeService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/InterventionTypeService.scala @@ -10,7 +10,7 @@ import scala.concurrent.Future object InterventionTypeService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[InterventionType], totalFound: Int) extends 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" diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/KeywordService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/KeywordService.scala deleted file mode 100644 index 8824c41..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/KeywordService.scala +++ /dev/null @@ -1,28 +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.KeywordWithLabels - -import scala.concurrent.Future - -object KeywordService { - - sealed trait GetListReply - object GetListReply { - case class EntityList(xs: Seq[KeywordWithLabels], totalFound: Int) extends GetListReply - - case object AuthorizationError extends GetListReply with DomainError.AuthorizationError { - def userMessage: String = "Access denied" - } - } -} - -trait KeywordService { - - import KeywordService._ - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/LabelService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/LabelService.scala deleted file mode 100644 index aadc5fb..0000000 --- a/src/main/scala/xyz/driver/pdsuidomain/services/LabelService.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.Label - -import scala.concurrent.Future - -object LabelService { - - sealed trait GetListReply - object GetListReply { - case class EntityList(xs: Seq[Label], totalFound: Int) extends GetListReply - - case object AuthorizationError extends GetListReply with DomainError.AuthorizationError { - def userMessage: String = "Access denied" - } - } -} - -trait LabelService { - import LabelService._ - - def getAll(sorting: Option[Sorting] = None)( - implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] -} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordService.scala index f077d82..b2fc9f9 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordService.scala @@ -25,13 +25,13 @@ object MedicalRecordService { sealed trait GetByIdReply object GetByIdReply { - case class Entity(x: MedicalRecord) extends GetByIdReply + final case class Entity(x: MedicalRecord) extends GetByIdReply type Error = GetByIdReply with DomainError case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - case class CommonError(userMessage: String) extends GetByIdReply with DomainError + final case class CommonError(userMessage: String) extends GetByIdReply with DomainError case object AuthorizationError extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -41,7 +41,7 @@ object MedicalRecordService { object GetPdfSourceReply { type Error = GetPdfSourceReply with DomainError - case class Entity(x: PdfSource.Channel) extends GetPdfSourceReply + final case class Entity(x: PdfSource.Channel) extends GetPdfSourceReply case object AuthorizationError extends GetPdfSourceReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -52,12 +52,12 @@ object MedicalRecordService { case object RecordNotFoundError extends GetPdfSourceReply with DomainError.NotFoundError with DefaultNotFoundError - case class CommonError(userMessage: String) extends GetPdfSourceReply with DomainError + final case class CommonError(userMessage: String) extends GetPdfSourceReply with DomainError } sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[MedicalRecord], totalFound: Int, lastUpdate: Option[LocalDateTime]) + final case class EntityList(xs: Seq[MedicalRecord], totalFound: Int, lastUpdate: Option[LocalDateTime]) extends GetListReply case object AuthorizationError @@ -66,24 +66,24 @@ object MedicalRecordService { sealed trait CreateReply object CreateReply { - case class Created(x: MedicalRecord) extends CreateReply + final case class Created(x: MedicalRecord) extends CreateReply } sealed trait UpdateReply object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(updated: MedicalRecord) extends UpdateReply + 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 - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError } - case class Settings(pdfSourceBucket: String) + final case class Settings(pdfSourceBucket: String) } trait MedicalRecordService { diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala index df57e17..6718f26 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala @@ -23,18 +23,18 @@ object MessageService { sealed trait CreateReply object CreateReply { type Error = CreateReply with DomainError - case class Created(x: Message) extends CreateReply + final case class Created(x: Message) extends CreateReply case object AuthorizationError extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends CreateReply with DomainError + final case class CommonError(userMessage: String) extends CreateReply with DomainError } sealed trait GetByIdReply object GetByIdReply { type Error = GetByIdReply with DomainError - case class Entity(x: Message) extends GetByIdReply - case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - case class CommonError(userMessage: String) extends 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 } @@ -42,7 +42,8 @@ object MessageService { sealed trait GetListReply object GetListReply { type Error = GetListReply with DomainError - case class EntityList(xs: Seq[Message], totalFound: Int, lastUpdate: Option[LocalDateTime]) extends GetListReply + final case class EntityList(xs: Seq[Message], totalFound: Int, lastUpdate: Option[LocalDateTime]) + extends GetListReply case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError } @@ -50,10 +51,10 @@ object MessageService { sealed trait UpdateReply object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(updated: Message) extends UpdateReply + final case class Updated(updated: Message) extends UpdateReply case object AuthorizationError extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError } sealed trait DeleteReply @@ -62,8 +63,8 @@ object MessageService { 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 - case class CommonError(userMessage: String) extends DeleteReply with DomainError + case object NotFoundError extends DeleteReply with DomainError.NotFoundError with DefaultNotFoundError + final case class CommonError(userMessage: String) extends DeleteReply with DomainError } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala index c2f7b50..9ff3879 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala @@ -13,9 +13,9 @@ import scala.concurrent.Future object PatientCriterionService { - case class DraftPatientCriterion(id: LongId[PatientCriterion], - eligibilityStatus: Option[FuzzyValue], - isVerified: Option[Boolean]) { + final case class DraftPatientCriterion(id: LongId[PatientCriterion], + eligibilityStatus: Option[FuzzyValue], + isVerified: Option[Boolean]) { def applyTo(orig: PatientCriterion) = { orig.copy( eligibilityStatus = eligibilityStatus.orElse(orig.eligibilityStatus), @@ -40,9 +40,9 @@ object PatientCriterionService { object GetListReply { type Error = GetListReply with DomainError - case class EntityList(xs: Seq[(PatientCriterion, LongId[Label], List[PatientCriterionArm])], - totalFound: Int, - lastUpdate: Option[LocalDateTime]) + final case class EntityList(xs: Seq[(PatientCriterion, LongId[Label], List[PatientCriterionArm])], + totalFound: Int, + lastUpdate: Option[LocalDateTime]) extends GetListReply case object AuthorizationError @@ -51,7 +51,7 @@ object PatientCriterionService { case object PatientNotFoundError extends GetListReply with DomainError.NotFoundError with DefaultPatientNotFoundError - case class CommonError(userMessage: String) extends GetListReply with DomainError + final case class CommonError(userMessage: String) extends GetListReply with DomainError } @@ -59,7 +59,7 @@ object PatientCriterionService { object GetByIdReply { type Error = GetByIdReply with DomainError - case class Entity(x: PatientCriterion, labelId: LongId[Label], armList: List[PatientCriterionArm]) + final case class Entity(x: PatientCriterion, labelId: LongId[Label], armList: List[PatientCriterionArm]) extends GetByIdReply case object AuthorizationError @@ -70,7 +70,7 @@ object PatientCriterionService { case object PatientNotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultPatientNotFoundError - case class CommonError(userMessage: String) extends GetByIdReply with DomainError + 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)" @@ -82,7 +82,7 @@ object PatientCriterionService { object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(x: PatientCriterion, labelId: LongId[Label], armList: List[PatientCriterionArm]) + final case class Updated(x: PatientCriterion, labelId: LongId[Label], armList: List[PatientCriterionArm]) extends UpdateReply case object UpdatedList extends UpdateReply @@ -93,7 +93,7 @@ object PatientCriterionService { case object PatientNotFoundError extends UpdateReply with DomainError.NotFoundError with DefaultPatientNotFoundError - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala index 12cd4f3..2c17f74 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala @@ -23,7 +23,10 @@ object PatientEligibleTrialService { def userMessage: String = "Access denied" } - case class RichPatientEligibleTrial(trial: Trial, group: PatientTrialArmGroupView, arms: List[PatientCriterionArm]) + 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})" @@ -32,7 +35,7 @@ object PatientEligibleTrialService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[RichPatientEligibleTrial], totalFound: Int) extends GetListReply + final case class EntityList(xs: Seq[RichPatientEligibleTrial], totalFound: Int) extends GetListReply case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -40,12 +43,12 @@ object PatientEligibleTrialService { case object PatientNotFoundError extends GetListReply with DefaultPatientNotFoundError with DomainError.NotFoundError - case class CommonError(userMessage: String) extends GetListReply with DomainError + final case class CommonError(userMessage: String) extends GetListReply with DomainError } sealed trait GetByIdReply object GetByIdReply { - case class Entity(x: RichPatientEligibleTrial) extends GetByIdReply + final case class Entity(x: RichPatientEligibleTrial) extends GetByIdReply type Error = GetByIdReply with DomainError @@ -57,7 +60,7 @@ object PatientEligibleTrialService { case object AuthorizationError extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends GetByIdReply with DomainError + 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)" @@ -67,7 +70,7 @@ object PatientEligibleTrialService { sealed trait GetCriterionListOfGroupReply object GetCriterionListOfGroupReply { - case class EntityList(xs: Seq[(PatientCriterion, LongId[Label], List[PatientCriterionArm])], totalFound: Int) + final case class EntityList(xs: Seq[(PatientCriterion, LongId[Label], List[PatientCriterionArm])], totalFound: Int) extends GetCriterionListOfGroupReply type Error = GetCriterionListOfGroupReply with DomainError @@ -81,14 +84,14 @@ object PatientEligibleTrialService { case object PatientNotFoundError extends GetCriterionListOfGroupReply with DefaultPatientNotFoundError with DomainError.NotFoundError - case class CommonError(userMessage: String) extends GetCriterionListOfGroupReply with DomainError + final case class CommonError(userMessage: String) extends GetCriterionListOfGroupReply with DomainError } sealed trait UpdateReply object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(updated: RichPatientEligibleTrial) extends UpdateReply + final case class Updated(updated: RichPatientEligibleTrial) extends UpdateReply case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError @@ -98,7 +101,7 @@ object PatientEligibleTrialService { case object AuthorizationError extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError implicit def toPhiString(reply: UpdateReply): PhiString = reply match { case Updated(x) => phi"Updated($x)" diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala index a15e11f..f782cab 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala @@ -25,7 +25,7 @@ object PatientHypothesisService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[(PatientHypothesis, Boolean)], totalFound: Int) extends GetListReply + final case class EntityList(xs: Seq[(PatientHypothesis, Boolean)], totalFound: Int) extends GetListReply case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -33,12 +33,12 @@ object PatientHypothesisService { case object PatientNotFoundError extends GetListReply with DefaultPatientNotFoundError with DomainError.NotFoundError - case class CommonError(userMessage: String) extends GetListReply with DomainError + final case class CommonError(userMessage: String) extends GetListReply with DomainError } sealed trait GetByIdReply object GetByIdReply { - case class Entity(x: PatientHypothesis, isRequired: Boolean) extends GetByIdReply + final case class Entity(x: PatientHypothesis, isRequired: Boolean) extends GetByIdReply type Error = GetByIdReply with DomainError @@ -50,7 +50,7 @@ object PatientHypothesisService { case object AuthorizationError extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends GetByIdReply with DomainError + 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)" @@ -62,7 +62,7 @@ object PatientHypothesisService { object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(updated: PatientHypothesis) extends UpdateReply + final case class Updated(updated: PatientHypothesis) extends UpdateReply case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError @@ -72,7 +72,7 @@ object PatientHypothesisService { case object AuthorizationError extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError implicit def toPhiString(reply: UpdateReply): PhiString = reply match { case Updated(x) => phi"Updated($x)" diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala index 2586798..56e2e3d 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala @@ -20,7 +20,7 @@ object PatientLabelEvidenceService { sealed trait GetByIdReply object GetByIdReply { - case class Entity(x: PatientLabelEvidenceView) extends GetByIdReply + final case class Entity(x: PatientLabelEvidenceView) extends GetByIdReply type Error = GetByIdReply with DomainError @@ -34,7 +34,7 @@ object PatientLabelEvidenceService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[PatientLabelEvidenceView], totalFound: Int) extends GetListReply + final case class EntityList(xs: Seq[PatientLabelEvidenceView], totalFound: Int) extends GetListReply type Error = GetListReply with DomainError @@ -44,7 +44,7 @@ object PatientLabelEvidenceService { case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends GetListReply with DomainError + final case class CommonError(userMessage: String) extends GetListReply with DomainError } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala index 5fa2a4d..71b8bd4 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala @@ -25,7 +25,7 @@ object PatientLabelService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[(PatientLabel, Boolean)], totalFound: Int) extends GetListReply + final case class EntityList(xs: Seq[(PatientLabel, Boolean)], totalFound: Int) extends GetListReply case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -33,12 +33,12 @@ object PatientLabelService { case object PatientNotFoundError extends GetListReply with DefaultPatientNotFoundError with DomainError.NotFoundError - case class CommonError(userMessage: String) extends GetListReply with DomainError + final case class CommonError(userMessage: String) extends GetListReply with DomainError } sealed trait GetDefiningCriteriaListReply object GetDefiningCriteriaListReply { - case class EntityList(xs: Seq[PatientLabel], totalFound: Int) extends GetDefiningCriteriaListReply + final case class EntityList(xs: Seq[PatientLabel], totalFound: Int) extends GetDefiningCriteriaListReply case object AuthorizationError extends GetDefiningCriteriaListReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -46,12 +46,12 @@ object PatientLabelService { case object PatientNotFoundError extends GetDefiningCriteriaListReply with DefaultPatientNotFoundError with DomainError.NotFoundError - case class CommonError(userMessage: String) extends GetDefiningCriteriaListReply with DomainError + final case class CommonError(userMessage: String) extends GetDefiningCriteriaListReply with DomainError } sealed trait GetByLabelIdReply object GetByLabelIdReply { - case class Entity(x: PatientLabel, isVerified: Boolean) extends GetByLabelIdReply + final case class Entity(x: PatientLabel, isVerified: Boolean) extends GetByLabelIdReply type Error = GetByLabelIdReply with DomainError @@ -63,7 +63,7 @@ object PatientLabelService { case object AuthorizationError extends GetByLabelIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends GetByLabelIdReply with DomainError + 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)" @@ -75,7 +75,7 @@ object PatientLabelService { object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(updated: PatientLabel, isVerified: Boolean) extends UpdateReply + final case class Updated(updated: PatientLabel, isVerified: Boolean) extends UpdateReply case object NotFoundError extends UpdateReply with DefaultNotFoundError with DomainError.NotFoundError @@ -85,7 +85,7 @@ object PatientLabelService { case object AuthorizationError extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends UpdateReply with DomainError + 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)" diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/PatientService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/PatientService.scala index 4619011..ce70934 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/PatientService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/PatientService.scala @@ -23,7 +23,8 @@ object PatientService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[Patient], totalFound: Int, lastUpdate: Option[LocalDateTime]) extends 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 @@ -31,7 +32,7 @@ object PatientService { sealed trait GetByIdReply object GetByIdReply { - case class Entity(x: Patient) extends GetByIdReply + final case class Entity(x: Patient) extends GetByIdReply type Error = GetByIdReply with DomainError @@ -40,7 +41,7 @@ object PatientService { case object AuthorizationError extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) + final case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) extends GetByIdReply with DomainError implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { @@ -53,14 +54,14 @@ object PatientService { object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(updated: Patient) extends UpdateReply + 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 - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError implicit def toPhiString(reply: UpdateReply): PhiString = reply match { case Updated(x) => phi"Updated($x)" diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ProviderTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ProviderTypeService.scala index ef48aa0..cad17a4 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/ProviderTypeService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/ProviderTypeService.scala @@ -10,7 +10,7 @@ import scala.concurrent.Future object ProviderTypeService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[ProviderType], totalFound: Int) extends 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" } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/QueueUploadService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/QueueUploadService.scala index f201fd9..340733d 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/QueueUploadService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/QueueUploadService.scala @@ -20,28 +20,28 @@ object QueueUploadService { object CreateReply { type Error = CreateReply with DomainError - case class Created(x: BridgeUploadQueue.Item) extends CreateReply + final case class Created(x: BridgeUploadQueue.Item) extends CreateReply case object AuthorizationError extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends CreateReply with DomainError + final case class CommonError(userMessage: String) extends CreateReply with DomainError } sealed trait GetByIdReply object GetByIdReply { type Error = GetByIdReply with DomainError - case class Entity(x: BridgeUploadQueue.Item) extends GetByIdReply + 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 - case class CommonError(userMessage: String) extends GetByIdReply with DomainError + 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 - case class EntityList(xs: Seq[BridgeUploadQueue.Item], totalFound: Int) extends GetListReply + final case class EntityList(xs: Seq[BridgeUploadQueue.Item], totalFound: Int) extends GetListReply case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -51,10 +51,10 @@ object QueueUploadService { object ResetReply { type Error = ResetReply with DomainError - 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 - case class CommonError(userMessage: String) extends 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 } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/ScrapedTrialsService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/ScrapedTrialsService.scala index b595584..233495e 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/ScrapedTrialsService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/ScrapedTrialsService.scala @@ -11,7 +11,7 @@ object ScrapedTrialsService { object GetRawTrialReply { type Error = GetRawTrialReply with DomainError - case class TrialRawEntity(rawTrial: ScrapedTrial) extends GetRawTrialReply + 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" @@ -20,12 +20,12 @@ object ScrapedTrialsService { sealed trait GetRawTrialOptReply object GetRawTrialOptReply { - case class TrialRawEntity(rawTrial: Option[ScrapedTrial]) extends GetRawTrialOptReply + final case class TrialRawEntity(rawTrial: Option[ScrapedTrial]) extends GetRawTrialOptReply } sealed trait GetAllRawTrialsExceptReply object GetAllRawTrialsExceptReply { - case class MultipleRawTrials(rawTrials: Seq[ScrapedTrial]) extends GetAllRawTrialsExceptReply + final case class MultipleRawTrials(rawTrials: Seq[ScrapedTrial]) extends GetAllRawTrialsExceptReply } sealed trait GetHtmlForReply @@ -35,7 +35,7 @@ object ScrapedTrialsService { /** * @param trialHtmlMap nctId -> html */ - case class HtmlMap(trialHtmlMap: TrialHtmlMap) extends GetHtmlForReply + final case class HtmlMap(trialHtmlMap: TrialHtmlMap) extends GetHtmlForReply } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/StudyDesignService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/StudyDesignService.scala index a1ce613..e98c1ec 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/StudyDesignService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/StudyDesignService.scala @@ -10,7 +10,7 @@ import scala.concurrent.Future object StudyDesignService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[StudyDesign], totalFound: Int) extends 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" diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/TrialHistoryService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/TrialHistoryService.scala index 9ad9fc1..bcf1c53 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/TrialHistoryService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/TrialHistoryService.scala @@ -22,10 +22,10 @@ object TrialHistoryService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[TrialHistory], totalFound: Int, lastUpdate: Option[LocalDateTime]) + final case class EntityList(xs: Seq[TrialHistory], totalFound: Int, lastUpdate: Option[LocalDateTime]) extends GetListReply - case object AuthorizationError + final case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultAccessDeniedError } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/TrialIssueService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/TrialIssueService.scala index df231ac..726feda 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/TrialIssueService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/TrialIssueService.scala @@ -23,18 +23,18 @@ object TrialIssueService { sealed trait CreateReply object CreateReply { type Error = CreateReply with DomainError - case class Created(x: TrialIssue) extends CreateReply + final case class Created(x: TrialIssue) extends CreateReply case object AuthorizationError extends CreateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends CreateReply with DomainError + final case class CommonError(userMessage: String) extends CreateReply with DomainError } sealed trait GetByIdReply object GetByIdReply { type Error = GetByIdReply with DomainError - case class Entity(x: TrialIssue) extends GetByIdReply - case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - case class CommonError(userMessage: String) extends 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 } @@ -42,7 +42,7 @@ object TrialIssueService { sealed trait GetListByTrialIdReply object GetListByTrialIdReply { type Error = GetListByTrialIdReply with DomainError - case class EntityList(xs: Seq[TrialIssue], totalFound: Int, lastUpdate: Option[LocalDateTime]) + 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 @@ -52,10 +52,10 @@ object TrialIssueService { sealed trait UpdateReply object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(updated: TrialIssue) extends UpdateReply + final case class Updated(updated: TrialIssue) extends UpdateReply case object AuthorizationError extends UpdateReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError } sealed trait DeleteReply @@ -64,8 +64,8 @@ object TrialIssueService { 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 - case class CommonError(userMessage: String) extends DeleteReply with DomainError + case object NotFoundError extends DeleteReply with DomainError.NotFoundError with DefaultNotFoundError + final case class CommonError(userMessage: String) extends DeleteReply with DomainError } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/TrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/TrialService.scala index 47f76f2..3148842 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/TrialService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/TrialService.scala @@ -24,7 +24,8 @@ object TrialService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[Trial], totalFound: Int, lastUpdate: Option[LocalDateTime]) extends 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 @@ -32,7 +33,7 @@ object TrialService { sealed trait GetByIdReply object GetByIdReply { - case class Entity(x: Trial) extends GetByIdReply + final case class Entity(x: Trial) extends GetByIdReply type Error = GetByIdReply with DomainError @@ -41,7 +42,7 @@ object TrialService { case object AuthorizationError extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) + final case class CommonError(userMessage: String)(implicit requestContext: AuthenticatedRequestContext) extends GetByIdReply with DomainError implicit def toPhiString(reply: GetByIdReply): PhiString = reply match { @@ -54,7 +55,7 @@ object TrialService { object GetPdfSourceReply { type Error = GetPdfSourceReply with DomainError - case class Entity(x: PdfSource) extends GetPdfSourceReply + final case class Entity(x: PdfSource) extends GetPdfSourceReply case object AuthorizationError extends GetPdfSourceReply with DomainError.AuthorizationError with DefaultAccessDeniedError @@ -65,21 +66,21 @@ object TrialService { case object TrialNotFoundError extends GetPdfSourceReply with DomainError.NotFoundError with DefaultNotFoundError - case class CommonError(userMessage: String) extends GetPdfSourceReply with DomainError + final case class CommonError(userMessage: String) extends GetPdfSourceReply with DomainError } sealed trait UpdateReply object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(updated: Trial) extends UpdateReply + 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 - case class CommonError(userMessage: String) extends UpdateReply with DomainError + final case class CommonError(userMessage: String) extends UpdateReply with DomainError implicit def toPhiString(reply: UpdateReply): PhiString = reply match { case Updated(x) => phi"Updated($x)" @@ -119,5 +120,4 @@ trait TrialService { def unassign(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] - def removeTrialDetails(trialId: StringId[Trial]): Unit } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala index e342813..a29e041 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala @@ -11,7 +11,7 @@ object UserHistoryService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[UserHistory], totalFound: Int) extends 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" diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/UserService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/UserService.scala index b54b6a9..85b93ed 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/UserService.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/UserService.scala @@ -24,7 +24,7 @@ object UserService { sealed trait ActivateExecutorReply object ActivateExecutorReply { type Error = ActivateExecutorReply with DomainError - case class Entity(x: User) extends ActivateExecutorReply + final case class Entity(x: User) extends ActivateExecutorReply case object NotFoundError extends ActivateExecutorReply with DomainError.NotFoundError { val userMessage = "Info about you is not found on the server" } @@ -33,16 +33,16 @@ object UserService { sealed trait GetByIdReply object GetByIdReply { type Error = GetByIdReply with DomainError - case class Entity(x: User) extends GetByIdReply + final case class Entity(x: User) extends GetByIdReply case object AuthorizationError extends GetByIdReply with DomainError.AuthorizationError with DefaultAccessDeniedError - case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError - case class CommonError(userMessage: String) extends GetByIdReply with DomainError + case object NotFoundError extends GetByIdReply with DomainError.NotFoundError with DefaultNotFoundError + final case class CommonError(userMessage: String) extends GetByIdReply with DomainError } sealed trait GetByEmailReply object GetByEmailReply { - case class Entity(x: User) extends GetByEmailReply + final case class Entity(x: User) extends GetByEmailReply case object NotFoundError extends GetByEmailReply with DefaultNotFoundError with DomainError.NotFoundError { override def userMessage: String = "Incorrect email. Try again." } @@ -50,7 +50,7 @@ object UserService { sealed trait GetByCredentialsReply object GetByCredentialsReply { - case class Entity(x: User) extends GetByCredentialsReply + final case class Entity(x: User) extends GetByCredentialsReply case object AuthenticationError extends GetByCredentialsReply with DefaultCredentialsError with DomainError.AuthenticationError case object NotFoundError extends GetByCredentialsReply with DomainError.NotFoundError with DefaultNotFoundError @@ -58,41 +58,41 @@ object UserService { sealed trait GetListReply object GetListReply { - case class EntityList(xs: Seq[User], totalFound: Int) extends GetListReply - case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultNotFoundError + final case class EntityList(xs: Seq[User], totalFound: Int) extends GetListReply + case object AuthorizationError extends GetListReply with DomainError.AuthorizationError with DefaultNotFoundError } sealed trait CreateReply object CreateReply { type Error = CreateReply with DomainError - case class Created(x: User) extends CreateReply - case object AuthorizationError extends CreateReply with DefaultNotFoundError with DomainError.AuthorizationError - case class UserAlreadyExistsError(email: Email) extends CreateReply with DomainError { + final case class Created(x: User) extends CreateReply + case object AuthorizationError extends CreateReply with DefaultNotFoundError with DomainError.AuthorizationError + final case class UserAlreadyExistsError(email: Email) extends CreateReply with DomainError { val userMessage = s"The user with this email already exists." } - case class CommonError(userMessage: String) extends CreateReply with DomainError + final case class CommonError(userMessage: String) extends CreateReply with DomainError } sealed trait UpdateReply object UpdateReply { type Error = UpdateReply with DomainError - case class Updated(updated: User) extends UpdateReply + final case class Updated(updated: User) extends UpdateReply case object AuthorizationError extends UpdateReply with DefaultAccessDeniedError with DomainError.AuthorizationError - case class CommonError(userMessage: String) extends UpdateReply with DomainError + 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 class AuthorizationError(user: User) + final case class AuthorizationError(user: User) extends DeleteReply with DefaultAccessDeniedError with DomainError.AuthorizationError case object AssignedToRecordAndDocumentError extends DeleteReply with DomainError { val userMessage = "User is can not be deleted because he has record and document in work" } - case object NotFoundError extends DeleteReply with DefaultNotFoundError with DomainError.NotFoundError - case class CommonError(userMessage: String) extends DeleteReply with DomainError + case object NotFoundError extends DeleteReply with DefaultNotFoundError with DomainError.NotFoundError + final case class CommonError(userMessage: String) extends DeleteReply with DomainError } } diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala new file mode 100644 index 0000000..299e6f8 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala @@ -0,0 +1,99 @@ +package xyz.driver.pdsuidomain.services.rest + +import akka.http.scaladsl.marshalling.Marshal +import scala.concurrent.{ExecutionContext, Future} + +import akka.http.scaladsl.model._ +import akka.stream.ActorMaterializer +import xyz.driver.core.rest._ +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: ActorMaterializer, + protected val exec: ExecutionContext) + extends ArmService with RestHelper { + + import xyz.driver.pdsuidomain.services.ArmService._ + import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + + // GET /v1/arm xyz.driver.server.controllers.ArmController.getList + // GET /v1/arm/:id xyz.driver.server.controllers.ArmController.getById(id: Long) + // POST /v1/arm xyz.driver.server.controllers.ArmController.create + // PATCH /v1/arm/:id xyz.driver.server.controllers.ArmController.update(id: Long) + // DELETE /v1/arm/:id xyz.driver.server.controllers.ArmController.delete(id: Long) + + 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], GetListReply](response) { api => + GetListReply.EntityList(api.items.map(_.toDomain), api.meta.itemsCount) + }() + } yield { + reply + } + } + + 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, GetByIdReply](response) { api => + GetByIdReply.Entity(api.toDomain) + }() + } yield { + reply + } + } + + 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, CreateReply](response) { api => + CreateReply.Created(api.toDomain) + }() + } yield { + reply + } + } + + 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, UpdateReply](response) { api => + UpdateReply.Updated(api.toDomain) + }() + } yield { + reply + } + } + + 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) + reply <- apiResponse[ApiArm, DeleteReply](response) { _ => + DeleteReply.Deleted + }() + } yield { + reply + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala new file mode 100644 index 0000000..b27ce3d --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala @@ -0,0 +1,108 @@ +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.ActorMaterializer +import xyz.driver.core.rest._ +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: ActorMaterializer, + 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._ + + // GET /v1/criterion xyz.driver.server.controllers.CriterionController.getList + // GET /v1/criterion/:id xyz.driver.server.controllers.CriterionController.getById(id: Long) + // PATCH /v1/criterion/:id xyz.driver.server.controllers.CriterionController.update(id: Long) + // POST /v1/criterion xyz.driver.server.controllers.CriterionController.create + // DELETE /v1/criterion/:id xyz.driver.server.controllers.CriterionController.delete(id: Long) + + 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, CreateReply](response) { api => + CreateReply.Created(api.toDomain) + }() + } yield { + reply + } + } + + 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, GetByIdReply](response) { api => + GetByIdReply.Entity(api.toDomain) + }() + } yield { + reply + } + } + + 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], GetListReply](response) { api => + GetListReply.EntityList( + api.items.map(_.toDomain), + api.meta.itemsCount, + api.meta.lastUpdate + ) + }() + } yield { + reply + } + } + + 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, UpdateReply](response) { api => + UpdateReply.Updated(api.toDomain) + }() + } yield { + reply + } + } + + 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) + reply <- apiResponse[ApiCriterion, DeleteReply](response) { _ => + DeleteReply.Deleted + }() + } yield { + reply + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala new file mode 100644 index 0000000..7d2838b --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala @@ -0,0 +1,139 @@ +package xyz.driver.pdsuidomain.services.rest + +import java.lang.RuntimeException + +import scala.concurrent.{ExecutionContext, Future} + +import akka.http.scaladsl.model.{HttpMethods, HttpRequest, HttpResponse, ResponseEntity, StatusCode, StatusCodes, Uri} +import akka.http.scaladsl.unmarshalling.{Unmarshal, Unmarshaller} +import akka.stream.Materializer +import xyz.driver.core.rest.ServiceRequestContext +import xyz.driver.pdsuicommon.auth.{AnonymousRequestContext, AuthenticatedRequestContext} +import xyz.driver.pdsuicommon.db.{ + Pagination, + SearchFilterBinaryOperation, + SearchFilterExpr, + SearchFilterNAryOperation, + Sorting, + SortingOrder +} +import xyz.driver.pdsuicommon.error.DomainError + +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 get(baseUri: Uri, path: String, query: Seq[(String, String)] = Seq.empty): HttpRequest = + HttpRequest(HttpMethods.GET, endpointUri(baseUri, path, 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.toHexString + ) + } + + /** Utility method to parse responses that encode success and errors as subtypes + * of a common reply type. + * + * @tparam ApiReply The type of the serialized reply object, contained in the HTTP entity + * @tparam DomainReply The type of the domain object that will be created from a successful reply. + * + * @param response The HTTP response to parse. + * @param successMapper Transformation function from a deserialized api entity to a domain object. + * @param errorMapper Transformation function from general domain errors to + * specialized errors of the given DomainReply. Note that if a domain error + * is not explicitly handled, it will be encoded as a failure in the returned future. + * @param unmarshaller An unmarshaller that converts a successful response to an api reply. + */ + def apiResponse[ApiReply, DomainReply](response: HttpResponse)(successMapper: ApiReply => DomainReply)( + errorMapper: PartialFunction[DomainError, DomainReply] = PartialFunction.empty)( + implicit unmarshaller: Unmarshaller[ResponseEntity, ApiReply]): Future[DomainReply] = { + + val domainErrors: Map[StatusCode, DomainError] = Map( + StatusCodes.Unauthorized -> new DomainError.AuthenticationError { + override protected def userMessage: String = "unauthorized" + }, // 401 + StatusCodes.Forbidden -> new DomainError.AuthorizationError { + override protected def userMessage: String = "forbidden" + }, // 403 + StatusCodes.NotFound -> new DomainError.NotFoundError { + override protected def userMessage: String = "not found" + } // 404 + ) + + if (response.status.isSuccess) { + val reply = Unmarshal(response.entity).to[ApiReply] + reply.map(successMapper) + } else { + val domainError = domainErrors.get(response.status) + domainError.flatMap(errorMapper.lift) match { + case Some(error) => Future.successful(error) + case None => + Future.failed( + new RuntimeException( + s"Unhandled domain error for HTTP status ${response.status}. Message ${response.entity}") + ) + } + } + } + + implicit def toServiceRequestContext(requestContext: AnonymousRequestContext): ServiceRequestContext = { + val auth: Map[String, String] = requestContext match { + case ctx: AuthenticatedRequestContext => Map("Auth-token" -> ctx.authToken) + case _ => Map() + } + new ServiceRequestContext(contextHeaders = auth) + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHypothesisService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHypothesisService.scala new file mode 100644 index 0000000..ff9d490 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHypothesisService.scala @@ -0,0 +1,39 @@ +package xyz.driver.pdsuidomain.services.rest + +import scala.concurrent.{ExecutionContext, Future} + +import akka.http.scaladsl.model._ +import akka.stream.ActorMaterializer +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: ActorMaterializer, + protected val exec: ExecutionContext) + extends HypothesisService with RestHelper { + + import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import xyz.driver.pdsuidomain.services.HypothesisService._ + + // GET /v1/hypothesis xyz.driver.server.controllers.HypothesisController.getList + + 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], GetListReply](response) { api => + GetListReply.EntityList(api.items.map(_.toDomain), api.meta.itemsCount) + }() + } yield { + reply + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala new file mode 100644 index 0000000..810a9d6 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala @@ -0,0 +1,78 @@ +package xyz.driver.pdsuidomain.services.rest + +import akka.http.scaladsl.marshalling.Marshal +import scala.concurrent.{ExecutionContext, Future} + +import akka.http.scaladsl.model._ +import akka.stream.ActorMaterializer +import xyz.driver.core.rest._ +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: ActorMaterializer, + protected val exec: ExecutionContext) + extends InterventionService with RestHelper { + + import xyz.driver.pdsuidomain.services.InterventionService._ + import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + + // GET /v1/intervention xyz.driver.server.controllers.InterventionController.getList + // GET /v1/intervention/:id xyz.driver.server.controllers.InterventionController.getById(id: Long) + // PATCH /v1/intervention/:id xyz.driver.server.controllers.InterventionController.update(id: Long) + + 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], GetListReply](response) { api => + GetListReply.EntityList(api.items.map(_.toDomain), api.meta.itemsCount) + }() + } yield { + reply + } + } + + 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, GetByIdReply](response) { api => + GetByIdReply.Entity(api.toDomain) + }() + } yield { + reply + } + } + + 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, UpdateReply](response) { api => + UpdateReply.Updated(api.toDomain) + }() + } yield { + reply + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala new file mode 100644 index 0000000..1243500 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala @@ -0,0 +1,40 @@ +package xyz.driver.pdsuidomain.services.rest + +import scala.concurrent.{ExecutionContext, Future} + +import akka.http.scaladsl.model._ +import akka.stream.ActorMaterializer +import xyz.driver.core.rest._ +import xyz.driver.pdsuicommon.auth._ +import xyz.driver.pdsuicommon.db._ +import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuidomain.formats.json.intervention.ApiInterventionType +import xyz.driver.pdsuidomain.services.InterventionTypeService + +class RestInterventionTypeService(transport: ServiceTransport, baseUri: Uri)( + implicit protected val materializer: ActorMaterializer, + 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] = { + + for { + response <- transport.sendRequestGetResponse(requestContext)( + get(baseUri, "/v1/intervention-type", query = sortingQuery(sorting))) + reply <- apiResponse[ListResponse[ApiInterventionType], GetListReply](response) { list => + val domain = list.items.map(_.toDomain) + GetListReply.EntityList(domain.toList, list.meta.itemsCount) + } { + case _: DomainError.AuthorizationError => GetListReply.AuthorizationError + } + } yield { + reply + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala new file mode 100644 index 0000000..61d2050 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala @@ -0,0 +1,103 @@ +package xyz.driver.pdsuidomain.services.rest + +import akka.http.scaladsl.marshalling.Marshal +import scala.concurrent.{ExecutionContext, Future} + +import akka.http.scaladsl.model._ +import akka.stream.ActorMaterializer +import xyz.driver.core.rest._ +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: ActorMaterializer, + protected val exec: ExecutionContext) + extends MessageService with RestHelper { + + import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import xyz.driver.pdsuidomain.services.MessageService._ + + // GET /v1/message xyz.driver.server.controllers.MessageController.getList + // POST /v1/message xyz.driver.server.controllers.MessageController.create + // PATCH /v1/message/:id xyz.driver.server.controllers.MessageController.update(id: Long) + // DELETE /v1/message/:id xyz.driver.server.controllers.MessageController.delete(id: Long) + + 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, CreateReply](response) { api => + CreateReply.Created(api.toDomain) + }() + } yield { + reply + } + } + + def getById(messageId: LongId[Message])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = { + import SearchFilterExpr._ + import SearchFilterBinaryOperation._ + 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], GetListReply](response) { api => + GetListReply.EntityList(api.items.map(_.toDomain), api.meta.itemsCount, api.meta.lastUpdate) + }() + } yield { + reply + } + } + + 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, UpdateReply](response) { api => + UpdateReply.Updated(api.toDomain) + }() + } yield { + reply + } + } + + def delete(messageId: LongId[Message])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] = { + val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/message/${messageId.id}")) + + for { + response <- transport.sendRequestGetResponse(requestContext)(request) + reply <- apiResponse[ApiMessage, DeleteReply](response) { _ => + DeleteReply.Deleted + }() + } yield { + reply + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala new file mode 100644 index 0000000..66f7a78 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala @@ -0,0 +1,37 @@ +package xyz.driver.pdsuidomain.services.rest + +import scala.concurrent.{ExecutionContext, Future} + +import akka.http.scaladsl.model._ +import akka.stream.ActorMaterializer +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: ActorMaterializer, + protected val exec: ExecutionContext) + extends StudyDesignService with RestHelper { + + import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import xyz.driver.pdsuidomain.services.StudyDesignService._ + + // GET /v1/study-design xyz.driver.server.controllers.StudyDesignController.getList + + 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], GetListReply](response) { api => + GetListReply.EntityList(api.items.map(_.toDomain), api.meta.itemsCount) + }() + } yield { + reply + } + } + +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala new file mode 100644 index 0000000..9b4b576 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala @@ -0,0 +1,117 @@ +package xyz.driver.pdsuidomain.services.rest + +import akka.http.scaladsl.marshalling.Marshal +import scala.NotImplementedError +import scala.concurrent.{ExecutionContext, Future} + +import akka.http.scaladsl.model._ +import akka.stream.ActorMaterializer +import xyz.driver.core.rest._ +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.trial.ApiTrial +import xyz.driver.pdsuidomain.services.TrialService +import xyz.driver.pdsuidomain.formats.json.ListResponse + +class RestTrialService(transport: ServiceTransport, baseUri: Uri)( + implicit protected val materializer: ActorMaterializer, + protected val exec: ExecutionContext) + extends TrialService with RestHelper { + + import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ + import xyz.driver.pdsuidomain.services.TrialService._ + + // GET /v1/trial xyz.driver.server.controllers.TrialController.getList + // GET /v1/trial/:id xyz.driver.server.controllers.TrialController.getById(id: String) + // GET /v1/trial/:id/source xyz.driver.server.controllers.TrialController.getSource(id: String) + // PATCH /v1/trial/:id xyz.driver.server.controllers.TrialController.update(id: String) + // POST /v1/trial/:id/start xyz.driver.server.controllers.TrialController.start(id: String) + // POST /v1/trial/:id/submit xyz.driver.server.controllers.TrialController.submit(id: String) + // POST /v1/trial/:id/restart xyz.driver.server.controllers.TrialController.restart(id: String) + // POST /v1/trial/:id/flag xyz.driver.server.controllers.TrialController.flag(id: String) + // POST /v1/trial/:id/resolve xyz.driver.server.controllers.TrialController.resolve(id: String) + // POST /v1/trial/:id/archive xyz.driver.server.controllers.TrialController.archive(id: String) + // POST /v1/trial/:id/unassign xyz.driver.server.controllers.TrialController.unassign(id: String) + + 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, GetByIdReply](response) { api => + GetByIdReply.Entity(api.toDomain) + }() + } yield { + reply + } + } + + def getPdfSource(trialId: StringId[Trial])( + implicit requestContext: AuthenticatedRequestContext): Future[GetPdfSourceReply] = Future.failed( + new NotImplementedError("Streaming PDF over network is not supported.") + ) + + 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], GetListReply](response) { api => + GetListReply.EntityList(api.items.map(_.toDomain), api.meta.itemsCount, api.meta.lastUpdate) + }() + } yield { + reply + } + } + + 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, UpdateReply](response) { api => + UpdateReply.Updated(api.toDomain) + }() + } yield { + reply + } + } + + 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, UpdateReply](response) { api => + UpdateReply.Updated(api.toDomain) + }() + } yield { + reply + } + } + + 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") + +} |