1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2020 Make.org
4  *
5  * This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  *
18  */
19 
20 package org.make.core.technical
21 
22 import scala.util.Try
23 import eu.timepit.refined.refineV
24 import eu.timepit.refined.numeric.NonNegative
25 import eu.timepit.refined.api.Refined
26 import eu.timepit.refined.auto._
27 import io.circe.Decoder
28 
29 trait Pagination {
30 
31   val value: Int Refined NonNegative
32 
33   def extractInt: Int = value
34 }
35 
36 object Pagination {
37 
38   final case class Offset(value: Int Refined NonNegative) extends Pagination
39 
40   private val RefinedZero: Int Refined NonNegative = 0
41 
42   private def nonNegativeOrZero(number: Int): Int Refined NonNegative =
43     refineV[NonNegative](number).getOrElse(RefinedZero)
44 
45   object Offset {
46 
47     def zero: Offset = new Offset(RefinedZero)
48 
49     def apply(offset: Int): Offset =
50       new Offset(nonNegativeOrZero(offset))
51   }
52 
53   final case class End(value: Int Refined NonNegative) extends Pagination {
54 
55     def toLimit(offset: Offset): Limit =
56       new Limit(nonNegativeOrZero(value - offset.value))
57   }
58 
59   object End {
60 
61     def apply(end: Int): End =
62       new End(nonNegativeOrZero(end))
63   }
64 
65   final case class Limit(value: Int Refined NonNegative) extends Pagination {
66 
67     def toEnd(offset: Offset): End =
68       End(value + offset.value)
69   }
70 
71   object Limit {
72 
73     def apply(limit: Int): Limit =
74       new Limit(nonNegativeOrZero(limit))
75   }
76 
77   implicit class RichOptionOffset(val self: Option[Offset]) extends AnyVal {
78     def orZero: Offset = self.getOrElse(Offset.zero)
79   }
80 
81   private val nonNegativeDecoder: Decoder[Int Refined NonNegative] =
82     Decoder.decodeString
83       .emapTry(str => Try(str.toInt))
84       .emap(refineV[NonNegative](_))
85 
86   implicit val offsetDecoder: Decoder[Offset] =
87     nonNegativeDecoder.map(Offset(_))
88 
89   implicit val limitDecoder: Decoder[Limit] =
90     nonNegativeDecoder.map(Limit(_))
91 }
Line Stmt Id Pos Tree Symbol Tests Code
33 2685 1058 - 1063 Select org.make.core.technical.Pagination.value org.scalatest.testsuite,org.make.api.proposal.proposalservicetest,org.make.core.proposal.searchquerytest Pagination.this.value
33 432 1058 - 1058 Select eu.timepit.refined.api.RefType.refinedRefType org.scalatest.testsuite,org.make.api.proposal.proposalservicetest,org.make.core.proposal.searchquerytest api.this.RefType.refinedRefType
33 3945 1058 - 1063 ApplyToImplicitArgs eu.timepit.refined.auto.autoUnwrap org.scalatest.testsuite,org.make.api.proposal.proposalservicetest,org.make.core.proposal.searchquerytest eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](Pagination.this.value)(api.this.RefType.refinedRefType)
43 4336 1318 - 1318 Select scala.math.Numeric.IntIsIntegral org.make.api.operation.operationofquestionservicetest,org.scalatest.testsuite,org.make.core.proposal.searchquerytest math.this.Numeric.IntIsIntegral
43 2966 1318 - 1318 Select shapeless.Witness.witness0 org.make.api.operation.operationofquestionservicetest,org.scalatest.testsuite,org.make.core.proposal.searchquerytest shapeless.this.Witness.witness0
43 1049 1318 - 1318 Select shapeless.ops.nat.ToInt.toInt0 org.make.api.operation.operationofquestionservicetest,org.scalatest.testsuite,org.make.core.proposal.searchquerytest nat.this.ToInt.toInt0
43 3954 1298 - 1349 Apply scala.util.Either.getOrElse org.make.api.operation.operationofquestionservicetest,org.scalatest.testsuite,org.make.core.proposal.searchquerytest eu.timepit.refined.`package`.refineV[eu.timepit.refined.numeric.NonNegative].apply[Int](number)(boolean.this.Not.notValidate[Int, eu.timepit.refined.numeric.Negative, this.R](numeric.this.Less.lessValidate[Int, shapeless.nat._0](internal.this.WitnessAs.natWitnessAs[Int, shapeless.nat._0](shapeless.this.Witness.witness0, nat.this.ToInt.toInt0, math.this.Numeric.IntIsIntegral), math.this.Numeric.IntIsIntegral))).getOrElse[eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.NonNegative]](Pagination.this.RefinedZero)
43 2698 1318 - 1318 ApplyToImplicitArgs eu.timepit.refined.boolean.Not.notValidate org.make.api.operation.operationofquestionservicetest,org.scalatest.testsuite,org.make.core.proposal.searchquerytest boolean.this.Not.notValidate[Int, eu.timepit.refined.numeric.Negative, this.R](numeric.this.Less.lessValidate[Int, shapeless.nat._0](internal.this.WitnessAs.natWitnessAs[Int, shapeless.nat._0](shapeless.this.Witness.witness0, nat.this.ToInt.toInt0, math.this.Numeric.IntIsIntegral), math.this.Numeric.IntIsIntegral))
43 4468 1318 - 1318 ApplyToImplicitArgs eu.timepit.refined.numeric.Less.lessValidate org.make.api.operation.operationofquestionservicetest,org.scalatest.testsuite,org.make.core.proposal.searchquerytest numeric.this.Less.lessValidate[Int, shapeless.nat._0](internal.this.WitnessAs.natWitnessAs[Int, shapeless.nat._0](shapeless.this.Witness.witness0, nat.this.ToInt.toInt0, math.this.Numeric.IntIsIntegral), math.this.Numeric.IntIsIntegral)
43 553 1337 - 1348 Select org.make.core.technical.Pagination.RefinedZero Pagination.this.RefinedZero
43 5631 1318 - 1318 Select scala.math.Numeric.IntIsIntegral org.make.api.operation.operationofquestionservicetest,org.scalatest.testsuite,org.make.core.proposal.searchquerytest math.this.Numeric.IntIsIntegral
43 2285 1318 - 1318 ApplyToImplicitArgs eu.timepit.refined.internal.WitnessAs.natWitnessAs org.make.api.operation.operationofquestionservicetest,org.scalatest.testsuite,org.make.core.proposal.searchquerytest internal.this.WitnessAs.natWitnessAs[Int, shapeless.nat._0](shapeless.this.Witness.witness0, nat.this.ToInt.toInt0, math.this.Numeric.IntIsIntegral)
47 2975 1404 - 1415 Select org.make.core.technical.Pagination.RefinedZero org.make.api.feature.activefeatureservicetest,org.make.api.user.adminuserapitest Pagination.this.RefinedZero
47 851 1393 - 1416 Apply org.make.core.technical.Pagination.Offset.<init> org.make.api.feature.activefeatureservicetest,org.make.api.user.adminuserapitest new Pagination.this.Offset(Pagination.this.RefinedZero)
50 2298 1461 - 1498 Apply org.make.core.technical.Pagination.Offset.<init> org.make.api.operation.operationofquestionservicetest,org.scalatest.testsuite,org.make.core.proposal.searchquerytest new Pagination.this.Offset(Pagination.this.nonNegativeOrZero(offset))
50 4019 1472 - 1497 Apply org.make.core.technical.Pagination.nonNegativeOrZero org.make.api.operation.operationofquestionservicetest,org.scalatest.testsuite,org.make.core.proposal.searchquerytest Pagination.this.nonNegativeOrZero(offset)
56 2488 1664 - 1676 Select org.make.core.technical.Pagination.Offset.value offset.value
56 3962 1664 - 1676 ApplyToImplicitArgs eu.timepit.refined.auto.autoUnwrap eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](offset.value)(api.this.RefType.refinedRefType)
56 4479 1656 - 1656 Select eu.timepit.refined.api.RefType.refinedRefType api.this.RefType.refinedRefType
56 1853 1656 - 1676 Apply scala.Int.- eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](End.this.value)(api.this.RefType.refinedRefType).-(eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](offset.value)(api.this.RefType.refinedRefType))
56 561 1671 - 1671 Select eu.timepit.refined.api.RefType.refinedRefType api.this.RefType.refinedRefType
56 4319 1628 - 1678 Apply org.make.core.technical.Pagination.Limit.<init> new Pagination.this.Limit(Pagination.this.nonNegativeOrZero(eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](End.this.value)(api.this.RefType.refinedRefType).-(eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](offset.value)(api.this.RefType.refinedRefType))))
56 5589 1656 - 1661 Select org.make.core.technical.Pagination.End.value End.this.value
56 861 1638 - 1677 Apply org.make.core.technical.Pagination.nonNegativeOrZero Pagination.this.nonNegativeOrZero(eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](End.this.value)(api.this.RefType.refinedRefType).-(eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](offset.value)(api.this.RefType.refinedRefType)))
62 2227 1745 - 1767 Apply org.make.core.technical.Pagination.nonNegativeOrZero org.make.api.operation.operationofquestionservicetest Pagination.this.nonNegativeOrZero(end)
62 5596 1737 - 1768 Apply org.make.core.technical.Pagination.End.<init> org.make.api.operation.operationofquestionservicetest new Pagination.this.End(Pagination.this.nonNegativeOrZero(end))
68 1865 1908 - 1920 ApplyToImplicitArgs eu.timepit.refined.auto.autoUnwrap eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](offset.value)(api.this.RefType.refinedRefType)
68 4332 1896 - 1921 Apply org.make.core.technical.Pagination.End.apply Pagination.this.End.apply(eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](Limit.this.value)(api.this.RefType.refinedRefType).+(eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](offset.value)(api.this.RefType.refinedRefType)))
68 3901 1915 - 1915 Select eu.timepit.refined.api.RefType.refinedRefType api.this.RefType.refinedRefType
68 4406 1900 - 1905 Select org.make.core.technical.Pagination.Limit.value Limit.this.value
68 428 1908 - 1920 Select org.make.core.technical.Pagination.Offset.value offset.value
68 2494 1900 - 1900 Select eu.timepit.refined.api.RefType.refinedRefType api.this.RefType.refinedRefType
68 789 1900 - 1920 Apply scala.Int.+ eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](Limit.this.value)(api.this.RefType.refinedRefType).+(eu.timepit.refined.auto.autoUnwrap[eu.timepit.refined.api.Refined, Int, eu.timepit.refined.numeric.NonNegative](offset.value)(api.this.RefType.refinedRefType))
74 5387 1986 - 2021 Apply org.make.core.technical.Pagination.Limit.<init> org.make.api.operation.operationofquestionservicetest,org.scalatest.testsuite,org.make.api.proposal.defaultadminproposalapicomponenttest,org.make.core.proposal.searchquerytest new Pagination.this.Limit(Pagination.this.nonNegativeOrZero(limit))
74 2082 1996 - 2020 Apply org.make.core.technical.Pagination.nonNegativeOrZero org.make.api.operation.operationofquestionservicetest,org.scalatest.testsuite,org.make.api.proposal.defaultadminproposalapicomponenttest,org.make.core.proposal.searchquerytest Pagination.this.nonNegativeOrZero(limit)
78 2610 2129 - 2156 Apply scala.Option.getOrElse RichOptionOffset.this.self.getOrElse[org.make.core.technical.Pagination.Offset](Pagination.this.Offset.zero)
78 3514 2144 - 2155 Select org.make.core.technical.Pagination.Offset.zero Pagination.this.Offset.zero
83 711 2282 - 2291 Select scala.collection.StringOps.toInt scala.Predef.augmentString(str).toInt
83 3738 2278 - 2292 Apply scala.util.Try.apply scala.util.Try.apply[Int](scala.Predef.augmentString(str).toInt)
84 2622 2326 - 2326 ApplyToImplicitArgs eu.timepit.refined.boolean.Not.notValidate boolean.this.Not.notValidate[Int, eu.timepit.refined.numeric.Negative, this.R](numeric.this.Less.lessValidate[Int, shapeless.nat._0](internal.this.WitnessAs.natWitnessAs[Int, shapeless.nat._0](shapeless.this.Witness.witness0, nat.this.ToInt.toInt0, math.this.Numeric.IntIsIntegral), math.this.Numeric.IntIsIntegral))
84 3444 2326 - 2326 ApplyToImplicitArgs eu.timepit.refined.numeric.Less.lessValidate numeric.this.Less.lessValidate[Int, shapeless.nat._0](internal.this.WitnessAs.natWitnessAs[Int, shapeless.nat._0](shapeless.this.Witness.witness0, nat.this.ToInt.toInt0, math.this.Numeric.IntIsIntegral), math.this.Numeric.IntIsIntegral)
84 4341 2326 - 2326 Select scala.math.Numeric.IntIsIntegral math.this.Numeric.IntIsIntegral
84 800 2326 - 2326 Select shapeless.ops.nat.ToInt.toInt0 nat.this.ToInt.toInt0
84 716 2306 - 2329 ApplyToImplicitArgs eu.timepit.refined.internal.RefinePartiallyApplied.apply eu.timepit.refined.`package`.refineV[eu.timepit.refined.numeric.NonNegative].apply[Int](x$1)(boolean.this.Not.notValidate[Int, eu.timepit.refined.numeric.Negative, this.R](numeric.this.Less.lessValidate[Int, shapeless.nat._0](internal.this.WitnessAs.natWitnessAs[Int, shapeless.nat._0](shapeless.this.Witness.witness0, nat.this.ToInt.toInt0, math.this.Numeric.IntIsIntegral), math.this.Numeric.IntIsIntegral)))
84 5584 2326 - 2326 Select scala.math.Numeric.IntIsIntegral math.this.Numeric.IntIsIntegral
84 3891 2235 - 2330 Apply io.circe.Decoder.emap org.scalatest.testsuite,org.make.api.feature.activefeatureservicetest,org.make.api.user.adminuserapitest,org.make.core.proposal.searchquerytest io.circe.Decoder.decodeString.emapTry[Int](((str: String) => scala.util.Try.apply[Int](scala.Predef.augmentString(str).toInt))).emap[eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.NonNegative]](((x$1: Int) => eu.timepit.refined.`package`.refineV[eu.timepit.refined.numeric.NonNegative].apply[Int](x$1)(boolean.this.Not.notValidate[Int, eu.timepit.refined.numeric.Negative, this.R](numeric.this.Less.lessValidate[Int, shapeless.nat._0](internal.this.WitnessAs.natWitnessAs[Int, shapeless.nat._0](shapeless.this.Witness.witness0, nat.this.ToInt.toInt0, math.this.Numeric.IntIsIntegral), math.this.Numeric.IntIsIntegral)))))
84 1792 2326 - 2326 Select shapeless.Witness.witness0 shapeless.this.Witness.witness0
84 2360 2326 - 2326 ApplyToImplicitArgs eu.timepit.refined.internal.WitnessAs.natWitnessAs internal.this.WitnessAs.natWitnessAs[Int, shapeless.nat._0](shapeless.this.Witness.witness0, nat.this.ToInt.toInt0, math.this.Numeric.IntIsIntegral)
87 810 2384 - 2417 Apply io.circe.Decoder.map org.scalatest.testsuite,org.make.api.feature.activefeatureservicetest,org.make.api.user.adminuserapitest,org.make.core.proposal.searchquerytest Pagination.this.nonNegativeDecoder.map[org.make.core.technical.Pagination.Offset](((x$2: eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.NonNegative]) => Pagination.this.Offset.apply(x$2)))
87 1975 2407 - 2416 Apply org.make.core.technical.Pagination.Offset.apply Pagination.this.Offset.apply(x$2)
90 4269 2492 - 2500 Apply org.make.core.technical.Pagination.Limit.apply Pagination.this.Limit.apply(x$3)
90 2040 2469 - 2501 Apply io.circe.Decoder.map org.scalatest.testsuite,org.make.api.feature.activefeatureservicetest,org.make.api.user.adminuserapitest,org.make.core.proposal.searchquerytest Pagination.this.nonNegativeDecoder.map[org.make.core.technical.Pagination.Limit](((x$3: eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.NonNegative]) => Pagination.this.Limit.apply(x$3)))