diff --git a/src/main/java/net/dean/jraw/paginators/Paginator.java b/src/main/java/net/dean/jraw/paginators/Paginator.java index 4210908ae..fe142f3a1 100644 --- a/src/main/java/net/dean/jraw/paginators/Paginator.java +++ b/src/main/java/net/dean/jraw/paginators/Paginator.java @@ -8,8 +8,10 @@ import net.dean.jraw.models.Listing; import net.dean.jraw.models.Thing; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; /** @@ -68,8 +70,8 @@ public Paginator(RedditClient creator, Class thingType) { * @param forwards If true, this method will return the next listing. If false, it will return the first listing. * @return A new listing * @throws NetworkException If the request was not successful - * @throws IllegalStateException If a setter method (such as {@link #setLimit(int)} was called after the first listing was - * requested. + * @throws IllegalStateException If a setter method (such as {@link #setLimit(int)} was called after the first + * listing was requested and {@link #reset()} was not called. */ protected Listing getListing(boolean forwards) throws NetworkException, IllegalStateException { if (started && changed) { @@ -118,6 +120,38 @@ protected Listing parseListing(RedditResponse response) { return response.asListing(thingType); } + /** + * Creates a list of listings whose size is less than or equal to the given number of pages. The amount of time this + * method takes to return will grow linearly based on the maximum number of pages, and is therefore doubly important + * this this method be executed on another thread. + * + * @param maxPages The maximum amount of pages to retrieve + * @return A list of listings + * @throws NetworkException + */ + public final List> accumulate(int maxPages) throws NetworkException { + List> listings = new ArrayList<>(); + if (maxPages <= 0) { + throw new IllegalArgumentException("Pages must be greater than 0"); + } + + try { + while (hasNext() && getPageIndex() < maxPages) { + listings.add(next()); + } + } catch (IllegalStateException e) { + // Most likely cause will be a NetworkException because next() throws a NetworkException as a cause of an + // IllegalStateException + if (e.getCause().getClass().equals(NetworkException.class)) { + throw (NetworkException) e.getCause(); + } else { + throw e; + } + } + + return listings; + } + @Override public boolean hasNext() { return (current != null && current.getAfter() != null) || !started; diff --git a/src/main/java/net/dean/jraw/paginators/UserRecordPaginator.java b/src/main/java/net/dean/jraw/paginators/UserRecordPaginator.java index f81cafabe..3ecba70bb 100644 --- a/src/main/java/net/dean/jraw/paginators/UserRecordPaginator.java +++ b/src/main/java/net/dean/jraw/paginators/UserRecordPaginator.java @@ -50,11 +50,21 @@ protected Listing parseListing(RedditResponse response) { } JsonNode data = response.getJson().get("data"); - // A moderator listing only has a 'children' key - String before = where == Where.MODERATORS ? null : data.get("before").asText(); - String after = where == Where.MODERATORS ? null : data.get("after").asText(); - String modhash = where == Where.MODERATORS ? null : data.get("modhash").asText(); - return new FauxListing<>(list.build(), before, after, modhash); + return new FauxListing<>(list.build(), getJsonValue(data, "before"), + getJsonValue(data, "after"), getJsonValue(data, "after")); + } + + private String getJsonValue(JsonNode data, String key) { + if (where == Where.MODERATORS) { + // A moderator listing only has a 'children' key + return null; + } + + JsonNode node = data.get(key); + if (node.isNull()) { + return null; + } + return node.asText(); } @Override diff --git a/src/test/java/net/dean/jraw/test/auth/PaginationTest.java b/src/test/java/net/dean/jraw/test/auth/PaginationTest.java index a8bdb7fa6..07b06b54c 100644 --- a/src/test/java/net/dean/jraw/test/auth/PaginationTest.java +++ b/src/test/java/net/dean/jraw/test/auth/PaginationTest.java @@ -26,7 +26,6 @@ import org.testng.Assert; import org.testng.annotations.Test; -import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; @@ -200,10 +199,7 @@ protected void commonTest(Paginator p) { try { int numPages = 2; // Test that the paginator can retrieve the data - List> pages = new ArrayList<>(); - while (p.hasNext() && p.getPageIndex() < numPages) { - pages.add(p.next()); - } + List> pages = p.accumulate(numPages); for (Listing listing : pages) { // Validate the Listing @@ -216,12 +212,8 @@ protected void commonTest(Paginator p) { JrawUtils.logger().warn("Listing was empty"); } } - } catch (IllegalStateException e) { - if (e.getCause().getClass().equals(NetworkException.class)) { - handle(e.getCause()); - } else { - handle(e); - } + } catch (NetworkException e) { + handle(e); } } }