Sure,

For each method that returns paginated results, you will need two methods in 
the api: one without parameters that returns the entire list, and the other 
one, with the pagination parameters, that is able to return a single page. In 
jclouds:

* The first one, returning a single page, must return an 
`IterableWithMarker<T>`, which is just an Iterable with a marker that points to 
the next page.
* The second one, the entire list, must return a `PagedIterable<T>`, which is 
an Iterable that has a single page (an `IterableWithMarker<T>`) and knows how 
to get the next page given the next page marker.

Having this in mind, you need to figure out two things:

* How to build the `IterableWithMarker<T>` so it contains a marker with all the 
info required to fetch the next page.
* How to build the `PagedIterable<T>` to automatically fetch pages given a 
marker.

Building the first one should be pretty straightforward. You just need to 
create a class that extends the `IterableWithMarker<T>` abstract class and make 
sure the returned marker has all the info to fetch the next page. In your 
example, the "meta" fields could serve this purpose. Once you have your 
implementation, you just need to create a ResponseParser that builds your class 
given an HttpResponse. That's what the 
[ParseImages](https://github.com/jclouds/jclouds-labs-openstack/blob/master/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/functions/internal/ParseImages.java#L50)
 class in Glance does.

Next thing you have to do, is build a `PagedIterable<T>` given an 
`IterableWithMarker<T>`. Since the APIs always return a single page, in the 
end, the HttpResponses for the "listAll" and "listSinglePage" methods will be 
the same. That's why most "listAll" methods use the same response parser than 
above, and then use a transformation function to transform the resulting 
`IterableWithMarker<T>` into a `PagedIterable<T>` (see the [ImageApi 
annotations](https://github.com/jclouds/jclouds-labs-openstack/blob/master/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageApi.java#L80-L81)).

So, that `ToPagedIterable` is just a function that transforms an 
`IterableWithMarker<T>` into a `PagedIterable<T>`. This can be done in many 
ways, depending on the API. This functions usually build the iterable using the 
helper methods in the 
[PagedIterables](https://github.com/jclouds/jclouds/blob/master/core/src/main/java/org/jclouds/collect/PagedIterables.java)
 class, such as the 
[advance](https://github.com/jclouds/jclouds/blob/master/core/src/main/java/org/jclouds/collect/PagedIterables.java#L69-L76)
 one. If you take a look at that method you'll see that the PagedIterable is 
build given an `IterableWithMarker<T>` and an advancing function. That 
advancing function transforms an `Object` to an `IterablewithMarker<T>` where 
the Object is the current marker to the next page, and the result should be the 
next page. That advancing function will only be invoked if the marker to the 
next page is present.

So, in the end, you just need to create a function to transform an 
`IterableWithMarker<T>` into a `Pagediterable<T>`. How you build it is up to 
you. Here are a few examples you can take a look at, to get the whole idea:

* In Abiquo, for example, each page returns a link to the next one, so there is 
a [generic 
function](https://github.com/nacx/jclouds-labs/blob/198-pagination/abiquo/src/main/java/org/jclouds/abiquo/domain/PaginatedCollection.java#L91-L124)
 that simply performs a GET call to fetch the next page, given the marker (the 
link).
* In Glance, there is the 
[ParseImages#ToPagedIterable](https://github.com/jclouds/jclouds-labs-openstack/blob/master/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/functions/internal/ParseImages.java#L65-L91)
 that extends an existing helper class to build a new API call. The class it 
extends populates the caller arguments to the function, but this might not be 
the best example in your case and could bring confusion.
* There is a helper class that you could also use (and perhaps this is what I'd 
recommend if there is no generic way to do pagination for all API calls). You 
could create a function that extends the existing 
[ArgsToPagedIterable](https://github.com/jclouds/jclouds/blob/master/core/src/main/java/org/jclouds/collect/internal/ArgsToPagedIterable.java#L60).
 That class already has the common logic and you only have to implement its 
abstract method. That method must return a function that returns the next page 
given an `IterableWithMarker<T>`, but also receives as a parameter the list of 
arguments (the arguments of the invoked java method) used in the previous API 
call, which can be useful to build the call to the next page. You can take the 
[ParseImages#ToPagedIterable](https://github.com/jclouds/jclouds-labs-openstack/blob/master/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/functions/internal/ParseImages.java#L65-L91)
 as an example to get the idea, but apply t
 hat to t
 he 
[ArgsToPagedIterable](https://github.com/jclouds/jclouds/blob/master/core/src/main/java/org/jclouds/collect/internal/ArgsToPagedIterable.java)
 class.

Hope this helps!

P.S. If you join the #jclouds IRC channel in Freenode you might get better help 
:)

---
Reply to this email directly or view it on GitHub:
https://github.com/jclouds/jclouds-labs/pull/12#issuecomment-22927296

Reply via email to