You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ev...@apache.org on 2013/10/24 23:52:52 UTC

[2/2] git commit: Refactored OpenStack pagination. Removed Rackspace pagination. Prefer PaginationOptions.

Refactored OpenStack pagination. Removed Rackspace pagination. Prefer PaginationOptions.


Project: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/commit/10139865
Tree: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/tree/10139865
Diff: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/diff/10139865

Branch: refs/heads/master
Commit: 1013986585e5982476337dc54e873124a3facb8e
Parents: ac5559c
Author: Everett Toews <ev...@rackspace.com>
Authored: Wed Oct 23 21:28:39 2013 -0500
Committer: Everett Toews <ev...@rackspace.com>
Committed: Thu Oct 24 16:52:25 2013 -0500

----------------------------------------------------------------------
 .../keystone/v2_0/KeystoneFallbacks.java        |  2 +-
 .../v2_0/domain/PaginatedCollection.java        | 81 ----------------
 .../keystone/v2_0/features/TenantApi.java       |  2 +-
 .../keystone/v2_0/features/TenantAsyncApi.java  |  2 +-
 .../keystone/v2_0/features/UserApi.java         |  2 +-
 .../keystone/v2_0/features/UserAsyncApi.java    |  2 +-
 .../v2_0/functions/internal/ParseTenants.java   | 14 +--
 .../v2_0/functions/internal/ParseUsers.java     | 14 +--
 .../v2_0/domain/PaginatedCollection.java        | 93 +++++++++++++++++++
 .../v2_0/options/PaginationOptions.java         | 18 ++++
 .../v2_0/features/UserApiExpectTest.java        |  2 +-
 .../openstack/nova/v2_0/features/FlavorApi.java |  2 +-
 .../nova/v2_0/features/FlavorAsyncApi.java      |  2 +-
 .../openstack/nova/v2_0/features/ImageApi.java  |  2 +-
 .../nova/v2_0/features/ImageAsyncApi.java       |  2 +-
 .../openstack/nova/v2_0/features/ServerApi.java |  2 +-
 .../nova/v2_0/features/ServerAsyncApi.java      |  2 +-
 .../functions/internal/ParseDiagnostics.java    |  4 -
 .../functions/internal/ParseFlavorDetails.java  | 17 ++--
 .../v2_0/functions/internal/ParseFlavors.java   | 15 +--
 .../functions/internal/ParseImageDetails.java   | 16 ++--
 .../v2_0/functions/internal/ParseImages.java    | 15 +--
 .../functions/internal/ParseServerDetails.java  | 17 ++--
 .../v2_0/functions/internal/ParseServers.java   | 15 +--
 .../clouddns/v1/features/DomainApi.java         | 11 ++-
 .../clouddns/v1/features/RecordApi.java         |  8 +-
 .../v1/functions/DomainsToPagedIterable.java    |  4 +-
 .../clouddns/v1/functions/ParseDomains.java     |  2 +-
 .../clouddns/v1/functions/ParseRecords.java     |  4 +-
 .../clouddns/v1/functions/ParseSubdomains.java  |  2 +-
 .../v1/functions/RecordsToPagedIterable.java    |  4 +-
 .../v1/functions/SubdomainsToPagedIterable.java |  4 +-
 .../v2_0/CloudIdentityFallbacks.java            | 48 ----------
 .../v2_0/domain/PaginatedCollection.java        | 87 ------------------
 .../v2_0/options/PaginationOptions.java         | 97 --------------------
 .../v2_0/options/PaginationOptionsTest.java     | 89 ------------------
 .../v1/functions/ParseLoadBalancerUsages.java   |  9 +-
 .../v1/functions/ParseLoadBalancers.java        |  9 +-
 .../v1/functions/ParseNodes.java                |  9 +-
 39 files changed, 228 insertions(+), 502 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneFallbacks.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneFallbacks.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneFallbacks.java
index e05b51e..409022f 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneFallbacks.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneFallbacks.java
@@ -20,7 +20,7 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
 import static org.jclouds.Fallbacks.valOnNotFoundOr404;
 
 import org.jclouds.Fallback;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.v2_0.domain.Link;
 
 import com.google.common.collect.ImmutableSet;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/PaginatedCollection.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/PaginatedCollection.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/PaginatedCollection.java
deleted file mode 100644
index fc34481..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/PaginatedCollection.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF 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.openstack.keystone.v2_0.domain;
-
-import static org.jclouds.http.utils.Queries.queryParser;
-
-import java.util.Collection;
-import java.util.Iterator;
-
-import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.openstack.v2_0.domain.Link;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
-/**
- * base class for a paginated collection in openstack
- * 
- * @see <a
- *      href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Paginated_Collections-d1e325.html">
- *      docs</a>
- * @author Adrian Cole
- */
-@Beta
-public class PaginatedCollection<T> extends IterableWithMarker<T> {
-   private Iterable<T> resources;
-   private Iterable<Link> links;
-
-   protected PaginatedCollection(Iterable<T> resources, Iterable<Link> links) {
-      this.resources = resources != null ? resources : ImmutableSet.<T> of();
-      this.links = links != null ? links : ImmutableSet.<Link> of();
-   }
-
-   @Override
-   public Iterator<T> iterator() {
-      return resources.iterator();
-   }
-
-   /**
-    * links that relate to this collection
-    */
-   public Iterable<Link> getLinks() {
-      return links;
-   }
-
-   @Override
-   public Optional<Object> nextMarker() {
-      return FluentIterable.from(getLinks()).filter(new Predicate<Link>() {
-         @Override
-         public boolean apply(Link link) {
-            return Link.Relation.NEXT == link.getRelation();
-         }
-      }).transform(new Function<Link, Optional<Object>>() {
-         @Override
-         public Optional<Object> apply(Link link) {
-            Collection<String> markers = queryParser().apply(link.getHref().getRawQuery()).get("marker");
-            return Optional.<Object> fromNullable(markers == null ? null : Iterables.get(markers, 0));
-         }
-      }).first().or(Optional.absent());
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantApi.java
index 4f84acd..fa4a571 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantApi.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantApi.java
@@ -17,7 +17,7 @@
 package org.jclouds.openstack.keystone.v2_0.features;
 
 import org.jclouds.collect.PagedIterable;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
 import org.jclouds.openstack.v2_0.options.PaginationOptions;
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantAsyncApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantAsyncApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantAsyncApi.java
index ef40332..64b039b 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantAsyncApi.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantAsyncApi.java
@@ -28,7 +28,7 @@ import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
 import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
 import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseTenants;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserApi.java
index b68658e..ff51648 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserApi.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserApi.java
@@ -18,7 +18,7 @@ package org.jclouds.openstack.keystone.v2_0.features;
 
 import java.util.Set;
 import org.jclouds.collect.PagedIterable;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.keystone.v2_0.domain.Role;
 import org.jclouds.openstack.keystone.v2_0.domain.User;
 import org.jclouds.openstack.v2_0.options.PaginationOptions;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserAsyncApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserAsyncApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserAsyncApi.java
index f71b35f..7f6f540 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserAsyncApi.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserAsyncApi.java
@@ -31,7 +31,7 @@ import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
 import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.keystone.v2_0.domain.Role;
 import org.jclouds.openstack.keystone.v2_0.domain.User;
 import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/ParseTenants.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/ParseTenants.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/ParseTenants.java
index c049a7b..d6b1fbe 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/ParseTenants.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/ParseTenants.java
@@ -17,19 +17,19 @@
 package org.jclouds.openstack.keystone.v2_0.functions.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.openstack.v2_0.options.PaginationOptions.Builder.marker;
 
 import java.beans.ConstructorProperties;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import com.google.common.base.Optional;
 import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
 import org.jclouds.openstack.keystone.v2_0.KeystoneApi;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
 import org.jclouds.openstack.keystone.v2_0.features.TenantApi;
 import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseTenants.Tenants;
@@ -38,6 +38,7 @@ import org.jclouds.openstack.v2_0.domain.Link;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 import com.google.inject.TypeLiteral;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 
 /**
  * boiler plate until we determine a better way
@@ -61,7 +62,7 @@ public class ParseTenants extends ParseJson<Tenants> {
       super(json, TypeLiteral.get(Tenants.class));
    }
 
-   public static class ToPagedIterable extends CallerArg0ToPagedIterable<Tenant, ToPagedIterable> {
+   public static class ToPagedIterable extends Arg0ToPagedIterable.FromCaller<Tenant, ToPagedIterable> {
 
       private final KeystoneApi api;
 
@@ -71,14 +72,15 @@ public class ParseTenants extends ParseJson<Tenants> {
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<Tenant>> markerToNextForCallingArg0(final String ignored) {
+      protected Function<Object, IterableWithMarker<Tenant>> markerToNextForArg0(Optional<Object> ignored) {
          final TenantApi tenantApi = api.getTenantApi().get();
          return new Function<Object, IterableWithMarker<Tenant>>() {
 
             @SuppressWarnings("unchecked")
             @Override
             public IterableWithMarker<Tenant> apply(Object input) {
-               return IterableWithMarker.class.cast(tenantApi.list(marker(input.toString())));
+               PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+               return IterableWithMarker.class.cast(tenantApi.list(paginationOptions));
             }
 
             @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/ParseUsers.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/ParseUsers.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/ParseUsers.java
index a1a1803..f1df383 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/ParseUsers.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/ParseUsers.java
@@ -17,19 +17,19 @@
 package org.jclouds.openstack.keystone.v2_0.functions.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.openstack.v2_0.options.PaginationOptions.Builder.marker;
 
 import java.beans.ConstructorProperties;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import com.google.common.base.Optional;
 import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
 import org.jclouds.openstack.keystone.v2_0.KeystoneApi;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.keystone.v2_0.domain.User;
 import org.jclouds.openstack.keystone.v2_0.features.UserApi;
 import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseUsers.Users;
@@ -38,6 +38,7 @@ import org.jclouds.openstack.v2_0.domain.Link;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 import com.google.inject.TypeLiteral;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 
 /**
  * boiler plate until we determine a better way
@@ -61,7 +62,7 @@ public class ParseUsers extends ParseJson<Users> {
       super(json, TypeLiteral.get(Users.class));
    }
 
-   public static class ToPagedIterable extends CallerArg0ToPagedIterable<User, ToPagedIterable> {
+   public static class ToPagedIterable extends Arg0ToPagedIterable.FromCaller<User, ToPagedIterable> {
 
       private final KeystoneApi api;
 
@@ -71,14 +72,15 @@ public class ParseUsers extends ParseJson<Users> {
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<User>> markerToNextForCallingArg0(final String ignored) {
+      protected Function<Object, IterableWithMarker<User>> markerToNextForArg0(Optional<Object> ignored) {
          final UserApi userApi = api.getUserApi().get();
          return new Function<Object, IterableWithMarker<User>>() {
 
             @SuppressWarnings("unchecked")
             @Override
             public IterableWithMarker<User> apply(Object input) {
-               return IterableWithMarker.class.cast(userApi.list(marker(input.toString())));
+               PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+               return IterableWithMarker.class.cast(userApi.list(paginationOptions));
             }
 
             @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/domain/PaginatedCollection.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/domain/PaginatedCollection.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/domain/PaginatedCollection.java
new file mode 100644
index 0000000..aab728d
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/domain/PaginatedCollection.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.openstack.v2_0.domain;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
+
+import java.util.Iterator;
+
+import static org.jclouds.http.utils.Queries.queryParser;
+
+/**
+ * Base class for a paginated collection in OpenStack.
+ *
+ * @see <a
+ *      href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Paginated_Collections-d1e325.html">
+ *      docs</a>
+ * @author Everett Toews
+ */
+public class PaginatedCollection<T> extends IterableWithMarker<T> {
+   private final Iterable<T> resources;
+   private final Iterable<Link> links;
+   private final Integer totalEntries;
+
+   protected PaginatedCollection(Iterable<T> resources, Iterable<Link> links, @Nullable Integer totalEntries) {
+      this.resources = resources != null ? resources : ImmutableSet.<T> of();
+      this.links = links != null ? links : ImmutableSet.<Link> of();
+      this.totalEntries = totalEntries;
+   }
+
+   protected PaginatedCollection(Iterable<T> resources, Iterable<Link> links) {
+      this(resources, links, null);
+   }
+
+   @Override
+   public Iterator<T> iterator() {
+      return resources.iterator();
+   }
+
+   /**
+    * links that relate to this collection
+    */
+   public Iterable<Link> getLinks() {
+      return links;
+   }
+
+   /**
+    * @return The total number of entries in this collection, if that information is present.
+    */
+   public Optional<Integer> getTotalEntries() {
+      return Optional.fromNullable(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.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;
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/options/PaginationOptions.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/options/PaginationOptions.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/options/PaginationOptions.java
index 37bed95..c0a3615 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/options/PaginationOptions.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/options/PaginationOptions.java
@@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkState;
 
 import java.util.Date;
 
+import com.google.common.collect.Multimap;
 import org.jclouds.http.options.BaseHttpRequestOptions;
 
 /**
@@ -33,6 +34,16 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
  */
 public class PaginationOptions extends BaseHttpRequestOptions {
    /**
+    * Many OpenStack interfaces take different params for pagination. Using queryParams allows you to make
+    * use of them all if necessary.
+    */
+   public PaginationOptions queryParameters(Multimap<String, String> queryParams) {
+      checkNotNull(queryParams, "queryParams");
+      queryParameters.putAll(queryParams);
+      return this;
+   }
+
+   /**
     * Only return objects changed since this time.
     */
    public PaginationOptions changesSince(Date ifModifiedSince) {
@@ -65,6 +76,13 @@ public class PaginationOptions extends BaseHttpRequestOptions {
    }
 
    public static class Builder {
+      /**
+       * @see PaginationOptions#queryParameters(Multimap)
+       */
+      public static PaginationOptions queryParameters(Multimap<String, String> queryParams) {
+         PaginationOptions options = new PaginationOptions();
+         return options.queryParameters(queryParams);
+      }
 
       /**
        * @see PaginationOptions#marker(String)

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserApiExpectTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserApiExpectTest.java
index 23dd3ee..59e65db 100644
--- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserApiExpectTest.java
+++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserApiExpectTest.java
@@ -28,7 +28,7 @@ import java.util.Set;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.HttpResponseException;
 import org.jclouds.openstack.keystone.v2_0.KeystoneApi;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.keystone.v2_0.domain.Role;
 import org.jclouds.openstack.keystone.v2_0.domain.User;
 import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestApiExpectTest;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorApi.java
index 23a2f83..7924120 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorApi.java
@@ -17,7 +17,7 @@
 package org.jclouds.openstack.nova.v2_0.features;
 
 import org.jclouds.collect.PagedIterable;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.nova.v2_0.domain.Flavor;
 import org.jclouds.openstack.v2_0.domain.Resource;
 import org.jclouds.openstack.v2_0.options.PaginationOptions;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorAsyncApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorAsyncApi.java
index cdd7cf2..7c1552e 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorAsyncApi.java
@@ -31,7 +31,7 @@ import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.openstack.nova.v2_0.domain.Flavor;
 import org.jclouds.openstack.nova.v2_0.functions.internal.ParseFlavorDetails;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageApi.java
index dee653c..cc7f468 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageApi.java
@@ -19,7 +19,7 @@ package org.jclouds.openstack.nova.v2_0.features;
 import java.util.Map;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.nova.v2_0.domain.Image;
 import org.jclouds.openstack.v2_0.domain.Resource;
 import org.jclouds.openstack.v2_0.options.PaginationOptions;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageAsyncApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageAsyncApi.java
index 3711826..f45826c 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageAsyncApi.java
@@ -35,7 +35,7 @@ import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.openstack.nova.v2_0.binders.BindMetadataToJsonPayload;
 import org.jclouds.openstack.nova.v2_0.domain.Image;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerApi.java
index 9c65bff..9354d9a 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerApi.java
@@ -20,7 +20,7 @@ import com.google.common.base.Optional;
 import java.util.Map;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.nova.v2_0.domain.RebootType;
 import org.jclouds.openstack.nova.v2_0.domain.Server;
 import org.jclouds.openstack.nova.v2_0.domain.ServerCreated;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerAsyncApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerAsyncApi.java
index 43ae85d..2d63d65 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerAsyncApi.java
@@ -38,7 +38,7 @@ import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
 import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.openstack.nova.v2_0.binders.BindMetadataToJsonPayload;
 import org.jclouds.openstack.nova.v2_0.domain.RebootType;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseDiagnostics.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseDiagnostics.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseDiagnostics.java
index d1f7e94..366aa4c 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseDiagnostics.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseDiagnostics.java
@@ -19,14 +19,10 @@ package org.jclouds.openstack.nova.v2_0.functions.internal;
 import static com.google.common.base.Preconditions.checkNotNull;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.functions.ParseJson;
-import org.jclouds.json.internal.GsonWrapper;
 
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
-import com.google.common.base.Supplier;
-import com.google.common.collect.Iterables;
 import com.google.inject.Inject;
-import com.google.inject.TypeLiteral;
 import java.util.Map;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseFlavorDetails.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseFlavorDetails.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseFlavorDetails.java
index 6cbec6a..7e15016 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseFlavorDetails.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseFlavorDetails.java
@@ -17,18 +17,18 @@
 package org.jclouds.openstack.nova.v2_0.functions.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.openstack.v2_0.options.PaginationOptions.Builder.marker;
 
 import java.beans.ConstructorProperties;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import com.google.common.base.Optional;
 import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.domain.Flavor;
 import org.jclouds.openstack.nova.v2_0.features.FlavorApi;
@@ -38,6 +38,7 @@ import org.jclouds.openstack.v2_0.domain.Link;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 import com.google.inject.TypeLiteral;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 
 /**
  * boiler plate until we determine a better way
@@ -61,7 +62,7 @@ public class ParseFlavorDetails extends ParseJson<Flavors> {
       super(json, TypeLiteral.get(Flavors.class));
    }
 
-   public static class ToPagedIterable extends CallerArg0ToPagedIterable<Flavor, ToPagedIterable> {
+   public static class ToPagedIterable extends Arg0ToPagedIterable.FromCaller<Flavor, ToPagedIterable> {
 
       private final NovaApi api;
 
@@ -71,14 +72,16 @@ public class ParseFlavorDetails extends ParseJson<Flavors> {
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<Flavor>> markerToNextForCallingArg0(final String zone) {
+      protected Function<Object, IterableWithMarker<Flavor>> markerToNextForArg0(Optional<Object> arg0) {
+         String zone = arg0.get().toString();
          final FlavorApi flavorApi = api.getFlavorApiForZone(zone);
          return new Function<Object, IterableWithMarker<Flavor>>() {
 
             @SuppressWarnings("unchecked")
             @Override
             public IterableWithMarker<Flavor> apply(Object input) {
-               return IterableWithMarker.class.cast(flavorApi.listInDetail(marker(input.toString())));
+               PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+               return IterableWithMarker.class.cast(flavorApi.listInDetail(paginationOptions));
             }
 
             @Override
@@ -87,7 +90,5 @@ public class ParseFlavorDetails extends ParseJson<Flavors> {
             }
          };
       }
-
    }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseFlavors.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseFlavors.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseFlavors.java
index 6f8e5ba..5d183f4 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseFlavors.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseFlavors.java
@@ -17,18 +17,18 @@
 package org.jclouds.openstack.nova.v2_0.functions.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.openstack.v2_0.options.PaginationOptions.Builder.marker;
 
 import java.beans.ConstructorProperties;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import com.google.common.base.Optional;
 import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.features.FlavorApi;
 import org.jclouds.openstack.nova.v2_0.functions.internal.ParseFlavors.Flavors;
@@ -38,6 +38,7 @@ import org.jclouds.openstack.v2_0.domain.Resource;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 import com.google.inject.TypeLiteral;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 
 /**
  * boiler plate until we determine a better way
@@ -61,7 +62,7 @@ public class ParseFlavors extends ParseJson<Flavors> {
       super(json, TypeLiteral.get(Flavors.class));
    }
 
-   public static class ToPagedIterable extends CallerArg0ToPagedIterable<Resource, ToPagedIterable> {
+   public static class ToPagedIterable extends Arg0ToPagedIterable.FromCaller<Resource, ToPagedIterable> {
 
       private final NovaApi api;
 
@@ -71,14 +72,16 @@ public class ParseFlavors extends ParseJson<Flavors> {
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<Resource>> markerToNextForCallingArg0(final String zone) {
+      protected Function<Object, IterableWithMarker<Resource>> markerToNextForArg0(Optional<Object> arg0) {
+         String zone = arg0.get().toString();
          final FlavorApi flavorApi = api.getFlavorApiForZone(zone);
          return new Function<Object, IterableWithMarker<Resource>>() {
 
             @SuppressWarnings("unchecked")
             @Override
             public IterableWithMarker<Resource> apply(Object input) {
-               return IterableWithMarker.class.cast(flavorApi.list(marker(input.toString())));
+               PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+               return IterableWithMarker.class.cast(flavorApi.list(paginationOptions));
             }
 
             @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseImageDetails.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseImageDetails.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseImageDetails.java
index 4f2cdb3..c69103a 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseImageDetails.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseImageDetails.java
@@ -17,18 +17,18 @@
 package org.jclouds.openstack.nova.v2_0.functions.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.openstack.v2_0.options.PaginationOptions.Builder.marker;
 
 import java.beans.ConstructorProperties;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import com.google.common.base.Optional;
 import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.domain.Image;
 import org.jclouds.openstack.nova.v2_0.features.ImageApi;
@@ -38,6 +38,7 @@ import org.jclouds.openstack.v2_0.domain.Link;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 import com.google.inject.TypeLiteral;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 
 /**
  * boiler plate until we determine a better way
@@ -61,7 +62,7 @@ public class ParseImageDetails extends ParseJson<Images> {
       super(json, TypeLiteral.get(Images.class));
    }
 
-   public static class ToPagedIterable extends CallerArg0ToPagedIterable<Image, ToPagedIterable> {
+   public static class ToPagedIterable extends Arg0ToPagedIterable.FromCaller<Image, ToPagedIterable> {
 
       private final NovaApi api;
 
@@ -71,14 +72,16 @@ public class ParseImageDetails extends ParseJson<Images> {
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<Image>> markerToNextForCallingArg0(final String zone) {
+      protected Function<Object, IterableWithMarker<Image>> markerToNextForArg0(Optional<Object> arg0) {
+         String zone = arg0.get().toString();
          final ImageApi imageApi = api.getImageApiForZone(zone);
          return new Function<Object, IterableWithMarker<Image>>() {
 
             @SuppressWarnings("unchecked")
             @Override
             public IterableWithMarker<Image> apply(Object input) {
-               return IterableWithMarker.class.cast(imageApi.listInDetail(marker(input.toString())));
+               PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+               return IterableWithMarker.class.cast(imageApi.listInDetail(paginationOptions));
             }
 
             @Override
@@ -87,7 +90,6 @@ public class ParseImageDetails extends ParseJson<Images> {
             }
          };
       }
-
    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseImages.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseImages.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseImages.java
index 140f0c0..a939134 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseImages.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseImages.java
@@ -17,18 +17,18 @@
 package org.jclouds.openstack.nova.v2_0.functions.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.openstack.v2_0.options.PaginationOptions.Builder.marker;
 
 import java.beans.ConstructorProperties;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import com.google.common.base.Optional;
 import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.features.ImageApi;
 import org.jclouds.openstack.nova.v2_0.functions.internal.ParseImages.Images;
@@ -38,6 +38,7 @@ import org.jclouds.openstack.v2_0.domain.Resource;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 import com.google.inject.TypeLiteral;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 
 /**
  * boiler plate until we determine a better way
@@ -61,7 +62,7 @@ public class ParseImages extends ParseJson<Images> {
       super(json, TypeLiteral.get(Images.class));
    }
 
-   public static class ToPagedIterable extends CallerArg0ToPagedIterable<Resource, ToPagedIterable> {
+   public static class ToPagedIterable extends Arg0ToPagedIterable.FromCaller<Resource, ToPagedIterable> {
 
       private final NovaApi api;
 
@@ -71,14 +72,16 @@ public class ParseImages extends ParseJson<Images> {
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<Resource>> markerToNextForCallingArg0(final String zone) {
+      protected Function<Object, IterableWithMarker<Resource>> markerToNextForArg0(Optional<Object> arg0) {
+         String zone = arg0.get().toString();
          final ImageApi imageApi = api.getImageApiForZone(zone);
          return new Function<Object, IterableWithMarker<Resource>>() {
 
             @SuppressWarnings("unchecked")
             @Override
             public IterableWithMarker<Resource> apply(Object input) {
-               return IterableWithMarker.class.cast(imageApi.list(marker(input.toString())));
+               PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+               return IterableWithMarker.class.cast(imageApi.list(paginationOptions));
             }
 
             @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseServerDetails.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseServerDetails.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseServerDetails.java
index 77e94a5..4af2cea 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseServerDetails.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseServerDetails.java
@@ -17,18 +17,18 @@
 package org.jclouds.openstack.nova.v2_0.functions.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.openstack.v2_0.options.PaginationOptions.Builder.marker;
 
 import java.beans.ConstructorProperties;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import com.google.common.base.Optional;
 import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.domain.Server;
 import org.jclouds.openstack.nova.v2_0.features.ServerApi;
@@ -38,6 +38,7 @@ import org.jclouds.openstack.v2_0.domain.Link;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 import com.google.inject.TypeLiteral;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 
 /**
  * boiler plate until we determine a better way
@@ -61,7 +62,7 @@ public class ParseServerDetails extends ParseJson<Servers> {
       super(json, TypeLiteral.get(Servers.class));
    }
 
-   public static class ToPagedIterable extends CallerArg0ToPagedIterable<Server, ToPagedIterable> {
+   public static class ToPagedIterable extends Arg0ToPagedIterable.FromCaller<Server, ToPagedIterable> {
 
       private final NovaApi api;
 
@@ -71,14 +72,16 @@ public class ParseServerDetails extends ParseJson<Servers> {
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<Server>> markerToNextForCallingArg0(final String zone) {
+      protected Function<Object, IterableWithMarker<Server>> markerToNextForArg0(Optional<Object> arg0) {
+         String zone = arg0.get().toString();
          final ServerApi serverApi = api.getServerApiForZone(zone);
          return new Function<Object, IterableWithMarker<Server>>() {
 
             @SuppressWarnings("unchecked")
             @Override
             public IterableWithMarker<Server> apply(Object input) {
-               return IterableWithMarker.class.cast(serverApi.listInDetail(marker(input.toString())));
+               PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+               return IterableWithMarker.class.cast(serverApi.listInDetail(paginationOptions));
             }
 
             @Override
@@ -87,7 +90,5 @@ public class ParseServerDetails extends ParseJson<Servers> {
             }
          };
       }
-
    }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseServers.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseServers.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseServers.java
index e9d0315..2de8c76 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseServers.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/functions/internal/ParseServers.java
@@ -17,18 +17,18 @@
 package org.jclouds.openstack.nova.v2_0.functions.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.openstack.v2_0.options.PaginationOptions.Builder.marker;
 
 import java.beans.ConstructorProperties;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import com.google.common.base.Optional;
 import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.features.ServerApi;
 import org.jclouds.openstack.nova.v2_0.functions.internal.ParseServers.Servers;
@@ -38,6 +38,7 @@ import org.jclouds.openstack.v2_0.domain.Resource;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 import com.google.inject.TypeLiteral;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 
 /**
  * boiler plate until we determine a better way
@@ -61,7 +62,7 @@ public class ParseServers extends ParseJson<Servers> {
       super(json, TypeLiteral.get(Servers.class));
    }
 
-   public static class ToPagedIterable extends CallerArg0ToPagedIterable<Resource, ToPagedIterable> {
+   public static class ToPagedIterable extends Arg0ToPagedIterable.FromCaller<Resource, ToPagedIterable> {
 
       private final NovaApi api;
 
@@ -71,14 +72,16 @@ public class ParseServers extends ParseJson<Servers> {
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<Resource>> markerToNextForCallingArg0(final String zone) {
+      protected Function<Object, IterableWithMarker<Resource>> markerToNextForArg0(Optional<Object> arg0) {
+         String zone = arg0.get().toString();
          final ServerApi serverApi = api.getServerApiForZone(zone);
          return new Function<Object, IterableWithMarker<Resource>>() {
 
             @SuppressWarnings("unchecked")
             @Override
             public IterableWithMarker<Resource> apply(Object input) {
-               return IterableWithMarker.class.cast(serverApi.list(marker(input.toString())));
+               PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+               return IterableWithMarker.class.cast(serverApi.list(paginationOptions));
             }
 
             @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/features/DomainApi.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/features/DomainApi.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/features/DomainApi.java
index e72c9f0..bf17e1c 100644
--- a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/features/DomainApi.java
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/features/DomainApi.java
@@ -37,7 +37,10 @@ import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks;
 import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 import org.jclouds.rackspace.clouddns.v1.CloudDNSApi;
 import org.jclouds.rackspace.clouddns.v1.binders.FormatAndContentsToJSON;
 import org.jclouds.rackspace.clouddns.v1.binders.UpdateDomainsToJSON;
@@ -55,10 +58,8 @@ import org.jclouds.rackspace.clouddns.v1.functions.ParseJob;
 import org.jclouds.rackspace.clouddns.v1.functions.ParseSubdomains;
 import org.jclouds.rackspace.clouddns.v1.functions.SubdomainsToPagedIterable;
 import org.jclouds.rackspace.clouddns.v1.predicates.JobPredicates;
-import org.jclouds.rackspace.cloudidentity.v2_0.CloudIdentityFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
-import org.jclouds.rackspace.cloudidentity.v2_0.domain.PaginatedCollection;
 import org.jclouds.rackspace.cloudidentity.v2_0.functions.DateParser;
-import org.jclouds.rackspace.cloudidentity.v2_0.options.PaginationOptions;
+
 import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.Endpoint;
 import org.jclouds.rest.annotations.Fallback;
@@ -144,7 +145,7 @@ public interface DomainApi {
    @GET
    @ResponseParser(ParseDomains.class)
    @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
+   @Fallback(KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404.class)
    @Path("/domains")
    PaginatedCollection<Domain> list(PaginationOptions options);
 
@@ -168,7 +169,7 @@ public interface DomainApi {
    @GET
    @ResponseParser(ParseSubdomains.class)
    @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
+   @Fallback(KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404.class)
    @Path("/domains/{domainId}/subdomains")
    PaginatedCollection<Subdomain> listSubdomains(@PathParam("domainId") int domainId,
          PaginationOptions options);

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/features/RecordApi.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/features/RecordApi.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/features/RecordApi.java
index 9761025..20a26be 100644
--- a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/features/RecordApi.java
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/features/RecordApi.java
@@ -35,7 +35,10 @@ import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks;
 import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 import org.jclouds.rackspace.clouddns.v1.CloudDNSApi;
 import org.jclouds.rackspace.clouddns.v1.binders.UpdateRecordsToJSON;
 import org.jclouds.rackspace.clouddns.v1.config.CloudDNS;
@@ -48,9 +51,6 @@ import org.jclouds.rackspace.clouddns.v1.functions.ParseRecord;
 import org.jclouds.rackspace.clouddns.v1.functions.ParseRecords;
 import org.jclouds.rackspace.clouddns.v1.functions.RecordsToPagedIterable;
 import org.jclouds.rackspace.clouddns.v1.predicates.JobPredicates;
-import org.jclouds.rackspace.cloudidentity.v2_0.CloudIdentityFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
-import org.jclouds.rackspace.cloudidentity.v2_0.domain.PaginatedCollection;
-import org.jclouds.rackspace.cloudidentity.v2_0.options.PaginationOptions;
 import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.Endpoint;
 import org.jclouds.rest.annotations.Fallback;
@@ -142,7 +142,7 @@ public interface RecordApi {
    @GET
    @ResponseParser(ParseRecords.class)
    @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
+   @Fallback(KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404.class)
    @Path("/records")
    PaginatedCollection<RecordDetail> list(PaginationOptions options);
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/DomainsToPagedIterable.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/DomainsToPagedIterable.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/DomainsToPagedIterable.java
index fcde322..eba9e03 100644
--- a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/DomainsToPagedIterable.java
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/DomainsToPagedIterable.java
@@ -22,11 +22,11 @@ import javax.inject.Inject;
 
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.internal.Arg0ToPagedIterable;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 import org.jclouds.rackspace.clouddns.v1.CloudDNSApi;
 import org.jclouds.rackspace.clouddns.v1.domain.Domain;
 import org.jclouds.rackspace.clouddns.v1.features.DomainApi;
-import org.jclouds.rackspace.cloudidentity.v2_0.domain.PaginatedCollection;
-import org.jclouds.rackspace.cloudidentity.v2_0.options.PaginationOptions;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseDomains.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseDomains.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseDomains.java
index 70dbe07..2317693 100644
--- a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseDomains.java
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseDomains.java
@@ -25,8 +25,8 @@ import javax.inject.Inject;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.rackspace.clouddns.v1.domain.Domain;
-import org.jclouds.rackspace.cloudidentity.v2_0.domain.PaginatedCollection;
 
 import com.google.common.base.Function;
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseRecords.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseRecords.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseRecords.java
index 70599aa..85ca49d 100644
--- a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseRecords.java
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseRecords.java
@@ -26,9 +26,9 @@ import javax.inject.Inject;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.rackspace.clouddns.v1.domain.RecordDetail;
 import org.jclouds.rackspace.clouddns.v1.functions.ParseRecord.RawRecord;
-import org.jclouds.rackspace.cloudidentity.v2_0.domain.PaginatedCollection;
 
 import com.google.common.base.Function;
 
@@ -49,7 +49,7 @@ public class ParseRecords implements Function<HttpResponse, PaginatedCollection<
       RawRecords rawRecords = json.apply(response);
       Iterable<RecordDetail> records = rawRecords.transform(toRecordDetails);
 
-      return new Records(records, rawRecords.getLinks(), rawRecords.getTotalEntries());
+      return new Records(records, rawRecords.getLinks(), rawRecords.getTotalEntries().get());
    }
 
    private static class RawRecords extends PaginatedCollection<RawRecord> {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseSubdomains.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseSubdomains.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseSubdomains.java
index 520771d..9b7d0bd 100644
--- a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseSubdomains.java
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/ParseSubdomains.java
@@ -26,8 +26,8 @@ import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.rackspace.clouddns.v1.domain.Subdomain;
-import org.jclouds.rackspace.cloudidentity.v2_0.domain.PaginatedCollection;
 import org.jclouds.rest.InvocationContext;
 
 import com.google.common.base.Function;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/RecordsToPagedIterable.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/RecordsToPagedIterable.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/RecordsToPagedIterable.java
index 3bab55c..cfb7d46 100644
--- a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/RecordsToPagedIterable.java
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/RecordsToPagedIterable.java
@@ -22,11 +22,11 @@ import javax.inject.Inject;
 
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.internal.Arg0ToPagedIterable;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 import org.jclouds.rackspace.clouddns.v1.CloudDNSApi;
 import org.jclouds.rackspace.clouddns.v1.domain.RecordDetail;
 import org.jclouds.rackspace.clouddns.v1.features.RecordApi;
-import org.jclouds.rackspace.cloudidentity.v2_0.domain.PaginatedCollection;
-import org.jclouds.rackspace.cloudidentity.v2_0.options.PaginationOptions;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/SubdomainsToPagedIterable.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/SubdomainsToPagedIterable.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/SubdomainsToPagedIterable.java
index e8bd48f..0895186 100644
--- a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/SubdomainsToPagedIterable.java
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/functions/SubdomainsToPagedIterable.java
@@ -22,11 +22,11 @@ import javax.inject.Inject;
 
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.internal.Arg0ToPagedIterable;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 import org.jclouds.rackspace.clouddns.v1.CloudDNSApi;
 import org.jclouds.rackspace.clouddns.v1.domain.Subdomain;
 import org.jclouds.rackspace.clouddns.v1.features.DomainApi;
-import org.jclouds.rackspace.cloudidentity.v2_0.domain.PaginatedCollection;
-import org.jclouds.rackspace.cloudidentity.v2_0.options.PaginationOptions;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityFallbacks.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityFallbacks.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityFallbacks.java
deleted file mode 100644
index f4dfde0..0000000
--- a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityFallbacks.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF 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);
-      }
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/domain/PaginatedCollection.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/domain/PaginatedCollection.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/domain/PaginatedCollection.java
deleted file mode 100644
index b8356f2..0000000
--- a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/domain/PaginatedCollection.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF 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;
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/options/PaginationOptions.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/options/PaginationOptions.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/options/PaginationOptions.java
deleted file mode 100644
index 2e2aaf5..0000000
--- a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/options/PaginationOptions.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF 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);
-      }
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v2_0/options/PaginationOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v2_0/options/PaginationOptionsTest.java b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v2_0/options/PaginationOptionsTest.java
deleted file mode 100644
index 0552f7a..0000000
--- a/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v2_0/options/PaginationOptionsTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF 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());
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancerUsages.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancerUsages.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancerUsages.java
index b5a7787..84e9d5e 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancerUsages.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancerUsages.java
@@ -17,7 +17,6 @@
 package org.jclouds.rackspace.cloudloadbalancers.v1.functions;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.openstack.v2_0.options.PaginationOptions.Builder.marker;
 
 import java.beans.ConstructorProperties;
 
@@ -28,8 +27,9 @@ import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 import org.jclouds.rackspace.cloudloadbalancers.v1.CloudLoadBalancersApi;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.LoadBalancerUsage;
 import org.jclouds.rackspace.cloudloadbalancers.v1.features.ReportApi;
@@ -71,14 +71,15 @@ public class ParseLoadBalancerUsages extends ParseJson<LoadBalancerUsages> {
 
       @Override
       protected Function<Object, IterableWithMarker<LoadBalancerUsage>> markerToNextForArg0(Optional<Object> arg0) {
-         String zone = arg0.isPresent() ? arg0.get().toString() : null;
+         String zone = arg0.get().toString();
          final ReportApi reportApi = api.getReportApiForZone(zone);
          
          return new Function<Object, IterableWithMarker<LoadBalancerUsage>>() {
 
             @Override
             public IterableWithMarker<LoadBalancerUsage> apply(Object input) {
-               IterableWithMarker<LoadBalancerUsage> list = reportApi.listLoadBalancerUsage(marker(input.toString()));
+               PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+               IterableWithMarker<LoadBalancerUsage> list = reportApi.listLoadBalancerUsage(paginationOptions);
                return list;
             }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/10139865/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancers.java
----------------------------------------------------------------------
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancers.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancers.java
index 55b4cb8..7b250c9 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancers.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancers.java
@@ -17,7 +17,6 @@
 package org.jclouds.rackspace.cloudloadbalancers.v1.functions;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.openstack.v2_0.options.PaginationOptions.Builder.marker;
 
 import java.beans.ConstructorProperties;
 import java.net.URI;
@@ -30,8 +29,9 @@ import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.functions.ParseJson;
-import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
 import org.jclouds.rackspace.cloudloadbalancers.v1.CloudLoadBalancersApi;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.LoadBalancer;
 import org.jclouds.rackspace.cloudloadbalancers.v1.features.LoadBalancerApi;
@@ -106,14 +106,15 @@ public class ParseLoadBalancers implements Function<HttpResponse, IterableWithMa
 
       @Override
       protected Function<Object, IterableWithMarker<LoadBalancer>> markerToNextForArg0(Optional<Object> arg0) {
-         String zone = arg0.isPresent() ? arg0.get().toString() : null;
+         String zone = arg0.get().toString();
          final LoadBalancerApi loadBalancerApi = api.getLoadBalancerApiForZone(zone);
          
          return new Function<Object, IterableWithMarker<LoadBalancer>>() {
 
             @Override
             public IterableWithMarker<LoadBalancer> apply(Object input) {
-               IterableWithMarker<LoadBalancer> list = loadBalancerApi.list(marker(input.toString()));
+               PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+               IterableWithMarker<LoadBalancer> list = loadBalancerApi.list(paginationOptions);
                return list;
             }