diff options
Diffstat (limited to 'src/main/scala/xyz/driver/pdsuicommon')
10 files changed, 70 insertions, 208 deletions
diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala index 5574c01..748e76a 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorCode.scala @@ -1,7 +1,6 @@ package xyz.driver.pdsuicommon.error -import play.api.libs.functional.syntax._ -import play.api.libs.json.{Format, Reads, Writes} +import xyz.driver.core.json.EnumJsonFormat @SuppressWarnings(Array("org.wartremover.warts.Enumeration")) object ErrorCode extends Enumeration { @@ -9,9 +8,13 @@ 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) + implicit val jsonFormat = new EnumJsonFormat[ErrorCode]( + "200" -> ErrorCode.Value(200), + "400" -> ErrorCode.Value(400), + "401" -> ErrorCode.Value(401), + "403" -> ErrorCode.Value(403), + "404" -> ErrorCode.Value(404), + "500" -> ErrorCode.Value(500) + ) } diff --git a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala index 3761cc5..540bfbb 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala @@ -1,18 +1,14 @@ package xyz.driver.pdsuicommon.error -import xyz.driver.pdsuicommon.json.Serialization.seqJsonFormat -import ErrorCode.{ErrorCode, Unspecified} +import spray.json._ +import ErrorCode._ 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 +import xyz.driver.pdsuicommon.auth.RequestId final case class ErrorsResponse(errors: Seq[ResponseError], requestId: RequestId) object ErrorsResponse { + import DefaultJsonProtocol._ /** * @param data Any data that can be associated with particular error.Ex.: error field name @@ -25,59 +21,34 @@ object ErrorsResponse { 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 responseErrorJsonFormat: RootJsonFormat[ResponseError] = jsonFormat3(ResponseError.apply) } - 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)) + implicit val errorsResponseJsonFormat: RootJsonFormat[ErrorsResponse] = new RootJsonFormat[ErrorsResponse] { + override def write(obj: ErrorsResponse): JsValue = { + JsObject( + "errors" -> obj.errors.map(_.toJson).toJson, + "requestId" -> obj.requestId.value.toJson + ) + } - // 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 - ) - } + override def read(json: JsValue) = json match { + case JsObject(fields) => + val errors = fields + .get("errors") + .map(_.convertTo[Seq[ResponseError]]) + .getOrElse(deserializationError(s"ErrorsResponse json object does not contain `errors` field: $json")) - // 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 - } + val requestId = fields + .get("requestId") + .map(id => RequestId(id.convertTo[String])) + .getOrElse(deserializationError(s"ErrorsResponse json object does not contain `requestId` field: $json")) - fromString(message, httpStatus) - } - // scalastyle:on null + ErrorsResponse(errors, requestId) - // 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 - ) + case _ => deserializationError(s"Expected json as ErrorsResponse, but got $json") } - - new ErrorsResponse(errors, context.requestId) } } diff --git a/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala b/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala index e9a4132..fd1856b 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/http/Directives.scala @@ -12,7 +12,7 @@ import xyz.driver.pdsuicommon.error.ErrorsResponse.ResponseError import xyz.driver.pdsuicommon.parsers._ import xyz.driver.pdsuicommon.db.{Pagination, Sorting, SearchFilterExpr} import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuicommon.serialization.PlayJsonSupport._ +import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ import xyz.driver.core.rest.AuthProvider import scala.util.control._ @@ -83,9 +83,9 @@ trait Directives { def domainRejectionHandler(req: RequestId): RejectionHandler = { def wrapContent(message: String) = { - import play.api.libs.json._ - val err = ErrorsResponse(Seq(ResponseError(None, message, ErrorCode.Unspecified)), req) - val text = Json.stringify(implicitly[Writes[ErrorsResponse]].writes(err)) + import ErrorsResponse._ + val err: ErrorsResponse = ErrorsResponse(Seq(ResponseError(None, message, ErrorCode.Unspecified)), req) + val text = errorsResponseJsonFormat.write(err).toString() HttpEntity(ContentTypes.`application/json`, text) } RejectionHandler.default.mapRejectionResponse { diff --git a/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala b/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala deleted file mode 100644 index 4ff4034..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/json/JsResultOps.scala +++ /dev/null @@ -1,15 +0,0 @@ -package xyz.driver.pdsuicommon.json - -import play.api.libs.json.JsResult - -import scala.util.{Failure, Success, Try} - -final class JsResultOps[T](val self: JsResult[T]) extends AnyVal { - - def toTry: Try[T] = { - self.fold[Try[T]]( - errors => Failure(new JsonValidationException(errors)), - Success(_) - ) - } -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/json/JsonValidationException.scala b/src/main/scala/xyz/driver/pdsuicommon/json/JsonValidationException.scala deleted file mode 100644 index 21750b4..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/json/JsonValidationException.scala +++ /dev/null @@ -1,5 +0,0 @@ -package xyz.driver.pdsuicommon.json - -import xyz.driver.pdsuicommon.validation.JsonValidationErrors - -class JsonValidationException(val errors: JsonValidationErrors) extends Exception diff --git a/src/main/scala/xyz/driver/pdsuicommon/json/Serialization.scala b/src/main/scala/xyz/driver/pdsuicommon/json/Serialization.scala deleted file mode 100644 index 8231ddb..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/json/Serialization.scala +++ /dev/null @@ -1,46 +0,0 @@ -package xyz.driver.pdsuicommon.json - -import java.net.URI - -import play.api.libs.functional.syntax._ -import play.api.libs.json._ -import xyz.driver.pdsuicommon.domain._ -import xyz.driver.pdsuidomain.entities.CaseId - -object Serialization { - - // @TODO Test and check all items in an array - private def seqJsonReads[T](implicit argFormat: Reads[T]): Reads[Seq[T]] = Reads { - case JsArray(xs) => - JsSuccess(xs.map { x => - argFormat.reads(x).get - }) - case x => JsError(s"Expected JsArray, but got $x") - } - - private def seqJsonWrites[T](implicit argFormat: Writes[T]): Writes[Seq[T]] = Writes { xs => - JsArray(xs.map(argFormat.writes)) - } - - implicit def seqJsonFormat[T](implicit f: Format[T]): Format[Seq[T]] = Format(seqJsonReads[T], seqJsonWrites[T]) - - private val uriJsonReads: Reads[URI] = Reads.StringReads.map(URI.create) - private val uriJsonWrites: Writes[URI] = Writes(uri => JsString(uri.toString)) - implicit val uriJsonFormat: Format[URI] = Format(uriJsonReads, uriJsonWrites) - - private def uuidIdJsonReads[T]: Reads[UuidId[T]] = Reads.uuidReads.map(x => UuidId[T](x)) - private def uuidIdJsonWrites[T]: Writes[UuidId[T]] = Writes.UuidWrites.contramap(_.id) - implicit def uuidIdJsonFormat[T]: Format[UuidId[T]] = Format(uuidIdJsonReads, uuidIdJsonWrites) - - private def longIdJsonReads[T]: Reads[LongId[T]] = Reads.LongReads.map(x => LongId[T](x)) - private def longIdJsonWrites[T]: Writes[LongId[T]] = Writes.LongWrites.contramap(_.id) - implicit def longIdJsonFormat[T]: Format[LongId[T]] = Format(longIdJsonReads, longIdJsonWrites) - - private val emailJsonReads: Reads[Email] = Reads.email.map(Email.apply) - private val emailJsonWrites: Writes[Email] = Writes(email => JsString(email.value)) - implicit val emailJsonFormat: Format[Email] = Format(emailJsonReads, emailJsonWrites) - - private val caseIdJsonReads: Reads[CaseId] = Reads.StringReads.map(CaseId(_)) - private val caseIdJsonWrites: Writes[CaseId] = Writes(caseId => JsString(caseId.id)) - implicit val caseIdJsonFormat: Format[CaseId] = Format(caseIdJsonReads, caseIdJsonWrites) -} diff --git a/src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala b/src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala deleted file mode 100644 index 5158dab..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/serialization/PlayJsonSupport.scala +++ /dev/null @@ -1,34 +0,0 @@ -package xyz.driver.pdsuicommon.serialization - -import akka.http.scaladsl.server.{RejectionError, ValidationRejection} -import akka.http.scaladsl.unmarshalling.Unmarshaller -import play.api.libs.json.{Reads, Writes} -import play.api.libs.json.Json -import akka.http.scaladsl.marshalling.ToEntityMarshaller -import akka.http.scaladsl.unmarshalling.FromEntityUnmarshaller -import akka.http.scaladsl.model.MediaTypes.`application/json` - -trait PlayJsonSupport { - import akka.http.scaladsl.marshalling.Marshaller - - implicit def playJsonUnmarshaller[A: Reads]: FromEntityUnmarshaller[A] = { - val reads = implicitly[Reads[A]] - Unmarshaller.stringUnmarshaller - .forContentTypes(`application/json`) - .map(Json.parse) - .map(reads.reads) - .map(_.recoverTotal { error => - throw RejectionError(ValidationRejection(s"Error reading JSON response as ${reads}.")) - }) - } - - implicit def playJsonMarshaller[A: Writes]: ToEntityMarshaller[A] = { - Marshaller - .stringMarshaller(`application/json`) - .compose(Json.prettyPrint) - .compose(implicitly[Writes[A]].writes) - } - -} - -object PlayJsonSupport extends PlayJsonSupport diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/CustomSwaggerJsonFormats.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/CustomSwaggerJsonFormats.scala index 34c7495..a79071e 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/CustomSwaggerJsonFormats.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/utils/CustomSwaggerJsonFormats.scala @@ -6,16 +6,16 @@ import io.swagger.models.properties.Property import spray.json.JsValue import xyz.driver.pdsuicommon.domain.{LongId, StringId, UuidId} import xyz.driver.pdsuidomain.entities._ -import xyz.driver.pdsuidomain.formats.json.sprayformats.listresponse._ +import xyz.driver.pdsuidomain.formats.json.listresponse._ import xyz.driver.core.swagger.CustomSwaggerJsonConverter._ import xyz.driver.entities.patient.CancerType import xyz.driver.pdsuicommon.concurrent.BridgeUploadQueue import xyz.driver.pdsuidomain.entities.export.patient.ExportPatientWithLabels import xyz.driver.pdsuidomain.entities.export.trial.ExportTrialWithLabels import xyz.driver.pdsuidomain.fakes.entities.common -import xyz.driver.pdsuidomain.formats.json.sprayformats.bridgeuploadqueue._ -import xyz.driver.pdsuidomain.formats.json.sprayformats.record._ -import xyz.driver.pdsuidomain.formats.json.sprayformats.document._ +import xyz.driver.pdsuidomain.formats.json.bridgeuploadqueue._ +import xyz.driver.pdsuidomain.formats.json.record._ +import xyz.driver.pdsuidomain.formats.json.document._ import xyz.driver.pdsuidomain.services.CriterionService.RichCriterion import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData import xyz.driver.pdsuidomain.services.PatientCriterionService.{DraftPatientCriterion, RichPatientCriterion} @@ -83,17 +83,17 @@ object CustomSwaggerJsonFormats { object trialcuration { import xyz.driver.pdsuidomain.fakes.entities.trialcuration._ import xyz.driver.pdsuidomain.fakes.entities.export - import xyz.driver.pdsuidomain.formats.json.sprayformats.export._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.arm._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.slotarm._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.eligibilityarm._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.criterion._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.intervention._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.hypothesis._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.studydesign._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.trial._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.trialhistory._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.trialissue._ + import xyz.driver.pdsuidomain.formats.json.export._ + import xyz.driver.pdsuidomain.formats.json.arm._ + import xyz.driver.pdsuidomain.formats.json.slotarm._ + import xyz.driver.pdsuidomain.formats.json.eligibilityarm._ + import xyz.driver.pdsuidomain.formats.json.criterion._ + import xyz.driver.pdsuidomain.formats.json.intervention._ + import xyz.driver.pdsuidomain.formats.json.hypothesis._ + import xyz.driver.pdsuidomain.formats.json.studydesign._ + import xyz.driver.pdsuidomain.formats.json.trial._ + import xyz.driver.pdsuidomain.formats.json.trialhistory._ + import xyz.driver.pdsuidomain.formats.json.trialissue._ val customTrialCurationProperties = immutable.Map[Class[_], Property]( classOf[Trial.Status] -> stringProperty(), @@ -102,7 +102,7 @@ object CustomSwaggerJsonFormats { ) ++ customCommonProperties val customTrialCurationObjectsExamples = immutable.Map[Class[_], JsValue]( - classOf[Trial] -> trialWriter.write(nextTrial()), + classOf[Trial] -> trialFormat.write(nextTrial()), classOf[Arm] -> armFormat.write(nextArm()), classOf[TrialHistory] -> trialHistoryFormat.write(nextTrialHistory()), classOf[TrialIssue] -> trialIssueWriter.write(nextTrialIssue()), @@ -134,12 +134,12 @@ object CustomSwaggerJsonFormats { object recordprocessing { import xyz.driver.pdsuidomain.fakes.entities.recordprocessing._ import xyz.driver.pdsuidomain.fakes.entities.export - import xyz.driver.pdsuidomain.formats.json.sprayformats.export._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.documentissue._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.documenthistory._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.recordissue._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.recordhistory._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.extracteddata._ + import xyz.driver.pdsuidomain.formats.json.export._ + import xyz.driver.pdsuidomain.formats.json.documentissue._ + import xyz.driver.pdsuidomain.formats.json.documenthistory._ + import xyz.driver.pdsuidomain.formats.json.recordissue._ + import xyz.driver.pdsuidomain.formats.json.recordhistory._ + import xyz.driver.pdsuidomain.formats.json.extracteddata._ val customRecordProcessingProperties = immutable.Map[Class[_], Property]( classOf[MedicalRecord.Status] -> stringProperty(), @@ -176,14 +176,14 @@ object CustomSwaggerJsonFormats { object treatmentmatching { import xyz.driver.pdsuidomain.fakes.entities.treatmentmatching._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patient._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patientcriterion._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patientdefiningcriteria._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patienteligibletrial._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patientlabel._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patienthypothesis._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patienthistory._ - import xyz.driver.pdsuidomain.formats.json.sprayformats.patientissue._ + import xyz.driver.pdsuidomain.formats.json.patient._ + import xyz.driver.pdsuidomain.formats.json.patientcriterion._ + import xyz.driver.pdsuidomain.formats.json.patientdefiningcriteria._ + import xyz.driver.pdsuidomain.formats.json.patienteligibletrial._ + import xyz.driver.pdsuidomain.formats.json.patientlabel._ + import xyz.driver.pdsuidomain.formats.json.patienthypothesis._ + import xyz.driver.pdsuidomain.formats.json.patienthistory._ + import xyz.driver.pdsuidomain.formats.json.patientissue._ val customTreatmentMatchingProperties = immutable.Map[Class[_], Property]( classOf[Patient.Status] -> stringProperty(), @@ -192,7 +192,7 @@ object CustomSwaggerJsonFormats { ) ++ customCommonProperties val customTreatmentMatchingObjectsExamples = immutable.Map[Class[_], JsValue]( - classOf[Patient] -> patientWriter.write(nextPatient()), + classOf[Patient] -> patientFormat.write(nextPatient()), classOf[RichPatientLabel] -> richPatientLabelWriter.write(nextRichPatientLabel()), classOf[PatientLabel] -> patientLabelDefiningCriteriaWriter.write(nextPatientLabel()), classOf[RichPatientCriterion] -> patientCriterionWriter.write(nextRichPatientCriterion()), diff --git a/src/main/scala/xyz/driver/pdsuicommon/utils/Implicits.scala b/src/main/scala/xyz/driver/pdsuicommon/utils/Implicits.scala index 9411beb..0b18093 100644 --- a/src/main/scala/xyz/driver/pdsuicommon/utils/Implicits.scala +++ b/src/main/scala/xyz/driver/pdsuicommon/utils/Implicits.scala @@ -1,8 +1,5 @@ package xyz.driver.pdsuicommon.utils -import play.api.libs.json.JsResult -import xyz.driver.pdsuicommon.json.JsResultOps - import scala.collection.generic.CanBuildFrom object Implicits { @@ -23,7 +20,6 @@ object Implicits { implicit def toMapOps[K, V](x: Map[K, V]): MapOps[K, V] = new MapOps(x) - implicit def toCharOps(self: Char): CharOps = new CharOps(self) - implicit def toStringOps(self: String): StringOps = new StringOps(self) - implicit def toJsResultOps[T](self: JsResult[T]): JsResultOps[T] = new JsResultOps(self) + implicit def toCharOps(self: Char): CharOps = new CharOps(self) + implicit def toStringOps(self: String): StringOps = new StringOps(self) } diff --git a/src/main/scala/xyz/driver/pdsuicommon/validation/package.scala b/src/main/scala/xyz/driver/pdsuicommon/validation/package.scala deleted file mode 100644 index 9a31a93..0000000 --- a/src/main/scala/xyz/driver/pdsuicommon/validation/package.scala +++ /dev/null @@ -1,8 +0,0 @@ -package xyz.driver.pdsuicommon - -import play.api.data.validation.{ValidationError => PlayValidationError} -import play.api.libs.json.JsPath - -package object validation { - type JsonValidationErrors = Seq[(JsPath, Seq[PlayValidationError])] -} |