From 1f14adf4eaadbcaf13184b1a89624c09ae60e180 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Thu, 1 Sep 2011 17:42:46 -0700 Subject: [PATCH] Issue 158: added response parser for ProductPackage --- .../jclouds/softlayer/domain/ProductItem.java | 189 ++++++++++++++++++ .../softlayer/domain/ProductItemPrice.java | 143 +++++++++++++ .../softlayer/domain/ProductPackage.java | 174 ++++++++++++++++ .../features/ProductPackageAsyncClient.java | 11 +- .../features/ProductPackageClient.java | 5 +- .../ProductPackageAsyncClientTest.java | 10 +- .../ProductPackageClientLiveTest.java | 39 +++- 7 files changed, 560 insertions(+), 11 deletions(-) create mode 100644 sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductItem.java create mode 100644 sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductItemPrice.java create mode 100644 sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductPackage.java 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; } }