11package com .codacy .client .bitbucket .client
22
3+ import java .net .URI
34import java .util .concurrent .{SynchronousQueue , ThreadPoolExecutor , TimeUnit }
45
56import com .codacy .client .bitbucket .util .HTTPStatusCodes
7+ import com .codacy .client .bitbucket .util .Implicits .URIQueryParam
68import com .ning .http .client .AsyncHttpClientConfig
79import play .api .http .{ContentTypeOf , Writeable }
810import play .api .libs .json ._
@@ -26,7 +28,7 @@ class BitbucketClient(key: String, secretKey: String, token: String, secretToken
2628 */
2729 def execute [T ](request : Request [T ])(implicit reader : Reads [T ]): RequestResponse [T ] = {
2830 get(request.url) match {
29- case Right (json) => json.validate[T ].fold(_ => FailedResponse (s " Failed to parse json: $json" ), a => SuccessfulResponse (a))
31+ case Right (json) => json.validate[T ].fold(e => FailedResponse (s " Failed to parse json ( $e ) : $json" ), a => SuccessfulResponse (a))
3032 case Left (error) => FailedResponse (error.detail)
3133 }
3234 }
@@ -35,16 +37,33 @@ class BitbucketClient(key: String, secretKey: String, token: String, secretToken
3537 * Does a paginated API request and parses the json output into a sequence of classes
3638 */
3739 def executePaginated [T ](request : Request [Seq [T ]])(implicit reader : Reads [T ]): RequestResponse [Seq [T ]] = {
40+ val FIRST_PAGE = 1
41+
42+ def extractValues (json : JsValue ): RequestResponse [Seq [T ]] =
43+ (json \ " values" ).validate[Seq [T ]].fold(e => FailedResponse (s " Failed to parse json ( $e): $json" ), a => SuccessfulResponse (a))
44+
3845 get(request.url) match {
3946 case Right (json) =>
40- val nextPage = (json \ " next" ).asOpt[String ]
41- val nextRepos = nextPage.map {
42- nextUrl =>
43- executePaginated(Request (nextUrl, request.classType))
44- }.getOrElse(SuccessfulResponse (Seq .empty))
45-
46- val values = (json \ " values" ).validate[Seq [T ]].fold(_ => FailedResponse (s " Failed to parse json: $json" ), a => SuccessfulResponse (a))
47- RequestResponse .apply(values, nextRepos)
47+ val nextPages = (for {
48+ size <- (json \ " size" ).asOpt[Double ]
49+ pagelen <- (json \ " pagelen" ).asOpt[Double ]
50+ } yield {
51+ val lastPage = math.ceil(size / pagelen).toInt
52+ (FIRST_PAGE + 1 to lastPage).par.map { page =>
53+ val nextUrl = new URI (request.url).addQuery(s " page= $page" ).toString
54+ get(nextUrl) match {
55+ case Right (json) => extractValues(json)
56+ case Left (error) => FailedResponse (error.detail)
57+ }
58+ }.to[Seq ]
59+ }).getOrElse(Seq (SuccessfulResponse (Seq .empty)))
60+
61+ val values = extractValues(json)
62+
63+ (values +: nextPages).foldLeft[RequestResponse [Seq [T ]]](SuccessfulResponse (Seq .empty[T ])) {
64+ (a, b) =>
65+ RequestResponse .apply(a, b)
66+ }
4867
4968 case Left (error) =>
5069 FailedResponse (error.detail)
@@ -153,7 +172,7 @@ class BitbucketClient(key: String, secretKey: String, token: String, secretToken
153172 case Success (jsValue) =>
154173 jsValue
155174 case Failure (e) =>
156- Left (ResponseError (" Failed to parse json" ,e.getStackTrace.mkString(System .lineSeparator),e.getMessage))
175+ Left (ResponseError (" Failed to parse json" , e.getStackTrace.mkString(System .lineSeparator), e.getMessage))
157176 }
158177 }
159178
0 commit comments