+ * Operations that create, update, or delete resources may take some time to process. Therefore they return
+ * a Job containing information, which allows the status and response information of the job to be
+ * retrieved at a later point in time.
+ *
+ * You likely won't need to use this method directly. Use {@link JobPredicates#awaitComplete(CloudDNSApi, Job)}.
+ *
+ * @return null, if not found.
+ */
+ @Named("job:get")
+ @Endpoint(CloudDNS.class)
+ @RequestFilters(AuthenticateRequest.class)
+ @GET
+ @Consumes(APPLICATION_JSON)
+ @ResponseParser(ParseJob.class)
+ @Fallback(NullOnNotFoundOr404.class)
+ @QueryParams(keys = "showDetails", values = "true")
+ @Path("/status/{jobId}")
+ @Nullable
+ Job getJob(@PathParam("jobId") String jobId);
+
+ /**
+ * Provides access to Limit features.
+ */
+ @Delegate
+ LimitApi getLimitApi();
+
+ /**
+ * Provides access to Domain features.
+ */
+ @Delegate
+ DomainApi getDomainApi();
+
+ /**
+ * Provides access to Record features.
+ */
+ @Delegate
+ @Path("/domains/{domainId}")
+ RecordApi getRecordApiForDomain(@PathParam("domainId") int domainId);
+
+ /**
+ * Provides access to Reverse DNS features.
+ */
+ @Delegate
+ ReverseDNSApi getReverseDNSApiForService(@PayloadParam("serviceName") @PathParam("serviceName") String serviceName);
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/CloudDNSApiMetadata.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/CloudDNSApiMetadata.java
new file mode 100644
index 0000000000..fd9acad76b
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/CloudDNSApiMetadata.java
@@ -0,0 +1,95 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.clouddns.v1;
+
+import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
+import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
+import static org.jclouds.rackspace.cloudidentity.v2_0.ServiceType.DNS;
+import static org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes.API_KEY_CREDENTIALS;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ProviderModule;
+import org.jclouds.rackspace.clouddns.v1.config.CloudDNSHttpApiModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationApiModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ApiMetadata} for Rackspace Cloud DNS 1.0 API
+ *
+ * @author Everett Toews
+ */
+public class CloudDNSApiMetadata extends BaseHttpApiMetadata {
+
+ @Override
+ public Builder toBuilder() {
+ return new Builder().fromApiMetadata(this);
+ }
+
+ public CloudDNSApiMetadata() {
+ this(new Builder());
+ }
+
+ protected CloudDNSApiMetadata(Builder builder) {
+ super(builder);
+ }
+
+ public static Properties defaultProperties() {
+ Properties properties = BaseHttpApiMetadata.defaultProperties();
+ properties.setProperty(SERVICE_TYPE, DNS);
+ properties.setProperty(CREDENTIAL_TYPE, API_KEY_CREDENTIALS);
+ return properties;
+ }
+
+ public static class Builder extends BaseHttpApiMetadata.Builder {
+
+ protected Builder() {
+ id("rackspace-clouddns")
+ .name("Rackspace Cloud DNS API")
+ .identityName("Username")
+ .credentialName("API Key")
+ .documentation(URI.create("http://docs.rackspace.com/cdns/api/v1.0/cdns-devguide/content/index.html"))
+ .version("1.0")
+ .defaultEndpoint("https://identity.api.rackspacecloud.com/v2.0/")
+ .defaultProperties(CloudDNSApiMetadata.defaultProperties())
+ .defaultModules(ImmutableSet.> builder()
+ .add(CloudIdentityAuthenticationApiModule.class)
+ .add(CloudIdentityAuthenticationModule.class)
+ .add(ProviderModule.class)
+ .add(CloudDNSHttpApiModule.class)
+ .build());
+ }
+
+ @Override
+ public CloudDNSApiMetadata build() {
+ return new CloudDNSApiMetadata(this);
+ }
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/CloudDNSExceptions.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/CloudDNSExceptions.java
new file mode 100644
index 0000000000..20be0af97c
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/CloudDNSExceptions.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.clouddns.v1;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.rackspace.clouddns.v1.domain.Job;
+
+/**
+ * Exceptions likely to be encountered when using {@link CloudDNSApi}
+ *
+ * @author Everett Toews
+ */
+public interface CloudDNSExceptions {
+ /**
+ * A Job errored out.
+ */
+ public static class JobErrorException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+ private final Job.Error jobError;
+
+ public JobErrorException(Job.Error jobError) {
+ super(jobError.toString());
+ this.jobError = checkNotNull(jobError, "jobError");
+ }
+
+ public Job.Error getJobError() {
+ return jobError;
+ }
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/CreateReverseDNSToJSON.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/CreateReverseDNSToJSON.java
new file mode 100644
index 0000000000..6d45d088a9
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/CreateReverseDNSToJSON.java
@@ -0,0 +1,79 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.clouddns.v1.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.json.Json;
+import org.jclouds.rackspace.clouddns.v1.domain.Record;
+import org.jclouds.rest.MapBinder;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * @author Everett Toews
+ */
+public class CreateReverseDNSToJSON implements MapBinder {
+ private final Json jsonBinder;
+
+ @Inject
+ public CreateReverseDNSToJSON(Json jsonBinder) {
+ this.jsonBinder = checkNotNull(jsonBinder, "jsonBinder");
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public R bindToRequest(R request, Map postParams) {
+ checkArgument(checkNotNull(postParams.get("href"), "href") instanceof URI, "href is only valid for a URI!");
+ checkArgument(checkNotNull(postParams.get("records"), "records") instanceof Iterable,
+ "records is only valid for an Iterable!");
+ checkNotNull(postParams.get("serviceName"), "serviceName");
+
+ Iterable records = Iterable.class.cast(postParams.get("records"));
+ URI deviceURI = URI.class.cast(postParams.get("href"));
+ String serviceName = postParams.get("serviceName").toString();
+
+ String json = toJSON(records, deviceURI, serviceName);
+ request.setPayload(json);
+ request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_JSON);
+
+ return (R) request.toBuilder().payload(json).build();
+ }
+
+ private String toJSON(Iterable records, URI deviceURI, String serviceName) {
+ return jsonBinder.toJson(ImmutableMap. of(
+ "recordsList", ImmutableMap.of("records", records),
+ "link", ImmutableMap. of(
+ "href", deviceURI,
+ "rel", serviceName)));
+ }
+
+ @Override
+ public R bindToRequest(R request, Object input) {
+ throw new UnsupportedOperationException("use map form");
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/FormatAndContentsToJSON.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/FormatAndContentsToJSON.java
new file mode 100644
index 0000000000..473b007235
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/FormatAndContentsToJSON.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.clouddns.v1.binders;
+
+import static java.lang.String.format;
+
+import java.util.List;
+import java.util.Map;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.MapBinder;
+
+import com.google.common.base.Joiner;
+
+/**
+ * @author Everett Toews
+ */
+public class FormatAndContentsToJSON implements MapBinder {
+ private static final String template = "{\"domains\":[{\"contentType\":\"%s\",\"contents\":\"%s\"}]}";
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public R bindToRequest(R request, Map postParams) {
+ String format = postParams.get("format").toString();
+ List contents = List.class.cast(postParams.get("contents"));
+
+ return (R) request.toBuilder().payload(toJSON(format, contents)).build();
+ }
+
+ private String toJSON(String format, List contents) {
+ String contentsAsOneString = Joiner.on("\\n").join(contents);
+
+ return format(template, format, contentsAsOneString);
+ }
+
+ @Override
+ public R bindToRequest(R request, Object input) {
+ throw new UnsupportedOperationException("use map form");
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/UpdateDomainsToJSON.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/UpdateDomainsToJSON.java
new file mode 100644
index 0000000000..fb6d0e42f2
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/UpdateDomainsToJSON.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.clouddns.v1.binders;
+
+import static java.lang.String.format;
+
+import java.util.List;
+import java.util.Map;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.MapBinder;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+
+/**
+ * @author Everett Toews
+ */
+public class UpdateDomainsToJSON implements MapBinder {
+ private static final String template = "{\"domains\":[%s]}";
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public R bindToRequest(R request, Map postParams) {
+ Iterable ids = Iterable.class.cast(postParams.get("ids"));
+ String key, value, updateTemplate;
+
+ if (postParams.get("emailAddress") != null) {
+ updateTemplate = "{\"id\":%s,\"%s\":\"%s\"}";
+ key = "emailAddress";
+ } else if (postParams.get("ttl") != null) {
+ updateTemplate = "{\"id\":%s,\"%s\":%s}";
+ key = "ttl";
+ } else {
+ throw new IllegalStateException("emailAddress or ttl not found in " + postParams);
+ }
+
+ value = postParams.get(key).toString();
+ return (R) request.toBuilder().payload(toJSON(ids, updateTemplate, key, value)).build();
+ }
+
+ private String toJSON(Iterable ids, String updateTemplate, String key, String value) {
+ List json = Lists.newArrayList();
+
+ for (Integer id: ids) {
+ json.add(format(updateTemplate, id, key, value));
+ }
+
+ String contentsAsOneString = Joiner.on(",").join(json);
+
+ return format(template, contentsAsOneString);
+ }
+
+ @Override
+ public R bindToRequest(R request, Object input) {
+ throw new UnsupportedOperationException("use map form");
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/UpdateRecordsToJSON.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/UpdateRecordsToJSON.java
new file mode 100644
index 0000000000..4fcd9d00cc
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/UpdateRecordsToJSON.java
@@ -0,0 +1,98 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.clouddns.v1.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.json.Json;
+import org.jclouds.rackspace.clouddns.v1.domain.Record;
+import org.jclouds.rest.Binder;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+/**
+ * Binds the Records to the request as a JSON payload.
+ *
+ * @author Everett Toews
+ */
+@Singleton
+public class UpdateRecordsToJSON implements Binder {
+
+ private final Json jsonBinder;
+
+ @Inject
+ public UpdateRecordsToJSON(Json jsonBinder) {
+ this.jsonBinder = checkNotNull(jsonBinder, "jsonBinder");
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public R bindToRequest(R request, Object input) {
+ checkArgument(checkNotNull(input, "input") instanceof Map, "This binder is only valid for Map");
+ checkNotNull(request, "request");
+
+ Map idsToRecords = (Map) input;
+ List updateRecords = toUpdateRecordList(idsToRecords);
+
+ String json = jsonBinder.toJson(ImmutableMap.of("records", updateRecords));
+ request.setPayload(json);
+ request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_JSON);
+
+ return request;
+ }
+
+ static List toUpdateRecordList(Map idsToRecords) {
+ List updateRecords = Lists.newArrayList();
+
+ for (String recordId: idsToRecords.keySet()) {
+ Record record = idsToRecords.get(recordId);
+
+ UpdateRecord updateRecord = new UpdateRecord();
+ updateRecord.id = recordId;
+ updateRecord.name = record.getName();
+ updateRecord.ttl = record.getTTL().isPresent() ? record.getTTL().get() : null;
+ updateRecord.data = record.getData();
+ updateRecord.priority = record.getPriority();
+ updateRecord.comment = record.getComment();
+
+ updateRecords.add(updateRecord);
+ }
+
+ return updateRecords;
+ }
+
+ static final class UpdateRecord {
+ public String id;
+ public String name;
+ public Integer ttl;
+ public String data;
+ public Integer priority;
+ public String comment;
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/UpdateReverseDNSToJSON.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/UpdateReverseDNSToJSON.java
new file mode 100644
index 0000000000..3546e7521f
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/binders/UpdateReverseDNSToJSON.java
@@ -0,0 +1,83 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.clouddns.v1.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.json.Json;
+import org.jclouds.rackspace.clouddns.v1.binders.UpdateRecordsToJSON.UpdateRecord;
+import org.jclouds.rackspace.clouddns.v1.domain.Record;
+import org.jclouds.rest.MapBinder;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * @author Everett Toews
+ */
+public class UpdateReverseDNSToJSON implements MapBinder {
+ private final Json jsonBinder;
+
+ @Inject
+ public UpdateReverseDNSToJSON(Json jsonBinder) {
+ this.jsonBinder = checkNotNull(jsonBinder, "jsonBinder");
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public R bindToRequest(R request, Map postParams) {
+ checkArgument(checkNotNull(postParams.get("href"), "href") instanceof URI,
+ "href is only valid for a URI!");
+ checkArgument(checkNotNull(postParams.get("idsToRecords"), "idsToRecords") instanceof Map,
+ "records is only valid for a Map!");
+ checkNotNull(postParams.get("serviceName"), "serviceName");
+
+ Map idsToRecords = Map.class.cast(postParams.get("idsToRecords"));
+ List updateRecords = UpdateRecordsToJSON.toUpdateRecordList(idsToRecords);
+ URI deviceURI = URI.class.cast(postParams.get("href"));
+ String serviceName = postParams.get("serviceName").toString();
+
+ String json = toJSON(updateRecords, deviceURI, serviceName);
+ request.setPayload(json);
+ request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_JSON);
+
+ return (R) request.toBuilder().payload(json).build();
+ }
+
+ private String toJSON(Iterable records, URI deviceURI, String serviceName) {
+ return jsonBinder.toJson(ImmutableMap. of(
+ "recordsList", ImmutableMap.of("records", records),
+ "link", ImmutableMap. of(
+ "href", deviceURI,
+ "rel", serviceName)));
+ }
+
+ @Override
+ public R bindToRequest(R request, Object input) {
+ throw new UnsupportedOperationException("use map form");
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/config/CloudDNS.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/config/CloudDNS.java
new file mode 100644
index 0000000000..764e0c9aa6
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/config/CloudDNS.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.clouddns.v1.config;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Represents a component related to Rackspace Cloud DNS.
+ *
+ * @author Everett Toews
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+@Qualifier
+public @interface CloudDNS {
+
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/config/CloudDNSHttpApiModule.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/config/CloudDNSHttpApiModule.java
new file mode 100644
index 0000000000..ccfa36f45a
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/config/CloudDNSHttpApiModule.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.clouddns.v1.config;
+
+import java.net.URI;
+
+import org.jclouds.json.config.GsonModule.DateAdapter;
+import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
+import org.jclouds.rackspace.clouddns.v1.CloudDNSApi;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+
+import com.google.common.base.Supplier;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Configures Rackspace Cloud DNS.
+ *
+ * @author Everett Toews
+ */
+@ConfiguresHttpApi
+public class CloudDNSHttpApiModule extends HttpApiModule {
+
+ @Override
+ protected void configure() {
+ bind(new TypeLiteral>() {}).annotatedWith(CloudDNS.class).to(new TypeLiteral>() {});
+ bind(DateAdapter.class).to(Iso8601DateAdapter.class);
+ super.configure();
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/CreateDomain.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/CreateDomain.java
new file mode 100644
index 0000000000..8f8a0ae5a7
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/CreateDomain.java
@@ -0,0 +1,206 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, String 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.clouddns.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Create a Domain or Subdomain.
+ *
+ * @author Everett Toews
+ */
+public class CreateDomain {
+ private final String name;
+ private final String emailAddress;
+ private final Optional ttl;
+ private final Optional comment;
+ // subdomains is an ImmutableMap for serialization
+ private final ImmutableMap> subdomains;
+ // recordList is an ImmutableMap for serialization
+ private final ImmutableMap> recordsList;
+
+ private CreateDomain(String name, String email, Optional ttl, Optional comment,
+ ImmutableMap> subdomains,
+ ImmutableMap> recordsList) {
+ this.name = checkNotNull(name, "name required");
+ this.emailAddress = checkNotNull(email, "email required");
+ this.ttl = ttl;
+ this.comment = comment;
+ this.subdomains = subdomains != null ? subdomains : ImmutableMap.> of();
+ this.recordsList = recordsList != null ? recordsList : ImmutableMap.> of();
+ }
+
+ /**
+ * @see Builder#name(String)
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @see Builder#email(String)
+ */
+ public String getEmail() {
+ return emailAddress;
+ }
+
+ /**
+ * @see Builder#ttl(Integer)
+ */
+ public Optional getTTL() {
+ return ttl;
+ }
+
+ /**
+ * @see Builder#comment(String)
+ */
+ public Optional getComment() {
+ return comment;
+ }
+
+ /**
+ * @see Builder#subdomains(Iterable)
+ */
+ public Iterable getSubdomains() {
+ return subdomains.get("domains");
+ }
+
+ /**
+ * @see Builder#records(Iterable)
+ */
+ public Iterable getRecords() {
+ return recordsList.get("records");
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ CreateDomain that = CreateDomain.class.cast(obj);
+
+ return Objects.equal(this.name, that.name);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this).omitNullValues().add("name", name).add("email", emailAddress)
+ .add("ttl", ttl.orNull()).add("comment", comment.orNull()).add("subdomains", subdomains)
+ .add("records", recordsList);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static class Builder {
+ private String name;
+ private String emailAddress;
+ private Optional ttl = Optional.absent();
+ private Optional comment = Optional.absent();
+ private ImmutableMap> subdomains;
+ private ImmutableMap> records;
+
+ /**
+ * The name for the domain or subdomain. Must be a fully qualified domain name (FQDN) that doesn't end in a '.'.
+ */
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Email address to use for contacting the domain administrator. Used as the email-addr (rname) in the SOA record.
+ */
+ public Builder email(String email) {
+ this.emailAddress = email;
+ return this;
+ }
+
+ /**
+ * The duration in seconds that the record may be cached by clients. If specified, must be greater than 300. The
+ * default value, if not specified, is 3600.
+ */
+ public Builder ttl(Integer ttl) {
+ this.ttl = Optional.fromNullable(ttl);
+ return this;
+ }
+
+ /**
+ * If included, its length must be less than or equal to 160 characters.
+ */
+ public Builder comment(String comment) {
+ this.comment = Optional.fromNullable(comment);
+ return this;
+ }
+
+ /**
+ * Create Subdomains of this Domain.
+ */
+ public Builder subdomains(Iterable subdomains) {
+ if (subdomains != null) {
+ this.subdomains = ImmutableMap.of("domains", subdomains);
+ }
+
+ return this;
+ }
+
+ /**
+ * Create Records for this Domain.
+ *
+ * See
+ * Supported Record Types
+ */
+ public Builder records(Iterable records) {
+ if (records != null) {
+ this.records = ImmutableMap.of("records", records);
+ }
+
+ return this;
+ }
+
+ public CreateDomain build() {
+ return new CreateDomain(name, emailAddress, ttl, comment, subdomains, records);
+ }
+
+ public Builder from(CreateDomain in) {
+ return this.name(in.getName()).email(in.getEmail()).ttl(in.getTTL().orNull())
+ .comment(in.getComment().orNull()).subdomains(in.getSubdomains()).records(in.getRecords());
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().from(this);
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/CreateSubdomain.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/CreateSubdomain.java
new file mode 100644
index 0000000000..da94cb5176
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/CreateSubdomain.java
@@ -0,0 +1,153 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, String 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.clouddns.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+
+/**
+ * @author Everett Toews
+ */
+public class CreateSubdomain {
+ private final String name;
+ private final String emailAddress;
+ private final Optional ttl;
+ private final Optional comment;
+
+ private CreateSubdomain(String name, String email, Optional ttl, Optional comment) {
+ this.name = checkNotNull(name, "name required");
+ this.emailAddress = checkNotNull(email, "email required");
+ this.ttl = ttl;
+ this.comment = comment;
+ }
+
+ /**
+ * @see Builder#name(String)
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @see Builder#email(String)
+ */
+ public String getEmail() {
+ return emailAddress;
+ }
+
+ /**
+ * @see Builder#ttl(Integer)
+ */
+ public Optional getTTL() {
+ return ttl;
+ }
+
+ /**
+ * @see Builder#comment(String)
+ */
+ public Optional getComment() {
+ return comment;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ CreateSubdomain that = CreateSubdomain.class.cast(obj);
+
+ return Objects.equal(this.name, that.name);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this).omitNullValues().add("name", name).add("email", emailAddress)
+ .add("ttl", ttl.orNull()).add("comment", comment.orNull());
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static class Builder {
+ private String name;
+ private String emailAddress;
+ private Optional ttl = Optional.absent();
+ private Optional comment = Optional.absent();
+
+ /**
+ * The name for the subdomain. Must be a fully qualified domain name (FQDN) that doesn't end in a '.'.
+ */
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Email address to use for contacting the domain administrator. Used as the email-addr (rname) in the SOA record.
+ */
+ public Builder email(String email) {
+ this.emailAddress = email;
+ return this;
+ }
+
+ /**
+ * The duration in seconds that the record may be cached. If specified, must be greater than 300. The default
+ * value, if not specified, is 3600.
+ */
+ public Builder ttl(Integer ttl) {
+ this.ttl = Optional.fromNullable(ttl);
+ return this;
+ }
+
+ /**
+ * If included, its length must be less than or equal to 160 characters.
+ */
+ public Builder comment(String comment) {
+ this.comment = Optional.fromNullable(comment);
+ return this;
+ }
+
+ public CreateSubdomain build() {
+ return new CreateSubdomain(name, emailAddress, ttl, comment);
+ }
+
+ public Builder from(CreateSubdomain in) {
+ return this.name(in.getName()).email(in.getEmail()).ttl(in.getTTL().orNull())
+ .comment(in.getComment().orNull());
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().from(this);
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/Domain.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/Domain.java
new file mode 100644
index 0000000000..9ed8c6d162
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/Domain.java
@@ -0,0 +1,162 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.clouddns.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.util.Date;
+import java.util.Set;
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * A domain is an entity/container of all DNS-related information containing one or more records. Within Rackspace DNS,
+ * the account which creates the domain is the domain owner.
+ *
+ * @author Everett Toews
+ */
+public class Domain {
+ private final int id;
+ private final String name;
+ private final String email;
+ private final Optional comment;
+ private final Date created;
+ private final Date updated;
+ private final int accountId;
+ private final int ttl;
+ private final Set nameservers;
+ private final Set subdomains;
+ private final Set records;
+
+ @ConstructorProperties({ "id", "name", "emailAddress", "comment", "created", "updated", "accountId", "ttl",
+ "nameservers", "subdomains", "recordsList" })
+ protected Domain(int id, String name, String email, @Nullable String comment, Date created, Date updated,
+ int accountId, int ttl, @Nullable Set nameservers, @Nullable Set nameToSubdomain,
+ @Nullable Set records) {
+ this.id = id;
+ this.name = name;
+ this.email = email;
+ this.comment = Optional.fromNullable(comment);
+ this.created = created;
+ this.updated = updated;
+ this.accountId = accountId;
+ this.ttl = ttl;
+ this.nameservers = nameservers != null ? nameservers : ImmutableSet. of();
+ this.subdomains = nameToSubdomain != null ? nameToSubdomain : ImmutableSet. of();
+ this.records = records != null ? records : ImmutableSet. of();
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public Optional getComment() {
+ return comment;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+
+ public Date getUpdated() {
+ return updated;
+ }
+
+ public int getAccountId() {
+ return accountId;
+ }
+
+ public int getTTL() {
+ return ttl;
+ }
+
+ public Set getNameservers() {
+ return nameservers;
+ }
+
+ public Set getSubdomains() {
+ return subdomains;
+ }
+
+ public Set getRecords() {
+ return records;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ Domain that = Domain.class.cast(obj);
+
+ return Objects.equal(this.id, that.id);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this).omitNullValues().add("id", id).add("name", name).add("email", email)
+ .add("comment", comment.orNull()).add("created", created).add("updated", updated)
+ .add("accountId", accountId).add("ttl", ttl).add("nameservers", nameservers)
+ .add("subdomains", subdomains).add("records", records);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ protected Domain from(Domain in) {
+ return new Domain(in.getId(), in.getName(), in.getEmail(), in.getComment().orNull(), in.getCreated(),
+ in.getUpdated(), in.getAccountId(), in.getTTL(), in.getNameservers(), in.getSubdomains(), in.getRecords());
+ }
+
+ public enum Format {
+ BIND_9,
+
+ UNRECOGNIZED;
+
+ public static Format fromValue(String format) {
+ try {
+ return valueOf(checkNotNull(format, "format").toUpperCase());
+ }
+ catch (IllegalArgumentException e) {
+ return UNRECOGNIZED;
+ }
+ }
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/DomainChange.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/DomainChange.java
new file mode 100644
index 0000000000..6e134cac3e
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/DomainChange.java
@@ -0,0 +1,188 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, String 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.clouddns.v1.domain;
+
+import static com.google.common.base.Objects.equal;
+
+import java.beans.ConstructorProperties;
+import java.util.Date;
+import java.util.List;
+
+import com.google.common.base.Objects;
+
+public class DomainChange {
+ private final Date from;
+ private final Date to;
+ private final List changes;
+
+ @ConstructorProperties({ "from", "to", "changes" })
+ private DomainChange(Date from, Date to, List changes) {
+ this.from = from;
+ this.to = to;
+ this.changes = changes;
+ }
+
+ public Date getFrom() {
+ return from;
+ }
+
+ public Date getTo() {
+ return to;
+ }
+
+ public List getChanges() {
+ return changes;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(from, to, changes);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ DomainChange that = DomainChange.class.cast(obj);
+ return equal(this.from, that.from) && equal(this.to, that.to) && equal(this.changes, that.changes);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this).omitNullValues().add("from", from).add("to", to).add("changes", changes)
+ .toString();
+ }
+
+ public static class Change {
+ private final String domain;
+ private final String action;
+ private final String targetType;
+ private final int accountId;
+ private final int targetId;
+ private final List changeDetails;
+
+ @ConstructorProperties({ "domain", "action", "targetType", "accountId", "targetId", "changeDetails" })
+ protected Change(String domain, String action, String targetType, int accountId, int targetId,
+ List changeDetails) {
+ this.domain = domain;
+ this.action = action;
+ this.targetType = targetType;
+ this.accountId = accountId;
+ this.targetId = targetId;
+ this.changeDetails = changeDetails;
+ }
+
+ public String getDomain() {
+ return domain;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public String getTargetType() {
+ return targetType;
+ }
+
+ public int getAccountId() {
+ return accountId;
+ }
+
+ public int getTargetId() {
+ return targetId;
+ }
+
+ public List getChangeDetails() {
+ return changeDetails;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(domain, action, targetType, accountId, targetId, changeDetails);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ Change that = Change.class.cast(obj);
+ return equal(this.domain, that.domain) && equal(this.action, that.action)
+ && equal(this.targetType, that.targetType) && equal(this.accountId, that.accountId)
+ && equal(this.targetId, that.targetId) && equal(this.changeDetails, that.changeDetails);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this).omitNullValues().add("domain", domain).add("action", action)
+ .add("targetType", targetType).add("accountId", accountId).add("targetId", targetId)
+ .add("changeDetails", changeDetails).toString();
+ }
+ }
+
+ public static class ChangeDetail {
+ private final String field;
+ private final String originalValue;
+ private final String newValue;
+
+ @ConstructorProperties({ "field", "originalValue", "newValue" })
+ protected ChangeDetail(String field, String originalValue, String newValue) {
+ this.field = field;
+ this.originalValue = originalValue;
+ this.newValue = newValue;
+ }
+
+ public String getField() {
+ return field;
+ }
+
+ public String getOriginalValue() {
+ return originalValue;
+ }
+
+ public String getNewValue() {
+ return newValue;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(field, originalValue, newValue);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ ChangeDetail that = ChangeDetail.class.cast(obj);
+ return equal(this.field, that.field) && equal(this.originalValue, that.originalValue)
+ && equal(this.newValue, that.newValue);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this).omitNullValues().add("field", field).add("originalValue", originalValue)
+ .add("newValue", newValue).toString();
+ }
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/Job.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/Job.java
new file mode 100644
index 0000000000..fc8d79ff32
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/Job.java
@@ -0,0 +1,129 @@
+package org.jclouds.rackspace.clouddns.v1.domain;
+
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+
+import org.jclouds.rackspace.clouddns.v1.CloudDNSApi;
+
+import com.google.common.base.Optional;
+
+/**
+ * @see CloudDNSApi#getJob(String)
+ * @author Everett Toews
+ */
+public class Job {
+ private final String id;
+ private final Status status;
+ private final Optional error;
+ private final Optional resource;
+
+ private Job(String id, Status status, Optional error, Optional resource) {
+ this.id = id;
+ this.status = status;
+ this.error = error;
+ this.resource = resource;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ public Optional getError() {
+ return error;
+ }
+
+ public Optional getResource() {
+ return resource;
+ }
+
+ public enum Status {
+ /**
+ * INITIALIZED is the status that immediately precedes RUNNING and is the first possible state of a job.
+ * It indicates acceptance of the job.
+ */
+ INITIALIZED,
+
+ RUNNING, COMPLETED, ERROR, UNRECOGNIZED;
+
+ public static Status fromValue(String status) {
+ try {
+ return valueOf(checkNotNull(status, "status").toUpperCase());
+ }
+ catch (IllegalArgumentException e) {
+ return UNRECOGNIZED;
+ }
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private String id;
+ private Status status;
+ private Optional error = Optional.absent();
+ private Optional resource = Optional.absent();
+
+ public Builder id(String id) {
+ this.id = id;
+ return this;
+ }
+
+ public Builder status(Status status) {
+ this.status = status;
+ return this;
+ }
+
+ public Builder error(Error error) {
+ this.error = Optional.fromNullable(error);
+ return this;
+ }
+
+ public Builder resource(T resource) {
+ this.resource = Optional.fromNullable(resource);
+ return this;
+ }
+
+ public Job build() {
+ return new Job(id, status, error, resource);
+ }
+ }
+
+ public static final class Error {
+
+ private final int code;
+ private final String message;
+ private final String details;
+
+ @ConstructorProperties({ "code", "message", "details" })
+ protected Error(int code, String message, String details) {
+ this.code = code;
+ this.message = message;
+ this.details = details;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String getDetails() {
+ return details;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("code", code).add("message", message).add("details", details).toString();
+ }
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/Record.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/Record.java
new file mode 100644
index 0000000000..a7c9f94207
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/Record.java
@@ -0,0 +1,221 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.clouddns.v1.domain;
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+
+/**
+ * @author Everett Toews
+ */
+public class Record {
+ private final String name;
+ private final String type;
+ private final Optional ttl;
+ private final String data;
+ private final Integer priority;
+ private final String comment;
+
+ private Record(@Nullable String name, @Nullable String type, Optional ttl, @Nullable String data,
+ @Nullable Integer priority, @Nullable String comment) {
+ this.name = name;
+ this.type = type;
+ this.ttl = ttl;
+ this.data = data;
+ this.priority = priority;
+ this.comment = comment;
+ }
+
+ /**
+ * @see Record.Builder#name(String)
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @see Record.Builder#type(String)
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * @see Record.Builder#ttl(Integer)
+ */
+ public Optional getTTL() {
+ return ttl;
+ }
+
+ /**
+ * @see Record.Builder#data(String)
+ */
+ public String getData() {
+ return data;
+ }
+
+ /**
+ * @see Record.Builder#priority(Integer)
+ */
+ @Nullable
+ public Integer getPriority() {
+ return priority;
+ }
+
+ /**
+ * @see Record.Builder#comment(String)
+ */
+ @Nullable
+ public String getComment() {
+ return comment;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name, type, ttl, data, priority, comment);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ Record that = Record.class.cast(obj);
+
+ return equal(this.name, that.name) && equal(this.type, that.type) && equal(this.ttl, that.ttl)
+ && equal(this.data, that.data) && equal(this.priority, that.priority) && equal(this.comment, that.comment);
+ }
+
+ protected ToStringHelper string() {
+ return toStringHelper(this).omitNullValues().add("name", name).add("type", type).add("ttl", ttl)
+ .add("data", data).add("priority", priority).add("comment", comment);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public final static class Builder {
+ private String name;
+ private String type;
+ private Optional ttl = Optional.absent();
+ private String data;
+ private Integer priority;
+ private String comment;
+
+ /**
+ * The name for the domain or subdomain. Must be a fully qualified domain name (FQDN) that doesn't end in a '.'.
+ *
+ * Users can add one or more wildcard records to any domain or sub-domain on their account. For information on the
+ * intent and use of wildcard records, see the DNS literature including RFC 1034, section 4.3.3, and RFC 4595.
+ *
+ * Wildcards are supported for A, AAAA, CNAME, MX, SRV and TXT record types.
+ *
+ * A valid wildcard DNS record is specified by using an asterisk ("*") as the leftmost part of a record name, for
+ * example *.example.com. An asterisk in any other part of a record name is invalid. Only the asterisk ("*") is
+ * accepted as a wildcard character.
+ *
+ * For SRV records, this specifies the entire service name, which is made up of the service, protocol, and domain
+ * name to which the record belongs. The service and protocol fields of the service name can be modified but not
+ * the domain name field.
+ */
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * The record type to add.
+ *
+ * See
+ * Supported Record Types
+ */
+ public Builder type(String type) {
+ this.type = type;
+ return this;
+ }
+
+ /**
+ * The duration in seconds that the record may be cached by clients. If specified, must be greater than 300. The
+ * default value, if not specified, is 3600.
+ */
+ public Builder ttl(int ttl) {
+ this.ttl = Optional.fromNullable(ttl);
+ return this;
+ }
+
+ /**
+ * @see Builder#ttl(int)
+ */
+ public Builder ttl(Optional ttl) {
+ this.ttl = ttl;
+ return this;
+ }
+
+ /**
+ * The data field for PTR, A, and AAAA records must be a valid IPv4 or IPv6 IP address.
+ */
+ public Builder data(String data) {
+ this.data = data;
+ return this;
+ }
+
+ /**
+ * Required for MX and SRV records, but forbidden for other record types. If specified, must be an integer from 0
+ * to 65535.
+ */
+ public Builder priority(Integer priority) {
+ this.priority = priority;
+ return this;
+ }
+
+ /**
+ * If included, its length must be less than or equal to 160 characters.
+ */
+ public Builder comment(String comment) {
+ this.comment = comment;
+ return this;
+ }
+
+ public Record build() {
+ return new Record(name, type, ttl, data, priority, comment);
+ }
+
+ public Builder from(Record in) {
+ return name(in.getName()).type(in.getType()).ttl(in.getTTL()).data(in.getData()).priority(in.getPriority())
+ .comment(in.getComment());
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return builder().from(this);
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/RecordDetail.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/RecordDetail.java
new file mode 100644
index 0000000000..d7f35b1f67
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/RecordDetail.java
@@ -0,0 +1,186 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.clouddns.v1.domain;
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Date;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * @author Everett Toews
+ */
+public class RecordDetail {
+ private final String id;
+ private final Date created;
+ private final Date updated;
+ private final Record record;
+
+ private RecordDetail(String id, Date created, Date updated, Record record) {
+ this.id = checkNotNull(id, "id required");
+ this.created = checkNotNull(created, "created required");
+ this.updated = checkNotNull(updated, "updated required");
+ this.record = checkNotNull(record, "record required");
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * When this record was created.
+ */
+ public Date getCreated() {
+ return created;
+ }
+
+ /**
+ * When this record was updated.
+ */
+ public Date getUpdated() {
+ return updated;
+ }
+
+ /**
+ * The Record.
+ */
+ public Record getRecord() {
+ return record;
+ }
+
+ /**
+ * @see Record.Builder#name(String)
+ */
+ public String getName() {
+ return record.getName();
+ }
+
+ /**
+ * @see Record.Builder#type(String)
+ */
+ public String getType() {
+ return record.getType();
+ }
+
+ /**
+ * @see Record.Builder#ttl(Integer)
+ */
+ public int getTTL() {
+ return record.getTTL().get();
+ }
+
+ /**
+ * @see Record.Builder#data(String)
+ */
+ public String getData() {
+ return record.getData();
+ }
+
+ /**
+ * @see Record.Builder#priority(Integer)
+ */
+ public Integer getPriority() {
+ return record.getPriority();
+ }
+
+ /**
+ * @see Record.Builder#comment(String)
+ */
+ public String getComment() {
+ return record.getComment();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ RecordDetail that = RecordDetail.class.cast(obj);
+
+ return equal(this.id, that.id);
+ }
+
+ protected ToStringHelper string() {
+ return toStringHelper(this).omitNullValues().add("id", id).add("created", created).add("updated", updated)
+ .add("record", record);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public final static class Builder {
+ private String id;
+ private Date created;
+ private Date updated;
+ private Record record;
+
+ public Builder id(String id) {
+ this.id = id;
+ return this;
+ }
+
+ public Builder created(Date created) {
+ this.created = created;
+ return this;
+ }
+
+ public Builder updated(Date updated) {
+ this.updated = updated;
+ return this;
+ }
+
+ public Builder record(Record record) {
+ this.record = record;
+ return this;
+ }
+
+ public Builder record(Record.Builder recordBuilder) {
+ this.record = recordBuilder.build();
+ return this;
+ }
+
+ public RecordDetail build() {
+ return new RecordDetail(id, created, updated, record);
+ }
+
+ public Builder from(RecordDetail in) {
+ return this.id(in.getId()).created(in.getCreated()).updated(in.getUpdated()).record(in.getRecord());
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return builder().from(this);
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/Subdomain.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/Subdomain.java
new file mode 100644
index 0000000000..097c859e9f
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/Subdomain.java
@@ -0,0 +1,98 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, String 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.clouddns.v1.domain;
+
+import java.beans.ConstructorProperties;
+import java.util.Date;
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+
+/**
+ * Subdomains are domains within a parent domain. Subdomains allow you to delegate domains. Subdomains can themselves
+ * have subdomains, so third-level, fourth-level, fifth-level, and deeper levels of nesting are possible.
+ *
+ * @author Everett Toews
+ */
+public class Subdomain {
+ private final int id;
+ private final String name;
+ private final String emailAddress;
+ private final Optional comment;
+ private final Date created;
+ private final Date updated;
+
+ @ConstructorProperties({ "id", "name", "emailAddress", "comment", "created", "updated" })
+ private Subdomain(int id, String name, String email, @Nullable String comment, Date created, Date updated) {
+ this.id = id;
+ this.name = name;
+ this.emailAddress = email;
+ this.comment = Optional.fromNullable(comment);
+ this.created = created;
+ this.updated = updated;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getEmail() {
+ return emailAddress;
+ }
+
+ public Optional getComment() {
+ return comment;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+
+ public Date getUpdated() {
+ return updated;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ Subdomain that = Subdomain.class.cast(obj);
+
+ return Objects.equal(this.id, that.id);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this).omitNullValues().add("id", id).add("name", name).add("email", emailAddress)
+ .add("comment", comment.orNull()).add("created", created).add("updated", updated).toString();
+ }
+}
diff --git a/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/UpdateDomain.java b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/UpdateDomain.java
new file mode 100644
index 0000000000..ebd0b50048
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/domain/UpdateDomain.java
@@ -0,0 +1,125 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, String 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.clouddns.v1.domain;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+
+/**
+ * Update a Domain or Subdomain.
+ *
+ * @author Everett Toews
+ */
+public class UpdateDomain {
+ private final Optional emailAddress;
+ private final Optional ttl;
+ private final Optional comment;
+
+ private UpdateDomain(Optional email, Optional ttl, Optional comment) {
+ this.emailAddress = email;
+ this.ttl = ttl;
+ this.comment = comment;
+ }
+
+ public Optional getEmail() {
+ return emailAddress;
+ }
+
+ public Optional getTTL() {
+ return ttl;
+ }
+
+ public Optional getComment() {
+ return comment;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(emailAddress, ttl, comment);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ UpdateDomain that = UpdateDomain.class.cast(obj);
+
+ return Objects.equal(this.emailAddress, that.emailAddress) && Objects.equal(this.ttl, that.ttl)
+ && Objects.equal(this.comment, that.comment);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this).omitNullValues().add("email", emailAddress.orNull()).add("ttl", ttl.orNull())
+ .add("comment", comment.orNull());
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static class Builder {
+ private Optional emailAddress = Optional.absent();
+ private Optional ttl = Optional.absent();
+ private Optional comment = Optional.absent();
+
+ /**
+ * Email address to use for contacting the domain administrator.
+ */
+ public Builder email(String email) {
+ this.emailAddress = Optional.fromNullable(email);
+ return this;
+ }
+
+ /**
+ * If specified, must be greater than 300.
+ */
+ public Builder ttl(Integer ttl) {
+ this.ttl = Optional.fromNullable(ttl);
+ return this;
+ }
+
+ /**
+ * If included, its length must be less than or equal to 160 characters.
+ */
+ public Builder comment(String comment) {
+ this.comment = Optional.fromNullable(comment);
+ return this;
+ }
+
+ public UpdateDomain build() {
+ return new UpdateDomain(emailAddress, ttl, comment);
+ }
+
+ public Builder from(UpdateDomain in) {
+ return this.email(in.getEmail().orNull()).ttl(in.getTTL().orNull()).comment(in.getComment().orNull());
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().from(this);
+ }
+}
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
new file mode 100644
index 0000000000..494c313116
--- /dev/null
+++ b/apis/rackspace-clouddns/src/main/java/org/jclouds/rackspace/clouddns/v1/features/DomainApi.java
@@ -0,0 +1,298 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, String 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.clouddns.v1.features;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
+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.filters.AuthenticateRequest;
+import org.jclouds.rackspace.clouddns.v1.CloudDNSApi;
+import org.jclouds.rackspace.clouddns.v1.binders.FormatAndContentsToJSON;
+import org.jclouds.rackspace.clouddns.v1.binders.UpdateDomainsToJSON;
+import org.jclouds.rackspace.clouddns.v1.config.CloudDNS;
+import org.jclouds.rackspace.clouddns.v1.domain.CreateDomain;
+import org.jclouds.rackspace.clouddns.v1.domain.Domain;
+import org.jclouds.rackspace.clouddns.v1.domain.DomainChange;
+import org.jclouds.rackspace.clouddns.v1.domain.Job;
+import org.jclouds.rackspace.clouddns.v1.domain.Subdomain;
+import org.jclouds.rackspace.clouddns.v1.domain.UpdateDomain;
+import org.jclouds.rackspace.clouddns.v1.functions.DomainsToPagedIterable;
+import org.jclouds.rackspace.clouddns.v1.functions.ParseDomain;
+import org.jclouds.rackspace.clouddns.v1.functions.ParseDomains;
+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;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.ParamParser;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.annotations.WrapWith;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+/**
+ * @author Everett Toews
+ */
+@Endpoint(CloudDNS.class)
+@RequestFilters(AuthenticateRequest.class)
+public interface DomainApi {
+ /**
+ * Provisions one or more new DNS domains based on the configuration defined in CreateDomain. If the domain
+ * creation cannot be fulfilled due to insufficient or invalid data, Job with an ERROR status will
+ * be returned with information regarding the nature of the failure in the body of the Job. Failures in the
+ * validation process are non-recoverable and require the caller to correct the cause of the failure.
+ * This is an atomic operation: if there is a failure in creation of even a single record, the entire process
+ * will fail.
+ *
+ * When a domain is created, and no Time To Live (TTL) is specified, the SOA minTTL (3600 seconds) is used as the
+ * default. When a record is added without a specified TTL, it will receive the domain TTL by default. When the
+ * domain and/or record TTL is supplied by the user, either via a create or update call, the TTL values must be 300
+ * seconds or more.
+ *
+ * To wait for this call to complete use {@link JobPredicates#awaitComplete(CloudDNSApi, Job)}.
+ */
+ @Named("domain:create")
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @ResponseParser(ParseJob.class)
+ @Path("/domains")
+ Job> create(@WrapWith("domains") Iterable createDomains);
+
+ /**
+ * The resulting list is flat, and does not break the domains down hierarchically by subdomain. All representative
+ * domains are included in the list, even if a domain is conceptually a subdomain of another domain in the list.
+ * Records are not included.
+ */
+ @Named("domain:list")
+ @GET
+ @Consumes(MediaType.APPLICATION_JSON)
+ @ResponseParser(ParseDomains.class)
+ @Transform(DomainsToPagedIterable.class)
+ @Path("/domains")
+ @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable list();
+
+ /**
+ * Filtering the search to limit the results returned can be performed by using the nameFilter parameter. For
+ * example, "hoola.com" matches hoola.com and similar names such as main.hoola.com and sub.hoola.com.
+ *
+ * Filter criteria may consist of:
+ *