diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductItem.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductItem.java
new file mode 100644
index 0000000000..ea5e283571
--- /dev/null
+++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductItem.java
@@ -0,0 +1,189 @@
+/**
+ * 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.softlayer.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+/**
+ * The SoftLayer_Product_Item data type contains general information relating to
+ * a single SoftLayer product.
+ *
+ * @author Adrian Cole
+ * @see
+ */
+public class ProductItem implements Comparable {
+
+ // TODO there are more elements than this.
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private long id = -1;
+ private String description;
+ private String units;
+ private Float capacity;
+ private Set prices = Sets.newLinkedHashSet();
+
+ public Builder id(long id) {
+ this.id = id;
+ return this;
+ }
+
+ public Builder description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public Builder units(String units) {
+ this.units = units;
+ return this;
+ }
+
+ public Builder capacity(Float capacity) {
+ this.capacity = capacity;
+ return this;
+ }
+
+ public Builder price(ProductItemPrice prices) {
+ this.prices.add(checkNotNull(prices, "prices"));
+ return this;
+ }
+
+ public Builder prices(Iterable prices) {
+ this.prices = ImmutableSet. copyOf(checkNotNull(prices, "prices"));
+ return this;
+ }
+
+ public ProductItem build() {
+ return new ProductItem(id, description, units, capacity, prices);
+ }
+
+ public static Builder fromProductItem(ProductItem in) {
+ return ProductItem.builder().id(in.getId()).description(in.getDescription()).units(in.getUnits())
+ .capacity(in.getCapacity()).prices(in.getPrices());
+ }
+ }
+
+ private long id = -1;
+ private String description;
+ private String units;
+ private Float capacity;
+ private Set prices = Sets.newLinkedHashSet();
+
+ // for deserializer
+ ProductItem() {
+
+ }
+
+ public ProductItem(long id, String description, String units, Float capacity, Iterable prices) {
+ this.id = id;
+ this.description = description;
+ this.units = units;
+ this.capacity = capacity;
+ this.prices = ImmutableSet. copyOf(checkNotNull(prices, "prices"));
+ }
+
+ @Override
+ public int compareTo(ProductItem arg0) {
+ return new Long(id).compareTo(arg0.getId());
+ }
+
+ /**
+ * @return The unique identifier of a specific location.
+ */
+ public long getId() {
+ return id;
+ }
+
+ /**
+ * @return A product's description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * @return The unit of measurement that a product item is measured in.
+ */
+ @Nullable
+ public String getUnits() {
+ return units;
+ }
+
+ /**
+ * @return Some Product Items have capacity information such as RAM and
+ * bandwidth, and others. This provides the numerical representation
+ * of the capacity given in the description of this product item.
+ */
+ @Nullable
+ public Float getCapacity() {
+ return capacity;
+ }
+
+ /**
+ *
+ * @return A product item's prices.
+ */
+ public Set getPrices() {
+ return prices;
+ }
+
+ public Builder toBuilder() {
+ return Builder.fromProductItem(this);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (id ^ (id >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ProductItem other = (ProductItem) obj;
+ if (id != other.id)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "ProductItem [id=" + id + ", description=" + description + ", units=" + units + ", capacity=" + capacity
+ + ", prices=" + prices + "]";
+ }
+}
diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductItemPrice.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductItemPrice.java
new file mode 100644
index 0000000000..a3b88c8f6a
--- /dev/null
+++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductItemPrice.java
@@ -0,0 +1,143 @@
+/**
+ * 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.softlayer.domain;
+
+import javax.annotation.Nullable;
+
+/**
+ * The SoftLayer_Product_Item_Price data type contains general information
+ * relating to a single SoftLayer product item price. You can find out what
+ * packages each price is in as well as which category under which this price is
+ * sold. All prices are returned in Floating point values measured in US Dollars
+ * ($USD).
+ *
+ * @author Adrian Cole
+ * @see
+ */
+public class ProductItemPrice implements Comparable {
+ // TODO there are more elements than this.
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private long id = -1;
+ private long itemId = -1;
+ private Float recurringFee;
+ private Float hourlyRecurringFee;
+
+ public Builder id(long id) {
+ this.id = id;
+ return this;
+ }
+
+ public Builder itemId(long itemId) {
+ this.itemId = itemId;
+ return this;
+ }
+
+ public Builder recurringFee(Float recurringFee) {
+ this.recurringFee = recurringFee;
+ return this;
+ }
+
+ public Builder hourlyRecurringFee(Float hourlyRecurringFee) {
+ this.hourlyRecurringFee = hourlyRecurringFee;
+ return this;
+ }
+
+ public ProductItemPrice build() {
+ return new ProductItemPrice(id, itemId, recurringFee, hourlyRecurringFee);
+ }
+
+ public static Builder fromPrice(ProductItemPrice in) {
+ return ProductItemPrice.builder().id(in.getId()).itemId(in.getItemId())
+ .hourlyRecurringFee(in.getHourlyRecurringFee()).recurringFee(in.getRecurringFee());
+ }
+ }
+
+ private long id = -1;
+ private long itemId = -1;
+ private Float recurringFee;
+ private Float hourlyRecurringFee;
+
+ // for deserializer
+ ProductItemPrice() {
+
+ }
+
+ public ProductItemPrice(long id, long itemId, Float recurringFee, Float hourlyRecurringFee) {
+ this.id = id;
+ this.itemId = itemId;
+ this.recurringFee = recurringFee;
+ this.hourlyRecurringFee = hourlyRecurringFee;
+ }
+
+ @Override
+ public int compareTo(ProductItemPrice arg0) {
+ return new Long(id).compareTo(arg0.getId());
+ }
+
+ /**
+ * @return The unique identifier of a Product Item Price.
+ */
+ public long getId() {
+ return id;
+ }
+
+ /**
+ * @return The unique identifier for a product Item
+ */
+ public long getItemId() {
+ return itemId;
+ }
+
+ /**
+ * @return A recurring fee is a fee that happens every billing period. This
+ * fee is represented as a Floating point decimal in US dollars
+ * ($USD).
+ */
+ @Nullable
+ public Float getRecurringFee() {
+ return recurringFee;
+ }
+
+ /**
+ * @return The hourly price for this item, should this item be part of an
+ * hourly pricing package.
+ */
+ @Nullable
+ public Float getHourlyRecurringFee() {
+ return hourlyRecurringFee;
+ }
+
+ public Builder toBuilder() {
+ return Builder.fromPrice(this);
+ }
+
+ @Override
+ public String toString() {
+ return "[id=" + id + ", itemId=" + itemId + ", recurringFee=" + recurringFee + ", hourlyRecurringFee="
+ + hourlyRecurringFee + "]";
+ }
+
+}
diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductPackage.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductPackage.java
new file mode 100644
index 0000000000..cb9ce12223
--- /dev/null
+++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductPackage.java
@@ -0,0 +1,174 @@
+/**
+ * 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.softlayer.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+/**
+ * The SoftLayer_Product_Package data type contains information about packages
+ * from which orders can be generated. Packages contain general information
+ * regarding what is in them, where they are currently sold, availability, and
+ * pricing.
+ *
+ * @author Adrian Cole
+ * @see
+ */
+public class ProductPackage implements Comparable {
+
+ // TODO there are more elements than this.
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private long id = -1;
+ private String name;
+ private String description;
+ private Set items = Sets.newLinkedHashSet();
+
+ public Builder id(long id) {
+ this.id = id;
+ return this;
+ }
+
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public Builder productItem(ProductItem items) {
+ this.items.add(checkNotNull(items, "items"));
+ return this;
+ }
+
+ public Builder items(Iterable items) {
+ this.items = ImmutableSet. copyOf(checkNotNull(items, "items"));
+ return this;
+ }
+
+ public ProductPackage build() {
+ return new ProductPackage(id, name, description, items);
+ }
+
+ public static Builder fromProductPackage(ProductPackage in) {
+ return ProductPackage.builder().id(in.getId()).name(in.getName()).description(in.getDescription())
+ .items(in.getItems());
+ }
+ }
+
+ private long id = -1;
+ private String name;
+ private String description;
+ private Set items = Sets.newLinkedHashSet();
+
+ // for deserializer
+ ProductPackage() {
+
+ }
+
+ public ProductPackage(long id, String name, String description, Iterable items) {
+ this.id = id;
+ this.name = name;
+ this.description = description;
+ this.items = ImmutableSet. copyOf(checkNotNull(items, "items"));
+ }
+
+ @Override
+ public int compareTo(ProductPackage arg0) {
+ return new Long(id).compareTo(arg0.getId());
+ }
+
+ /**
+ * @return A package's internal identifier. Everything regarding a
+ * SoftLayer_Product_Package is tied back to this id.
+ */
+ public long getId() {
+ return id;
+ }
+
+ /**
+ * @return The description of the package. For server packages, this is
+ * usually a detailed description of processor type and count.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return A generic description of the processor type and count. This
+ * includes HTML, so you may want to strip these tags if you plan to
+ * use it.
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ *
+ * @return A collection of valid items available for purchase in this
+ * package.
+ */
+ public Set getItems() {
+ return items;
+ }
+
+ public Builder toBuilder() {
+ return Builder.fromProductPackage(this);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (id ^ (id >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ProductPackage other = (ProductPackage) obj;
+ if (id != other.id)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "ProductPackage [id=" + id + ", name=" + name + ", description=" + description + ", items=" + items + "]";
+ }
+}
diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/features/ProductPackageAsyncClient.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/features/ProductPackageAsyncClient.java
index e642b2dd5d..e7805cda98 100644
--- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/features/ProductPackageAsyncClient.java
+++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/features/ProductPackageAsyncClient.java
@@ -18,13 +18,18 @@
*/
package org.jclouds.softlayer.features;
+import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
import org.jclouds.http.filters.BasicAuthentication;
+import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
+import org.jclouds.softlayer.domain.ProductPackage;
import com.google.common.util.concurrent.ListenableFuture;
@@ -47,9 +52,9 @@ public interface ProductPackageAsyncClient {
@GET
@Path("/SoftLayer_Product_Package/{id}.json")
@QueryParams(keys = "objectMask", values = PRODUCT_MASK)
-// @Consumes(MediaType.APPLICATION_JSON)
-// @ExceptionParser(ReturnNullOnNotFoundOr404.class)
- ListenableFuture getProductPackage(@PathParam("id") long id);
+ @Consumes(MediaType.APPLICATION_JSON)
+ @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+ ListenableFuture getProductPackage(@PathParam("id") long id);
}
diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/features/ProductPackageClient.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/features/ProductPackageClient.java
index 83df16d478..dbc6af02a3 100644
--- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/features/ProductPackageClient.java
+++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/features/ProductPackageClient.java
@@ -21,6 +21,7 @@ package org.jclouds.softlayer.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
+import org.jclouds.softlayer.domain.ProductPackage;
/**
* Provides synchronous access to ProductPackage.
@@ -30,7 +31,7 @@ import org.jclouds.concurrent.Timeout;
* @see
* @author Adrian Cole
*/
-@Timeout(duration = 4, timeUnit = TimeUnit.SECONDS)
+@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface ProductPackageClient {
/**
@@ -39,6 +40,6 @@ public interface ProductPackageClient {
* id of the product package
* @return product package or null if not found
*/
- String getProductPackage(long id);
+ ProductPackage getProductPackage(long id);
}
diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageAsyncClientTest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageAsyncClientTest.java
index bb17d2b465..90dd1fa6a7 100644
--- a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageAsyncClientTest.java
+++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageAsyncClientTest.java
@@ -22,8 +22,8 @@ import java.io.IOException;
import java.lang.reflect.Method;
import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ReturnStringIf2xx;
-import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
@@ -44,12 +44,12 @@ public class ProductPackageAsyncClientTest extends BaseSoftLayerAsyncClientTest<
assertRequestLineEquals(
httpRequest,
"GET https://api.softlayer.com/rest/v3/SoftLayer_Product_Package/1234.json?objectMask=items HTTP/1.1");
- assertNonPayloadHeadersEqual(httpRequest, "");
+ assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
- assertResponseParserClassEquals(method, httpRequest, ReturnStringIf2xx.class);
+ assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
assertSaxResponseParserClassEquals(method, null);
- assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
+ assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageClientLiveTest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageClientLiveTest.java
index 9d51b457f5..c0c790539b 100644
--- a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageClientLiveTest.java
+++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageClientLiveTest.java
@@ -18,6 +18,11 @@
*/
package org.jclouds.softlayer.features;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.softlayer.domain.ProductItem;
+import org.jclouds.softlayer.domain.ProductItemPrice;
+import org.jclouds.softlayer.domain.ProductPackage;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@@ -38,7 +43,39 @@ public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
@Test
public void testGetProductPackage() {
- client.getProductPackage(46);
+ ProductPackage response = client.getProductPackage(46);
+ assert null != response;
+ assert response.getId() > 0 : response;
+ assert response.getName() != null : response;
+ assert response.getDescription() != null : response;
+
+ assertTrue(response.getItems().size() >= 0);
+ for (ProductItem item : response.getItems()) {
+ // ProductItem newDetails = client.getProductItem(item.getId());
+ // assertEquals(item.getId(), newDetails.getId());
+ checkProductItem(item);
+ }
+ }
+
+ private void checkProductItem(ProductItem item) {
+ assert item.getId() > 0 : item;
+ assert item.getDescription() != null : item;
+ // units and capacity may be null
+
+ assertTrue(item.getPrices().size() >= 0);
+
+ for (ProductItemPrice price : item.getPrices()) {
+ // ProductItemPrice newDetails =
+ // client.getProductItemPrice(price.getId());
+ // assertEquals(item.getId(), newDetails.getId());
+ checkPrice(price);
+ }
+ }
+
+ private void checkPrice(ProductItemPrice price) {
+ assert price.getId() > 0 : price;
+ assert price.getItemId() > 0 : price;
+ assert price.getRecurringFee() != null || price.getHourlyRecurringFee() != null : price;
}
}