JCLOUDS-1406 - Add default location configuration to dimension data provider
diff --git a/dimensiondata/pom.xml b/dimensiondata/pom.xml
index 21995aa..0d98756 100644
--- a/dimensiondata/pom.xml
+++ b/dimensiondata/pom.xml
@@ -145,7 +145,6 @@
                                         <test.dimensiondata-cloudcontrol.credential>
                                             ${test.dimensiondata-cloudcontrol.credential}
                                         </test.dimensiondata-cloudcontrol.credential>
-                                        <jclouds.zones>NA9</jclouds.zones>
                                     </systemPropertyVariables>
                                 </configuration>
                             </execution>
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlProviderMetadata.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlProviderMetadata.java
index fd672a3..f25cd15 100644
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlProviderMetadata.java
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlProviderMetadata.java
@@ -23,6 +23,11 @@
 import java.net.URI;
 import java.util.Properties;
 
+import static org.jclouds.location.reference.LocationConstants.ISO3166_CODES;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_ZONE;
+
 /**
  * Implementation of {@link ProviderMetadata} for DimensionData CloudController.
  */
@@ -42,12 +47,31 @@
       super(builder());
    }
 
-   public DimensionDataCloudControlProviderMetadata(Builder builder) {
+   public DimensionDataCloudControlProviderMetadata(final Builder builder) {
       super(builder);
    }
 
    public static Properties defaultProperties() {
       Properties properties = DimensionDataCloudControlApiMetadata.defaultProperties();
+      properties.setProperty(PROPERTY_REGIONS, "na,eu,au,mea,ap,canada");
+      properties.setProperty(PROPERTY_REGION + ".na.zones", "NA9,NA12");
+      properties.setProperty(PROPERTY_ZONE + "NA9" + ISO3166_CODES, "US-VA");
+      properties.setProperty(PROPERTY_ZONE + "NA12" + ISO3166_CODES, "US-CA");
+      properties.setProperty(PROPERTY_REGION + ".eu.zones", "EU6,EU7,EU8");
+      properties.setProperty(PROPERTY_ZONE + "EU6" + ISO3166_CODES, "DE-HE");
+      properties.setProperty(PROPERTY_ZONE + "EU7" + ISO3166_CODES, "NL-NH");
+      properties.setProperty(PROPERTY_ZONE + "EU8" + ISO3166_CODES, "BE-BRU");
+      properties.setProperty(PROPERTY_REGION + ".au.zones", "AU9,AU10,AU11");
+      properties.setProperty(PROPERTY_ZONE + "AU9" + ISO3166_CODES, "AU-NSW");
+      properties.setProperty(PROPERTY_ZONE + "AU10" + ISO3166_CODES, "AU-VIC");
+      properties.setProperty(PROPERTY_ZONE + "AU11" + ISO3166_CODES, "NZ-WKO");
+      properties.setProperty(PROPERTY_REGION + ".mea.zones", "AF3");
+      properties.setProperty(PROPERTY_ZONE + "AF3" + ISO3166_CODES, "ZA-GT");
+      properties.setProperty(PROPERTY_REGION + ".ap.zones", "AP4,AP5");
+      properties.setProperty(PROPERTY_ZONE + "AP4" + ISO3166_CODES, "JP-13");
+      properties.setProperty(PROPERTY_ZONE + "AP5" + ISO3166_CODES, "HK");
+      properties.setProperty(PROPERTY_REGION + ".canada.zones", "CA2");
+      properties.setProperty(PROPERTY_ZONE + "CA2" + ISO3166_CODES, "CA-ON");
       return properties;
    }
 
@@ -68,7 +92,7 @@
       }
 
       @Override
-      public Builder fromProviderMetadata(ProviderMetadata in) {
+      public Builder fromProviderMetadata(final ProviderMetadata in) {
          super.fromProviderMetadata(in);
          return this;
       }
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/config/DimensionDataCloudControlHttpApiModule.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/config/DimensionDataCloudControlHttpApiModule.java
index 0c138e8..8a5af41 100644
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/config/DimensionDataCloudControlHttpApiModule.java
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/config/DimensionDataCloudControlHttpApiModule.java
@@ -18,13 +18,22 @@
 
 import com.google.common.base.Supplier;
 import com.google.inject.Provides;
+import com.google.inject.Scopes;
 import org.jclouds.collect.Memoized;
 import org.jclouds.dimensiondata.cloudcontrol.DimensionDataCloudControlApi;
 import org.jclouds.dimensiondata.cloudcontrol.handlers.DimensionDataCloudControlErrorHandler;
+import org.jclouds.dimensiondata.cloudcontrol.suppliers.RegionsToApiEndpoints;
 import org.jclouds.http.HttpErrorHandler;
 import org.jclouds.http.annotation.ClientError;
 import org.jclouds.http.annotation.Redirection;
 import org.jclouds.http.annotation.ServerError;
+import org.jclouds.location.suppliers.ImplicitLocationSupplier;
+import org.jclouds.location.suppliers.RegionIdToURISupplier;
+import org.jclouds.location.suppliers.ZoneIdToURISupplier;
+import org.jclouds.location.suppliers.ZoneIdsSupplier;
+import org.jclouds.location.suppliers.derived.ZoneIdToURIFromJoinOnRegionIdToURI;
+import org.jclouds.location.suppliers.derived.ZoneIdsFromRegionIdToZoneIdsValues;
+import org.jclouds.location.suppliers.implicit.OnlyLocationOrFirstZone;
 import org.jclouds.rest.AuthorizationException;
 import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.config.HttpApiModule;
@@ -41,6 +50,15 @@
 public class DimensionDataCloudControlHttpApiModule extends HttpApiModule<DimensionDataCloudControlApi> {
 
    @Override
+   protected void installLocations() {
+      super.installLocations();
+      bind(RegionIdToURISupplier.class).to(RegionsToApiEndpoints.class).in(Scopes.SINGLETON);
+      bind(ZoneIdsSupplier.class).to(ZoneIdsFromRegionIdToZoneIdsValues.class).in(Scopes.SINGLETON);
+      bind(ZoneIdToURISupplier.class).to(ZoneIdToURIFromJoinOnRegionIdToURI.class).in(Scopes.SINGLETON);
+      bind(ImplicitLocationSupplier.class).to(OnlyLocationOrFirstZone.class).in(Scopes.SINGLETON);
+   }
+
+   @Override
    protected void bindErrorHandlers() {
       bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(DimensionDataCloudControlErrorHandler.class);
       bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(DimensionDataCloudControlErrorHandler.class);
@@ -50,8 +68,9 @@
    @Provides
    @Singleton
    @Memoized
-   public final Supplier<String> getOrganisationIdForAccount(AtomicReference<AuthorizationException> authException,
-         @Named(PROPERTY_SESSION_INTERVAL) long seconds, DimensionDataCloudControlApi api) {
+   public final Supplier<String> getOrganisationIdForAccount(
+         final AtomicReference<AuthorizationException> authException,
+         @Named(PROPERTY_SESSION_INTERVAL) final long seconds, final DimensionDataCloudControlApi api) {
       return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier
             .create(authException, new OrganisationIdForAccount(api), seconds, TimeUnit.SECONDS);
    }
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Datacenter.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Datacenter.java
index c331fda..639af58 100644
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Datacenter.java
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/Datacenter.java
@@ -38,6 +38,7 @@
 
    public abstract String city();
 
+   @Nullable
    public abstract String state();
 
    public abstract String country();
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/PaginatedCollection.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/PaginatedCollection.java
index d8eca4d..f7d62e3 100644
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/PaginatedCollection.java
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/domain/PaginatedCollection.java
@@ -100,5 +100,4 @@
    private Object toPaginationOptions(Integer pageNumber) {
       return PaginationOptions.Builder.pageNumber(pageNumber);
    }
-
 }
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApi.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApi.java
index a2debef..2d76048 100644
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApi.java
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApi.java
@@ -29,8 +29,9 @@
 import org.jclouds.dimensiondata.cloudcontrol.domain.OperatingSystem;
 import org.jclouds.dimensiondata.cloudcontrol.domain.OperatingSystems;
 import org.jclouds.dimensiondata.cloudcontrol.domain.PaginatedCollection;
-import org.jclouds.dimensiondata.cloudcontrol.filters.DatacenterIdListDatacentersFilter;
 import org.jclouds.dimensiondata.cloudcontrol.filters.OrganisationIdFilter;
+import org.jclouds.dimensiondata.cloudcontrol.options.DatacenterIdListFilters;
+import org.jclouds.dimensiondata.cloudcontrol.options.IdListFilters;
 import org.jclouds.dimensiondata.cloudcontrol.options.PaginationOptions;
 import org.jclouds.http.filters.BasicAuthentication;
 import org.jclouds.http.functions.ParseJson;
@@ -45,9 +46,7 @@
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
-import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
-import java.util.Set;
 
 @RequestFilters({ BasicAuthentication.class, OrganisationIdFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
@@ -58,16 +57,14 @@
    @GET
    @Path("/datacenter")
    @ResponseParser(ParseDatacenters.class)
-   @RequestFilters(DatacenterIdListDatacentersFilter.class)
    @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
-   PaginatedCollection<Datacenter> listDatacenters(PaginationOptions options);
+   PaginatedCollection<Datacenter> listDatacenters(IdListFilters idListFilters);
 
    @Named("infrastructure:datacenter")
    @GET
    @Path("/datacenter")
    @Transform(ParseDatacenters.ToPagedIterable.class)
    @ResponseParser(ParseDatacenters.class)
-   @RequestFilters(DatacenterIdListDatacentersFilter.class)
    @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
    PagedIterable<Datacenter> listDatacenters();
 
@@ -76,8 +73,7 @@
    @Path("/operatingSystem")
    @ResponseParser(ParseOperatingSystems.class)
    @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
-   PaginatedCollection<OperatingSystem> listOperatingSystems(@QueryParam("datacenterId") Set<String> datacenterId,
-         PaginationOptions options);
+   PaginatedCollection<OperatingSystem> listOperatingSystems(DatacenterIdListFilters datacenterIdListFilters);
 
    @Named("infrastructure:operatingSystem")
    @GET
@@ -85,12 +81,12 @@
    @Transform(ParseOperatingSystems.ToPagedIterable.class)
    @ResponseParser(ParseOperatingSystems.class)
    @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
-   PagedIterable<OperatingSystem> listOperatingSystems(@QueryParam("datacenterId") Set<String> datacenterId);
+   PagedIterable<OperatingSystem> listOperatingSystems();
 
    final class ParseDatacenters extends ParseJson<Datacenters> {
 
       @Inject
-      ParseDatacenters(Json json) {
+      ParseDatacenters(final Json json) {
          super(json, TypeLiteral.get(Datacenters.class));
       }
 
@@ -99,17 +95,19 @@
          private DimensionDataCloudControlApi api;
 
          @Inject
-         ToPagedIterable(DimensionDataCloudControlApi api) {
+         ToPagedIterable(final DimensionDataCloudControlApi api) {
             this.api = api;
          }
 
          @Override
-         protected Function<Object, IterableWithMarker<Datacenter>> markerToNextForArg0(Optional<Object> arg) {
+         protected Function<Object, IterableWithMarker<Datacenter>> markerToNextForArg0(final Optional<Object> arg) {
             return new Function<Object, IterableWithMarker<Datacenter>>() {
                @Override
                public IterableWithMarker<Datacenter> apply(Object input) {
-                  PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
-                  return api.getInfrastructureApi().listDatacenters(paginationOptions);
+                  IdListFilters idListFilters = arg.isPresent() ?
+                        ((IdListFilters) arg.get()).paginationOptions(PaginationOptions.class.cast(input)) :
+                        IdListFilters.Builder.paginationOptions(PaginationOptions.class.cast(input));
+                  return api.getInfrastructureApi().listDatacenters(idListFilters);
                }
             };
          }
@@ -119,7 +117,7 @@
    final class ParseOperatingSystems extends ParseJson<OperatingSystems> {
 
       @Inject
-      ParseOperatingSystems(Json json) {
+      ParseOperatingSystems(final Json json) {
          super(json, TypeLiteral.get(OperatingSystems.class));
       }
 
@@ -128,18 +126,20 @@
          private DimensionDataCloudControlApi api;
 
          @Inject
-         ToPagedIterable(DimensionDataCloudControlApi api) {
+         ToPagedIterable(final DimensionDataCloudControlApi api) {
             this.api = api;
          }
 
          @Override
          protected Function<Object, IterableWithMarker<OperatingSystem>> markerToNextForArg0(
-               final Optional<Object> arg) {
+               final Optional<Object> arg0) {
             return new Function<Object, IterableWithMarker<OperatingSystem>>() {
                @Override
                public IterableWithMarker<OperatingSystem> apply(Object input) {
-                  PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
-                  return api.getInfrastructureApi().listOperatingSystems((Set<String>) arg.get(), paginationOptions);
+                  DatacenterIdListFilters datacenterIdListFilters = arg0.isPresent() ?
+                        ((DatacenterIdListFilters) arg0.get()).paginationOptions(PaginationOptions.class.cast(input)) :
+                        DatacenterIdListFilters.Builder.paginationOptions(PaginationOptions.class.cast(input));
+                  return api.getInfrastructureApi().listOperatingSystems(datacenterIdListFilters);
                }
             };
          }
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerApi.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerApi.java
index 5ec225c..6338258 100644
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerApi.java
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerApi.java
@@ -31,8 +31,8 @@
 import org.jclouds.dimensiondata.cloudcontrol.domain.Servers;
 import org.jclouds.dimensiondata.cloudcontrol.domain.options.CloneServerOptions;
 import org.jclouds.dimensiondata.cloudcontrol.domain.options.CreateServerOptions;
-import org.jclouds.dimensiondata.cloudcontrol.filters.DatacenterIdFilter;
 import org.jclouds.dimensiondata.cloudcontrol.filters.OrganisationIdFilter;
+import org.jclouds.dimensiondata.cloudcontrol.options.DatacenterIdListFilters;
 import org.jclouds.dimensiondata.cloudcontrol.options.PaginationOptions;
 import org.jclouds.dimensiondata.cloudcontrol.utils.ParseResponse;
 import org.jclouds.http.filters.BasicAuthentication;
@@ -69,7 +69,7 @@
    @Path("/server")
    @ResponseParser(ParseServers.class)
    @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
-   PaginatedCollection<Server> listServers(PaginationOptions options);
+   PaginatedCollection<Server> listServers(DatacenterIdListFilters datacenterIdListFilters);
 
    @Named("server:list")
    @GET
@@ -77,7 +77,6 @@
    @Transform(ParseServers.ToPagedIterable.class)
    @ResponseParser(ParseServers.class)
    @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
-   @RequestFilters({ DatacenterIdFilter.class })
    PagedIterable<Server> listServers();
 
    @Named("server:get")
@@ -164,7 +163,7 @@
    final class ParseServers extends ParseJson<Servers> {
 
       @Inject
-      ParseServers(Json json) {
+      ParseServers(final Json json) {
          super(json, TypeLiteral.get(Servers.class));
       }
 
@@ -173,17 +172,19 @@
          private DimensionDataCloudControlApi api;
 
          @Inject
-         ToPagedIterable(DimensionDataCloudControlApi api) {
+         ToPagedIterable(final DimensionDataCloudControlApi api) {
             this.api = api;
          }
 
          @Override
-         protected Function<Object, IterableWithMarker<Server>> markerToNextForArg0(Optional<Object> arg0) {
+         protected Function<Object, IterableWithMarker<Server>> markerToNextForArg0(final Optional<Object> arg0) {
             return new Function<Object, IterableWithMarker<Server>>() {
                @Override
                public IterableWithMarker<Server> apply(Object input) {
-                  PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
-                  return api.getServerApi().listServers(paginationOptions);
+                  DatacenterIdListFilters datacenterIdListFilters = arg0.isPresent() ?
+                        ((DatacenterIdListFilters) arg0.get()).paginationOptions(PaginationOptions.class.cast(input)) :
+                        DatacenterIdListFilters.Builder.paginationOptions(PaginationOptions.class.cast(input));
+                  return api.getServerApi().listServers(datacenterIdListFilters);
                }
             };
          }
@@ -195,7 +196,7 @@
    final class ServerId extends ParseResponse {
 
       @Inject
-      ServerId(Json json) {
+      ServerId(final Json json) {
          super(json, "serverId");
       }
    }
@@ -204,7 +205,7 @@
    final class ImageId extends ParseResponse {
 
       @Inject
-      ImageId(Json json) {
+      ImageId(final Json json) {
          super(json, "imageId");
       }
    }
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerImageApi.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerImageApi.java
index 2736a3a..57c560c 100644
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerImageApi.java
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerImageApi.java
@@ -29,8 +29,8 @@
 import org.jclouds.dimensiondata.cloudcontrol.domain.OsImage;
 import org.jclouds.dimensiondata.cloudcontrol.domain.OsImages;
 import org.jclouds.dimensiondata.cloudcontrol.domain.PaginatedCollection;
-import org.jclouds.dimensiondata.cloudcontrol.filters.DatacenterIdFilter;
 import org.jclouds.dimensiondata.cloudcontrol.filters.OrganisationIdFilter;
+import org.jclouds.dimensiondata.cloudcontrol.options.DatacenterIdListFilters;
 import org.jclouds.dimensiondata.cloudcontrol.options.PaginationOptions;
 import org.jclouds.http.filters.BasicAuthentication;
 import org.jclouds.http.functions.ParseJson;
@@ -57,16 +57,14 @@
    @GET
    @Path("/osImage")
    @ResponseParser(ParseOsImages.class)
-   @RequestFilters(DatacenterIdFilter.class)
    @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
-   PaginatedCollection<OsImage> listOsImages(PaginationOptions options);
+   PaginatedCollection<OsImage> listOsImages(DatacenterIdListFilters datacenterIdListFilters);
 
    @Named("image:listOsImages")
    @GET
    @Path("/osImage")
    @Transform(ParseOsImages.ToPagedIterable.class)
    @ResponseParser(ParseOsImages.class)
-   @RequestFilters(DatacenterIdFilter.class)
    @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
    PagedIterable<OsImage> listOsImages();
 
@@ -74,16 +72,14 @@
    @GET
    @Path("/customerImage")
    @ResponseParser(ParseCustomerImages.class)
-   @RequestFilters(DatacenterIdFilter.class)
    @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
-   PaginatedCollection<CustomerImage> listCustomerImages(PaginationOptions options);
+   PaginatedCollection<CustomerImage> listCustomerImages(DatacenterIdListFilters datacenterIdListFilters);
 
    @Named("image:listCustomerImages")
    @GET
    @Path("/customerImage")
    @Transform(ParseCustomerImages.ToPagedIterable.class)
    @ResponseParser(ParseCustomerImages.class)
-   @RequestFilters(DatacenterIdFilter.class)
    @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
    PagedIterable<CustomerImage> listCustomerImages();
 
@@ -111,17 +107,19 @@
          private DimensionDataCloudControlApi api;
 
          @Inject
-         ToPagedIterable(DimensionDataCloudControlApi api) {
+         ToPagedIterable(final DimensionDataCloudControlApi api) {
             this.api = api;
          }
 
          @Override
-         protected Function<Object, IterableWithMarker<OsImage>> markerToNextForArg0(Optional<Object> arg0) {
+         protected Function<Object, IterableWithMarker<OsImage>> markerToNextForArg0(final Optional<Object> arg0) {
             return new Function<Object, IterableWithMarker<OsImage>>() {
                @Override
                public IterableWithMarker<OsImage> apply(Object input) {
-                  PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
-                  return api.getServerImageApi().listOsImages(paginationOptions);
+                  DatacenterIdListFilters datacenterIdListFilters = arg0.isPresent() ?
+                        ((DatacenterIdListFilters) arg0.get()).paginationOptions(PaginationOptions.class.cast(input)) :
+                        DatacenterIdListFilters.Builder.paginationOptions(PaginationOptions.class.cast(input));
+                  return api.getServerImageApi().listOsImages(datacenterIdListFilters);
                }
             };
          }
@@ -140,17 +138,20 @@
          private DimensionDataCloudControlApi api;
 
          @Inject
-         ToPagedIterable(DimensionDataCloudControlApi api) {
+         ToPagedIterable(final DimensionDataCloudControlApi api) {
             this.api = api;
          }
 
          @Override
-         protected Function<Object, IterableWithMarker<CustomerImage>> markerToNextForArg0(Optional<Object> arg0) {
+         protected Function<Object, IterableWithMarker<CustomerImage>> markerToNextForArg0(
+               final Optional<Object> arg0) {
             return new Function<Object, IterableWithMarker<CustomerImage>>() {
                @Override
                public IterableWithMarker<CustomerImage> apply(Object input) {
-                  PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
-                  return api.getServerImageApi().listCustomerImages(paginationOptions);
+                  DatacenterIdListFilters datacenterIdListFilters = arg0.isPresent() ?
+                        ((DatacenterIdListFilters) arg0.get()).paginationOptions(PaginationOptions.class.cast(input)) :
+                        DatacenterIdListFilters.Builder.paginationOptions(PaginationOptions.class.cast(input));
+                  return api.getServerImageApi().listCustomerImages(datacenterIdListFilters);
                }
             };
          }
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/filters/DatacenterIdFilter.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/filters/DatacenterIdFilter.java
deleted file mode 100644
index 41dab36..0000000
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/filters/DatacenterIdFilter.java
+++ /dev/null
@@ -1,49 +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.dimensiondata.cloudcontrol.filters;
-
-import com.google.common.base.Supplier;
-import org.jclouds.http.HttpException;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpRequestFilter;
-import org.jclouds.location.Zone;
-
-import javax.inject.Inject;
-import java.util.Set;
-
-/**
- * Adds set of Datacenter IDs as set in jclouds.zones JVM property.
- */
-public class DatacenterIdFilter implements HttpRequestFilter {
-
-   private final Supplier<Set<String>> datacenterIdsSupplier;
-
-   @Inject
-   DatacenterIdFilter(@Zone Supplier<Set<String>> datacenterIdsSupplier) {
-      this.datacenterIdsSupplier = datacenterIdsSupplier;
-   }
-
-   @Override
-   public HttpRequest filter(HttpRequest request) throws HttpException {
-      Set<String> datacenterIds = datacenterIdsSupplier.get();
-      if (datacenterIds != null && !datacenterIds.isEmpty()) {
-         return request.toBuilder().addQueryParam("datacenterId", datacenterIds).build();
-      } else {
-         return request;
-      }
-   }
-}
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/filters/DatacenterIdListDatacentersFilter.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/filters/DatacenterIdListDatacentersFilter.java
deleted file mode 100644
index a805867..0000000
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/filters/DatacenterIdListDatacentersFilter.java
+++ /dev/null
@@ -1,49 +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.dimensiondata.cloudcontrol.filters;
-
-import com.google.common.base.Supplier;
-import org.jclouds.http.HttpException;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpRequestFilter;
-import org.jclouds.location.Zone;
-
-import javax.inject.Inject;
-import java.util.Set;
-
-/**
- * Adds set of Datacenter IDs as set in jclouds.zones JVM property.
- */
-public class DatacenterIdListDatacentersFilter implements HttpRequestFilter {
-
-   private final Supplier<Set<String>> datacenterIdsSupplier;
-
-   @Inject
-   DatacenterIdListDatacentersFilter(@Zone Supplier<Set<String>> datacenterIdsSupplier) {
-      this.datacenterIdsSupplier = datacenterIdsSupplier;
-   }
-
-   @Override
-   public HttpRequest filter(HttpRequest request) throws HttpException {
-      Set<String> datacenterIds = datacenterIdsSupplier.get();
-      if (datacenterIds != null && !datacenterIds.isEmpty()) {
-         return request.toBuilder().addQueryParam("id", datacenterIds).build();
-      } else {
-         return request;
-      }
-   }
-}
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/options/DatacenterIdListFilters.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/options/DatacenterIdListFilters.java
new file mode 100644
index 0000000..2ec130c
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/options/DatacenterIdListFilters.java
@@ -0,0 +1,75 @@
+/*
+ * 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.dimensiondata.cloudcontrol.options;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+import java.util.Collection;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class DatacenterIdListFilters extends BaseHttpRequestOptions {
+
+   private DatacenterIdListFilters() {
+   }
+
+   public DatacenterIdListFilters datacenterIds(final String... datacenterIds) {
+      for (String datacenterId : datacenterIds) {
+         this.queryParameters.put("datacenterId", checkNotNull(datacenterId, "datacenterId"));
+      }
+      return this;
+   }
+
+   public DatacenterIdListFilters datacenterIds(final Collection<String> datacenterIds) {
+      for (String datacenterId : datacenterIds) {
+         this.queryParameters.put("datacenterId", checkNotNull(datacenterId, "datacenterId"));
+      }
+      return this;
+   }
+
+   public DatacenterIdListFilters paginationOptions(final PaginationOptions paginationOptions) {
+      this.queryParameters.putAll(paginationOptions.buildQueryParameters());
+      return this;
+   }
+
+   public static class Builder {
+
+      /**
+       * @see DatacenterIdListFilters#datacenterIds(Collection<String>)
+       */
+      public static DatacenterIdListFilters datacenterId(final Collection<String> datacenterIds) {
+         DatacenterIdListFilters options = new DatacenterIdListFilters();
+         return options.datacenterIds(datacenterIds);
+      }
+
+      /**
+       * @see DatacenterIdListFilters#datacenterIds(String...)
+       */
+      public static DatacenterIdListFilters datacenterId(final String... ids) {
+         DatacenterIdListFilters options = new DatacenterIdListFilters();
+         return options.datacenterIds(ids);
+      }
+
+      /**
+       * @see DatacenterIdListFilters#paginationOptions(PaginationOptions)
+       */
+      public static DatacenterIdListFilters paginationOptions(PaginationOptions paginationOptions) {
+         DatacenterIdListFilters options = new DatacenterIdListFilters();
+         return options.paginationOptions(paginationOptions);
+      }
+   }
+}
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/options/IdListFilters.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/options/IdListFilters.java
new file mode 100644
index 0000000..3f91c39
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/options/IdListFilters.java
@@ -0,0 +1,76 @@
+/*
+ * 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.dimensiondata.cloudcontrol.options;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+import java.util.Collection;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class IdListFilters extends BaseHttpRequestOptions {
+
+   private IdListFilters() {
+   }
+
+   public IdListFilters ids(final String... ids) {
+      for (String id : ids) {
+         this.queryParameters.put("id", checkNotNull(id, "id"));
+      }
+      return this;
+   }
+
+   public IdListFilters ids(final Collection<String> ids) {
+      for (String id : ids) {
+         this.queryParameters.put("id", checkNotNull(id, "id"));
+      }
+      return this;
+   }
+
+   public IdListFilters paginationOptions(final PaginationOptions paginationOptions) {
+      this.queryParameters.putAll(paginationOptions.buildQueryParameters());
+      return this;
+   }
+
+   public static class Builder {
+
+      /**
+       * @see IdListFilters#ids(Collection<String>)
+       */
+      public static IdListFilters ids(final Collection<String> ids) {
+         IdListFilters options = new IdListFilters();
+         return options.ids(ids);
+      }
+
+      /**
+       * @see IdListFilters#ids(String...)
+       */
+      public static IdListFilters ids(final String... ids) {
+         IdListFilters options = new IdListFilters();
+         return options.ids(ids);
+      }
+
+      /**
+       * @see IdListFilters#paginationOptions(PaginationOptions)
+       */
+      public static IdListFilters paginationOptions(PaginationOptions paginationOptions) {
+         IdListFilters options = new IdListFilters();
+         return options.paginationOptions(paginationOptions);
+      }
+   }
+}
+
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/options/PaginationOptions.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/options/PaginationOptions.java
index 06bd478..a989e0f 100644
--- a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/options/PaginationOptions.java
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/options/PaginationOptions.java
@@ -23,23 +23,39 @@
 
 public class PaginationOptions extends BaseHttpRequestOptions {
 
+   public static final String PAGE_NUMBER = "pageNumber";
+   public static final String ORDER_BY = "orderBy";
+   public static final String PAGE_SIZE = "pageSize";
+
    public PaginationOptions pageNumber(int pageNumber) {
-      this.queryParameters.put("pageNumber", Integer.toString(pageNumber));
+      this.queryParameters.put(PAGE_NUMBER, Integer.toString(pageNumber));
       return this;
    }
 
+   public String pageNumber() {
+      return getFirstQueryOrNull(PAGE_NUMBER);
+   }
+
    public PaginationOptions orderBy(String orderBy) {
-      this.queryParameters.put("orderBy", checkNotNull(orderBy, "orderBy"));
+      this.queryParameters.put(ORDER_BY, checkNotNull(orderBy, ORDER_BY));
       return this;
    }
 
+   public String orderBy() {
+      return getFirstQueryOrNull(ORDER_BY);
+   }
+
    public PaginationOptions pageSize(int pageSize) {
       checkState(pageSize >= 0, "pageSize must be >= 0");
       checkState(pageSize <= 10000, "limit must be <= 10000");
-      queryParameters.put("pageSize", Integer.toString(pageSize));
+      queryParameters.put(PAGE_SIZE, Integer.toString(pageSize));
       return this;
    }
 
+   public String pageSize() {
+      return getFirstQueryOrNull(PAGE_SIZE);
+   }
+
    public static class Builder {
 
       /**
diff --git a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/suppliers/RegionsToApiEndpoints.java b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/suppliers/RegionsToApiEndpoints.java
new file mode 100644
index 0000000..179d42b
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/suppliers/RegionsToApiEndpoints.java
@@ -0,0 +1,50 @@
+/*
+ * 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.dimensiondata.cloudcontrol.suppliers;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import org.jclouds.location.Region;
+import org.jclouds.location.suppliers.RegionIdToURISupplier;
+
+import javax.inject.Inject;
+import java.net.URI;
+import java.util.Map;
+import java.util.Set;
+
+public class RegionsToApiEndpoints implements RegionIdToURISupplier {
+
+   private static final String DIMENSION_DATA_API_URL_TEMPLATE = "https://api-%s.dimensiondata.com";
+   private final Supplier<Set<String>> regionIds;
+
+   @Inject
+   RegionsToApiEndpoints(@Region Supplier<Set<String>> regionIds) {
+      this.regionIds = regionIds;
+   }
+
+   @Override
+   public Map<String, Supplier<URI>> get() {
+      Builder<String, Supplier<URI>> regionToEndpoint = ImmutableMap.builder();
+      for (String region : regionIds.get()) {
+         URI endpoint = URI.create(String.format(DIMENSION_DATA_API_URL_TEMPLATE, region));
+         regionToEndpoint.put(region, Suppliers.ofInstance(endpoint));
+      }
+      return regionToEndpoint.build();
+   }
+}
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiLiveTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiLiveTest.java
index 640ec8b..b4fd485 100644
--- a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiLiveTest.java
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiLiveTest.java
@@ -17,14 +17,16 @@
 package org.jclouds.dimensiondata.cloudcontrol.features;
 
 import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
 import org.jclouds.dimensiondata.cloudcontrol.domain.Datacenter;
 import org.jclouds.dimensiondata.cloudcontrol.domain.OperatingSystem;
 import org.jclouds.dimensiondata.cloudcontrol.internal.BaseDimensionDataCloudControlApiLiveTest;
 import org.testng.annotations.Test;
 
-import java.util.Set;
 import java.util.HashSet;
+import java.util.Set;
 
+import static org.jclouds.dimensiondata.cloudcontrol.options.DatacenterIdListFilters.Builder.datacenterId;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 
@@ -52,7 +54,8 @@
       for (Datacenter dc : getDatacenters()) {
          datacenterIds.add(dc.id());
       }
-      FluentIterable<OperatingSystem> operatingSystems = api().listOperatingSystems(datacenterIds).concat();
+      ImmutableList<OperatingSystem> operatingSystems = api().listOperatingSystems(datacenterId(datacenterIds))
+            .toList();
       assertNotNull(operatingSystems);
       assertTrue(!operatingSystems.isEmpty());
       for (OperatingSystem operatingSystem : operatingSystems) {
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiMockTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiMockTest.java
index 2658d91..78d669b 100644
--- a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiMockTest.java
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiMockTest.java
@@ -16,10 +16,10 @@
  */
 package org.jclouds.dimensiondata.cloudcontrol.features;
 
-import com.google.common.collect.Sets;
 import org.jclouds.dimensiondata.cloudcontrol.domain.Datacenter;
 import org.jclouds.dimensiondata.cloudcontrol.domain.OperatingSystem;
 import org.jclouds.dimensiondata.cloudcontrol.internal.BaseAccountAwareCloudControlMockTest;
+import org.jclouds.dimensiondata.cloudcontrol.options.IdListFilters;
 import org.jclouds.http.Uris;
 import org.testng.annotations.Test;
 
@@ -35,49 +35,62 @@
 @Test(groups = "unit", testName = "InfrastructureApiMockTest", singleThreaded = true)
 public class InfrastructureApiMockTest extends BaseAccountAwareCloudControlMockTest {
 
+   private static final String DATACENTER_ID_QUERY_PARAM = "id";
+
    public void testListDatacenters() throws Exception {
       server.enqueue(jsonResponse("/datacenters.json"));
-      Iterable<Datacenter> datacenters = api.getInfrastructureApi().listDatacenters().concat();
+      Iterable<Datacenter> listedDatacenters = api.getInfrastructureApi().listDatacenters().concat();
 
-      assertEquals(size(datacenters), 1); // Force the PagedIterable to advance
+      assertEquals(size(listedDatacenters), 1); // Force the PagedIterable to advance
       assertEquals(server.getRequestCount(), 2);
 
-      assertSent(HttpMethod.GET, addZonesToUriBuilder(expectedListDatacentersUriBuilder()).toString());
+      assertSent(HttpMethod.GET, expectedListDatacentersUriBuilder().toString());
    }
 
    public void testListDatacentersWithPagination() throws Exception {
       server.enqueue(jsonResponse("/datacenters-page1.json"));
       server.enqueue(jsonResponse("/datacenters-page2.json"));
-      Iterable<Datacenter> datacenters = api.getInfrastructureApi().listDatacenters().concat();
+      Iterable<Datacenter> listedDatacenters = api.getInfrastructureApi().listDatacenters().concat();
 
-      consumeIterableAndAssertAdditionalPagesRequested(datacenters, 2, 1);
+      consumeIterableAndAssertAdditionalPagesRequested(listedDatacenters, 2, 1);
 
-      assertSent(HttpMethod.GET, addZonesToUriBuilder(expectedListDatacentersUriBuilder()).toString());
-      assertSent(HttpMethod.GET, addZonesToUriBuilder(expectedListDatacentersWithPaginationUriBuilder(2)).toString());
+      assertSent(HttpMethod.GET, expectedListDatacentersUriBuilder().toString());
+      assertSent(HttpMethod.GET,
+
+            expectedListDatacentersWithPaginationUriBuilder(2).toString());
+   }
+
+   public void testListDatacentersWithDatcenterFiltering() throws Exception {
+      server.enqueue(jsonResponse("/datacenters.json"));
+      Iterable<Datacenter> listedDatacenters = api.getInfrastructureApi()
+            .listDatacenters(IdListFilters.Builder.ids(this.datacenters));
+
+      assertEquals(size(listedDatacenters), 1); // Force the PagedIterable to advance
+      assertEquals(server.getRequestCount(), 2);
+
+      assertSent(HttpMethod.GET,
+            addZonesToUriBuilder(DATACENTER_ID_QUERY_PARAM, expectedListDatacentersUriBuilder()).toString());
    }
 
    public void testListDatacenters404() throws Exception {
       server.enqueue(response404());
       assertTrue(api.getInfrastructureApi().listDatacenters().concat().isEmpty());
-      assertSent(HttpMethod.GET, addZonesToUriBuilder(expectedListDatacentersUriBuilder()).toString());
+      assertSent(HttpMethod.GET, expectedListDatacentersUriBuilder().toString());
    }
 
    private Uris.UriBuilder expectedListDatacentersUriBuilder() {
-      Uris.UriBuilder uriBuilder = Uris
-            .uriBuilder("/caas/" + VERSION + "/6ac1e746-b1ea-4da5-a24e-caf1a978789d/infrastructure/datacenter");
-      return addZonesToUriBuilder(uriBuilder);
+      return Uris.uriBuilder("/caas/" + VERSION + "/6ac1e746-b1ea-4da5-a24e-caf1a978789d/infrastructure/datacenter");
    }
 
    private Uris.UriBuilder expectedListDatacentersWithPaginationUriBuilder(int pageNumber) {
       Uris.UriBuilder uriBuilder = Uris
             .uriBuilder("/caas/" + VERSION + "/6ac1e746-b1ea-4da5-a24e-caf1a978789d/infrastructure/datacenter");
-      return addZonesToUriBuilder(addPageNumberToUriBuilder(uriBuilder, pageNumber, true));
+      return addPageNumberToUriBuilder(uriBuilder, pageNumber, false);
    }
 
    public void testListOperatingSystems() throws Exception {
       server.enqueue(jsonResponse("/operatingSystems.json"));
-      Iterable<OperatingSystem> operatingSystems = api.getInfrastructureApi()
-            .listOperatingSystems(Sets.newHashSet("NA1", "NA9")).concat();
+      Iterable<OperatingSystem> operatingSystems = api.getInfrastructureApi().listOperatingSystems().concat();
 
       assertEquals(size(operatingSystems), 33);
       assertEquals(server.getRequestCount(), 2);
@@ -88,8 +101,7 @@
    public void testListOperatingSystemsWithPagination() throws Exception {
       server.enqueue(jsonResponse("/operatingSystems-page1.json"));
       server.enqueue(jsonResponse("/operatingSystems-page2.json"));
-      Iterable<OperatingSystem> operatingSystems = api.getInfrastructureApi()
-            .listOperatingSystems(Sets.newHashSet("NA1", "NA9")).concat();
+      Iterable<OperatingSystem> operatingSystems = api.getInfrastructureApi().listOperatingSystems().concat();
 
       consumeIterableAndAssertAdditionalPagesRequested(operatingSystems, 33, 1);
 
@@ -100,20 +112,19 @@
 
    public void testListOperatingSystems404() throws Exception {
       server.enqueue(response404());
-      assertTrue(api.getInfrastructureApi().listOperatingSystems(Sets.newHashSet("NA1", "NA9")).concat().isEmpty());
+      assertTrue(api.getInfrastructureApi().listOperatingSystems().concat().isEmpty());
       assertSent(HttpMethod.GET, expectedListOperatingSystemsUriBuilder().toString());
    }
 
    private Uris.UriBuilder expectedListOperatingSystemsUriBuilder() {
       Uris.UriBuilder uriBuilder = Uris
             .uriBuilder("/caas/" + VERSION + "/6ac1e746-b1ea-4da5-a24e-caf1a978789d/infrastructure/operatingSystem");
-      uriBuilder.addQuery("datacenterId", "NA1", "NA9");
       return uriBuilder;
    }
 
    private Uris.UriBuilder expectedListOperatingSystemsWithPaginationUriBuilder(int pageNumber) {
       Uris.UriBuilder uriBuilder = Uris
             .uriBuilder("/caas/" + VERSION + "/6ac1e746-b1ea-4da5-a24e-caf1a978789d/infrastructure/operatingSystem");
-      return addPageNumberToUriBuilder(uriBuilder.addQuery("datacenterId", "NA1", "NA9"), pageNumber, false);
+      return addPageNumberToUriBuilder(uriBuilder, pageNumber, false);
    }
 }
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApiLiveTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApiLiveTest.java
index b8e1c2b..020c0b2 100644
--- a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApiLiveTest.java
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/NetworkApiLiveTest.java
@@ -31,17 +31,17 @@
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
-import java.util.List;
 import java.util.Date;
+import java.util.List;
 
 import static org.jclouds.dimensiondata.cloudcontrol.features.NetworkApiMockTest.DEFAULT_ACTION;
 import static org.jclouds.dimensiondata.cloudcontrol.features.NetworkApiMockTest.DEFAULT_IP_VERSION;
 import static org.jclouds.dimensiondata.cloudcontrol.utils.DimensionDataCloudControlResponseUtils.generateFirewallRuleName;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
 
 @Test(groups = "live", testName = "NetworkApiLiveTest", singleThreaded = true)
 public class NetworkApiLiveTest extends BaseDimensionDataCloudControlApiLiveTest {
@@ -173,7 +173,7 @@
    @Test
    public void testDeployNetworkDomain() {
       networkDomainName = NetworkApiLiveTest.class.getSimpleName() + new Date().getTime();
-      networkDomainId = api().deployNetworkDomain(DATACENTERS.iterator().next(), networkDomainName,
+      networkDomainId = api().deployNetworkDomain(datacenters.iterator().next(), networkDomainName,
             NetworkApiLiveTest.class.getSimpleName() + new Date().getTime() + "description", "ESSENTIALS");
       assertNotNull(networkDomainId);
       assertTrue(networkDomainNormalPredicate.apply(networkDomainId),
@@ -182,7 +182,7 @@
 
    @Test(expectedExceptions = ResourceAlreadyExistsException.class)
    public void testDeploySameNetworkDomain() {
-      api().deployNetworkDomain(DATACENTERS.iterator().next(), networkDomainName, networkDomainName, "ESSENTIALS");
+      api().deployNetworkDomain(datacenters.iterator().next(), networkDomainName, networkDomainName, "ESSENTIALS");
    }
 
    @AfterClass
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerApiMockTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerApiMockTest.java
index f1db2d4..e396139 100644
--- a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerApiMockTest.java
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerApiMockTest.java
@@ -27,17 +27,16 @@
 import org.jclouds.dimensiondata.cloudcontrol.domain.options.CreateServerOptions;
 import org.jclouds.dimensiondata.cloudcontrol.internal.BaseAccountAwareCloudControlMockTest;
 import org.jclouds.http.Uris;
-import org.jclouds.location.suppliers.ZoneIdsSupplier;
 import org.jclouds.rest.ResourceNotFoundException;
 import org.testng.annotations.Test;
 
 import javax.ws.rs.HttpMethod;
 import java.util.List;
-import java.util.Set;
 
 import static javax.ws.rs.HttpMethod.GET;
 import static javax.ws.rs.HttpMethod.POST;
 import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
+import static org.jclouds.dimensiondata.cloudcontrol.options.DatacenterIdListFilters.Builder.datacenterId;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
@@ -107,13 +106,19 @@
       }
    }
 
-   private Uris.UriBuilder getListServerUriBuilder() {
-      Uris.UriBuilder uriBuilder = Uris.uriBuilder("/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/server/server");
-      Set<String> zones = ctx.utils().injector().getInstance(ZoneIdsSupplier.class).get();
-      for (String zone : zones) {
-         uriBuilder.addQuery("datacenterId", zone);
+   public void testListServersWithDatacenterFiltering() throws Exception {
+      server.enqueue(jsonResponse("/servers.json"));
+      List<Server> servers = serverApi().listServers(datacenterId(datacenters)).toList();
+      Uris.UriBuilder uriBuilder = addZonesToUriBuilder("datacenterId", getListServerUriBuilder());
+      assertSent(GET, uriBuilder.toString());
+      assertEquals(servers.size(), 1);
+      for (Server s : servers) {
+         assertNotNull(s);
       }
-      return uriBuilder;
+   }
+
+   private Uris.UriBuilder getListServerUriBuilder() {
+      return Uris.uriBuilder("/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/server/server");
    }
 
    public void testListServers_404() throws Exception {
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerImageApiMockTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerImageApiMockTest.java
index 8738903..c652423 100644
--- a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerImageApiMockTest.java
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/ServerImageApiMockTest.java
@@ -20,13 +20,12 @@
 import org.jclouds.dimensiondata.cloudcontrol.domain.OsImage;
 import org.jclouds.dimensiondata.cloudcontrol.internal.BaseAccountAwareCloudControlMockTest;
 import org.jclouds.http.Uris;
-import org.jclouds.location.suppliers.ZoneIdsSupplier;
 import org.testng.annotations.Test;
 
 import javax.ws.rs.HttpMethod;
-import java.util.Set;
 
 import static com.google.common.collect.Iterables.size;
+import static org.jclouds.dimensiondata.cloudcontrol.options.DatacenterIdListFilters.Builder.datacenterId;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
@@ -58,7 +57,16 @@
       assertEquals(size(osImages), 1);
       assertEquals(server.getRequestCount(), 2);
 
-      assertSent(HttpMethod.GET, getListOsImageUrl().toString());
+      assertSent(HttpMethod.GET, getOsImageUrl().toString());
+   }
+
+   public void testListOsImageWithDatacenterIdFiltering() throws Exception {
+      server.enqueue(jsonResponse("/osImages.json"));
+      Iterable<OsImage> osImages = api.getServerImageApi().listOsImages(datacenterId(datacenters)).toList();
+      assertEquals(size(osImages), 1);
+      assertEquals(server.getRequestCount(), 2);
+
+      assertSent(HttpMethod.GET, addZonesToUriBuilder("datacenterId", getOsImageUrl()).toString());
    }
 
    public void testListOsImageWithPagination() throws Exception {
@@ -68,24 +76,15 @@
       assertNotNull(osImages);
       consumeIterableAndAssertAdditionalPagesRequested(osImages, 2, 1);
 
-      Uris.UriBuilder uriBuilder = getListOsImageUrl();
+      Uris.UriBuilder uriBuilder = getOsImageUrl();
       assertSent(HttpMethod.GET, uriBuilder.toString());
-      assertSent(HttpMethod.GET, addPageNumberToUriBuilder(uriBuilder, 2, false).toString());
+      assertSent(HttpMethod.GET, addPageNumberToUriBuilder(uriBuilder, 2, true).toString());
    }
 
    public void testListOsImage_404() throws Exception {
       server.enqueue(response404());
       assertTrue(api.getServerImageApi().listOsImages().concat().isEmpty());
-      assertSent(HttpMethod.GET, getListOsImageUrl().toString());
-   }
-
-   private Uris.UriBuilder getListOsImageUrl() {
-      Uris.UriBuilder uriBuilder = getOsImageUrl();
-      Set<String> zones = ctx.utils().injector().getInstance(ZoneIdsSupplier.class).get();
-      for (String zone : zones) {
-         uriBuilder.addQuery("datacenterId", zone);
-      }
-      return uriBuilder;
+      assertSent(HttpMethod.GET, getOsImageUrl().toString());
    }
 
    public void testGetCustomerImage() throws Exception {
@@ -108,7 +107,16 @@
       assertEquals(size(customerImages), 1);
       assertEquals(server.getRequestCount(), 2);
 
-      assertSent(HttpMethod.GET, getListCustomerImageUrl().toString());
+      assertSent(HttpMethod.GET, getCustomerImageUrl().toString());
+   }
+
+   public void testListCustomerImageWithDatacenterFiltering() throws Exception {
+      server.enqueue(jsonResponse("/customerImages.json"));
+      Iterable<CustomerImage> customerImages = api.getServerImageApi().listCustomerImages(datacenterId(datacenters));
+      assertEquals(size(customerImages), 1);
+      assertEquals(server.getRequestCount(), 2);
+
+      assertSent(HttpMethod.GET, addZonesToUriBuilder("datacenterId", getCustomerImageUrl()).toString());
    }
 
    public void testListCustomerImageWithPagination() throws Exception {
@@ -118,25 +126,16 @@
       assertNotNull(customerImages);
       consumeIterableAndAssertAdditionalPagesRequested(customerImages, 10, 1);
 
-      Uris.UriBuilder uriBuilder = getListCustomerImageUrl();
+      Uris.UriBuilder uriBuilder = getCustomerImageUrl();
 
       assertSent(HttpMethod.GET, uriBuilder.toString());
-      assertSent(HttpMethod.GET, addZonesToUriBuilder(addPageNumberToUriBuilder(uriBuilder, 2, true)).toString());
+      assertSent(HttpMethod.GET, addPageNumberToUriBuilder(uriBuilder, 2, true).toString());
    }
 
    public void testListCustomerImage_404() throws Exception {
       server.enqueue(response404());
       assertTrue(api.getServerImageApi().listCustomerImages().concat().isEmpty());
-      assertSent(HttpMethod.GET, getListCustomerImageUrl().toString());
-   }
-
-   private Uris.UriBuilder getListCustomerImageUrl() {
-      Uris.UriBuilder uriBuilder = getCustomerImageUrl();
-      Set<String> zones = ctx.utils().injector().getInstance(ZoneIdsSupplier.class).get();
-      for (String zone : zones) {
-         uriBuilder.addQuery("datacenterId", zone);
-      }
-      return uriBuilder;
+      assertSent(HttpMethod.GET, getCustomerImageUrl().toString());
    }
 
    private Uris.UriBuilder getOsImageUrl() {
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlApiLiveTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlApiLiveTest.java
index 1cffc47..85ce632 100644
--- a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlApiLiveTest.java
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlApiLiveTest.java
@@ -40,7 +40,7 @@
 import java.util.Properties;
 import java.util.Set;
 
-import static com.google.common.util.concurrent.MoreExecutors.newDirectExecutorService;
+import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
 import static org.jclouds.dimensiondata.cloudcontrol.config.DimensionDataCloudControlComputeServiceContextModule.NETWORK_DOMAIN_DELETED_PREDICATE;
 import static org.jclouds.dimensiondata.cloudcontrol.config.DimensionDataCloudControlComputeServiceContextModule.NETWORK_DOMAIN_NORMAL_PREDICATE;
 import static org.jclouds.dimensiondata.cloudcontrol.config.DimensionDataCloudControlComputeServiceContextModule.SERVER_DELETED_PREDICATE;
@@ -54,27 +54,18 @@
 @Test(groups = "live")
 public class BaseDimensionDataCloudControlApiLiveTest extends BaseApiLiveTest<DimensionDataCloudControlApi> {
 
-   private static final Set<Module> modules = ImmutableSet.<Module>of(new ExecutorServiceModule(newDirectExecutorService()));
+   protected ApiContext<DimensionDataCloudControlApi> ctx;
+   private final Set<Module> modules = ImmutableSet.<Module>of(new ExecutorServiceModule(sameThreadExecutor()));
+   protected Set<String> datacenters;
 
    protected static final String PREPARED_CUSTOMER_IMAGE_ID = "fb438e00-10f8-47ac-a434-f3f9461c3a76";
-
    protected static final String NETWORK_DOMAIN_ID = System
          .getProperty("networkDomainId", "690de302-bb80-49c6-b401-8c02bbefb945");
    protected static final String VLAN_ID = System.getProperty("vlanId", "6b25b02e-d3a2-4e69-8ca7-9bab605deebd");
    protected static final String IMAGE_ID = System.getProperty("imageId", "4c02126c-32fc-4b4c-9466-9824c1b5aa0f");
-
    protected static final String PREPARED_NETWORK_DOMAIN_ID = System
          .getProperty("networkDomainId", "d122949b-8990-46d6-98f0-91c8676fc720");
    protected static final String PREPARED_PRIVATE_IPV4_ADDRESS = "10.0.0.6";
-   protected static ApiContext<DimensionDataCloudControlApi> ctx;
-   protected static Set<String> DATACENTERS;
-
-   @BeforeClass
-   public static void setUp() {
-      ctx = ContextBuilder.newBuilder(DimensionDataCloudControlProviderMetadata.builder().build()).credentials("", "")
-            .modules(modules).overrides(new Properties()).build();
-      DATACENTERS = ctx.utils().injector().getInstance(ZoneIdsSupplier.class).get();
-   }
    protected static final String SERVER_ID = System.getProperty("serverId", "b1c537bb-018c-49ba-beef-e0600e948149");
 
    protected Predicate<String> vlanDeletedPredicate;
@@ -91,6 +82,17 @@
       provider = "dimensiondata-cloudcontrol";
    }
 
+   @BeforeClass
+   public void setUp() {
+      ctx = ContextBuilder.newBuilder(DimensionDataCloudControlProviderMetadata.builder().build()).credentials("", "")
+            .modules(modules).overrides(new Properties()).build();
+      datacenters = getZones();
+   }
+
+   private Set<String> getZones() {
+      return ctx.utils().injector().getInstance(ZoneIdsSupplier.class).get();
+   }
+
    @Override
    protected ApiMetadata createApiMetadata() {
       return new DimensionDataCloudControlApiMetadata();
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java
index c22504c..72dfd2c 100644
--- a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java
@@ -17,6 +17,7 @@
 package org.jclouds.dimensiondata.cloudcontrol.internal;
 
 import com.google.common.base.Charsets;
+import com.google.common.base.Supplier;
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.io.Resources;
@@ -31,7 +32,8 @@
 import org.jclouds.dimensiondata.cloudcontrol.DimensionDataCloudControlProviderMetadata;
 import org.jclouds.http.Uris;
 import org.jclouds.json.Json;
-import org.jclouds.location.suppliers.ZoneIdsSupplier;
+import org.jclouds.location.suppliers.ImplicitRegionIdSupplier;
+import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
 import org.jclouds.rest.ApiContext;
 import org.testng.IHookCallBack;
 import org.testng.IHookable;
@@ -42,6 +44,7 @@
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import java.io.IOException;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
@@ -68,6 +71,7 @@
    protected ApiContext<DimensionDataCloudControlApi> ctx;
    private Json json;
    private int assertedRequestCount;
+   protected Set<String> datacenters;
 
    // So that we can ignore formatting.
    private final JsonParser parser = new JsonParser();
@@ -77,11 +81,19 @@
       server = new MockWebServer();
       server.play();
       ctx = ContextBuilder.newBuilder(DimensionDataCloudControlProviderMetadata.builder().build()).credentials("", "")
-            .endpoint(url("/caas/")).modules(modules).overrides(overrides()).build();
+            .endpoint(url("/caas/")).modules(modules).overrides(new Properties()).build();
       json = ctx.utils().injector().getInstance(Json.class);
       api = ctx.getApi();
       applyAdditionalServerConfig();
       assertedRequestCount = 0;
+      datacenters = getZones();
+   }
+
+   private Set<String> getZones() {
+      final String region = ctx.utils().injector().getInstance(ImplicitRegionIdSupplier.class).get();
+      final Map<String, Supplier<Set<String>>> regionToZoneMap = ctx.utils().injector()
+            .getInstance(RegionIdToZoneIdsSupplier.class).get();
+      return regionToZoneMap.get(region).get();
    }
 
    /**
@@ -122,10 +134,6 @@
       api.close();
    }
 
-   protected Properties overrides() {
-      return new Properties();
-   }
-
    protected String url(String path) {
       return server.getUrl(path).toString();
    }
@@ -207,16 +215,15 @@
    }
 
    protected Uris.UriBuilder addPageNumberToUriBuilder(Uris.UriBuilder uriBuilder, int pageNumber, boolean clearQuery) {
-      if (clearQuery){
+      if (clearQuery) {
          uriBuilder.clearQuery();
       }
       return uriBuilder.addQuery("pageNumber", Integer.toString(pageNumber));
    }
 
-   protected Uris.UriBuilder addZonesToUriBuilder(Uris.UriBuilder uriBuilder) {
-      Set<String> zones = ctx.utils().injector().getInstance(ZoneIdsSupplier.class).get();
-      for (String zone : zones) {
-         uriBuilder.addQuery("datacenterId", zone);
+   protected Uris.UriBuilder addZonesToUriBuilder(String zoneQueryParameter, Uris.UriBuilder uriBuilder) {
+      for (String datacenter : datacenters) {
+         uriBuilder.addQuery(zoneQueryParameter, datacenter);
       }
       return uriBuilder;
    }
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/options/DatacenterIdListFiltersTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/options/DatacenterIdListFiltersTest.java
new file mode 100644
index 0000000..3335f06
--- /dev/null
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/options/DatacenterIdListFiltersTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.dimensiondata.cloudcontrol.options;
+
+import org.testng.annotations.Test;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import static org.jclouds.dimensiondata.cloudcontrol.options.DatacenterIdListFilters.Builder.datacenterId;
+import static org.jclouds.dimensiondata.cloudcontrol.options.DatacenterIdListFilters.Builder.paginationOptions;
+import static org.jclouds.dimensiondata.cloudcontrol.options.PaginationOptions.Builder.pageNumber;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+public class DatacenterIdListFiltersTest {
+
+   @Test
+   public void testDatacenterId_Varargs() {
+      final Collection<String> queryIds = datacenterId("A", "B").buildQueryParameters().get("datacenterId");
+      assertNotNull(queryIds, "Expected to have a value for query parameter for id");
+      assertEquals(queryIds.size(), 2, "Query parameter count does not match");
+      assertTrue(queryIds.contains("A"), "Expected query parameter value A not found");
+      assertTrue(queryIds.contains("B"), "Expected query parameter value B not found");
+   }
+
+   @Test
+   public void testDatacenterId_Collection() {
+      final DatacenterIdListFilters datacenterIdListFilters = datacenterId(Collections.singletonList("value"));
+      final Collection<String> id = datacenterIdListFilters.buildQueryParameters().get("datacenterId");
+      assertNotNull(id, "Expected to have a value for query parameter for id");
+      assertEquals("value", id.iterator().next());
+   }
+
+   @Test
+   public void testPaginationOptions() {
+      final PaginationOptions paginationOptions = pageNumber(1).pageSize(2).orderBy("orderBy");
+      final DatacenterIdListFilters datacenterIdListFilters = paginationOptions(paginationOptions);
+      assertEquals(paginationOptions.buildQueryParameters(), datacenterIdListFilters.buildQueryParameters(),
+            "Query Parameters are not equal");
+   }
+}
diff --git a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/options/IdListFiltersTest.java b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/options/IdListFiltersTest.java
new file mode 100644
index 0000000..96f502f
--- /dev/null
+++ b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/options/IdListFiltersTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.dimensiondata.cloudcontrol.options;
+
+import org.testng.annotations.Test;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import static org.jclouds.dimensiondata.cloudcontrol.options.IdListFilters.Builder.ids;
+import static org.jclouds.dimensiondata.cloudcontrol.options.IdListFilters.Builder.paginationOptions;
+import static org.jclouds.dimensiondata.cloudcontrol.options.PaginationOptions.Builder.pageNumber;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+public class IdListFiltersTest {
+
+   @Test
+   public void testIds_Varargs() {
+      final Collection<String> queryIds = ids().ids("A", "B").buildQueryParameters().get("id");
+      assertNotNull(queryIds, "Expected to have a value for query parameter for id");
+      assertEquals(queryIds.size(), 2, "Query parameter count does not match");
+      assertTrue(queryIds.contains("A"), "Expected query parameter value A not found");
+      assertTrue(queryIds.contains("B"), "Expected query parameter value B not found");
+   }
+
+   @Test
+   public void testIds_Collection() {
+      final IdListFilters idListFilters = ids(Collections.singletonList("datacenterId"));
+      final Collection<String> id = idListFilters.buildQueryParameters().get("id");
+      assertNotNull(id, "Expected to have a value for query parameter for id");
+      assertEquals("datacenterId", id.iterator().next());
+   }
+
+   @Test
+   public void testPaginationOptions() {
+      final PaginationOptions paginationOptions = pageNumber(1).pageSize(2).orderBy("orderBy");
+      final IdListFilters idListFilters = paginationOptions(paginationOptions);
+      assertEquals(paginationOptions.buildQueryParameters(), idListFilters.buildQueryParameters(),
+            "Query Parameters are not equal");
+   }
+}