mirror of https://github.com/apache/jclouds.git
Merge pull request #1460 from rackspace/rax-pagination
PaginatedCollection for Rackspace style pagination.
This commit is contained in:
commit
b943a8c19f
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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.rackspace.cloudidentity.v2_0.domain;
|
||||
|
||||
import static org.jclouds.http.utils.Queries.queryParser;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.jclouds.collect.IterableWithMarker;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.openstack.v2_0.domain.Link;
|
||||
import org.jclouds.rackspace.cloudidentity.v2_0.options.PaginationOptions;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* Base class for a paginated collection in Rackspace.
|
||||
*
|
||||
* @author Everett Toews
|
||||
*/
|
||||
@Beta
|
||||
public class PaginatedCollection<T> extends IterableWithMarker<T> {
|
||||
private Iterable<T> resources;
|
||||
private Iterable<Link> links;
|
||||
private int totalEntries;
|
||||
|
||||
protected PaginatedCollection(@Nullable Iterable<T> resources, @Nullable Iterable<Link> links, int totalEntries) {
|
||||
this.resources = resources != null ? resources : ImmutableSet.<T> of();
|
||||
this.links = links != null ? links : ImmutableSet.<Link> of();
|
||||
this.totalEntries = totalEntries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return resources.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* links that relate to this collection
|
||||
*/
|
||||
public Iterable<Link> getLinks() {
|
||||
return links;
|
||||
}
|
||||
|
||||
public int getTotalEntries() {
|
||||
return totalEntries;
|
||||
}
|
||||
|
||||
public PaginationOptions nextPaginationOptions() {
|
||||
return PaginationOptions.class.cast(nextMarker().get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Object> nextMarker() {
|
||||
for (Link link: getLinks()) {
|
||||
if (Link.Relation.NEXT == link.getRelation()) {
|
||||
return Optional.<Object> of(toPaginationOptions(link));
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
private Object toPaginationOptions(Link link) {
|
||||
Multimap<String, String> queryParams = queryParser().apply(link.getHref().getRawQuery());
|
||||
PaginationOptions paginationOptions = PaginationOptions.Builder.queryParameters(queryParams);
|
||||
|
||||
return paginationOptions;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* 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.rackspace.cloudidentity.v2_0.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.date.DateService;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* Takes a Date and return a yyyy-MM-dd String.
|
||||
*
|
||||
* @author Everett Toews
|
||||
*/
|
||||
@Singleton
|
||||
public class DateParser implements Function<Object, String> {
|
||||
|
||||
private final DateService dateService;
|
||||
|
||||
@Inject
|
||||
DateParser(DateService dateService) {
|
||||
this.dateService = dateService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(Object input) {
|
||||
checkArgument(checkNotNull(input, "input") instanceof Date, "This function is only valid for Dates!");
|
||||
Date date = Date.class.cast(input);
|
||||
|
||||
return dateService.iso8601SecondsDateFormat(date);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* 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.rackspace.cloudidentity.v2_0.options;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* Options used to control paginated results (aka list commands).
|
||||
*
|
||||
* @author Everett Toews
|
||||
*/
|
||||
public class PaginationOptions extends BaseHttpRequestOptions {
|
||||
public PaginationOptions queryParameters(Multimap<String, String> queryParams) {
|
||||
checkNotNull(queryParams, "queryParams");
|
||||
queryParameters.putAll(queryParams);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset is the starting point for the return data. Offset must be a multiple of the limit (or zero).
|
||||
*/
|
||||
public PaginationOptions offset(int offset) {
|
||||
checkState(offset >= 0, "offset must be >= 0");
|
||||
queryParameters.put("offset", String.valueOf(offset));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit is the restriction on the maximum number of items for that type that can be returned.
|
||||
* <p/>
|
||||
* Note that list operations never return itemNotFound (404) faults.
|
||||
*/
|
||||
public PaginationOptions limit(int limit) {
|
||||
checkState(limit >= 0, "limit must be >= 0");
|
||||
checkState(limit <= 10000, "limit must be <= 10000");
|
||||
queryParameters.put("limit", Integer.toString(limit));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name is a filter on the result set.
|
||||
*/
|
||||
public PaginationOptions name(String nameFilter) {
|
||||
queryParameters.put("name", nameFilter);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
public static PaginationOptions queryParameters(Multimap<String, String> queryParams) {
|
||||
PaginationOptions options = new PaginationOptions();
|
||||
return options.queryParameters(queryParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PaginationOptions#offset(int)
|
||||
*/
|
||||
public static PaginationOptions offset(int offset) {
|
||||
PaginationOptions options = new PaginationOptions();
|
||||
return options.offset(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PaginationOptions#limit(int)
|
||||
*/
|
||||
public static PaginationOptions limit(int limit) {
|
||||
PaginationOptions options = new PaginationOptions();
|
||||
return options.limit(limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PaginationOptions#name(String)
|
||||
*/
|
||||
public static PaginationOptions name(String name) {
|
||||
PaginationOptions options = new PaginationOptions();
|
||||
return options.name(name);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* 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.rackspace.cloudidentity.v2_0;
|
||||
|
||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||
import static org.jclouds.Fallbacks.valOnNotFoundOr404;
|
||||
|
||||
import org.jclouds.Fallback;
|
||||
import org.jclouds.openstack.v2_0.domain.Link;
|
||||
import org.jclouds.rackspace.cloudidentity.v2_0.domain.PaginatedCollection;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
public final class CloudIdentityFallbacks {
|
||||
private CloudIdentityFallbacks() {
|
||||
}
|
||||
|
||||
public static final class EmptyPaginatedCollectionOnNotFoundOr404 implements Fallback<PaginatedCollection<Object>> {
|
||||
private static final PaginatedCollection<Object> EMPTY = new PaginatedCollection<Object>(
|
||||
ImmutableSet.<Object> of(), ImmutableSet.<Link> of(), 0) {
|
||||
};
|
||||
|
||||
@Override
|
||||
public ListenableFuture<PaginatedCollection<Object>> create(Throwable t) throws Exception {
|
||||
return immediateFuture(createOrPropagate(t));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaginatedCollection<Object> createOrPropagate(Throwable t) throws Exception {
|
||||
return valOnNotFoundOr404(EMPTY, t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* 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.rackspace.cloudidentity.v2_0.options;
|
||||
|
||||
import static org.jclouds.rackspace.cloudidentity.v2_0.options.PaginationOptions.Builder.limit;
|
||||
import static org.jclouds.rackspace.cloudidentity.v2_0.options.PaginationOptions.Builder.name;
|
||||
import static org.jclouds.rackspace.cloudidentity.v2_0.options.PaginationOptions.Builder.offset;
|
||||
import static org.jclouds.rackspace.cloudidentity.v2_0.options.PaginationOptions.Builder.queryParameters;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
|
||||
/**
|
||||
* @author Everett Toews
|
||||
*/
|
||||
@Test(groups = "unit", testName = "PaginationOptionsTest")
|
||||
public class PaginationOptionsTest {
|
||||
|
||||
public void testQueryParameters() {
|
||||
ImmutableSetMultimap<String, String> queryParameters = ImmutableSetMultimap.<String, String> of(
|
||||
"limit", "1",
|
||||
"offset", "1",
|
||||
"name", "foo");
|
||||
PaginationOptions options = new PaginationOptions().queryParameters(queryParameters);
|
||||
assertEquals(queryParameters, options.buildQueryParameters());
|
||||
}
|
||||
|
||||
public void testMaxResults() {
|
||||
int limit = 1;
|
||||
PaginationOptions options = new PaginationOptions().limit(limit);
|
||||
assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("limit"));
|
||||
}
|
||||
|
||||
public void testOffset() {
|
||||
int offset = 1;
|
||||
PaginationOptions options = new PaginationOptions().offset(offset);
|
||||
assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("offset"));
|
||||
}
|
||||
|
||||
public void testNameFilter() {
|
||||
String nameFilter = "foo";
|
||||
PaginationOptions options = new PaginationOptions().name(nameFilter);
|
||||
assertEquals(ImmutableList.of("foo"), options.buildQueryParameters().get("name"));
|
||||
}
|
||||
|
||||
public void testMaxResultsStatic() {
|
||||
int limit = 1;
|
||||
PaginationOptions options = limit(limit);
|
||||
assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("limit"));
|
||||
}
|
||||
|
||||
public void testOffsetStatic() {
|
||||
int offset = 1;
|
||||
PaginationOptions options = offset(offset);
|
||||
assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("offset"));
|
||||
}
|
||||
|
||||
public void testNameFilterStatic() {
|
||||
String nameFilter = "foo";
|
||||
PaginationOptions options = name(nameFilter);
|
||||
assertEquals(ImmutableList.of("foo"), options.buildQueryParameters().get("name"));
|
||||
}
|
||||
|
||||
public void testQueryParametersStatic() {
|
||||
ImmutableSetMultimap<String, String> queryParameters = ImmutableSetMultimap.<String, String> of(
|
||||
"limit", "1",
|
||||
"offset", "1",
|
||||
"name", "foo");
|
||||
PaginationOptions options = queryParameters(queryParameters);
|
||||
assertEquals(queryParameters, options.buildQueryParameters());
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ package org.jclouds.http.options;
|
|||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
|
@ -134,8 +135,9 @@ public class BaseHttpRequestOptions implements HttpRequestOptions {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[formParameters=" + formParameters + ", headers=" + headers + ", pathSuffix=" + pathSuffix + ", payload="
|
||||
+ payload + ", queryParameters=" + queryParameters + "]";
|
||||
return Objects.toStringHelper(this).omitNullValues().add("formParameters", formParameters)
|
||||
.add("headers", headers).add("pathSuffix", pathSuffix).add("payload", payload)
|
||||
.add("queryParameters", queryParameters).toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue