Skip to content

Commit

Permalink
Remove implements Serializable from BasePage and implements Iterable …
Browse files Browse the repository at this point in the history
…from Page

- Add values() method to page, to return results
- Add javadoc to BasePage to highlight that Iterable<T> must be serializable
- Delete BlobPage and BlobPageTest classes
- Add BlobPageFetcher and LazyBlobIterable to Bucket class
- Implement Bucket.list using BasePage, BlobPageFetcher and LazyBlobIterable
- Update StorageExaple to iterate through pages
  • Loading branch information
mziccard committed Nov 4, 2015
1 parent ea36a9e commit 0511989
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 209 deletions.
21 changes: 12 additions & 9 deletions gcloud-java-core/src/main/java/com/google/gcloud/BasePage.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,38 @@

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

/**
* Base implementation for Google Cloud paginated results.
*/
public class BasePage<T extends Serializable> implements Page<T>, Serializable {
public class BasePage<T> implements Page<T>, Serializable {

private static final long serialVersionUID = -6937287874908527950L;
private static final long serialVersionUID = 3914827379823557934L;

private final String cursor;
private final Iterable<T> results;
private final NextPageFetcher<T> pageFetcher;

public interface NextPageFetcher<T extends Serializable> extends Serializable {
public interface NextPageFetcher<T> extends Serializable {
Page<T> nextPage();
}

/**
* Creates a {@code BasePage} object. In order for the object to be serializable the {@code
* result} parameter must be serializable.
*/
public BasePage(NextPageFetcher<T> pageFetcher, String cursor, Iterable<T> results) {
this.pageFetcher = pageFetcher;
this.cursor = cursor;
this.results = results;
}

@Override
public Iterable<T> values() {
return results == null ? Collections.EMPTY_LIST : results;
}

@Override
public String nextPageCursor() {
return cursor;
Expand All @@ -55,11 +63,6 @@ public Page<T> nextPage() {
return pageFetcher.nextPage();
}

@Override
public Iterator<T> iterator() {
return results == null ? Collections.<T>emptyIterator() : results.iterator();
}

@Override
public int hashCode() {
return Objects.hash(cursor, results);
Expand Down
19 changes: 18 additions & 1 deletion gcloud-java-core/src/main/java/com/google/gcloud/Page.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,25 @@

/**
* Interface for Google Cloud paginated results.
*
* <p>
* A typical {@code Page} usage:
* <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>
*/
public interface Page<T> extends Iterable<T> {
public interface Page<T> {

/**
* Returns the values contained in this page.
*/
Iterable<T> values();

/**
* Returns the cursor for the nextPage or {@code null} if no more results.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import static org.junit.Assert.assertEquals;

import com.google.common.collect.ImmutableList;
import com.google.gcloud.BasePage;

import org.junit.Test;

Expand All @@ -42,7 +41,6 @@ public BasePage<String> nextPage() {
BasePage<String> result = new BasePage<>(fetcher, "c", values);
assertEquals(nextResult, result.nextPage());
assertEquals("c", result.nextPageCursor());
assertEquals(values, ImmutableList.copyOf(result.iterator()));

assertEquals(values, ImmutableList.copyOf(result.values().iterator()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.google.gcloud.AuthCredentials;
import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials;
import com.google.gcloud.Page;
import com.google.gcloud.RetryParams;
import com.google.gcloud.spi.StorageRpc.Tuple;
import com.google.gcloud.storage.Blob;
Expand Down Expand Up @@ -213,8 +214,12 @@ String parse(String... args) {
public void run(Storage storage, String bucketName) {
if (bucketName == null) {
// list buckets
for (BucketInfo b : storage.list()) {
System.out.println(b);
Page<BucketInfo> bucketPage = storage.list();
while (bucketPage != null) {
for (BucketInfo b : bucketPage.values()) {
System.out.println(b);
}
bucketPage = bucketPage.nextPage();
}
} else {
// list a bucket's blobs
Expand All @@ -223,8 +228,12 @@ public void run(Storage storage, String bucketName) {
System.out.println("No such bucket");
return;
}
for (Blob b : bucket.list()) {
System.out.println(b.info());
Page<Blob> blobPage = bucket.list();
while (blobPage != null) {
for (Blob b : blobPage.values()) {
System.out.println(b.info());
}
blobPage = blobPage.nextPage();
}
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,24 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Iterators;
import com.google.gcloud.BasePage;
import com.google.gcloud.Page;
import com.google.gcloud.storage.Storage.BlobSourceOption;
import com.google.gcloud.storage.Storage.BlobTargetOption;
import com.google.gcloud.storage.Storage.BlobWriteOption;
import com.google.gcloud.storage.Storage.BucketSourceOption;
import com.google.gcloud.storage.Storage.BucketTargetOption;
import java.io.InputStream;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

Expand All @@ -47,6 +54,71 @@ public final class Bucket {
private final Storage storage;
private final BucketInfo info;

private static class BlobPageFetcher implements BasePage.NextPageFetcher<Blob> {

private static final long serialVersionUID = 3221100177471323801L;

private final StorageOptions options;
private final Page<BlobInfo> infoPage;

BlobPageFetcher(StorageOptions options, Page<BlobInfo> infoPage) {
this.options = options;
this.infoPage = infoPage;
}

@Override
public Page<Blob> nextPage() {
Page<BlobInfo> nextInfoPage = infoPage.nextPage();
return new BasePage<Blob>(new BlobPageFetcher(options, nextInfoPage),
nextInfoPage.nextPageCursor(), new LazyBlobIterable(options, nextInfoPage.values()));
}
}

private static class LazyBlobIterable implements Iterable<Blob>, Serializable {

private static final long serialVersionUID = -3092290247725378832L;

private final StorageOptions options;
private Iterable<BlobInfo> infoIterable;
private transient Storage storage;

public LazyBlobIterable(StorageOptions options, Iterable<BlobInfo> infoIterable) {
this.options = options;
this.infoIterable = infoIterable;
this.storage = options.service();
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
this.storage = options.service();
}

@Override
public Iterator<Blob> iterator() {
return Iterators.transform(infoIterable.iterator(), new Function<BlobInfo, Blob>() {
@Override
public Blob apply(BlobInfo blobInfo) {
return new Blob(storage, blobInfo);
}
});
}

@Override
public int hashCode() {
return Objects.hash(options, infoIterable);
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof LazyBlobIterable)) {
return false;
}
LazyBlobIterable other = (LazyBlobIterable) obj;
return Objects.equals(options, other.options)
&& Objects.equals(infoIterable, other.infoIterable);
}
}

/**
* Constructs a {@code Bucket} object for the provided {@code BucketInfo}. The storage service is
* used to issue requests.
Expand Down Expand Up @@ -136,7 +208,10 @@ public boolean delete(BucketSourceOption... options) {
* @throws StorageException upon failure
*/
public Page<Blob> list(Storage.BlobListOption... options) {
return new BlobPage(storage, storage.list(info.name(), options));
Page<BlobInfo> infoPage = storage.list(info.name(), options);
StorageOptions storageOptions = storage.options();
return new BasePage<Blob>(new BlobPageFetcher(storageOptions, infoPage),
infoPage.nextPageCursor(), new LazyBlobIterable(storageOptions, infoPage.values()));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ public DeleteBucketTask(Storage storage, String bucket) {
@Override
public Boolean call() throws Exception {
while (true) {
for (BlobInfo info : storage.list(bucket)) {
for (BlobInfo info : storage.list(bucket).values()) {
storage.delete(bucket, info.name());
}
try {
Expand Down
Loading

0 comments on commit 0511989

Please sign in to comment.