aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvlad <vlad@driver.xyz>2017-07-20 10:37:08 -0700
committervlad <vlad@driver.xyz>2017-07-20 10:37:08 -0700
commit5279d01cedb35a759347f194c0e8adb21d19e88e (patch)
treee340bb2eaba41d917bbca8c5e42b0b76bd164e37 /src
parentd9c3283c307105e03253c621b9b25a6308ac3b94 (diff)
parent7f7bd651122754a3df47894b64ddb0456561bbe7 (diff)
downloadrest-query-5279d01cedb35a759347f194c0e8adb21d19e88e.tar.gz
rest-query-5279d01cedb35a759347f194c0e8adb21d19e88e.tar.bz2
rest-query-5279d01cedb35a759347f194c0e8adb21d19e88e.zip
Merge remote-tracking branch 'origin/master'
# Conflicts: # build.sbt # src/main/scala/xyz/driver/pdsuicommon/auth/AuthenticatedRequestContext.scala # src/main/scala/xyz/driver/pdsuicommon/domain/User.scala # src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/auth/AuthenticatedRequestContext.scala2
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapter.scala4
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/concurrent/Cron.scala6
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/concurrent/SafeBridgeUploadQueue.scala2
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/db/MySqlContext.scala26
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/db/Pagination.scala2
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/db/QueryBuilder.scala31
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/db/SearchFilterExpr.scala6
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/db/Sorting.scala4
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/domain/Id.scala8
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/domain/User.scala12
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/error/DomainError.scala11
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala17
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala83
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala2
-rw-r--r--src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala34
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/entities/DirectReport.scala14
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala48
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/entities/Message.scala6
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientDocument.scala20
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala26
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala25
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/ListResponse.scala4
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiArm.scala15
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala39
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiMessage.scala22
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiTrial.scala62
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala8
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/ArmService.scala10
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/CategoryService.scala27
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/CriterionService.scala18
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/DocumentService.scala19
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/DocumentTypeService.scala2
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/ExportService.scala6
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/ExtractedDataService.scala18
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/HypothesisService.scala2
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/InterventionService.scala10
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/InterventionTypeService.scala2
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/KeywordService.scala28
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/LabelService.scala27
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/MedicalRecordService.scala18
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/MessageService.scala21
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/PatientCriterionService.scala22
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/PatientEligibleTrialService.scala21
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/PatientHypothesisService.scala12
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelEvidenceService.scala6
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/PatientLabelService.scala16
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/PatientService.scala11
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/ProviderTypeService.scala2
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/QueueUploadService.scala20
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/ScrapedTrialsService.scala8
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/StudyDesignService.scala2
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/TrialHistoryService.scala4
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/TrialIssueService.scala20
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/TrialService.scala16
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/UserHistoryService.scala2
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala81
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala86
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala125
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHypothesisService.scala33
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala64
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala36
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala88
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala33
-rw-r--r--src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala95
65 files changed, 1181 insertions, 369 deletions
diff --git a/src/main/scala/xyz/driver/pdsuicommon/auth/AuthenticatedRequestContext.scala b/src/main/scala/xyz/driver/pdsuicommon/auth/AuthenticatedRequestContext.scala
index a21b011..42f7435 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/auth/AuthenticatedRequestContext.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/auth/AuthenticatedRequestContext.scala
@@ -4,7 +4,7 @@ import xyz.driver.entities.users.UserInfo
import xyz.driver.pdsuicommon.logging._
import xyz.driver.pdsuicommon.domain.User
-class AuthenticatedRequestContext(val driverUser: UserInfo, override val requestId: RequestId, val authToken: String = "")
+class AuthenticatedRequestContext(val driverUser: UserInfo, override val requestId: RequestId, val authToken: String)
extends AnonymousRequestContext(requestId) {
val executor: User = new User(driverUser)
diff --git a/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapter.scala b/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapter.scala
index 48c81c2..3bf9192 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapter.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/concurrent/BridgeUploadQueueRepositoryAdapter.scala
@@ -77,8 +77,8 @@ object BridgeUploadQueueRepositoryAdapter {
sealed trait OnAttempt
object OnAttempt {
- case object Complete extends OnAttempt
- case class Continue(interval: Duration) extends OnAttempt
+ case object Complete extends OnAttempt
+ final case class Continue(interval: Duration) extends OnAttempt
implicit def toPhiString(x: OnAttempt): PhiString = Unsafe(x.toString)
}
diff --git a/src/main/scala/xyz/driver/pdsuicommon/concurrent/Cron.scala b/src/main/scala/xyz/driver/pdsuicommon/concurrent/Cron.scala
index dd84beb..6659088 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/concurrent/Cron.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/concurrent/Cron.scala
@@ -45,9 +45,9 @@ class Cron(settings: Cron.Settings) extends Closeable with StrictLogging {
* Checks unused jobs
*/
def verify(): Unit = {
- import scala.collection.JavaConversions.asScalaSet
+ import scala.collection.JavaConverters._
- val unusedJobs = settings.intervals.keySet -- jobs.toSet
+ val unusedJobs = settings.intervals.keySet -- jobs.asScala.toSet
unusedJobs.foreach { job =>
logger.warn(s"The job '$job' is listed, but not registered or ignored")
}
@@ -60,7 +60,7 @@ class Cron(settings: Cron.Settings) extends Closeable with StrictLogging {
object Cron {
- case class Settings(disable: String, intervals: Map[String, FiniteDuration])
+ final case class Settings(disable: String, intervals: Map[String, FiniteDuration])
private class SingletonTask(taskName: String, job: () => Future[Unit])(implicit ec: ExecutionContext)
extends TimerTask with StrictLogging {
diff --git a/src/main/scala/xyz/driver/pdsuicommon/concurrent/SafeBridgeUploadQueue.scala b/src/main/scala/xyz/driver/pdsuicommon/concurrent/SafeBridgeUploadQueue.scala
index 0bc8220..2f7fe6c 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/concurrent/SafeBridgeUploadQueue.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/concurrent/SafeBridgeUploadQueue.scala
@@ -11,7 +11,7 @@ object SafeBridgeUploadQueue {
trait Tag extends Product with Serializable
- case class SafeTask[T <: Tag](tag: T, private[SafeBridgeUploadQueue] val queueItem: BridgeUploadQueue.Item)
+ final case class SafeTask[T <: Tag](tag: T, private[SafeBridgeUploadQueue] val queueItem: BridgeUploadQueue.Item)
object SafeTask {
implicit def toPhiString[T <: Tag](x: SafeTask[T]): PhiString = {
diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/MySqlContext.scala b/src/main/scala/xyz/driver/pdsuicommon/db/MySqlContext.scala
index f804e87..c547bf4 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/db/MySqlContext.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/db/MySqlContext.scala
@@ -18,20 +18,20 @@ import scala.util.{Failure, Success, Try}
object MySqlContext extends PhiLogging {
- case class DbCredentials(user: String,
- password: String,
- host: String,
- port: Int,
- dbName: String,
- dbCreateFlag: Boolean,
- dbContext: String,
- connectionParams: String,
- url: String)
+ final case class DbCredentials(user: String,
+ password: String,
+ host: String,
+ port: Int,
+ dbName: String,
+ dbCreateFlag: Boolean,
+ dbContext: String,
+ connectionParams: String,
+ url: String)
- case class Settings(credentials: DbCredentials,
- connection: Config,
- connectionAttemptsOnStartup: Int,
- threadPoolSize: Int)
+ final case class Settings(credentials: DbCredentials,
+ connection: Config,
+ connectionAttemptsOnStartup: Int,
+ threadPoolSize: Int)
def apply(settings: Settings): MySqlContext = {
// Prevent leaking credentials to a log
diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/Pagination.scala b/src/main/scala/xyz/driver/pdsuicommon/db/Pagination.scala
index e72b5c2..92689dd 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/db/Pagination.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/db/Pagination.scala
@@ -5,7 +5,7 @@ import xyz.driver.pdsuicommon.logging._
/**
* @param pageNumber Starts with 1
*/
-case class Pagination(pageSize: Int, pageNumber: Int)
+final case class Pagination(pageSize: Int, pageNumber: Int)
object Pagination {
diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/QueryBuilder.scala b/src/main/scala/xyz/driver/pdsuicommon/db/QueryBuilder.scala
index f941627..aa32166 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/db/QueryBuilder.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/db/QueryBuilder.scala
@@ -23,15 +23,15 @@ object QueryBuilder {
*/
type Binder = PreparedStatement => PreparedStatement
- case class TableData(tableName: String,
- lastUpdateFieldName: Option[String] = None,
- nullableFields: Set[String] = Set.empty)
+ final case class TableData(tableName: String,
+ lastUpdateFieldName: Option[String] = None,
+ nullableFields: Set[String] = Set.empty)
val AllFields = Set("*")
}
-case class TableLink(keyColumnName: String, foreignTableName: String, foreignKeyColumnName: String)
+final case class TableLink(keyColumnName: String, foreignTableName: String, foreignKeyColumnName: String)
object QueryBuilderParameters {
val AllFields = Set("*")
@@ -57,10 +57,11 @@ sealed trait QueryBuilderParameters {
def toSql(countQuery: Boolean, fields: Set[String], namingStrategy: NamingStrategy): (String, QueryBuilder.Binder) = {
val escapedTableName = namingStrategy.table(tableData.tableName)
val fieldsSql: String = if (countQuery) {
- "count(*)" + (tableData.lastUpdateFieldName match {
+ val suffix: String = (tableData.lastUpdateFieldName match {
case Some(lastUpdateField) => s", max($escapedTableName.${namingStrategy.column(lastUpdateField)})"
case None => ""
})
+ "count(*)" + suffix
} else {
if (fields == QueryBuilderParameters.AllFields) {
s"$escapedTableName.*"
@@ -260,11 +261,11 @@ sealed trait QueryBuilderParameters {
}
-case class PostgresQueryBuilderParameters(tableData: QueryBuilder.TableData,
- links: Map[String, TableLink] = Map.empty,
- filter: SearchFilterExpr = SearchFilterExpr.Empty,
- sorting: Sorting = Sorting.Empty,
- pagination: Option[Pagination] = None)
+final case class PostgresQueryBuilderParameters(tableData: QueryBuilder.TableData,
+ links: Map[String, TableLink] = Map.empty,
+ filter: SearchFilterExpr = SearchFilterExpr.Empty,
+ sorting: Sorting = Sorting.Empty,
+ pagination: Option[Pagination] = None)
extends QueryBuilderParameters {
def limitToSql(): String = {
@@ -279,11 +280,11 @@ case class PostgresQueryBuilderParameters(tableData: QueryBuilder.TableData,
/**
* @param links Links to another tables grouped by foreignTableName
*/
-case class MysqlQueryBuilderParameters(tableData: QueryBuilder.TableData,
- links: Map[String, TableLink] = Map.empty,
- filter: SearchFilterExpr = SearchFilterExpr.Empty,
- sorting: Sorting = Sorting.Empty,
- pagination: Option[Pagination] = None)
+final case class MysqlQueryBuilderParameters(tableData: QueryBuilder.TableData,
+ links: Map[String, TableLink] = Map.empty,
+ filter: SearchFilterExpr = SearchFilterExpr.Empty,
+ sorting: Sorting = Sorting.Empty,
+ pagination: Option[Pagination] = None)
extends QueryBuilderParameters {
def limitToSql(): String =
diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/SearchFilterExpr.scala b/src/main/scala/xyz/driver/pdsuicommon/db/SearchFilterExpr.scala
index 4b66f22..0577921 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/db/SearchFilterExpr.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/db/SearchFilterExpr.scala
@@ -16,7 +16,7 @@ object SearchFilterExpr {
value = "false"
)
- case class Dimension(tableName: Option[String], name: String) {
+ final case class Dimension(tableName: Option[String], name: String) {
def isForeign: Boolean = tableName.isDefined
}
@@ -33,13 +33,13 @@ object SearchFilterExpr {
}
object Atom {
- case class Binary(dimension: Dimension, op: SearchFilterBinaryOperation, value: AnyRef) extends Atom
+ final case class Binary(dimension: Dimension, op: SearchFilterBinaryOperation, value: AnyRef) extends Atom
object Binary {
def apply(field: String, op: SearchFilterBinaryOperation, value: AnyRef): Binary =
Binary(Dimension(None, field), op, value)
}
- case class NAry(dimension: Dimension, op: SearchFilterNAryOperation, values: Seq[AnyRef]) extends Atom
+ final case class NAry(dimension: Dimension, op: SearchFilterNAryOperation, values: Seq[AnyRef]) extends Atom
object NAry {
def apply(field: String, op: SearchFilterNAryOperation, values: Seq[AnyRef]): NAry =
NAry(Dimension(None, field), op, values)
diff --git a/src/main/scala/xyz/driver/pdsuicommon/db/Sorting.scala b/src/main/scala/xyz/driver/pdsuicommon/db/Sorting.scala
index b796b83..a2c5a75 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/db/Sorting.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/db/Sorting.scala
@@ -23,11 +23,11 @@ object Sorting {
* @param name Dimension name
* @param order Order
*/
- case class Dimension(tableName: Option[String], name: String, order: SortingOrder) extends Sorting {
+ final case class Dimension(tableName: Option[String], name: String, order: SortingOrder) extends Sorting {
def isForeign: Boolean = tableName.isDefined
}
- case class Sequential(sorting: Seq[Dimension]) extends Sorting {
+ final case class Sequential(sorting: Seq[Dimension]) extends Sorting {
override def toString: String = if (isEmpty(this)) "Empty" else super.toString
}
diff --git a/src/main/scala/xyz/driver/pdsuicommon/domain/Id.scala b/src/main/scala/xyz/driver/pdsuicommon/domain/Id.scala
index 1bb70f8..e238245 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/domain/Id.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/domain/Id.scala
@@ -6,9 +6,9 @@ import xyz.driver.pdsuicommon.logging._
sealed trait Id[+T]
-case class CompoundId[Id1 <: Id[_], Id2 <: Id[_]](part1: Id1, part2: Id2) extends Id[(Id1, Id2)]
+final case class CompoundId[Id1 <: Id[_], Id2 <: Id[_]](part1: Id1, part2: Id2) extends Id[(Id1, Id2)]
-case class LongId[+T](id: Long) extends Id[T] {
+final case class LongId[+T](id: Long) extends Id[T] {
override def toString: String = id.toString
def is(longId: Long): Boolean = {
@@ -20,7 +20,7 @@ object LongId {
implicit def toPhiString[T](x: LongId[T]): PhiString = Unsafe(s"LongId(${x.id})")
}
-case class StringId[+T](id: String) extends Id[T] {
+final case class StringId[+T](id: String) extends Id[T] {
override def toString: String = id
def is(stringId: String): Boolean = {
@@ -32,7 +32,7 @@ object StringId {
implicit def toPhiString[T](x: StringId[T]): PhiString = Unsafe(s"StringId(${x.id})")
}
-case class UuidId[+T](id: UUID) extends Id[T] {
+final case class UuidId[+T](id: UUID) extends Id[T] {
override def toString: String = id.toString
}
diff --git a/src/main/scala/xyz/driver/pdsuicommon/domain/User.scala b/src/main/scala/xyz/driver/pdsuicommon/domain/User.scala
index b400a71..654af1a 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/domain/User.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/domain/User.scala
@@ -8,12 +8,12 @@ import xyz.driver.pdsuicommon.logging._
import xyz.driver.pdsuicommon.domain.User.Role
import xyz.driver.pdsuicommon.utils.Utils
-case class User(id: StringId[User],
- email: Email,
- name: String,
- roles: Set[Role],
- latestActivity: Option[LocalDateTime],
- deleted: Option[LocalDateTime]) {
+final case class User(id: StringId[User],
+ email: Email,
+ name: String,
+ roles: Set[Role],
+ latestActivity: Option[LocalDateTime],
+ deleted: Option[LocalDateTime]) {
def this(driverUser: xyz.driver.entities.users.UserInfo) {
this(
diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/DomainError.scala b/src/main/scala/xyz/driver/pdsuicommon/error/DomainError.scala
index 4bf90d1..c761414 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/error/DomainError.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/error/DomainError.scala
@@ -28,3 +28,14 @@ object DomainError {
Unsafe(Utils.getClassSimpleName(x.getClass))
}
}
+
+/** Subclasses of this exception correspond to subclasses of DomainError. They
+ * are used in REST service implementations to fail futures rather than
+ * returning successful futures, completed with corresponding DomainErrors. */
+// scalastyle:off null
+@SuppressWarnings(Array("org.wartremover.warts.Null"))
+class DomainException(message: String, cause: Throwable = null) extends RuntimeException(message, cause)
+class NotFoundException(message: String) extends DomainException(message) // 404
+class AuthenticationException(message: String) extends DomainException(message) // 401
+class AuthorizationException(message: String) extends DomainException(message) // 403
+// scalastyle:on null
diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala
new file mode 100644
index 0000000..5574c01
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala
@@ -0,0 +1,17 @@
+package xyz.driver.pdsuicommon.error
+
+import play.api.libs.functional.syntax._
+import play.api.libs.json.{Format, Reads, Writes}
+
+@SuppressWarnings(Array("org.wartremover.warts.Enumeration"))
+object ErrorCode extends Enumeration {
+
+ type ErrorCode = Value
+ val Unspecified = Value(1)
+
+ private val fromJsonReads: Reads[ErrorCode] = Reads.of[Int].map(ErrorCode.apply)
+ private val toJsonWrites: Writes[ErrorCode] = Writes.of[Int].contramap(_.id)
+
+ implicit val jsonFormat: Format[ErrorCode] = Format(fromJsonReads, toJsonWrites)
+
+}
diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala
new file mode 100644
index 0000000..3761cc5
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala
@@ -0,0 +1,83 @@
+package xyz.driver.pdsuicommon.error
+
+import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat
+import ErrorCode.{ErrorCode, Unspecified}
+import ErrorsResponse.ResponseError
+import xyz.driver.pdsuicommon.auth.{AnonymousRequestContext, RequestId}
+import xyz.driver.pdsuicommon.utils.Utils
+import play.api.libs.functional.syntax._
+import play.api.libs.json._
+import play.api.mvc.Results
+import xyz.driver.pdsuicommon.validation.JsonValidationErrors
+
+final case class ErrorsResponse(errors: Seq[ResponseError], requestId: RequestId)
+
+object ErrorsResponse {
+
+ /**
+ * @param data Any data that can be associated with particular error.Ex.: error field name
+ * @param message Error message
+ * @param code Unique error code
+ *
+ * @see https://driverinc.atlassian.net/wiki/display/RA/REST+API+Specification#RESTAPISpecification-HTTPStatuscodes
+ */
+ final case class ResponseError(data: Option[String], message: String, code: ErrorCode)
+
+ object ResponseError {
+
+ implicit val responseErrorJsonFormat: Format[ResponseError] = (
+ (JsPath \ "data").formatNullable[String] and
+ (JsPath \ "message").format[String] and
+ (JsPath \ "code").format[ErrorCode]
+ )(ResponseError.apply, unlift(ResponseError.unapply))
+
+ }
+
+ implicit val errorsResponseJsonFormat: Format[ErrorsResponse] = (
+ (JsPath \ "errors").format[Seq[ResponseError]] and
+ (JsPath \ "requestId").format[String]
+ )((errs, req) => ErrorsResponse.apply(errs, RequestId(req)), res => (res.errors, res.requestId.value))
+
+ // deprecated, will be removed in REP-436
+ def fromString(message: String, httpStatus: Results#Status)(
+ implicit context: AnonymousRequestContext): ErrorsResponse = {
+ new ErrorsResponse(
+ errors = Seq(
+ ResponseError(
+ data = None,
+ message = message,
+ code = Unspecified
+ )),
+ requestId = context.requestId
+ )
+ }
+
+ // scalastyle:off null
+ def fromExceptionMessage(e: Throwable, httpStatus: Results#Status = Results.InternalServerError)(
+ implicit context: AnonymousRequestContext): ErrorsResponse = {
+ val message = if (e.getMessage == null || e.getMessage.isEmpty) {
+ Utils.getClassSimpleName(e.getClass)
+ } else {
+ e.getMessage
+ }
+
+ fromString(message, httpStatus)
+ }
+ // scalastyle:on null
+
+ // deprecated, will be removed in REP-436
+ def fromJsonValidationErrors(validationErrors: JsonValidationErrors)(
+ implicit context: AnonymousRequestContext): ErrorsResponse = {
+ val errors = validationErrors.map {
+ case (path, xs) =>
+ ResponseError(
+ data = Some(path.toString()),
+ message = xs.map(_.message).mkString("\n"),
+ code = Unspecified
+ )
+ }
+
+ new ErrorsResponse(errors, context.requestId)
+ }
+
+}
diff --git a/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala b/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala
index 07dfefc..4ff4034 100644
--- a/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala
+++ b/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala
@@ -7,7 +7,7 @@ import scala.util.{Failure, Success, Try}
final class JsResultOps[T](val self: JsResult[T]) extends AnyVal {
def toTry: Try[T] = {
- self.fold(
+ self.fold[Try[T]](
errors => Failure(new JsonValidationException(errors)),
Success(_)
)
diff --git a/src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala b/src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala
new file mode 100644
index 0000000..5158dab
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala
@@ -0,0 +1,34 @@
+package xyz.driver.pdsuicommon.serialization
+
+import akka.http.scaladsl.server.{RejectionError, ValidationRejection}
+import akka.http.scaladsl.unmarshalling.Unmarshaller
+import play.api.libs.json.{Reads, Writes}
+import play.api.libs.json.Json
+import akka.http.scaladsl.marshalling.ToEntityMarshaller
+import akka.http.scaladsl.unmarshalling.FromEntityUnmarshaller
+import akka.http.scaladsl.model.MediaTypes.`application/json`
+
+trait PlayJsonSupport {
+ import akka.http.scaladsl.marshalling.Marshaller
+
+ implicit def playJsonUnmarshaller[A: Reads]: FromEntityUnmarshaller[A] = {
+ val reads = implicitly[Reads[A]]
+ Unmarshaller.stringUnmarshaller
+ .forContentTypes(`application/json`)
+ .map(Json.parse)
+ .map(reads.reads)
+ .map(_.recoverTotal { error =>
+ throw RejectionError(ValidationRejection(s"Error reading JSON response as ${reads}."))
+ })
+ }
+
+ implicit def playJsonMarshaller[A: Writes]: ToEntityMarshaller[A] = {
+ Marshaller
+ .stringMarshaller(`application/json`)
+ .compose(Json.prettyPrint)
+ .compose(implicitly[Writes[A]].writes)
+ }
+
+}
+
+object PlayJsonSupport extends PlayJsonSupport
diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/DirectReport.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/DirectReport.scala
index c09a1d8..42ac55b 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/entities/DirectReport.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/entities/DirectReport.scala
@@ -32,10 +32,10 @@ object DirectReport {
}
}
-case class DirectReport(id: UuidId[DirectReport],
- patientId: UuidId[Patient],
- reportType: ReportType,
- date: LocalDate,
- documentType: String,
- providerType: String,
- providerName: String)
+final case class DirectReport(id: UuidId[DirectReport],
+ patientId: UuidId[Patient],
+ reportType: ReportType,
+ date: LocalDate,
+ documentType: String,
+ providerType: String,
+ providerName: String)
diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala
index 9f38283..3b53945 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/entities/MedicalRecord.scala
@@ -32,11 +32,11 @@ object MedicalRecord {
object Meta {
- case class Duplicate(predicted: Option[Boolean],
- startPage: Double,
- endPage: Double,
- startOriginalPage: Double,
- endOriginalPage: Option[Double])
+ final case class Duplicate(predicted: Option[Boolean],
+ startPage: Double,
+ endPage: Double,
+ startOriginalPage: Double,
+ endOriginalPage: Option[Double])
extends Meta {
override val metaType = "duplicate"
override def confirmed: Duplicate = copy(predicted = predicted.map(_ => false))
@@ -50,7 +50,7 @@ object MedicalRecord {
}
}
- case class Reorder(predicted: Option[Boolean], items: Seq[Int]) extends Meta {
+ final case class Reorder(predicted: Option[Boolean], items: Seq[Int]) extends Meta {
override val metaType = "reorder"
override def confirmed: Reorder = copy(predicted = predicted.map(_ => false))
}
@@ -62,7 +62,7 @@ object MedicalRecord {
}
}
- case class Rotation(predicted: Option[Boolean], items: Map[String, Int]) extends Meta {
+ final case class Rotation(predicted: Option[Boolean], items: Map[String, Int]) extends Meta {
override val metaType = "rotation"
override def confirmed: Rotation = copy(predicted = predicted.map(_ => false))
}
@@ -129,7 +129,7 @@ object MedicalRecord {
case object Empty extends PdfSource
/** @param createResource Constructor of the resource which is represents the file */
- case class Channel(createResource: () => ReadableByteChannel) extends PdfSource
+ final case class Channel(createResource: () => ReadableByteChannel) extends PdfSource
}
implicit def toPhiString(x: MedicalRecord): PhiString = {
@@ -139,22 +139,22 @@ object MedicalRecord {
}
}
-case class MedicalRecord(id: LongId[MedicalRecord],
- status: MedicalRecord.Status,
- previousStatus: Option[MedicalRecord.Status],
- assignee: Option[StringId[User]],
- previousAssignee: Option[StringId[User]],
- lastActiveUserId: Option[StringId[User]],
- patientId: UuidId[Patient],
- requestId: RecordRequestId,
- disease: String,
- caseId: Option[CaseId],
- physician: Option[String],
- sourceName: String,
- meta: Option[TextJson[List[Meta]]],
- predictedMeta: Option[TextJson[List[Meta]]],
- predictedDocuments: Option[TextJson[List[Document]]],
- lastUpdate: LocalDateTime) {
+final case class MedicalRecord(id: LongId[MedicalRecord],
+ status: MedicalRecord.Status,
+ previousStatus: Option[MedicalRecord.Status],
+ assignee: Option[StringId[User]],
+ previousAssignee: Option[StringId[User]],
+ lastActiveUserId: Option[StringId[User]],
+ patientId: UuidId[Patient],
+ requestId: RecordRequestId,
+ disease: String,
+ caseId: Option[CaseId],
+ physician: Option[String],
+ sourceName: String,
+ meta: Option[TextJson[List[Meta]]],
+ predictedMeta: Option[TextJson[List[Meta]]],
+ predictedDocuments: Option[TextJson[List[Document]]],
+ lastUpdate: LocalDateTime) {
import MedicalRecord.Status._
diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Message.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Message.scala
index f02f481..3bdbac8 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/entities/Message.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/entities/Message.scala
@@ -24,10 +24,10 @@ object Message {
implicit def toPhiString(x: Message): PhiString = {
import x._
- val entityId = recordId
- .orElse(documentId)
- .orElse(patientId)
+ val entityId: Option[String] = recordId
.map(_.toString)
+ .orElse(documentId.map(_.toString))
+ .orElse(patientId.map(_.toString))
phi"Message(id=$id, userId=$userId, isDraft=$isDraft, entityId=${Unsafe(entityId)}"
}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientDocument.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientDocument.scala
index 8e72023..b66483c 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientDocument.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/entities/RawPatientDocument.scala
@@ -5,16 +5,16 @@ import java.time.LocalDate
import xyz.driver.pdsuicommon.domain.{LongId, UuidId}
import xyz.driver.pdsuicommon.logging._
-case class RawPatientDocument(disease: String,
- patientId: UuidId[Patient],
- requestId: RecordRequestId,
- recordId: LongId[MedicalRecord],
- recordStatus: MedicalRecord.Status,
- documentId: LongId[Document],
- documentType: String,
- documentProviderType: String,
- documentStartDate: LocalDate,
- documentStatus: Document.Status)
+final case class RawPatientDocument(disease: String,
+ patientId: UuidId[Patient],
+ requestId: RecordRequestId,
+ recordId: LongId[MedicalRecord],
+ recordStatus: MedicalRecord.Status,
+ documentId: LongId[Document],
+ documentType: String,
+ documentProviderType: String,
+ documentStartDate: LocalDate,
+ documentStatus: Document.Status)
object RawPatientDocument {
diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala
index 82204c2..9e69c87 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/entities/RawTrialLabel.scala
@@ -5,19 +5,19 @@ import java.time.LocalDateTime
import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId}
import xyz.driver.pdsuicommon.logging._
-case class RawTrialLabel(nctId: StringId[Trial],
- trialId: UuidId[Trial],
- condition: String,
- lastReviewed: LocalDateTime,
- armName: String,
- armId: LongId[Arm],
- labelId: LongId[Label],
- value: Option[Boolean],
- criterionId: LongId[Criterion],
- criteria: String,
- criterionArmId: LongId[Arm],
- isCompound: Boolean,
- isDefining: Boolean)
+final case class RawTrialLabel(nctId: StringId[Trial],
+ trialId: UuidId[Trial],
+ condition: String,
+ lastReviewed: LocalDateTime,
+ armName: String,
+ armId: LongId[Arm],
+ labelId: LongId[Label],
+ value: Option[Boolean],
+ criterionId: LongId[Criterion],
+ criteria: String,
+ criterionArmId: LongId[Arm],
+ isCompound: Boolean,
+ isDefining: Boolean)
object RawTrialLabel {
diff --git a/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala b/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala
index 3fe8176..2f90820 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/entities/Trial.scala
@@ -52,16 +52,15 @@ object Trial {
implicit def toPhiString(x: Status): PhiString = Unsafe(Utils.getClassSimpleName(x.getClass))
}
- case class PdfSource(path: Path) extends AnyVal
+ final case class PdfSource(path: Path) extends AnyVal
implicit def toPhiString(x: Trial): PhiString = {
import x._
phi"Trial(id=$id, externalId=$externalId, status=$status, previousStatus=$previousStatus, " +
- phi"lastActiveUserId=$lastActiveUserId, assignee=$assignee, previousAssignee=$previousAssignee, " +
- phi"isSummaryReviewed=$isSummaryReviewed, isCriteriaReviewed=$isCriteriaReviewed)"
+ phi"lastActiveUserId=$lastActiveUserId, assignee=$assignee, previousAssignee=$previousAssignee, "
}
- case class Locations(locations: List[String])
+ final case class Locations(locations: List[String])
sealed trait Condition
@@ -71,7 +70,14 @@ object Trial {
case object Lung extends Condition
case object Prostate extends Condition
- val All = Set(Breast, Lung, Prostate)
+ def fromString(condition: String): Option[Condition] = condition match {
+ case "Breast" => Some(Breast)
+ case "Lung" => Some(Lung)
+ case "Prostate" => Some(Prostate)
+ case _ => None
+ }
+
+ val All: Set[Condition] = Set(Breast, Lung, Prostate)
}
}
@@ -93,14 +99,7 @@ final case class Trial(id: StringId[Trial],
overviewTemplate: String,
isUpdated: Boolean,
title: String,
- originalTitle: String,
- isSummaryReviewed: Boolean,
- isCriteriaReviewed: Boolean,
- eligibilityCriteriaChecksum: String,
- briefSummaryChecksum: String,
- detailedDescriptionChecksum: String,
- armDescriptionChecksum: String) {
-
+ originalTitle: String) {
import Trial.Status._
if (previousStatus.nonEmpty) {
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/ListResponse.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/ListResponse.scala
index c823df5..3fbeac8 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/ListResponse.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/ListResponse.scala
@@ -7,11 +7,11 @@ import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat
import play.api.libs.functional.syntax._
import play.api.libs.json._
-case class ListResponse[+T](items: Seq[T], meta: ListResponse.Meta)
+final case class ListResponse[+T](items: Seq[T], meta: ListResponse.Meta)
object ListResponse {
- case class Meta(itemsCount: Int, pageNumber: Int, pageSize: Int, lastUpdate: Option[LocalDateTime])
+ final case class Meta(itemsCount: Int, pageNumber: Int, pageSize: Int, lastUpdate: Option[LocalDateTime])
object Meta {
def apply(itemsCount: Int, pagination: Pagination, lastUpdate: Option[LocalDateTime]): Meta = {
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiArm.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiArm.scala
index 2185e3a..32e2b54 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiArm.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/arm/ApiArm.scala
@@ -1,22 +1,35 @@
package xyz.driver.pdsuidomain.formats.json.arm
+import xyz.driver.pdsuicommon.domain.{LongId, StringId}
import xyz.driver.pdsuidomain.entities.Arm
import play.api.libs.functional.syntax._
import play.api.libs.json._
-final case class ApiArm(id: Long, name: String, trialId: String)
+final case class ApiArm(id: Long, name: String, originalName: String, trialId: String) {
+
+ def toDomain: Arm = Arm(
+ id = LongId(this.id),
+ name = this.name,
+ originalName = this.originalName,
+ trialId = StringId(this.trialId),
+ deleted = None // if we have an ApiArm object, the Arm itself has not been deleted
+ )
+
+}
object ApiArm {
implicit val format: Format[ApiArm] = (
(JsPath \ "id").format[Long] and
(JsPath \ "name").format[String] and
+ (JsPath \ "originalName").format[String] and
(JsPath \ "trialId").format[String]
)(ApiArm.apply, unlift(ApiArm.unapply))
def fromDomain(arm: Arm): ApiArm = ApiArm(
id = arm.id.id,
name = arm.name,
+ originalName = arm.originalName,
trialId = arm.trialId.id
)
}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala
index 39e0000..39acbde 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/intervention/ApiIntervention.scala
@@ -1,6 +1,7 @@
package xyz.driver.pdsuidomain.formats.json.intervention
-import xyz.driver.pdsuidomain.entities.InterventionWithArms
+import xyz.driver.pdsuicommon.domain.{LongId, StringId}
+import xyz.driver.pdsuidomain.entities.{Intervention, InterventionArm, InterventionWithArms}
import play.api.libs.functional.syntax._
import play.api.libs.json.{Format, JsPath}
@@ -10,7 +11,31 @@ final case class ApiIntervention(id: Long,
description: String,
isActive: Boolean,
arms: List[Long],
- trialId: String)
+ trialId: String,
+ originalName: String,
+ originalDescription: String,
+ originalType: Option[String]) {
+
+ def toDomain = {
+ val intervention = Intervention(
+ id = LongId(this.id),
+ trialId = StringId(this.trialId),
+ name = this.name,
+ originalName = this.originalName,
+ typeId = this.typeId.map(id => LongId(id)),
+ originalType = this.originalType.map(id => id.toString),
+ description = this.description,
+ originalDescription = this.originalDescription,
+ isActive = this.isActive
+ )
+
+ InterventionWithArms(intervention, this.arms.map { armId =>
+ InterventionArm(LongId(armId), intervention.id)
+ })
+
+ }
+
+}
object ApiIntervention {
@@ -21,7 +46,10 @@ object ApiIntervention {
(JsPath \ "description").format[String] and
(JsPath \ "isActive").format[Boolean] and
(JsPath \ "arms").format[List[Long]] and
- (JsPath \ "trialId").format[String]
+ (JsPath \ "trialId").format[String] and
+ (JsPath \ "originalName").format[String] and
+ (JsPath \ "originalDescription").format[String] and
+ (JsPath \ "originalType").formatNullable[String]
)(ApiIntervention.apply, unlift(ApiIntervention.unapply))
def fromDomain(interventionWithArms: InterventionWithArms): ApiIntervention = {
@@ -35,7 +63,10 @@ object ApiIntervention {
description = intervention.description,
isActive = intervention.isActive,
arms = arms.map(_.armId.id),
- trialId = intervention.trialId.id
+ trialId = intervention.trialId.id,
+ originalName = intervention.originalName,
+ originalDescription = intervention.originalDescription,
+ originalType = intervention.originalType
)
}
}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiMessage.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiMessage.scala
index 2591509..425eeac 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiMessage.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/message/ApiMessage.scala
@@ -4,6 +4,7 @@ import java.time.{ZoneId, ZonedDateTime}
import play.api.libs.functional.syntax._
import play.api.libs.json.{Format, JsPath}
+import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId}
import xyz.driver.pdsuidomain.entities.Message
final case class ApiMessage(id: Long,
@@ -19,7 +20,26 @@ final case class ApiMessage(id: Long,
endPage: Option[Double],
evidence: Option[String],
archiveRequired: Option[Boolean],
- meta: Option[String])
+ meta: Option[String]) {
+
+ def toDomain = Message(
+ id = LongId(this.id),
+ text = this.text,
+ lastUpdate = this.lastUpdate.toLocalDateTime(),
+ userId = StringId(this.userId),
+ isDraft = this.isDraft,
+ recordId = this.recordId.map(id => LongId(id)),
+ documentId = this.documentId.map(id => LongId(id)),
+ patientId = this.patientId.map(id => UuidId(id)),
+ trialId = this.trialId.map(id => StringId(id)),
+ startPage = this.startPage,
+ endPage = this.endPage,
+ evidence = this.evidence,
+ archiveRequired = this.archiveRequired,
+ meta = this.meta
+ )
+
+}
object ApiMessage {
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiTrial.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiTrial.scala
index 940f1f0..f59836e 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiTrial.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/trial/ApiTrial.scala
@@ -2,65 +2,103 @@ package xyz.driver.pdsuidomain.formats.json.trial
import java.time.{ZoneId, ZonedDateTime}
import java.util.UUID
+import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId}
import xyz.driver.pdsuidomain.entities.Trial
import play.api.libs.functional.syntax._
import play.api.libs.json._
final case class ApiTrial(id: String,
- lastUpdate: Option[ZonedDateTime],
+ externalId: UUID,
+ lastUpdate: ZonedDateTime,
status: String,
assignee: Option[String],
previousStatus: Option[String],
previousAssignee: Option[String],
lastActiveUser: Option[String],
- condition: Option[String],
- phase: Option[String],
+ condition: String,
+ phase: String,
hypothesisId: Option[UUID],
studyDesignId: Option[Long],
+ originalStudyDesign: Option[String],
isPartner: Boolean,
overview: Option[String],
overviewTemplate: String,
isUpdated: Boolean,
- title: String)
+ title: String,
+ originalTitle: String) {
+
+ def toDomain = Trial(
+ id = StringId(this.id),
+ externalId = UuidId(this.externalId),
+ status = TrialStatus.statusFromString(this.status),
+ assignee = this.assignee.map(id => StringId(id)),
+ previousStatus = this.previousStatus.map(s => TrialStatus.statusFromString(s)),
+ previousAssignee = this.previousAssignee.map(id => StringId(id)),
+ lastActiveUserId = this.lastActiveUser.map(id => StringId(id)),
+ lastUpdate = this.lastUpdate.toLocalDateTime(),
+ condition = Trial.Condition
+ .fromString(this.condition)
+ .getOrElse(
+ throw new NoSuchElementException(s"unknown condition ${this.condition}")
+ ),
+ phase = this.phase,
+ hypothesisId = this.hypothesisId.map(id => UuidId(id)),
+ studyDesignId = this.studyDesignId.map(id => LongId(id)),
+ originalStudyDesign = this.originalStudyDesign,
+ isPartner = this.isPartner,
+ overview = this.overview,
+ overviewTemplate = this.overviewTemplate,
+ isUpdated = this.isUpdated,
+ title = this.title,
+ originalTitle = this.originalTitle
+ )
+
+}
object ApiTrial {
implicit val format: Format[ApiTrial] = (
(JsPath \ "id").format[String] and
- (JsPath \ "lastUpdate").formatNullable[ZonedDateTime] and
+ (JsPath \ "externalid").format[UUID] and
+ (JsPath \ "lastUpdate").format[ZonedDateTime] and
(JsPath \ "status").format[String] and
(JsPath \ "assignee").formatNullable[String] and
(JsPath \ "previousStatus").formatNullable[String] and
(JsPath \ "previousAssignee").formatNullable[String] and
(JsPath \ "lastActiveUser").formatNullable[String] and
- (JsPath \ "condition").formatNullable[String] and
- (JsPath \ "phase").formatNullable[String] and
+ (JsPath \ "condition").format[String] and
+ (JsPath \ "phase").format[String] and
(JsPath \ "hypothesisId").formatNullable[UUID] and
(JsPath \ "studyDesignId").formatNullable[Long] and
+ (JsPath \ "originalStudyDesignId").formatNullable[String] and
(JsPath \ "isPartner").format[Boolean] and
(JsPath \ "overview").formatNullable[String] and
(JsPath \ "overviewTemplate").format[String] and
(JsPath \ "isUpdated").format[Boolean] and
- (JsPath \ "title").format[String]
+ (JsPath \ "title").format[String] and
+ (JsPath \ "otiginalTitle").format[String]
)(ApiTrial.apply, unlift(ApiTrial.unapply))
def fromDomain(trial: Trial): ApiTrial = ApiTrial(
id = trial.id.id,
+ externalId = trial.externalId.id,
status = TrialStatus.statusToString(trial.status),
assignee = trial.assignee.map(_.id),
previousStatus = trial.previousStatus.map(TrialStatus.statusToString),
previousAssignee = trial.previousAssignee.map(_.id),
lastActiveUser = trial.lastActiveUserId.map(_.id),
- lastUpdate = Option(ZonedDateTime.of(trial.lastUpdate, ZoneId.of("Z"))),
- condition = Option(trial.condition.toString),
- phase = Option(trial.phase),
+ lastUpdate = ZonedDateTime.of(trial.lastUpdate, ZoneId.of("Z")),
+ condition = trial.condition.toString,
+ phase = trial.phase,
hypothesisId = trial.hypothesisId.map(_.id),
studyDesignId = trial.studyDesignId.map(_.id),
+ originalStudyDesign = trial.originalStudyDesign,
isPartner = trial.isPartner,
overview = trial.overview,
overviewTemplate = trial.overviewTemplate,
isUpdated = trial.isUpdated,
- title = trial.title
+ title = trial.title,
+ originalTitle = trial.originalTitle
)
}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala
index 2f476e7..cf20d32 100644
--- a/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala
+++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/user/ApiPartialUser.scala
@@ -68,9 +68,9 @@ object ApiPartialUser {
_.length > 255),
Writes.StringWrites
)) and
- (JsPath \ "roleId").formatNullable[Seq[String]](
- Format(
- seqJsonFormat[String].filter(ValidationError("unknown role"))(_.forall(UserRole.roleFromString.isDefinedAt)),
- Writes.of[Seq[String]]))
+ (JsPath \ "roles").formatNullable[Seq[String]](
+ Format(seqJsonFormat[String].filter(ValidationError("unknown roles"))(
+ _.forall(UserRole.roleFromString.isDefinedAt)),
+ Writes.of[Seq[String]]))
)(ApiPartialUser.apply, unlift(ApiPartialUser.unapply))
}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/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/rest/RestArmService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala
new file mode 100644
index 0000000..0a29c08
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestArmService.scala
@@ -0,0 +1,81 @@
+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.{Pagination => _, _}
+import xyz.driver.pdsuicommon.auth._
+import xyz.driver.pdsuicommon.db._
+import xyz.driver.pdsuicommon.domain._
+import xyz.driver.pdsuidomain.entities._
+import xyz.driver.pdsuidomain.formats.json.ListResponse
+import xyz.driver.pdsuidomain.formats.json.arm.ApiArm
+import xyz.driver.pdsuidomain.services.ArmService
+
+class RestArmService(transport: ServiceTransport, baseUri: Uri)(implicit protected val materializer: ActorMaterializer,
+ protected val exec: ExecutionContext)
+ extends ArmService with RestHelper {
+
+ import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._
+ import xyz.driver.pdsuidomain.services.ArmService._
+
+ def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty,
+ sorting: Option[Sorting] = None,
+ pagination: Option[Pagination] = None)(
+ implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = {
+ val request = HttpRequest(
+ HttpMethods.GET,
+ endpointUri(baseUri, "/v1/arm", filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination)))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ListResponse[ApiArm]](response)
+ } yield {
+ GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount)
+ }
+ }
+
+ def getById(armId: LongId[Arm])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = {
+ val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/arm/$armId"))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiArm](response)
+ } yield {
+ GetByIdReply.Entity(reply.toDomain)
+ }
+ }
+
+ def create(draftArm: Arm)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = {
+ for {
+ entity <- Marshal(ApiArm.fromDomain(draftArm)).to[RequestEntity]
+ request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/arm")).withEntity(entity)
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiArm](response)
+ } yield {
+ CreateReply.Created(reply.toDomain)
+ }
+ }
+
+ def update(origArm: Arm, draftArm: Arm)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = {
+ val id = origArm.id
+ val request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/arm/$id"))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiArm](response)
+ } yield {
+ UpdateReply.Updated(reply.toDomain)
+ }
+ }
+
+ def delete(id: LongId[Arm])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] = {
+ val request = HttpRequest(HttpMethods.DELETE, endpointUri(baseUri, s"/v1/arm/$id"))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiArm](response)
+ } yield {
+ DeleteReply.Deleted
+ }
+ }
+
+}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala
new file mode 100644
index 0000000..7470de1
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestCriterionService.scala
@@ -0,0 +1,86 @@
+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.{Pagination => _, _}
+import xyz.driver.pdsuicommon.auth._
+import xyz.driver.pdsuicommon.db._
+import xyz.driver.pdsuicommon.domain._
+import xyz.driver.pdsuidomain.entities._
+import xyz.driver.pdsuidomain.formats.json.ListResponse
+import xyz.driver.pdsuidomain.services.CriterionService
+
+class RestCriterionService(transport: ServiceTransport, baseUri: Uri)(
+ implicit protected val materializer: 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._
+
+ def create(draftRichCriterion: RichCriterion)(
+ implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = {
+ for {
+ entity <- Marshal(ApiCriterion.fromDomain(draftRichCriterion)).to[RequestEntity]
+ request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/criterion")).withEntity(entity)
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiCriterion](response)
+ } yield {
+ CreateReply.Created(reply.toDomain)
+ }
+ }
+
+ def getById(id: LongId[Criterion])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = {
+ val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/criterion/$id"))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiCriterion](response)
+ } yield {
+ GetByIdReply.Entity(reply.toDomain)
+ }
+ }
+
+ def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty,
+ sorting: Option[Sorting] = None,
+ pagination: Option[Pagination] = None)(
+ implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = {
+ val request = HttpRequest(HttpMethods.GET,
+ endpointUri(baseUri,
+ s"/v1/criterion",
+ filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination)))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ListResponse[ApiCriterion]](response)
+ } yield {
+ GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate)
+ }
+ }
+
+ def update(origRichCriterion: RichCriterion, draftRichCriterion: RichCriterion)(
+ implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = {
+ val id = origRichCriterion.criterion.id
+ for {
+ entity <- Marshal(ApiCriterion.fromDomain(draftRichCriterion)).to[RequestEntity]
+ request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/criterion/$id")).withEntity(entity)
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiCriterion](response)
+ } yield {
+ UpdateReply.Updated(reply.toDomain)
+ }
+ }
+
+ def delete(id: LongId[Criterion])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] = {
+ val request = HttpRequest(HttpMethods.DELETE, endpointUri(baseUri, s"/v1/criterion/$id"))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiCriterion](response)
+ } yield {
+ DeleteReply.Deleted
+ }
+ }
+
+}
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..bc886ba
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala
@@ -0,0 +1,125 @@
+package xyz.driver.pdsuidomain.services.rest
+
+import scala.concurrent.{ExecutionContext, Future}
+
+import akka.http.scaladsl.model.{HttpResponse, ResponseEntity, StatusCodes, Uri}
+import akka.http.scaladsl.unmarshalling.{Unmarshal, Unmarshaller}
+import akka.stream.Materializer
+import xyz.driver.core.rest.ServiceRequestContext
+import xyz.driver.pdsuicommon.auth.{AnonymousRequestContext, AuthenticatedRequestContext}
+import xyz.driver.pdsuicommon.db.{
+ Pagination,
+ SearchFilterBinaryOperation,
+ SearchFilterExpr,
+ SearchFilterNAryOperation,
+ Sorting,
+ SortingOrder
+}
+import xyz.driver.pdsuicommon.error._
+
+trait RestHelper {
+
+ implicit protected val materializer: Materializer
+ implicit protected val exec: ExecutionContext
+
+ protected def endpointUri(baseUri: Uri, path: String) =
+ baseUri.withPath(Uri.Path(path))
+
+ protected def endpointUri(baseUri: Uri, path: String, query: Seq[(String, String)]) =
+ baseUri.withPath(Uri.Path(path)).withQuery(Uri.Query(query: _*))
+
+ def sortingQuery(sorting: Option[Sorting]): Seq[(String, String)] = {
+ def dimensionQuery(dimension: Sorting.Dimension) = {
+ val ord = dimension.order match {
+ case SortingOrder.Ascending => ""
+ case SortingOrder.Descending => "-"
+ }
+ s"$ord${dimension.name}"
+ }
+
+ sorting match {
+ case None => Seq.empty
+ case Some(dimension: Sorting.Dimension) => Seq("sort" -> dimensionQuery(dimension))
+ case Some(Sorting.Sequential(dimensions)) => Seq("sort" -> dimensions.map(dimensionQuery).mkString(","))
+ }
+ }
+
+ def filterQuery(expr: SearchFilterExpr): Seq[(String, String)] = {
+ def opToString(op: SearchFilterBinaryOperation) = op match {
+ case SearchFilterBinaryOperation.Eq => "eq"
+ case SearchFilterBinaryOperation.NotEq => "ne"
+ case SearchFilterBinaryOperation.Like => "like"
+ case SearchFilterBinaryOperation.Gt => "gt"
+ case SearchFilterBinaryOperation.GtEq => "ge"
+ case SearchFilterBinaryOperation.Lt => "lt"
+ case SearchFilterBinaryOperation.LtEq => "le"
+ }
+
+ def exprToQuery(expr: SearchFilterExpr): Seq[(String, String)] = expr match {
+ case SearchFilterExpr.Empty => Seq.empty
+ case SearchFilterExpr.Atom.Binary(dimension, op, value) =>
+ Seq("filters" -> s"${dimension.name} ${opToString(op)} $value")
+ case SearchFilterExpr.Atom.NAry(dimension, SearchFilterNAryOperation.In, values) =>
+ Seq("filters" -> s"${dimension.name} in ${values.mkString(",")}")
+ case SearchFilterExpr.Intersection(ops) =>
+ ops.flatMap(op => exprToQuery(op))
+ case expr => sys.error(s"No parser available for filter expression $expr.")
+ }
+
+ exprToQuery(expr)
+ }
+
+ def paginationQuery(pagination: Option[Pagination]): Seq[(String, String)] = pagination match {
+ case None => Seq.empty
+ case Some(pp) =>
+ Seq(
+ "pageNumber" -> pp.pageNumber.toString,
+ "pageSize" -> pp.pageSize.toString
+ )
+ }
+
+ /** Utility method to parse responses from records-acquisition-server.
+ *
+ * Non-2xx HTTP error codes will be cause the returned future to fail with a corresponding
+ * `DomainException`.
+ * @tparam ApiReply The type of the serialized reply object, contained in the HTTP entity
+ * @param response The HTTP response to parse.
+ * @param unmarshaller An unmarshaller that converts a successful response to an api reply.
+ */
+ def apiResponse[ApiReply](response: HttpResponse)(
+ implicit unmarshaller: Unmarshaller[ResponseEntity, ApiReply]): Future[ApiReply] = {
+
+ def extractErrorMessage(response: HttpResponse): Future[String] = {
+ import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._
+ Unmarshal(response.entity)
+ .to[ErrorsResponse]
+ .transform(
+ response => response.errors.map(_.message).mkString(", "),
+ ex => new DomainException("Response has invalid format", ex)
+ )
+ }
+
+ if (response.status.isSuccess) {
+ Unmarshal(response.entity).to[ApiReply]
+ } else {
+ extractErrorMessage(response).flatMap { message =>
+ Future.failed(response.status match {
+ case StatusCodes.Unauthorized => new AuthenticationException(message)
+ case StatusCodes.Forbidden => new AuthorizationException(message)
+ case StatusCodes.NotFound => new NotFoundException(message)
+ case other =>
+ new DomainException(s"Unhandled domain error for HTTP status ${other.value}. ${message}")
+ })
+ }
+ }
+ }
+
+ implicit def toServiceRequestContext(requestContext: AnonymousRequestContext): ServiceRequestContext = {
+ val auth: Map[String, String] = requestContext match {
+ case ctx: AuthenticatedRequestContext => Map("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..37b28ae
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHypothesisService.scala
@@ -0,0 +1,33 @@
+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._
+
+ def getAll(sorting: Option[Sorting] = None)(
+ implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = {
+ val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/hypothesis", sortingQuery(sorting)))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ListResponse[ApiHypothesis]](response)
+ } yield {
+ GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount)
+ }
+ }
+
+}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala
new file mode 100644
index 0000000..aa59657
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionService.scala
@@ -0,0 +1,64 @@
+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.{Pagination => _, _}
+import xyz.driver.pdsuicommon.auth._
+import xyz.driver.pdsuicommon.db._
+import xyz.driver.pdsuicommon.domain._
+import xyz.driver.pdsuidomain.entities._
+import xyz.driver.pdsuidomain.formats.json.ListResponse
+import xyz.driver.pdsuidomain.formats.json.intervention.ApiIntervention
+import xyz.driver.pdsuidomain.services.InterventionService
+
+class RestInterventionService(transport: ServiceTransport, baseUri: Uri)(
+ implicit protected val materializer: ActorMaterializer,
+ protected val exec: ExecutionContext)
+ extends InterventionService with RestHelper {
+
+ import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._
+ import xyz.driver.pdsuidomain.services.InterventionService._
+
+ def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty,
+ sorting: Option[Sorting] = None,
+ pagination: Option[Pagination] = None)(
+ implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = {
+ val request = HttpRequest(HttpMethods.GET,
+ endpointUri(baseUri,
+ "/v1/intervention",
+ filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination)))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ListResponse[ApiIntervention]](response)
+ } yield {
+ GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount)
+ }
+ }
+
+ def getById(id: LongId[Intervention])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = {
+ val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/intervention/$id"))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiIntervention](response)
+ } yield {
+ GetByIdReply.Entity(reply.toDomain)
+ }
+ }
+
+ def update(origIntervention: InterventionWithArms, draftIntervention: InterventionWithArms)(
+ implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = {
+ val id = origIntervention.intervention.id
+ for {
+ entity <- Marshal(ApiIntervention.fromDomain(draftIntervention)).to[RequestEntity]
+ request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/intervention/$id")).withEntity(entity)
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiIntervention](response)
+ } yield {
+ UpdateReply.Updated(reply.toDomain)
+ }
+ }
+
+}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala
new file mode 100644
index 0000000..fad2841
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestInterventionTypeService.scala
@@ -0,0 +1,36 @@
+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.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] = {
+ val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/intervention-type", sortingQuery(sorting)))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ListResponse[ApiInterventionType]](response)
+ } yield {
+ {
+ val domain = reply.items.map(_.toDomain)
+ GetListReply.EntityList(domain.toList, reply.meta.itemsCount)
+ }
+ }
+ }
+
+}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala
new file mode 100644
index 0000000..1527ad5
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestMessageService.scala
@@ -0,0 +1,88 @@
+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.{Pagination => _, _}
+import xyz.driver.pdsuicommon.auth._
+import xyz.driver.pdsuicommon.db._
+import xyz.driver.pdsuicommon.domain._
+import xyz.driver.pdsuidomain.entities._
+import xyz.driver.pdsuidomain.formats.json.ListResponse
+import xyz.driver.pdsuidomain.formats.json.message.ApiMessage
+import xyz.driver.pdsuidomain.services.MessageService
+
+class RestMessageService(transport: ServiceTransport, baseUri: Uri)(
+ implicit protected val materializer: ActorMaterializer,
+ protected val exec: ExecutionContext)
+ extends MessageService with RestHelper {
+
+ import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._
+ import xyz.driver.pdsuidomain.services.MessageService._
+
+ def create(draftMessage: Message)(implicit requestContext: AuthenticatedRequestContext): Future[CreateReply] = {
+ for {
+ entity <- Marshal(ApiMessage.fromDomain(draftMessage)).to[RequestEntity]
+ request = HttpRequest(HttpMethods.POST, endpointUri(baseUri, "/v1/message")).withEntity(entity)
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiMessage](response)
+ } yield {
+ CreateReply.Created(reply.toDomain)
+ }
+ }
+
+ def getById(messageId: LongId[Message])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = {
+ import xyz.driver.pdsuicommon.db.SearchFilterBinaryOperation._
+ import xyz.driver.pdsuicommon.db.SearchFilterExpr._
+ val filter = Atom.Binary("id", Eq, messageId)
+ getAll(filter).map({
+ case GetListReply.EntityList(messages, _, _) if messages.isEmpty =>
+ GetByIdReply.NotFoundError
+ case GetListReply.EntityList(messages, _, _) =>
+ GetByIdReply.Entity(messages.head)
+ case GetListReply.AuthorizationError =>
+ GetByIdReply.AuthorizationError
+ })
+ }
+
+ def getAll(filter: SearchFilterExpr = SearchFilterExpr.Empty,
+ sorting: Option[Sorting] = None,
+ pagination: Option[Pagination] = None)(
+ implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = {
+ val request = HttpRequest(
+ HttpMethods.GET,
+ endpointUri(baseUri, "/v1/message", filterQuery(filter) ++ sortingQuery(sorting) ++ paginationQuery(pagination)))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ListResponse[ApiMessage]](response)
+ } yield {
+ GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate)
+ }
+ }
+
+ def update(origMessage: Message, draftMessage: Message)(
+ implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = {
+ for {
+ entity <- Marshal(ApiMessage.fromDomain(draftMessage)).to[RequestEntity]
+ id = origMessage.id.id
+ request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/message/$id")).withEntity(entity)
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiMessage](response)
+ } yield {
+ UpdateReply.Updated(reply.toDomain)
+ }
+ }
+
+ def delete(messageId: LongId[Message])(implicit requestContext: AuthenticatedRequestContext): Future[DeleteReply] = {
+ val request = HttpRequest(HttpMethods.DELETE, endpointUri(baseUri, s"/v1/message/${messageId.id}"))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiMessage](response)
+ } yield {
+ DeleteReply.Deleted
+ }
+ }
+
+}
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..4fba287
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestStudyDesignService.scala
@@ -0,0 +1,33 @@
+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._
+
+ def getAll(sorting: Option[Sorting] = None)(
+ implicit requestContext: AuthenticatedRequestContext): Future[GetListReply] = {
+ val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, "/v1/study-design", sortingQuery(sorting)))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ListResponse[ApiStudyDesign]](response)
+ } yield {
+ GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount)
+ }
+ }
+
+}
diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala
new file mode 100644
index 0000000..e1f9d87
--- /dev/null
+++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestTrialService.scala
@@ -0,0 +1,95 @@
+package xyz.driver.pdsuidomain.services.rest
+
+import scala.NotImplementedError
+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.{Pagination => _, _}
+import xyz.driver.pdsuicommon.auth._
+import xyz.driver.pdsuicommon.db._
+import xyz.driver.pdsuicommon.domain._
+import xyz.driver.pdsuidomain.entities._
+import xyz.driver.pdsuidomain.formats.json.ListResponse
+import xyz.driver.pdsuidomain.formats.json.trial.ApiTrial
+import xyz.driver.pdsuidomain.services.TrialService
+
+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._
+
+ def getById(id: StringId[Trial])(implicit requestContext: AuthenticatedRequestContext): Future[GetByIdReply] = {
+ val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/trial/$id"))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiTrial](response)
+ } yield {
+ GetByIdReply.Entity(reply.toDomain)
+ }
+ }
+
+ def 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]](response)
+ } yield {
+ GetListReply.EntityList(reply.items.map(_.toDomain), reply.meta.itemsCount, reply.meta.lastUpdate)
+ }
+ }
+
+ def update(origTrial: Trial, draftTrial: Trial)(
+ implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = {
+ val id = origTrial.id.id
+ for {
+ entity <- Marshal(ApiTrial.fromDomain(draftTrial)).to[RequestEntity]
+ request = HttpRequest(HttpMethods.PATCH, endpointUri(baseUri, s"/v1/trial/$id")).withEntity(entity)
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiTrial](response)
+ } yield {
+ UpdateReply.Updated(reply.toDomain)
+ }
+ }
+
+ private def singleAction(origTrial: Trial, action: String)(
+ implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] = {
+ val id = origTrial.id.id
+ val request = HttpRequest(HttpMethods.GET, endpointUri(baseUri, s"/v1/trial/$id/$action"))
+ for {
+ response <- transport.sendRequestGetResponse(requestContext)(request)
+ reply <- apiResponse[ApiTrial](response)
+ } yield {
+ UpdateReply.Updated(reply.toDomain)
+ }
+ }
+
+ def start(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] =
+ singleAction(origTrial, "start")
+ def submit(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] =
+ singleAction(origTrial, "submit")
+ def restart(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] =
+ singleAction(origTrial, "restart")
+ def flag(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] =
+ singleAction(origTrial, "flag")
+ def resolve(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] =
+ singleAction(origTrial, "resolve")
+ def archive(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] =
+ singleAction(origTrial, "archive")
+ def unassign(origTrial: Trial)(implicit requestContext: AuthenticatedRequestContext): Future[UpdateReply] =
+ singleAction(origTrial, "unassign")
+
+}