aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKseniya Tomskikh <ktomskih@datamonsters.co>2018-03-01 18:24:01 +0700
committerKseniya Tomskikh <ktomskih@datamonsters.co>2018-03-01 18:24:01 +0700
commit1ecaf78e466aa6df37379d5202c3f907aefd3775 (patch)
tree8cbd19c8a641ad0d8dd368059440abf9a998a1d0
parentab589175d1f0fd9d8f54cf3067e8eeef44a1bea8 (diff)
downloaddriver-core-1ecaf78e466aa6df37379d5202c3f907aefd3775.tar.gz
driver-core-1ecaf78e466aa6df37379d5202c3f907aefd3775.tar.bz2
driver-core-1ecaf78e466aa6df37379d5202c3f907aefd3775.zip
TRIAL-287 Created ListResponse class and directive for pagination parsing
-rw-r--r--src/main/scala/xyz/driver/core/rest/package.scala44
1 files changed, 42 insertions, 2 deletions
diff --git a/src/main/scala/xyz/driver/core/rest/package.scala b/src/main/scala/xyz/driver/core/rest/package.scala
index 5fd9417..78d04f4 100644
--- a/src/main/scala/xyz/driver/core/rest/package.scala
+++ b/src/main/scala/xyz/driver/core/rest/package.scala
@@ -14,7 +14,7 @@ import akka.util.ByteString
import xyz.driver.tracing.TracingDirectives
import scala.concurrent.Future
-import scala.util.Try
+import scala.util.{Failure, Success, Try}
import scalaz.{Functor, OptionT}
import scalaz.Scalaz.{intInstance, stringInstance}
import scalaz.syntax.equal._
@@ -36,10 +36,39 @@ trait ServiceTransport {
object Pagination {
val Default = Pagination(pageSize = 100, pageNumber = 1)
+
+ def parse(query: Seq[(String, String)]): Try[Pagination] = {
+ val IntString = """(\d+)""".r
+ def validate(field: String, default: Int) = query.collectFirst { case (`field`, size) => size } match {
+ case Some(IntString(x)) if x.toInt > 0 => x.toInt
+ case Some(IntString(x)) => throw new Exception(s"$field must greater than zero (found $x)")
+ case Some(str) => throw new Exception(s"$field must be an integer (found $str)")
+ case None => default
+ }
+
+ Try {
+ Pagination(
+ validate("pageSize", Pagination.Default.pageSize),
+ validate("pageNumber", Pagination.Default.pageNumber))
+ }
+ }
}
final case class Pagination(pageSize: Int, pageNumber: Int) {
- def offset: Int = pageSize * pageNumber
+ def offset: Int = pageSize * (pageNumber - 1)
+}
+
+final case class ListResponse[+T](items: Seq[T], meta: ListResponse.Meta)
+
+object ListResponse {
+
+ final case class Meta(itemsCount: Int, pageNumber: Int, pageSize: Int)
+
+ object Meta {
+ def apply(itemsCount: Int, pagination: Pagination): Meta =
+ Meta(itemsCount, pagination.pageNumber, pagination.pageSize)
+ }
+
}
object `package` {
@@ -204,4 +233,15 @@ object `package` {
val sanitizeRequestEntity: Directive0 = {
mapRequest(request => request.mapEntity(entity => entity.transformDataBytes(Flow.fromFunction(escapeScriptTags))))
}
+
+ val paginated: Directive1[Pagination] = parameterSeq.flatMap { params =>
+ Pagination.parse(params) match {
+ case Success(pagination) => provide(pagination)
+ case Failure(ex) =>
+ reject(ValidationRejection("invalid pagination parameter", Some(ex)))
+ }
+ }
+
+ def paginationQuery(pagination: Pagination) =
+ Seq("pageNumber" -> pagination.pageNumber.toString, "pageSize" -> pagination.pageSize.toString)
}