Skip to content

Commit

Permalink
Add iterateAll method to Page, update example and snippet
Browse files Browse the repository at this point in the history
  • Loading branch information
mziccard committed Nov 6, 2015
1 parent 0e32a4b commit 22c655e
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 22 deletions.
22 changes: 19 additions & 3 deletions gcloud-java-core/src/main/java/com/google/gcloud/Page.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,30 @@

package com.google.gcloud;

import java.util.Iterator;

/**
* Interface for Google Cloud paginated results.
*
* <p>
* A typical {@code Page} usage:
* Use {@code Page} to iterate through all values (also in next pages):
* <pre> {@code
* Page<T> page = ...; // get a Page<T> instance
* Iterator<T> iterator = page.iterateAll();
* while (iterator.hasNext()) {
* T value = iterator.next();
* // do something with value
* }}</pre>
* <p>
* Or handle pagination explicitly:
* <pre> {@code
* Page<T> page = ...; // get a Page<T> instance
* while (page != null) {
* for (T value : page.values()) {
* // do something with value
* }
* page = page.nextPage();
* }
* }</pre>
* }}</pre>
*/
public interface Page<T> {

Expand All @@ -38,6 +48,12 @@ public interface Page<T> {
*/
Iterable<T> values();

/**
* Returns an iterator for all values, possibly also in the next pages. Once current page's values
* are traversed the iterator fetches next page, if any.
*/
Iterator<T> iterateAll();

/**
* Returns the cursor for the nextPage or {@code null} if no more results.
*/
Expand Down
51 changes: 51 additions & 0 deletions gcloud-java-core/src/main/java/com/google/gcloud/PageImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import java.io.Serializable;
import java.util.Collections;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;

/**
Expand All @@ -35,6 +37,50 @@ public interface NextPageFetcher<T> extends Serializable {
Page<T> nextPage();
}

static class PageIterator<T> implements java.util.Iterator<T> {

private Iterator<T> currentPageIterator;
private Page<T> currentPage;

PageIterator(Page<T> currentPage) {
this.currentPageIterator = currentPage.values().iterator();
this.currentPage = currentPage;
}

@Override
public boolean hasNext() {
if (currentPageIterator.hasNext()) {
return true;
}
Page<T> nextPage = currentPage.nextPage();
if (nextPage != null) {
currentPage = nextPage;
currentPageIterator = currentPage.values().iterator();
return currentPageIterator.hasNext();
}
return false;
}

@Override
public T next() {
if (currentPageIterator.hasNext()) {
return currentPageIterator.next();
}
Page<T> nextPage = currentPage.nextPage();
if (nextPage != null) {
currentPage = nextPage;
currentPageIterator = currentPage.values().iterator();
return currentPageIterator.next();
}
throw new NoSuchElementException();
}

@Override
public void remove() {
throw new UnsupportedOperationException("Can not call remove on page iterator");
}
}

/**
* Creates a {@code PageImpl} object. In order for the object to be serializable the {@code
* results} parameter must be serializable.
Expand All @@ -50,6 +96,11 @@ public Iterable<T> values() {
return results == null ? Collections.EMPTY_LIST : results;
}

@Override
public Iterator<T> iterateAll() {
return new PageIterator<T>(this);
}

@Override
public String nextPageCursor() {
return cursor;
Expand Down
31 changes: 24 additions & 7 deletions gcloud-java-core/src/test/java/com/google/gcloud/PageImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,38 @@

public class PageImplTest {

private static final ImmutableList<String> VALUES = ImmutableList.of("1", "2");
private static final ImmutableList<String> NEXT_VALUES = ImmutableList.of("3", "4");
private static final ImmutableList<String> ALL_VALUES = ImmutableList.<String>builder()
.addAll(VALUES)
.addAll(NEXT_VALUES)
.build();

@Test
public void testPage() throws Exception {
ImmutableList<String> values = ImmutableList.of("1", "2");
final PageImpl<String> nextResult =
new PageImpl<>(null, "c", Collections.<String>emptyList());
public void testPage() {
final PageImpl<String> nextResult = new PageImpl<>(null, "c", NEXT_VALUES);
PageImpl.NextPageFetcher<String> fetcher = new PageImpl.NextPageFetcher<String>() {

@Override
public PageImpl<String> nextPage() {
return nextResult;
}
};
PageImpl<String> result = new PageImpl<>(fetcher, "c", values);
PageImpl<String> result = new PageImpl<>(fetcher, "c", VALUES);
assertEquals(nextResult, result.nextPage());
assertEquals("c", result.nextPageCursor());
assertEquals(values, ImmutableList.copyOf(result.values().iterator()));
assertEquals(VALUES, result.values());
}

@Test
public void testIterateAll() {
final PageImpl<String> nextResult = new PageImpl<>(null, "c", NEXT_VALUES);
PageImpl.NextPageFetcher<String> fetcher = new PageImpl.NextPageFetcher<String>() {
@Override
public PageImpl<String> nextPage() {
return nextResult;
}
};
PageImpl<String> result = new PageImpl<>(fetcher, "c", VALUES);
assertEquals(ALL_VALUES, ImmutableList.copyOf(result.iterateAll()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -214,12 +215,9 @@ String parse(String... args) {
public void run(Storage storage, String bucketName) {
if (bucketName == null) {
// list buckets
Page<BucketInfo> bucketPage = storage.list();
while (bucketPage != null) {
for (BucketInfo b : bucketPage.values()) {
System.out.println(b);
}
bucketPage = bucketPage.nextPage();
Iterator<BucketInfo> bucketInfoIterator = storage.list().iterateAll();
while (bucketInfoIterator.hasNext()) {
System.out.println(bucketInfoIterator.next());
}
} else {
// list a bucket's blobs
Expand All @@ -228,12 +226,9 @@ public void run(Storage storage, String bucketName) {
System.out.println("No such bucket");
return;
}
Page<Blob> blobPage = bucket.list();
while (blobPage != null) {
for (Blob b : blobPage.values()) {
System.out.println(b.info());
}
blobPage = blobPage.nextPage();
Iterator<Blob> blobIterator = bucket.list().iterateAll();
while (blobIterator.hasNext()) {
System.out.println(blobIterator.next().info());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
Expand Down Expand Up @@ -90,6 +91,11 @@ public Page<BlobInfo> nextPage() {
public Iterable<BlobInfo> values() {
return BLOB_LIST;
}

@Override
public Iterator<BlobInfo> iterateAll() {
return null;
}
};
private static String keyPath = "/does/not/exist/key." + UUID.randomUUID().toString() + ".json";

Expand Down

0 comments on commit 22c655e

Please sign in to comment.