Issue 1011: PaginatedIterable with marker type as Object

This commit is contained in:
Adrian Cole 2012-07-09 10:26:14 -07:00
parent 797d9ae02d
commit 0383a80904
37 changed files with 505 additions and 452 deletions

View File

@ -24,8 +24,8 @@ import org.jclouds.cloudwatch.domain.Metric;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.features.MetricClient;
import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedSets;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.collect.PaginatedIterables;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
@ -46,11 +46,11 @@ public class CloudWatch {
* @return iterable of metrics fitting the criteria
*/
public static Iterable<Metric> listMetrics(final MetricClient metricClient, final ListMetricsOptions options) {
return PaginatedSets.lazyContinue(metricClient.list(options), new Function<String, PaginatedSet<Metric>>() {
return PaginatedIterables.lazyContinue(metricClient.list(options), new Function<Object, PaginatedIterable<Metric>>() {
@Override
public PaginatedSet<Metric> apply(String input) {
return metricClient.list(options.clone().nextMarker(input));
public PaginatedIterable<Metric> apply(Object input) {
return metricClient.list(options.clone().afterMarker(input));
}
@Override

View File

@ -33,7 +33,7 @@ import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions;
import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.cloudwatch.xml.GetMetricStatisticsResponseHandlerV2;
import org.jclouds.cloudwatch.xml.ListMetricsResponseHandler;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.RequestFilters;
@ -60,7 +60,7 @@ public interface MetricAsyncClient {
@Path("/")
@XMLResponseParser(ListMetricsResponseHandler.class)
@FormParams(keys = "Action", values = "ListMetrics")
ListenableFuture<? extends PaginatedSet<Metric>> list();
ListenableFuture<? extends PaginatedIterable<Metric>> list();
/**
* @see MetricClient#list(ListMetricsOptions)
@ -69,7 +69,7 @@ public interface MetricAsyncClient {
@Path("/")
@XMLResponseParser(ListMetricsResponseHandler.class)
@FormParams(keys = "Action", values = "ListMetrics")
ListenableFuture<? extends PaginatedSet<Metric>> list(ListMetricsOptions options);
ListenableFuture<? extends PaginatedIterable<Metric>> list(ListMetricsOptions options);
/**
* @see MetricClient#getMetricStatistics(GetMetricStatistics)

View File

@ -26,7 +26,7 @@ import org.jclouds.cloudwatch.domain.Metric;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions;
import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.concurrent.Timeout;
/**
@ -54,9 +54,9 @@ public interface MetricClient {
*
* @return the response object
*/
PaginatedSet<Metric> list(ListMetricsOptions options);
PaginatedIterable<Metric> list(ListMetricsOptions options);
PaginatedSet<Metric> list();
PaginatedIterable<Metric> list();
/**
* Gets statistics for the specified metric.

View File

@ -40,7 +40,7 @@ public class ListMetricsOptions extends BaseHttpRequestOptions implements Clonea
private Set<Dimension> dimensions = Sets.newLinkedHashSet();
private String metricName;
private String namespace;
private String nextToken;
private Object nextToken;
/**
* The namespace to filter against.
@ -97,7 +97,7 @@ public class ListMetricsOptions extends BaseHttpRequestOptions implements Clonea
*
* @return this {@code Builder} object
*/
public ListMetricsOptions nextMarker(String nextToken) {
public ListMetricsOptions afterMarker(Object nextToken) {
this.nextToken = nextToken;
return this;
}
@ -131,7 +131,7 @@ public class ListMetricsOptions extends BaseHttpRequestOptions implements Clonea
// If nextToken isn't specified, don't include it
if (nextToken != null) {
formParameters.put("NextToken", nextToken);
formParameters.put("NextToken", nextToken.toString());
}
return formParameters.build();
@ -139,7 +139,7 @@ public class ListMetricsOptions extends BaseHttpRequestOptions implements Clonea
@Override
public ListMetricsOptions clone() {
return Builder.namespace(namespace).metricName(metricName).dimensions(dimensions).nextMarker(nextToken);
return Builder.namespace(namespace).metricName(metricName).dimensions(dimensions).afterMarker(nextToken);
}
public static class Builder {
@ -173,10 +173,10 @@ public class ListMetricsOptions extends BaseHttpRequestOptions implements Clonea
}
/**
* @see ListMetricsOptions#nextMarker(String)
* @see ListMetricsOptions#afterMarker(String)
*/
public static ListMetricsOptions nextMarker(String nextToken) {
return new ListMetricsOptions().nextMarker(nextToken);
public static ListMetricsOptions afterMarker(String nextToken) {
return new ListMetricsOptions().afterMarker(nextToken);
}
}

View File

@ -21,7 +21,8 @@ package org.jclouds.cloudwatch.xml;
import java.util.Set;
import org.jclouds.cloudwatch.domain.Metric;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.collect.PaginatedIterables;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.SaxUtils;
import org.xml.sax.Attributes;
@ -35,7 +36,7 @@ import com.google.inject.Inject;
*
* @author Jeremy Whitlock
*/
public class ListMetricsResponseHandler extends ParseSax.HandlerForGeneratedRequestWithResult<PaginatedSet<Metric>> {
public class ListMetricsResponseHandler extends ParseSax.HandlerForGeneratedRequestWithResult<PaginatedIterable<Metric>> {
private final MetricHandler metricHandler;
@ -53,8 +54,8 @@ public class ListMetricsResponseHandler extends ParseSax.HandlerForGeneratedRequ
* {@inheritDoc}
*/
@Override
public PaginatedSet<Metric> getResult() {
return PaginatedSet.copyOfWithMarker(metrics, nextToken);
public PaginatedIterable<Metric> getResult() {
return PaginatedIterables.forwardWithMarker(metrics, nextToken);
}
/**

View File

@ -30,7 +30,8 @@ import org.jclouds.cloudwatch.domain.Metric;
import org.jclouds.cloudwatch.domain.MetricDatum;
import org.jclouds.cloudwatch.features.MetricClient;
import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.collect.PaginatedIterables;
import org.testng.Assert;
import org.testng.annotations.Test;
@ -57,7 +58,7 @@ public class CloudWatchTest {
CloudWatchClient client = createMock(CloudWatchClient.class);
MetricClient metricClient = createMock(MetricClient.class);
ListMetricsOptions options = new ListMetricsOptions();
PaginatedSet<Metric> response = PaginatedSet.copyOfWithMarker(ImmutableSet.of(createMock(Metric.class)), null);
PaginatedIterable<Metric> response = PaginatedIterables.forwardWithMarker(ImmutableSet.of(createMock(Metric.class)), null);
expect(client.getMetricClientForRegion(null))
.andReturn(metricClient)
@ -83,8 +84,8 @@ public class CloudWatchTest {
CloudWatchClient client = createMock(CloudWatchClient.class);
MetricClient metricClient = createMock(MetricClient.class);
ListMetricsOptions options = new ListMetricsOptions();
PaginatedSet<Metric> response1 = PaginatedSet.copyOfWithMarker(ImmutableSet.of(createMock(Metric.class)), "NEXTTOKEN");
PaginatedSet<Metric> response2 = PaginatedSet.copyOfWithMarker(ImmutableSet.of(createMock(Metric.class)), null);
PaginatedIterable<Metric> response1 = PaginatedIterables.forwardWithMarker(ImmutableSet.of(createMock(Metric.class)), "NEXTTOKEN");
PaginatedIterable<Metric> response2 = PaginatedIterables.forwardWithMarker(ImmutableSet.of(createMock(Metric.class)), null);
// Using EasyMock.eq("") because EasyMock makes it impossible to pass null as a String value here
expect(client.getMetricClientForRegion(EasyMock.eq("")))

View File

@ -78,7 +78,7 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
listMetrics, listMetricsResponse);
assertEquals(clientWhenMetricsExist.getMetricClientForRegion(null).list().toString(),
"PaginatedSet{contents=[Metric{namespace=AWS/EC2, metricName=CPUUtilization, dimension=[Dimension{name=InstanceId, value=i-689fcf0f}]}], marker=null}");
"{elements=[Metric{namespace=AWS/EC2, metricName=CPUUtilization, dimension=[Dimension{name=InstanceId, value=i-689fcf0f}]}], marker=null}");
}
// TODO: this should really be an empty set
@ -130,8 +130,8 @@ public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest {
"SOMEINSTANCEID"))
.metricName(EC2Constants.MetricName.CPU_UTILIZATION)
.namespace("SOMENEXTTOKEN")
.nextMarker(Namespaces.EC2)).toString(),
"PaginatedSet{contents=[Metric{namespace=AWS/EC2, metricName=CPUUtilization, dimension=[Dimension{name=InstanceId, value=i-689fcf0f}]}], marker=null}");
.afterMarker(Namespaces.EC2)).toString(),
"{elements=[Metric{namespace=AWS/EC2, metricName=CPUUtilization, dimension=[Dimension{name=InstanceId, value=i-689fcf0f}]}], marker=null}");
}
GetMetricStatistics stats = GetMetricStatistics.builder()

View File

@ -39,7 +39,7 @@ import org.jclouds.cloudwatch.domain.Statistics;
import org.jclouds.cloudwatch.domain.Unit;
import org.jclouds.cloudwatch.internal.BaseCloudWatchClientLiveTest;
import org.jclouds.cloudwatch.options.ListMetricsOptions;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.predicates.RetryablePredicate;
import org.testng.Assert;
import org.testng.annotations.Test;
@ -99,7 +99,7 @@ public class MetricClientLiveTest extends BaseCloudWatchClientLiveTest {
Assert.fail("Unable to gather the created CloudWatch data within the time (20m) allotted.");
}
PaginatedSet<Metric> lmr = client().list(lmo);
PaginatedIterable<Metric> lmr = client().list(lmo);
Date endTime = new Date(metricTimestampInCloudWatch.getTime() + (60 * 1000)); // Pad a minute just in case
Date startTime = new Date(metricTimestampInCloudWatch.getTime() - (60 * 1000)); // Pad a minute just in case
@ -145,10 +145,10 @@ public class MetricClientLiveTest extends BaseCloudWatchClientLiveTest {
// TODO: change this test to retrieve pre-seeded custom metrics
@Test
protected void testGetMetricStatistics() {
PaginatedSet<Metric> metricsResponse = client().list();
PaginatedIterable<Metric> metricsResponse = client().list();
// Walk through all datapoints in all metrics until we find a metric datapoint that returns statistics
if (metricsResponse.size() > 0) {
if (Iterables.size(metricsResponse) > 0) {
for (Metric metric : metricsResponse) {
Set<Dimension> dimensions = metric.getDimensions();
boolean testRan = false;
@ -195,7 +195,7 @@ public class MetricClientLiveTest extends BaseCloudWatchClientLiveTest {
@Test
protected void testListMetrics() {
PaginatedSet<Metric> response;
PaginatedIterable<Metric> response;
String testNamespace = Namespaces.EC2;
String testMetricName = EC2Constants.MetricName.CPU_UTILIZATION;
String testDimensionName = EC2Constants.Dimension.INSTANCE_TYPE;
@ -206,7 +206,7 @@ public class MetricClientLiveTest extends BaseCloudWatchClientLiveTest {
performDefaultMetricsTests(response);
if (response.size() > 0) {
if (Iterables.size(response) > 0) {
Metric metric = response.iterator().next();
testMetricName = metric.getMetricName();
@ -236,7 +236,7 @@ public class MetricClientLiveTest extends BaseCloudWatchClientLiveTest {
}
// Test with a NextToken, even if it's null
response = client().list(ListMetricsOptions.Builder.nextMarker(response.getNextMarker()));
response = client().list(ListMetricsOptions.Builder.afterMarker(response.getNextMarker().toString()));
performDefaultMetricsTests(response);
@ -281,9 +281,9 @@ public class MetricClientLiveTest extends BaseCloudWatchClientLiveTest {
}
}
private void performDefaultMetricsTests(PaginatedSet<Metric> response) {
private void performDefaultMetricsTests(PaginatedIterable<Metric> response) {
// If there are less than 500 metrics, NextToken should be null
if (response.size() < 500) {
if (Iterables.size(response) < 500) {
checkArgument(response.getNextMarker() == null,
"NextToken should be null for response with fewer than 500 metrics.");
}

View File

@ -0,0 +1,52 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.collect;
import java.util.Iterator;
import com.google.common.annotations.Beta;
import com.google.common.collect.ForwardingObject;
/**
* An iterator which forwards all its method calls to another iterator.
* Subclasses should override one or more methods to modify the behavior of the
* backing iterable as desired per the <a
* href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
*
* @author Adrian Cole
*/
@Beta
public abstract class ForwardingPaginatedIterable<T> extends ForwardingObject implements PaginatedIterable<T> {
/** Constructor for use by subclasses. */
protected ForwardingPaginatedIterable() {}
@Override protected abstract PaginatedIterable<T> delegate();
@Override
public Iterator<T> iterator() {
return delegate().iterator();
}
@Override
public Object getNextMarker() {
return delegate().getNextMarker();
}
}

View File

@ -0,0 +1,39 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.collect;
import com.google.common.annotations.Beta;
/**
* An {@code Iterable} that can be continued
*
* @author Adrian Cole
*/
@Beta
public interface PaginatedIterable<T> extends Iterable<T> {
/**
* If there is a next marker, then the set is incomplete and you should issue another command to
* retrieve the rest, setting the option {@code marker} to this value
*
* @return next marker, or null if list is complete
*/
Object getNextMarker();
}

View File

@ -0,0 +1,179 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy elements the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Iterator;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.ForwardingObject;
/**
* Utilities for using {@link PaginatedIterable}s.
*
* @author Adrian Cole, Jeremy Whitlock
*/
@Beta
public class PaginatedIterables {
/**
*
* @param initial
* the initial set elements data
* @param markerToNext
* produces the next set based on the marker
*
* @return iterable elements data which continues if the user iterates beyond the first page
*/
public static <T> Iterable<T> lazyContinue(final PaginatedIterable<T> initial,
final Function<Object, PaginatedIterable<T>> markerToNext) {
if (initial.getNextMarker() == null)
return initial;
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new AbstractIterator<T>() {
private PaginatedIterable<T> response = initial;
private Iterator<T> iterator = response.iterator();
/**
* {@inheritDoc}
*/
@Override
protected T computeNext() {
while (true) {
if (iterator == null) {
response = markerToNext.apply(response.getNextMarker());
iterator = response.iterator();
}
if (iterator.hasNext()) {
return iterator.next();
}
if (response.getNextMarker() == null) {
return endOfData();
}
iterator = null;
}
}
};
}
@Override
public String toString() {
return "lazyContinue(" + markerToNext + ")";
}
};
}
/**
* Returns a paginated iterable containing the given elements and null marker.
*
*
* @throws NullPointerException
* if {@code elements} are null
*/
public static <T> PaginatedIterable<T> forward(Iterable<T> elements) {
return forwardWithMarker(elements, null);
}
/**
* Returns a paginated iterable containing the given elements and marker.
*
*
* @throws NullPointerException
* if {@code elements} are null
*/
public static <T> PaginatedIterable<T> forwardWithMarker(final Iterable<T> elements, @Nullable final Object marker) {
return new ForwardingPaginatedIterable<T>() {
@Override
protected PaginatedIterable<T> delegate() {
return new ForwardedPaginatedIterable<T>(elements, marker);
}
};
}
private static final class ForwardedPaginatedIterable<T> extends ForwardingObject implements PaginatedIterable<T> {
private final Iterable<T> elements;
private final Object marker;
@Override
protected Iterable<T> delegate() {
return elements;
}
private ForwardedPaginatedIterable(Iterable<T> elements, @Nullable Object marker) {
this.elements = checkNotNull(elements, "elements");
;
this.marker = marker;
}
@Override
public Iterator<T> iterator() {
return delegate().iterator();
}
@Override
public Object getNextMarker() {
return marker;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(elements, marker);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ForwardedPaginatedIterable<?> other = ForwardedPaginatedIterable.class.cast(obj);
return Objects.equal(this.elements, other.elements) && Objects.equal(this.marker, other.marker);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return Objects.toStringHelper("").add("elements", elements).add("marker", marker).toString();
}
}
}

View File

@ -1,103 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.collect.ForwardingSet;
import com.google.common.collect.ImmutableSet;
/**
* An {@code Set} that can be continued
*
* @author Adrian Cole
*/
@Beta
public class PaginatedSet<T> extends ForwardingSet<T> {
public static <T> PaginatedSet<T> copyOf(Iterable<T> contents) {
return new PaginatedSet<T>(contents, null);
}
public static <T> PaginatedSet<T> copyOfWithMarker(Iterable<T> contents, String marker) {
return new PaginatedSet<T>(contents, marker);
}
private final Set<T> contents;
private final String marker;
protected PaginatedSet(Iterable<T> contents, @Nullable String marker) {
this.contents = ImmutableSet.<T> copyOf(checkNotNull(contents, "contents"));
this.marker = marker;
}
/**
* If there is a next marker, then the set is incomplete and you should issue another command to
* retrieve the rest, setting the option {@code marker} to this value
*
* @return next marker, or null if list is complete
*/
@Nullable
public String getNextMarker() {
return marker;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(contents, marker);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PaginatedSet<?> other = PaginatedSet.class.cast(obj);
return Objects.equal(this.contents, other.contents) && Objects.equal(this.marker, other.marker);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return Objects.toStringHelper(this).add("contents", contents).add("marker", marker).toString();
}
@Override
protected Set<T> delegate() {
return contents;
}
}

View File

@ -1,86 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.collect;
import java.util.Iterator;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.collect.AbstractIterator;
/**
* Utilities for using {@link PaginatedSet}s.
*
* @author Adrian Cole, Jeremy Whitlock
*/
@Beta
public class PaginatedSets {
/**
*
* @param initial
* the initial set of data
* @param markerToNext
* produces the next set based on the marker
*
* @return iterable of users fitting the criteria
*/
public static <T> Iterable<T> lazyContinue(final PaginatedSet<T> initial,
final Function<String, PaginatedSet<T>> markerToNext) {
if (initial.getNextMarker() == null)
return initial;
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new AbstractIterator<T>() {
private PaginatedSet<T> response = initial;
private Iterator<T> iterator = response.iterator();
/**
* {@inheritDoc}
*/
@Override
protected T computeNext() {
while (true) {
if (iterator == null) {
response = markerToNext.apply(response.getNextMarker());
iterator = response.iterator();
}
if (iterator.hasNext()) {
return iterator.next();
}
if (response.getNextMarker() == null) {
return endOfData();
}
iterator = null;
}
}
};
}
@Override
public String toString() {
return "lazyContinue(" + markerToNext.toString() + ")";
}
};
}
}

View File

@ -0,0 +1,76 @@
package org.jclouds.collect;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import org.easymock.EasyMock;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
/**
* Tests behavior of {@code PaginatedIterables}.
*
* @author Adrian Cole
*/
@Test(testName = "PaginatedIterablesTest")
public class PaginatedIterablesTest {
@SuppressWarnings("unchecked")
@Test
public void testSinglePageResultReturnsSame() {
PaginatedIterable<String> initial = PaginatedIterables.forward(ImmutableSet.of("foo", "bar"));
Function<Object, PaginatedIterable<String>> markerToNext = createMock(Function.class);
EasyMock.replay(markerToNext);
Assert.assertSame(PaginatedIterables.lazyContinue(initial, markerToNext), initial);
EasyMock.verify(markerToNext);
}
@SuppressWarnings("unchecked")
@Test
public void testMultiPage2Pages() {
PaginatedIterable<String> initial = PaginatedIterables.forwardWithMarker(ImmutableSet.of("foo", "bar"), "MARKER1");
Function<Object, PaginatedIterable<String>> markerToNext = createMock(Function.class);
expect(markerToNext.apply("MARKER1")).andReturn(
PaginatedIterables.forwardWithMarker(ImmutableSet.of("boo", "baz"), null));
EasyMock.replay(markerToNext);
Assert.assertEquals(ImmutableSet.copyOf(PaginatedIterables.lazyContinue(initial, markerToNext)), ImmutableSet.of(
"foo", "bar", "boo", "baz"));
EasyMock.verify(markerToNext);
}
@SuppressWarnings("unchecked")
@Test
public void testMultiPage3Pages() {
PaginatedIterable<String> initial = PaginatedIterables.forwardWithMarker(ImmutableSet.of("foo", "bar"), "MARKER1");
Function<Object, PaginatedIterable<String>> markerToNext = createMock(Function.class);
expect(markerToNext.apply("MARKER1")).andReturn(
PaginatedIterables.forwardWithMarker(ImmutableSet.of("boo", "baz"), "MARKER2"));
expect(markerToNext.apply("MARKER2")).andReturn(
PaginatedIterables.forwardWithMarker(ImmutableSet.of("ham", "cheeze"), null));
EasyMock.replay(markerToNext);
Assert.assertEquals(ImmutableSet.copyOf(PaginatedIterables.lazyContinue(initial, markerToNext)), ImmutableSet.of(
"foo", "bar", "boo", "baz", "ham", "cheeze"));
EasyMock.verify(markerToNext);
}
}

View File

@ -1,76 +0,0 @@
package org.jclouds.collect;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import org.easymock.EasyMock;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
/**
* Tests behavior of {@code PaginatedSets}.
*
* @author Adrian Cole
*/
@Test(testName = "PaginatedSetsTest")
public class PaginatedSetsTest {
@SuppressWarnings("unchecked")
@Test
public void testSinglePageResultReturnsSame() {
PaginatedSet<String> initial = PaginatedSet.copyOf(ImmutableSet.of("foo", "bar"));
Function<String, PaginatedSet<String>> markerToNext = createMock(Function.class);
EasyMock.replay(markerToNext);
Assert.assertSame(PaginatedSets.lazyContinue(initial, markerToNext), initial);
EasyMock.verify(markerToNext);
}
@SuppressWarnings("unchecked")
@Test
public void testMultiPage2Pages() {
PaginatedSet<String> initial = PaginatedSet.copyOfWithMarker(ImmutableSet.of("foo", "bar"), "MARKER1");
Function<String, PaginatedSet<String>> markerToNext = createMock(Function.class);
expect(markerToNext.apply("MARKER1")).andReturn(
PaginatedSet.copyOfWithMarker(ImmutableSet.of("boo", "baz"), null));
EasyMock.replay(markerToNext);
Assert.assertEquals(ImmutableSet.copyOf(PaginatedSets.lazyContinue(initial, markerToNext)), ImmutableSet.of(
"foo", "bar", "boo", "baz"));
EasyMock.verify(markerToNext);
}
@SuppressWarnings("unchecked")
@Test
public void testMultiPage3Pages() {
PaginatedSet<String> initial = PaginatedSet.copyOfWithMarker(ImmutableSet.of("foo", "bar"), "MARKER1");
Function<String, PaginatedSet<String>> markerToNext = createMock(Function.class);
expect(markerToNext.apply("MARKER1")).andReturn(
PaginatedSet.copyOfWithMarker(ImmutableSet.of("boo", "baz"), "MARKER2"));
expect(markerToNext.apply("MARKER2")).andReturn(
PaginatedSet.copyOfWithMarker(ImmutableSet.of("ham", "cheeze"), null));
EasyMock.replay(markerToNext);
Assert.assertEquals(ImmutableSet.copyOf(PaginatedSets.lazyContinue(initial, markerToNext)), ImmutableSet.of(
"foo", "bar", "boo", "baz", "ham", "cheeze"));
EasyMock.verify(markerToNext);
}
}

View File

@ -1,7 +1,7 @@
package org.jclouds.elb;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedSets;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.collect.PaginatedIterables;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.elb.features.LoadBalancerClient;
import org.jclouds.elb.options.ListLoadBalancersOptions;
@ -26,11 +26,11 @@ public class ELB {
* @return iterable of loadBalancers fitting the criteria
*/
public static Iterable<LoadBalancer> listLoadBalancers(final LoadBalancerClient loadBalancerClient, final ListLoadBalancersOptions options) {
return PaginatedSets.lazyContinue(loadBalancerClient.list(options), new Function<String, PaginatedSet<LoadBalancer>>() {
return PaginatedIterables.lazyContinue(loadBalancerClient.list(options), new Function<Object, PaginatedIterable<LoadBalancer>>() {
@Override
public PaginatedSet<LoadBalancer> apply(String input) {
return loadBalancerClient.list(options.clone().marker(input));
public PaginatedIterable<LoadBalancer> apply(Object input) {
return loadBalancerClient.list(options.clone().afterMarker(input));
}
@Override

View File

@ -25,7 +25,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.elb.binders.BindAvailabilityZonesToIndexedFormParams;
import org.jclouds.elb.binders.BindListenersToFormParams;
import org.jclouds.elb.binders.BindSecurityGroupsToIndexedFormParams;
@ -121,7 +121,7 @@ public interface LoadBalancerAsyncClient {
@Path("/")
@XMLResponseParser(DescribeLoadBalancersResultHandler.class)
@FormParams(keys = "Action", values = "DescribeLoadBalancers")
ListenableFuture<PaginatedSet<LoadBalancer>> list();
ListenableFuture<PaginatedIterable<LoadBalancer>> list();
/**
* @see LoadBalancerClient#list(ListLoadBalancersOptions)
@ -130,7 +130,7 @@ public interface LoadBalancerAsyncClient {
@Path("/")
@XMLResponseParser(DescribeLoadBalancersResultHandler.class)
@FormParams(keys = "Action", values = "DescribeLoadBalancers")
ListenableFuture<PaginatedSet<LoadBalancer>> list(ListLoadBalancersOptions options);
ListenableFuture<PaginatedIterable<LoadBalancer>> list(ListLoadBalancersOptions options);
/**
* @see LoadBalancerClient#delete()

View File

@ -20,7 +20,7 @@ package org.jclouds.elb.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.concurrent.Timeout;
import org.jclouds.elb.domain.Listener;
import org.jclouds.elb.domain.LoadBalancer;
@ -73,14 +73,14 @@ public interface LoadBalancerClient {
*
* @return the response object
*/
PaginatedSet<LoadBalancer> list(ListLoadBalancersOptions options);
PaginatedIterable<LoadBalancer> list(ListLoadBalancersOptions options);
/**
* Lists the loadBalancers all load balancers
*
* @return the response object
*/
PaginatedSet<LoadBalancer> list();
PaginatedIterable<LoadBalancer> list();
/**
* Deletes the specified LoadBalancer.

View File

@ -21,7 +21,6 @@ package org.jclouds.elb.options;
import java.util.Set;
import org.jclouds.http.options.BaseHttpRequestOptions;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.collect.Multimap;
@ -38,19 +37,21 @@ import com.google.common.collect.Sets;
*/
public class ListLoadBalancersOptions extends BaseHttpRequestOptions implements Cloneable {
private String marker;
private Object marker;
private Set<String> names = Sets.newLinkedHashSet();
/**
* @see ListLoadBalancersOptions#getMarker()
* Use this parameter only when paginating results, and only in a subsequent request after you've
* received a response where the results are truncated. Set it to the value of the Marker element
* in the response you just received.
*/
public ListLoadBalancersOptions marker(String marker) {
public ListLoadBalancersOptions afterMarker(Object marker) {
this.marker = marker;
return this;
}
/**
* @see ListLoadBalancersOptions#getNames()
* list of names associated with the LoadBalancers at creation time.
*/
public ListLoadBalancersOptions names(Set<String> names) {
this.names = names;
@ -58,37 +59,20 @@ public class ListLoadBalancersOptions extends BaseHttpRequestOptions implements
}
/**
* @see ListLoadBalancersOptions#getNames()
* @see #names
*/
public ListLoadBalancersOptions name(String name) {
this.names.add(name);
return this;
}
/**
* list of names associated with the LoadBalancers at creation time.
*/
public Set<String> getNames() {
return names;
}
/**
* Use this parameter only when paginating results, and only in a subsequent request after you've
* received a response where the results are truncated. Set it to the value of the Marker element
* in the response you just received.
*/
@Nullable
public String getMarker() {
return marker;
}
public static class Builder {
/**
* @see ListLoadBalancersOptions#getMarker()
*/
public static ListLoadBalancersOptions marker(String marker) {
return new ListLoadBalancersOptions().marker(marker);
public static ListLoadBalancersOptions afterMarker(Object marker) {
return new ListLoadBalancersOptions().afterMarker(marker);
}
/**
@ -110,7 +94,7 @@ public class ListLoadBalancersOptions extends BaseHttpRequestOptions implements
public Multimap<String, String> buildFormParameters() {
Multimap<String, String> params = super.buildFormParameters();
if (marker != null)
params.put("Marker", marker);
params.put("Marker", marker.toString());
if (names.size() > 0) {
int nameIndex = 1;
for (String name : names) {
@ -131,7 +115,7 @@ public class ListLoadBalancersOptions extends BaseHttpRequestOptions implements
@Override
public ListLoadBalancersOptions clone() {
return new ListLoadBalancersOptions().marker(marker).names(names);
return new ListLoadBalancersOptions().afterMarker(marker).names(names);
}
/**

View File

@ -23,7 +23,8 @@ import static org.jclouds.util.SaxUtils.equalsOrSuffix;
import java.util.Set;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.collect.PaginatedIterables;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.http.functions.ParseSax;
import org.xml.sax.Attributes;
@ -40,7 +41,7 @@ import com.google.inject.Inject;
* @author Adrian Cole
*/
public class DescribeLoadBalancersResultHandler extends
ParseSax.HandlerForGeneratedRequestWithResult<PaginatedSet<LoadBalancer>> {
ParseSax.HandlerForGeneratedRequestWithResult<PaginatedIterable<LoadBalancer>> {
private final LoadBalancerHandler loadBalancerHandler;
@ -60,8 +61,8 @@ public class DescribeLoadBalancersResultHandler extends
* {@inheritDoc}
*/
@Override
public PaginatedSet<LoadBalancer> getResult() {
return PaginatedSet.copyOfWithMarker(loadBalancers, marker);
public PaginatedIterable<LoadBalancer> getResult() {
return PaginatedIterables.forwardWithMarker(loadBalancers, marker);
}
/**

View File

@ -5,7 +5,8 @@ import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import org.easymock.EasyMock;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.collect.PaginatedIterables;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.elb.features.LoadBalancerClient;
import org.jclouds.elb.options.ListLoadBalancersOptions;
@ -28,7 +29,7 @@ public class ELBTest {
public void testSinglePageResult() throws Exception {
LoadBalancerClient loadBalancerClient = createMock(LoadBalancerClient.class);
ListLoadBalancersOptions options = new ListLoadBalancersOptions();
PaginatedSet<LoadBalancer> response = PaginatedSet.copyOf(ImmutableSet.of(createMock(LoadBalancer.class)));
PaginatedIterable<LoadBalancer> response = PaginatedIterables.forward(ImmutableSet.of(createMock(LoadBalancer.class)));
expect(loadBalancerClient.list(options))
.andReturn(response)
@ -44,8 +45,8 @@ public class ELBTest {
public void testMultiPageResult() throws Exception {
LoadBalancerClient loadBalancerClient = createMock(LoadBalancerClient.class);
ListLoadBalancersOptions options = new ListLoadBalancersOptions();
PaginatedSet<LoadBalancer> response1 = PaginatedSet.copyOfWithMarker(ImmutableSet.of(createMock(LoadBalancer.class)), "NEXTTOKEN");
PaginatedSet<LoadBalancer> response2 = PaginatedSet.copyOf(ImmutableSet.of(createMock(LoadBalancer.class)));
PaginatedIterable<LoadBalancer> response1 = PaginatedIterables.forwardWithMarker(ImmutableSet.of(createMock(LoadBalancer.class)), "NEXTTOKEN");
PaginatedIterable<LoadBalancer> response2 = PaginatedIterables.forward(ImmutableSet.of(createMock(LoadBalancer.class)));
expect(loadBalancerClient.list(anyObject(ListLoadBalancersOptions.class)))
.andReturn(response1)

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.elb.features;
import static org.jclouds.elb.options.ListLoadBalancersOptions.Builder.marker;
import static org.jclouds.elb.options.ListLoadBalancersOptions.Builder.afterMarker;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
@ -154,7 +154,7 @@ public class LoadBalancerClientExpectTest extends BaseELBClientExpectTest {
ELBClient clientWhenWithOptionsExist = requestSendsResponse(listWithOptions,
listWithOptionsResponse);
assertEquals(clientWhenWithOptionsExist.getLoadBalancerClientForRegion(null).list(marker("MARKER")).toString(),
assertEquals(clientWhenWithOptionsExist.getLoadBalancerClientForRegion(null).list(afterMarker("MARKER")).toString(),
new DescribeLoadBalancersResponseTest().expected().toString());
}
}

View File

@ -21,7 +21,7 @@ package org.jclouds.elb.features;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.elb.domain.ListenerWithPolicies;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.elb.internal.BaseELBClientLiveTest;
@ -29,6 +29,8 @@ import org.jclouds.elb.options.ListLoadBalancersOptions;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
*/
@ -70,7 +72,7 @@ public class LoadBalancerClientLiveTest extends BaseELBClientLiveTest {
@Test
protected void testDescribeLoadBalancers() {
PaginatedSet<LoadBalancer> response = client().list();
PaginatedIterable<LoadBalancer> response = client().list();
for (LoadBalancer loadBalancer : response) {
checkLoadBalancer(loadBalancer);
@ -79,13 +81,13 @@ public class LoadBalancerClientLiveTest extends BaseELBClientLiveTest {
}
}
if (response.size() > 0) {
if (Iterables.size(response) > 0) {
LoadBalancer loadBalancer = response.iterator().next();
Assert.assertEquals(client().get(loadBalancer.getName()), loadBalancer);
}
// Test with a Marker, even if it's null
response = client().list(ListLoadBalancersOptions.Builder.marker(response.getNextMarker()));
response = client().list(ListLoadBalancersOptions.Builder.afterMarker(response.getNextMarker()));
for (LoadBalancer loadBalancer : response) {
checkLoadBalancer(loadBalancer);
}

View File

@ -20,7 +20,7 @@ package org.jclouds.elb.loadbalancer;
import static org.testng.Assert.assertEquals;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.elb.ELBAsyncClient;
import org.jclouds.elb.ELBClient;
@ -60,7 +60,7 @@ public class ELBLoadBalancerServiceLiveTest extends BaseLoadBalancerServiceLiveT
instanceIds.add(node.getProviderId());
}
PaginatedSet<LoadBalancer> elbs = elbClient.getLoadBalancerClientForRegion(null).list();
PaginatedIterable<LoadBalancer> elbs = elbClient.getLoadBalancerClientForRegion(null).list();
for (LoadBalancer elb : elbs) {
if (elb.getName().equals(group))
assertEquals(elb.getInstanceIds(), instanceIds.build());

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.elb.options;
import static org.jclouds.elb.options.ListLoadBalancersOptions.Builder.marker;
import static org.jclouds.elb.options.ListLoadBalancersOptions.Builder.afterMarker;
import static org.jclouds.elb.options.ListLoadBalancersOptions.Builder.name;
import static org.testng.Assert.assertEquals;
@ -35,12 +35,12 @@ import com.google.common.collect.ImmutableSet;
public class ListLoadBalancersOptionsTest {
public void testMarker() {
ListLoadBalancersOptions options = new ListLoadBalancersOptions().marker("FFFFF");
ListLoadBalancersOptions options = new ListLoadBalancersOptions().afterMarker("FFFFF");
assertEquals(ImmutableSet.of("FFFFF"), options.buildFormParameters().get("Marker"));
}
public void testMarkerStatic() {
ListLoadBalancersOptions options = marker("FFFFF");
ListLoadBalancersOptions options = afterMarker("FFFFF");
assertEquals(ImmutableSet.of("FFFFF"), options.buildFormParameters().get("Marker"));
}

View File

@ -22,7 +22,8 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.collect.PaginatedIterables;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.elb.domain.HealthCheck;
import org.jclouds.elb.domain.ListenerWithPolicies;
@ -44,17 +45,17 @@ public class DescribeLoadBalancersResponseTest extends BaseHandlerTest {
public void test() {
InputStream is = getClass().getResourceAsStream("/describe_loadbalancers.xml");
PaginatedSet<LoadBalancer> expected = expected();
PaginatedIterable<LoadBalancer> expected = expected();
DescribeLoadBalancersResultHandler handler = injector.getInstance(DescribeLoadBalancersResultHandler.class);
PaginatedSet<LoadBalancer> result = factory.create(handler).parse(is);
PaginatedIterable<LoadBalancer> result = factory.create(handler).parse(is);
assertEquals(result.toString(), expected.toString());
}
public PaginatedSet<LoadBalancer> expected() {
return PaginatedSet.copyOf(ImmutableSet.of(
public PaginatedIterable<LoadBalancer> expected() {
return PaginatedIterables.forward(ImmutableSet.of(
LoadBalancer.builder()
.name("my-load-balancer")
.createdTime(new SimpleDateFormatDateService().iso8601DateParse("2010-03-03T20:54:45.110Z"))

View File

@ -22,7 +22,8 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.collect.PaginatedIterables;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.elb.domain.HealthCheck;
import org.jclouds.elb.domain.ListenerWithPolicies;
@ -45,17 +46,17 @@ public class DescribeVPCLoadBalancersResponseTest extends BaseHandlerTest {
public void test() {
InputStream is = getClass().getResourceAsStream("/describe_loadbalancers_vpc.xml");
PaginatedSet<LoadBalancer> expected = expected();
PaginatedIterable<LoadBalancer> expected = expected();
DescribeLoadBalancersResultHandler handler = injector.getInstance(DescribeLoadBalancersResultHandler.class);
PaginatedSet<LoadBalancer> result = factory.create(handler).parse(is);
PaginatedIterable<LoadBalancer> result = factory.create(handler).parse(is);
assertEquals(result.toString(), expected.toString());
}
public PaginatedSet<LoadBalancer> expected() {
return PaginatedSet.copyOf(ImmutableSet.of(
public PaginatedIterable<LoadBalancer> expected() {
return PaginatedIterables.forward(ImmutableSet.of(
LoadBalancer.builder()
.name("tests")
.createdTime(new SimpleDateFormatDateService().iso8601DateParse("2012-07-08T19:54:24.190Z"))

View File

@ -1,7 +1,7 @@
package org.jclouds.iam;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedSets;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.collect.PaginatedIterables;
import org.jclouds.iam.domain.User;
import org.jclouds.iam.features.UserClient;
import org.jclouds.iam.options.ListUsersOptions;
@ -26,11 +26,11 @@ public class IAM {
* @return iterable of users fitting the criteria
*/
public static Iterable<User> list(final UserClient userClient, final ListUsersOptions options) {
return PaginatedSets.lazyContinue(userClient.list(options), new Function<String, PaginatedSet<User>>() {
return PaginatedIterables.lazyContinue(userClient.list(options), new Function<Object, PaginatedIterable<User>>() {
@Override
public PaginatedSet<User> apply(String input) {
return userClient.list(options.clone().marker(input));
public PaginatedIterable<User> apply(Object input) {
return userClient.list(options.clone().afterMarker(input));
}
@Override

View File

@ -23,7 +23,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.iam.domain.User;
import org.jclouds.iam.options.ListUsersOptions;
import org.jclouds.iam.xml.ListUsersResultHandler;
@ -74,7 +74,7 @@ public interface UserAsyncClient {
@Path("/")
@XMLResponseParser(ListUsersResultHandler.class)
@FormParams(keys = "Action", values = "ListUsers")
ListenableFuture<PaginatedSet<User>> list();
ListenableFuture<PaginatedIterable<User>> list();
/**
* @see UserClient#list(ListUsersOptions)
@ -83,6 +83,6 @@ public interface UserAsyncClient {
@Path("/")
@XMLResponseParser(ListUsersResultHandler.class)
@FormParams(keys = "Action", values = "ListUsers")
ListenableFuture<PaginatedSet<User>> list(ListUsersOptions options);
ListenableFuture<PaginatedIterable<User>> list(ListUsersOptions options);
}

View File

@ -20,7 +20,7 @@ package org.jclouds.iam.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.concurrent.Timeout;
import org.jclouds.iam.domain.User;
import org.jclouds.iam.options.ListUsersOptions;
@ -62,7 +62,7 @@ public interface UserClient {
*
* @return the response object
*/
PaginatedSet<User> list(ListUsersOptions options);
PaginatedIterable<User> list(ListUsersOptions options);
/**
* Lists the users that have the specified path prefix. If there are none, the action returns an
@ -70,6 +70,6 @@ public interface UserClient {
*
* @return the response object
*/
PaginatedSet<User> list();
PaginatedIterable<User> list();
}

View File

@ -19,7 +19,6 @@
package org.jclouds.iam.options;
import org.jclouds.http.options.BaseHttpRequestOptions;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.collect.Multimap;
@ -35,29 +34,15 @@ public class ListUsersOptions extends BaseHttpRequestOptions implements Cloneabl
private Integer maxItems;
private String pathPrefix;
private String marker;
private Object afterMarker;
/**
* @see ListUsersOptions#getMarker()
* Use this parameter only when paginating results, and only in a subsequent request after you've
* received a response where the results are truncated. Set it to the value of the Marker element
* in the response you just received.
*/
public ListUsersOptions marker(String marker) {
this.marker = marker;
return this;
}
/**
* @see ListUsersOptions#getMaxItems()
*/
public ListUsersOptions maxItems(Integer maxItems) {
this.maxItems = maxItems;
return this;
}
/**
* @see ListUsersOptions#getPathPrefix()
*/
public ListUsersOptions pathPrefix(String pathPrefix) {
this.pathPrefix = pathPrefix;
public ListUsersOptions afterMarker(Object afterMarker) {
this.afterMarker = afterMarker;
return this;
}
@ -66,9 +51,9 @@ public class ListUsersOptions extends BaseHttpRequestOptions implements Cloneabl
* you want in the response. If there are additional user names beyond the maximum you specify,
* the IsTruncated response element is true.
*/
@Nullable
public Integer getMaxItems() {
return maxItems;
public ListUsersOptions maxItems(Integer maxItems) {
this.maxItems = maxItems;
return this;
}
/**
@ -78,39 +63,29 @@ public class ListUsersOptions extends BaseHttpRequestOptions implements Cloneabl
* This parameter is optional. If it is not included, it defaults to a slash (/), listing all
* user names.
*/
@Nullable
public String getPathPrefix() {
return pathPrefix;
}
/**
* Use this parameter only when paginating results, and only in a subsequent request after you've
* received a response where the results are truncated. Set it to the value of the Marker element
* in the response you just received.
*/
@Nullable
public String getMarker() {
return marker;
public ListUsersOptions pathPrefix(String pathPrefix) {
this.pathPrefix = pathPrefix;
return this;
}
public static class Builder {
/**
* @see ListUsersOptions#getMarker()
* @see ListUsersOptions#afterMarker
*/
public static ListUsersOptions marker(String marker) {
return new ListUsersOptions().marker(marker);
public static ListUsersOptions afterMarker(Object afterMarker) {
return new ListUsersOptions().afterMarker(afterMarker);
}
/**
* @see ListUsersOptions#getMaxItems()
* @see ListUsersOptions#maxItems
*/
public static ListUsersOptions maxItems(Integer maxItems) {
return new ListUsersOptions().maxItems(maxItems);
}
/**
* @see ListUsersOptions#getPathPrefix()
* @see ListUsersOptions#pathPrefix
*/
public static ListUsersOptions pathPrefix(String pathPrefix) {
return new ListUsersOptions().pathPrefix(pathPrefix);
@ -120,8 +95,8 @@ public class ListUsersOptions extends BaseHttpRequestOptions implements Cloneabl
@Override
public Multimap<String, String> buildFormParameters() {
Multimap<String, String> params = super.buildFormParameters();
if (marker != null)
params.put("Marker", marker);
if (afterMarker != null)
params.put("Marker", afterMarker.toString());
if (maxItems != null)
params.put("MaxItems", maxItems.toString());
if (pathPrefix != null)
@ -134,12 +109,12 @@ public class ListUsersOptions extends BaseHttpRequestOptions implements Cloneabl
*/
@Override
public int hashCode() {
return Objects.hashCode(marker, maxItems, pathPrefix);
return Objects.hashCode(afterMarker, maxItems, pathPrefix);
}
@Override
public ListUsersOptions clone() {
return new ListUsersOptions().marker(marker).maxItems(maxItems).pathPrefix(pathPrefix);
return new ListUsersOptions().afterMarker(afterMarker).maxItems(maxItems).pathPrefix(pathPrefix);
}
/**
@ -154,7 +129,7 @@ public class ListUsersOptions extends BaseHttpRequestOptions implements Cloneabl
if (getClass() != obj.getClass())
return false;
ListUsersOptions other = ListUsersOptions.class.cast(obj);
return Objects.equal(this.marker, other.marker) && Objects.equal(this.maxItems, other.maxItems)
return Objects.equal(this.afterMarker, other.afterMarker) && Objects.equal(this.maxItems, other.maxItems)
&& Objects.equal(this.pathPrefix, other.pathPrefix);
}
@ -163,7 +138,7 @@ public class ListUsersOptions extends BaseHttpRequestOptions implements Cloneabl
*/
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues().add("marker", marker).add("maxItems", maxItems).add(
return Objects.toStringHelper(this).omitNullValues().add("afterMarker", afterMarker).add("maxItems", maxItems).add(
"pathPrefix", pathPrefix).toString();
}
}

View File

@ -20,7 +20,8 @@ package org.jclouds.iam.xml;
import java.util.Set;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.collect.PaginatedIterables;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.iam.domain.User;
import org.jclouds.util.SaxUtils;
@ -35,14 +36,14 @@ import com.google.inject.Inject;
*
* @author Adrian Cole
*/
public class ListUsersResultHandler extends ParseSax.HandlerForGeneratedRequestWithResult<PaginatedSet<User>> {
public class ListUsersResultHandler extends ParseSax.HandlerForGeneratedRequestWithResult<PaginatedIterable<User>> {
private final UserHandler userHandler;
private StringBuilder currentText = new StringBuilder();
private Set<User> users = Sets.newLinkedHashSet();
private boolean inUsers;
private String marker;
private String afterMarker;
@Inject
public ListUsersResultHandler(UserHandler userHandler) {
@ -53,8 +54,8 @@ public class ListUsersResultHandler extends ParseSax.HandlerForGeneratedRequestW
* {@inheritDoc}
*/
@Override
public PaginatedSet<User> getResult() {
return PaginatedSet.copyOfWithMarker(users, marker);
public PaginatedIterable<User> getResult() {
return PaginatedIterables.forwardWithMarker(users, afterMarker);
}
/**
@ -84,7 +85,7 @@ public class ListUsersResultHandler extends ParseSax.HandlerForGeneratedRequestW
userHandler.endElement(uri, name, qName);
}
} else if (qName.equals("Marker")) {
marker = SaxUtils.currentOrNull(currentText);
afterMarker = SaxUtils.currentOrNull(currentText);
}
currentText = new StringBuilder();

View File

@ -5,7 +5,8 @@ import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import org.easymock.EasyMock;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.collect.PaginatedIterables;
import org.jclouds.iam.domain.User;
import org.jclouds.iam.features.UserClient;
import org.jclouds.iam.options.ListUsersOptions;
@ -28,7 +29,7 @@ public class IAMTest {
public void testSinglePageResult() throws Exception {
UserClient userClient = createMock(UserClient.class);
ListUsersOptions options = new ListUsersOptions();
PaginatedSet<User> response = PaginatedSet.copyOf(ImmutableSet.of(createMock(User.class)));
PaginatedIterable<User> response = PaginatedIterables.forward(ImmutableSet.of(createMock(User.class)));
expect(userClient.list(options))
.andReturn(response)
@ -44,8 +45,8 @@ public class IAMTest {
public void testMultiPageResult() throws Exception {
UserClient userClient = createMock(UserClient.class);
ListUsersOptions options = new ListUsersOptions();
PaginatedSet<User> response1 = PaginatedSet.copyOfWithMarker(ImmutableSet.of(createMock(User.class)), "NEXTTOKEN");
PaginatedSet<User> response2 = PaginatedSet.copyOf(ImmutableSet.of(createMock(User.class)));
PaginatedIterable<User> response1 = PaginatedIterables.forwardWithMarker(ImmutableSet.of(createMock(User.class)), "NEXTTOKEN");
PaginatedIterable<User> response2 = PaginatedIterables.forward(ImmutableSet.of(createMock(User.class)));
expect(userClient.list(anyObject(ListUsersOptions.class)))
.andReturn(response1)

View File

@ -182,7 +182,7 @@ public class UserClientExpectTest extends BaseIAMClientExpectTest {
IAMClient clientWhenWithOptionsExist = requestSendsResponse(listWithOptions,
listWithOptionsResponse);
assertEquals(clientWhenWithOptionsExist.getUserClient().list(pathPrefix("/foo").marker("MARKER")).toString(),
assertEquals(clientWhenWithOptionsExist.getUserClient().list(pathPrefix("/foo").afterMarker("MARKER")).toString(),
new ListUsersResponseTest().expected().toString());
}
}

View File

@ -20,13 +20,15 @@ package org.jclouds.iam.features;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.iam.domain.User;
import org.jclouds.iam.internal.BaseIAMClientLiveTest;
import org.jclouds.iam.options.ListUsersOptions;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
*/
@ -49,19 +51,19 @@ public class UserClientLiveTest extends BaseIAMClientLiveTest {
@Test
protected void testListUsers() {
PaginatedSet<User> response = client().list();
PaginatedIterable<User> response = client().list();
for (User user : response) {
checkUser(user);
}
if (response.size() > 0) {
if (Iterables.size(response) > 0) {
User user = response.iterator().next();
Assert.assertEquals(client().get(user.getName().get()), user);
}
// Test with a Marker, even if it's null
response = client().list(ListUsersOptions.Builder.marker(response.getNextMarker()));
response = client().list(ListUsersOptions.Builder.afterMarker(response.getNextMarker()));
for (User user : response) {
checkUser(user);
}

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.iam.options;
import static org.jclouds.iam.options.ListUsersOptions.Builder.marker;
import static org.jclouds.iam.options.ListUsersOptions.Builder.afterMarker;
import static org.jclouds.iam.options.ListUsersOptions.Builder.maxItems;
import static org.jclouds.iam.options.ListUsersOptions.Builder.pathPrefix;
import static org.testng.Assert.assertEquals;
@ -36,12 +36,12 @@ import com.google.common.collect.ImmutableSet;
public class ListUsersOptionsTest {
public void testMarker() {
ListUsersOptions options = new ListUsersOptions().marker("FFFFF");
ListUsersOptions options = new ListUsersOptions().afterMarker("FFFFF");
assertEquals(ImmutableSet.of("FFFFF"), options.buildFormParameters().get("Marker"));
}
public void testMarkerStatic() {
ListUsersOptions options = marker("FFFFF");
ListUsersOptions options = afterMarker("FFFFF");
assertEquals(ImmutableSet.of("FFFFF"), options.buildFormParameters().get("Marker"));
}

View File

@ -22,7 +22,8 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.collect.PaginatedIterable;
import org.jclouds.collect.PaginatedIterables;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.iam.domain.User;
@ -41,17 +42,17 @@ public class ListUsersResponseTest extends BaseHandlerTest {
public void test() {
InputStream is = getClass().getResourceAsStream("/list_users.xml");
PaginatedSet<User> expected = expected();
PaginatedIterable<User> expected = expected();
ListUsersResultHandler handler = injector.getInstance(ListUsersResultHandler.class);
PaginatedSet<User> result = factory.create(handler).parse(is);
PaginatedIterable<User> result = factory.create(handler).parse(is);
assertEquals(result.toString(), expected.toString());
}
public PaginatedSet<User> expected() {
return PaginatedSet.copyOf(ImmutableSet.of(
public PaginatedIterable<User> expected() {
return PaginatedIterables.forward(ImmutableSet.of(
User.builder()
.path("/division_abc/subdivision_xyz/engineering/")
.name("Andrew")