mirror of https://github.com/apache/jclouds.git
added paginated set functionality
This commit is contained in:
parent
01e27603f1
commit
763572f8ee
|
@ -0,0 +1,103 @@
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/**
|
||||||
|
* 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() + ")";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue