aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/pdsuicommon/error/ErrorsResponse.scala
blob: 3761cc5ab99367653a3518523d3ccf2ab540c639 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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)
  }

}