aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/pdsuicommon/parsers/PaginationParser.scala
blob: a6a7fae4857f21d9f78f868ddc47c64b368933fa (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
package xyz.driver.server.parsers

import xyz.driver.pdsuicommon.db.Pagination
import xyz.driver.server.parsers.errors.ParseQueryArgException
import play.api.data.validation._
import play.api.routing.sird.QueryString
import xyz.driver.pdsuicommon.validation.AdditionalConstraints

import scala.util.Try

object PaginationParser {

  private val oneQueryArgConstraint: Constraint[Seq[String]] = {
    Constraint("query.oneArg") {
      case Nil      => Valid
      case x +: Nil => Valid
      case xs =>
        Invalid(new ValidationError(Seq(s"must be one argument, but there are multiple: '${xs.mkString(", ")}'")))
    }
  }

  private val pageSizeCheckConstraint: Constraint[Seq[String]] = {
    Constraint("pagination.pageSize") { args =>
      oneQueryArgConstraint(args) match {
        case x: Invalid => x
        case Valid      => AdditionalConstraints.positivePrintedNumber(args.head)
      }
    }
  }

  private val pageNumberCheckConstraint: Constraint[Seq[String]] = {
    Constraint("pagination.pageNumber") { args =>
      oneQueryArgConstraint(args) match {
        case x: Invalid => x
        case Valid      => AdditionalConstraints.positivePrintedNumber(args.head)
      }
    }
  }

  def parse(queryString: QueryString): Try[Pagination] = Try {
    val rawPageSizes   = queryString.getOrElse("pageSize", Seq(Pagination.Default.pageSize.toString))
    val rawPageNumbers = queryString.getOrElse("pageNumber", Seq(Pagination.Default.pageNumber.toString))

    val validation = Seq(
      "pageSize"   -> pageSizeCheckConstraint(rawPageSizes),
      "pageNumber" -> pageNumberCheckConstraint(rawPageNumbers)
    )

    val validationErrors = validation.collect {
      case (fieldName, e: Invalid) => (fieldName, e.errors.mkString("; "))
    }

    if (validationErrors.isEmpty) {
      Pagination(Integer.parseInt(rawPageSizes.head), Integer.parseInt(rawPageNumbers.head))
    } else {
      throw new ParseQueryArgException(validationErrors: _*)
    }
  }

}