diff --git a/providers/softlayer/src/main/java/org/jclouds/softlayer/domain/Datacenter.java b/providers/softlayer/src/main/java/org/jclouds/softlayer/domain/Datacenter.java index b14bed97ca..496516712b 100644 --- a/providers/softlayer/src/main/java/org/jclouds/softlayer/domain/Datacenter.java +++ b/providers/softlayer/src/main/java/org/jclouds/softlayer/domain/Datacenter.java @@ -18,6 +18,13 @@ */ package org.jclouds.softlayer.domain; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; + +import java.util.Set; + +import static com.google.common.base.Preconditions.checkNotNull; + /** * * @author Adrian Cole @@ -34,6 +41,7 @@ public class Datacenter implements Comparable { private String name; private String longName; private Address locationAddress; + private Set regions = Sets.newLinkedHashSet(); public Builder id(int id) { this.id = id; @@ -55,12 +63,24 @@ public class Datacenter implements Comparable { return this; } + public Builder region(Region regions) { + this.regions.add(checkNotNull(regions, "regions")); + return this; + } + + public Builder regions(Iterable regions) { + this.regions = ImmutableSet. copyOf(checkNotNull(regions, "regions")); + return this; + } + public Datacenter build() { - return new Datacenter(id, name, longName, locationAddress); + return new Datacenter(id, name, longName, locationAddress, regions); } public static Builder fromDatacenter(Datacenter in) { - return Datacenter.builder().id(in.getId()).name(in.getName()).longName(in.getLongName()).locationAddress(in.getLocationAddress()); + return Datacenter.builder().id(in.getId()).name(in.getName()) + .longName(in.getLongName()).locationAddress(in.getLocationAddress()) + .regions(in.getRegions()); } } @@ -68,17 +88,18 @@ public class Datacenter implements Comparable { private String name; private String longName; private Address locationAddress; - + private Set regions = Sets.newLinkedHashSet(); // for deserializer Datacenter() { } - public Datacenter(int id, String name, String longName, Address locationAddress) { + public Datacenter(int id, String name, String longName, Address locationAddress, Iterable regions) { this.id = id; this.name = name; this.longName = longName; this.locationAddress = locationAddress; + this.regions = ImmutableSet. copyOf(checkNotNull(regions, "regions")); } @Override @@ -114,6 +135,16 @@ public class Datacenter implements Comparable { return locationAddress; } + /** + * A location can be a member of 1 or more regions. + * Sometimes the list of regions is empty, for example as a new Datacenter is being added. + * The list of regions usually contains one with keyName=FIRST_AVAILABLE which should be ignored. + * @return The regions to which a location belongs. + */ + public Set getRegions() { + return regions; + } + public Builder toBuilder() { return Builder.fromDatacenter(this); } @@ -142,7 +173,7 @@ public class Datacenter implements Comparable { @Override public String toString() { - return "[id=" + id + ", country=" + name + ", state=" + longName + "], locationAddress=" + locationAddress + "]"; + return "[id=" + id + ", country=" + name + ", state=" + longName + "], locationAddress=" + locationAddress + ", regions="+regions+"]"; } diff --git a/providers/softlayer/src/main/java/org/jclouds/softlayer/domain/Region.java b/providers/softlayer/src/main/java/org/jclouds/softlayer/domain/Region.java new file mode 100644 index 0000000000..c2536b169b --- /dev/null +++ b/providers/softlayer/src/main/java/org/jclouds/softlayer/domain/Region.java @@ -0,0 +1,128 @@ +/** + * 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 static com.google.common.base.Strings.emptyToNull; + +/** + * A region is made up of a keyname and a description of that region. + * A region keyname can be used as part of an order. + * Check the SoftLayer_Product_Order service for more details. + * + * @author Jason King + * @see + */ +public class Region implements Comparable { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String keyname; + private String description; + + public Builder keyname(String keyname) { + this.keyname = keyname; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Region build() { + return new Region(keyname, description); + } + + public static Builder fromAddress(Region in) { + return Region.builder().keyname(in.getKeyname()) + .description(in.getDescription()); + } + } + + /* An integer representing the order in which this element is displayed */ + private int sortOrder = 0; + private String keyname; + private String description; + + // for deserializer + Region() { + + } + + public Region(String keyname, String description) { + this.keyname = checkNotNull(emptyToNull(keyname),"keyname cannot be null or empty:"+keyname); + this.description = checkNotNull(emptyToNull(description),"country cannot be null or empty:"+description); + } + + @Override + public int compareTo(Region arg0) { + return new Integer(sortOrder).compareTo(arg0.sortOrder); + } + + /** + * @return A unique key name for a region. Provided for easy debugging. This is to be sent in with an order. + */ + public String getKeyname() { + return keyname; + } + + /** + * @return A short description of a region's name. This description is seen on the order forms. + */ + public String getDescription() { + return description; + } + + public Builder toBuilder() { + return Builder.fromAddress(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Region region = (Region) o; + + if (sortOrder != region.sortOrder) return false; + if (!description.equals(region.description)) return false; + if (!keyname.equals(region.keyname)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = sortOrder; + result = 31 * result + keyname.hashCode(); + result = 31 * result + description.hashCode(); + return result; + } + + @Override + public String toString() { + return "[keyname=" + keyname + ", description=" + description + "]"; + } + + +} diff --git a/providers/softlayer/src/main/java/org/jclouds/softlayer/features/DatacenterAsyncClient.java b/providers/softlayer/src/main/java/org/jclouds/softlayer/features/DatacenterAsyncClient.java index cdcf2eb916..a6f4a8921c 100644 --- a/providers/softlayer/src/main/java/org/jclouds/softlayer/features/DatacenterAsyncClient.java +++ b/providers/softlayer/src/main/java/org/jclouds/softlayer/features/DatacenterAsyncClient.java @@ -53,7 +53,7 @@ public interface DatacenterAsyncClient { */ @GET @Path("/SoftLayer_Location_Datacenter/Datacenters.json") - @QueryParams(keys = "objectMask", values = "locationAddress") + @QueryParams(keys = "objectMask", values = "locationAddress;regions") @Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) ListenableFuture> listDatacenters(); @@ -63,7 +63,7 @@ public interface DatacenterAsyncClient { */ @GET @Path("/SoftLayer_Location_Datacenter/{id}.json") - @QueryParams(keys = "objectMask", values = "locationAddress") + @QueryParams(keys = "objectMask", values = "locationAddress;regions") @Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ReturnNullOnNotFoundOr404.class) ListenableFuture getDatacenter(@PathParam("id") long id); diff --git a/providers/softlayer/src/main/java/org/jclouds/softlayer/features/ProductPackageAsyncClient.java b/providers/softlayer/src/main/java/org/jclouds/softlayer/features/ProductPackageAsyncClient.java index 7a11d7501c..363cba9589 100644 --- a/providers/softlayer/src/main/java/org/jclouds/softlayer/features/ProductPackageAsyncClient.java +++ b/providers/softlayer/src/main/java/org/jclouds/softlayer/features/ProductPackageAsyncClient.java @@ -43,7 +43,7 @@ import javax.ws.rs.core.MediaType; @RequestFilters(BasicAuthentication.class) @Path("/v{jclouds.api-version}") public interface ProductPackageAsyncClient { - public static String PRODUCT_MASK = "items.prices;items.categories;locations.locationAddress"; + public static String PRODUCT_MASK = "items.prices;items.categories;locations.locationAddress;locations.regions"; /** * @see ProductPackageClient#getProductPackage diff --git a/providers/softlayer/src/test/java/org/jclouds/softlayer/features/DatacenterAsyncClientTest.java b/providers/softlayer/src/test/java/org/jclouds/softlayer/features/DatacenterAsyncClientTest.java index d5398d0425..3a852f0b53 100644 --- a/providers/softlayer/src/test/java/org/jclouds/softlayer/features/DatacenterAsyncClientTest.java +++ b/providers/softlayer/src/test/java/org/jclouds/softlayer/features/DatacenterAsyncClientTest.java @@ -44,7 +44,7 @@ public class DatacenterAsyncClientTest extends BaseSoftLayerAsyncClientTest builder = ImmutableSet. builder(); + builder.add(Datacenter.builder().id(265592).name("ams01").longName("Amsterdam 1").build()); builder.add(Datacenter.builder().id(3).name("dal01").longName("Dallas").build()); builder.add(Datacenter.builder().id(18171).name("sea01").longName("Seattle").build()); builder.add(Datacenter.builder().id(168642).name("sjc01").longName("San Jose 1").build()); @@ -91,6 +93,12 @@ public class DatacenterClientLiveTest extends BaseSoftLayerClientLiveTest { assert dc.getId() > 0 : dc; assert dc.getName() != null : dc; assert dc.getLongName() != null : dc; + for( Region region: dc.getRegions()) checkRegion(region); + } + + private void checkRegion(Region region) { + assert !region.getDescription().isEmpty() : region; + assert !region.getKeyname().isEmpty() : region; } private void checkAddress(Address address) { diff --git a/providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageAsyncClientTest.java b/providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageAsyncClientTest.java index c31dfc9b11..de161ad5c8 100644 --- a/providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageAsyncClientTest.java +++ b/providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageAsyncClientTest.java @@ -43,7 +43,7 @@ public class ProductPackageAsyncClientTest extends BaseSoftLayerAsyncClientTest< assertRequestLineEquals( httpRequest, - "GET https://api.softlayer.com/rest/v3/SoftLayer_Product_Package/1234.json?objectMask=items.prices%3Bitems.categories%3Blocations.locationAddress HTTP/1.1"); + "GET https://api.softlayer.com/rest/v3/SoftLayer_Product_Package/1234.json?objectMask=items.prices%3Bitems.categories%3Blocations.locationAddress%3Blocations.regions HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); assertPayloadEquals(httpRequest, null, null, false); diff --git a/providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageClientLiveTest.java b/providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageClientLiveTest.java index bdac3cefd6..40cdd80cfb 100644 --- a/providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageClientLiveTest.java +++ b/providers/softlayer/src/test/java/org/jclouds/softlayer/features/ProductPackageClientLiveTest.java @@ -39,7 +39,7 @@ import static org.testng.Assert.*; * * @author Adrian Cole */ -@Test(groups = "live") +@Test(groups = "live", sequential = true) public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest { /** @@ -183,6 +183,12 @@ public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest { assert datacenter.getId() > 0 : datacenter; assert datacenter.getName() != null : datacenter; assert datacenter.getLongName() != null : datacenter; + for( Region region: datacenter.getRegions()) checkRegion(region); + } + + private void checkRegion(Region region) { + assert !region.getDescription().isEmpty() : region; + assert !region.getKeyname().isEmpty() : region; } private void checkAddress(Address address) {