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