daily pastebin goal
59%
SHARE
TWEET

Untitled

a guest Mar 26th, 2019 68 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import _root_.slick.ast.Ordering
  2. import _root_.slick.lifted.{BaseColumnExtensionMethods, ColumnOrdered, Query, Rep}
  3. import cats.data.NonEmptyList
  4. import cats.instances.option._
  5. import cats.syntax.apply._
  6. import cats.syntax.either._
  7.  
  8. object syntax {
  9.  
  10.   implicit class QueryOps[E, U, C[_]](val query: Query[E, U, C]) extends AnyVal {
  11.  
  12.     def applyPagination(paginationRequest: PaginationRequest)(sortingMapping: E => PartialFunction[String, Rep[_]])(
  13.         filteringMapping: E => PartialFunction[Filtering.Filter, FilteringEquality])(
  14.         defaultSortColumnMapping: E => Rep[_])(
  15.         implicit ev: Option[Boolean] => Rep[Option[Boolean]]): Either[PaginationRequestErrorList, Query[E, U, C]] = {
  16.  
  17.       val defaultSorting: Query[E, U, C] = {
  18.         query.sortBy { q =>
  19.           ColumnOrdered(
  20.             defaultSortColumnMapping(q),
  21.             Ordering().copy(direction = Ordering.Asc, nulls = Ordering.NullsFirst)
  22.           )
  23.         }
  24.       }
  25.  
  26.       def applySorting(query: Query[E, U, C])(
  27.           sorting: Sorting): Either[NonEmptyList[PaginationRequestError], Query[E, U, C]] = {
  28.         val (resQuery, sortingErrors) =
  29.           sorting.fields.distinct.reverse.foldLeft((query, List.empty[PaginationRequestError])) {
  30.             case ((q, errors), sf @ Sorting.Field(name, direction)) =>
  31.               Either.catchNonFatal {
  32.                 q.sortBy { e =>
  33.                   ColumnOrdered(
  34.                     sortingMapping(e)(name),
  35.                     direction match {
  36.                       case Sorting.Direction.Asc =>
  37.                         Ordering().copy(direction = Ordering.Asc, nulls = Ordering.NullsFirst)
  38.                       case Sorting.Direction.Desc =>
  39.                         Ordering().copy(direction = Ordering.Desc, nulls = Ordering.NullsLast)
  40.                     }
  41.                   )
  42.                 }
  43.               }.fold(_ => q -> (PaginationRequestError.SortingFieldError(sf) +: errors), res => res -> errors)
  44.           }
  45.  
  46.         sortingErrors match {
  47.           case Nil    => Right(resQuery)
  48.           case h :: t => Left(NonEmptyList(h, t))
  49.         }
  50.       }
  51.  
  52.       def applyFiltering(query: Query[E, U, C])(
  53.           filtering: Filtering): Either[NonEmptyList[PaginationRequestError], Query[E, U, C]] = {
  54.         val (resQuery, filteringErrors) =
  55.           filtering.filters.distinct.foldLeft((query, List.empty[PaginationRequestError])) {
  56.             case ((q, errors), filter) =>
  57.               Either.catchNonFatal {
  58.                 q.filter { e =>
  59.                   filteringMapping(e)(filter) match {
  60.                     case FilteringEquality.BooleanEq(v)          => ev(Some(v))
  61.                     case FilteringEquality.RepBooleanEq(v)       => new BaseColumnExtensionMethods(v).?
  62.                     case FilteringEquality.RepOptionBooleanEq(v) => v
  63.                   }
  64.                 }
  65.               }.fold(_ => q -> (PaginationRequestError.FilterError(filter) +: errors), res => res -> errors)
  66.           }
  67.  
  68.         filteringErrors match {
  69.           case Nil    => Right(resQuery)
  70.           case h :: t => Left(NonEmptyList(h, t).reverse)
  71.         }
  72.       }
  73.  
  74.       for {
  75.         _ <- {
  76.           val nelOpt1 = paginationRequest.sorting.map(applySorting(query)(_)).flatMap(_.left.toOption)
  77.           val nelOpt2 = paginationRequest.filtering.map(applyFiltering(query)(_)).flatMap(_.left.toOption)
  78.  
  79.           (nelOpt1, nelOpt2).mapN { case (nel1, nel2) => nel1 ::: nel2 } match {
  80.             case None    => Right(())
  81.             case Some(x) => Left(PaginationRequestError.ErrorList(x))
  82.           }
  83.         }
  84.         q1 <- paginationRequest.sorting
  85.                .map(applySorting(query)(_).left.map(PaginationRequestError.ErrorList))
  86.                .getOrElse(Right(defaultSorting))
  87.         q2 <- paginationRequest.filtering
  88.                .map(applyFiltering(q1)(_).left.map(PaginationRequestError.ErrorList))
  89.                .getOrElse(Right(q1))
  90.       } yield paginationRequest.pagination.map(p => q2.drop(p.offset).take(p.limit)).getOrElse(q2)
  91.     }
  92.   }
  93. }
  94.  
  95. sealed trait FilteringEquality extends Any
  96.  
  97. object FilteringEquality {
  98.   final case class BooleanEq(value: Boolean) extends AnyVal with FilteringEquality
  99.   object BooleanEq {
  100.     implicit def deriveBooleanEq(value: Boolean): BooleanEq = new BooleanEq(value)
  101.   }
  102.  
  103.   final case class RepBooleanEq(value: Rep[Boolean]) extends AnyVal with FilteringEquality
  104.   object RepBooleanEq {
  105.     implicit def deriveRepBooleanEq(value: Rep[Boolean]): RepBooleanEq = new RepBooleanEq(value)
  106.   }
  107.  
  108.   final case class RepOptionBooleanEq(value: Rep[Option[Boolean]]) extends AnyVal with FilteringEquality
  109.   object RepOptionBooleanEq {
  110.     implicit def deriveRepOptionEq(value: Rep[Option[Boolean]]): RepOptionBooleanEq =
  111.       new RepOptionBooleanEq(value)
  112.   }
  113. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top