diff --git a/apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Resource.java b/apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Resource.java index ffd68f87bf..0d82ffa894 100644 --- a/apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Resource.java +++ b/apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Resource.java @@ -22,31 +22,81 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentSkipListMap; import com.google.common.base.Functions; +import com.google.common.base.Predicate; import com.google.common.collect.Lists; +import sun.awt.image.ImageWatched; + +import javax.annotation.Nullable; /** * @author Dmitri Babaev + * @author Matt Stephenson */ public class Resource { private List> links = Lists.newArrayList(); - public URI getURI() { + //This is the preference order for returning a URI in getURI + private enum LinkType { + BOOKMARK_JSON(new Predicate>() { + @Override + public boolean apply(@Nullable Map linkMap) { + return Functions.forMap(linkMap, "").apply("rel").equals("bookmark") && + Functions.forMap(linkMap, "").apply("type").contains("json"); + } + }), + BOOKMARK_ANY(new Predicate>() { + @Override + public boolean apply(@Nullable Map linkMap) { + return Functions.forMap(linkMap, "").apply("rel").equals("bookmark"); + } + }), + SELF(new Predicate>() { + @Override + public boolean apply(@Nullable Map linkMap) { + return Functions.forMap(linkMap, "").apply("rel").equals("self"); + } + }); + + Predicate> linkPredicate; + + LinkType(Predicate> linkPredicate) { + this.linkPredicate = linkPredicate; + }; + } + + private final ConcurrentSkipListMap orderedSelfReferences = new ConcurrentSkipListMap(); + + private void populateOrderedSelfReferences() { for (Map linkProperties : links) { - try { - if (!Functions.forMap(linkProperties, "").apply("rel").equals("bookmark")) - continue; - if (!Functions.forMap(linkProperties, "").apply("type").contains("json")) - continue; - - return new URI(linkProperties.get("href")); - } catch (URISyntaxException e) { - throw new RuntimeException(e); + for (LinkType type : LinkType.values()) { + if(type.linkPredicate.apply(linkProperties)) { + try { + orderedSelfReferences.put(type, new URI(linkProperties.get("href"))); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } } } + if(orderedSelfReferences.isEmpty()) + throw new IllegalStateException("URI is not available"); + } - throw new IllegalStateException("URI is not available"); + public URI getURI() { + if(orderedSelfReferences.isEmpty()) + populateOrderedSelfReferences(); + + return orderedSelfReferences.firstEntry().getValue(); + } + + public URI getSelfURI() { + if(orderedSelfReferences.isEmpty()) + populateOrderedSelfReferences(); + + return orderedSelfReferences.get(LinkType.SELF); } } diff --git a/apis/nova/src/test/resources/test_list_servers_detail.json b/apis/nova/src/test/resources/test_list_servers_detail.json index 6891e92091..aa5cbbf185 100644 --- a/apis/nova/src/test/resources/test_list_servers_detail.json +++ b/apis/nova/src/test/resources/test_list_servers_detail.json @@ -9,6 +9,7 @@ "created" : "2010-08-10T12:00:00Z", "hostId" : "e4d909c290d0fb1ca068ffaddf22cbd0", "affinityId" : "fc88bcf8394db9c8d0564e08ca6a9724188a84d1", + "uuid" : "d84e2086-fc0d-11e0-8e08-2837371c69ae", "status" : "BUILD", "progress" : 60, "addresses" : { @@ -53,6 +54,7 @@ "created" : "2010-08-10T12:00:00Z", "hostId" : "9e107d9d372bb6826bd81d3542a419d6", "affinityId" : "b414fa41cb37b97dcb58d6c76112af1258e9eae2", + "uuid" : "e66d54d4-fc0d-11e0-b93f-2837371c69ae", "status" : "ACTIVE", "addresses" : { "public" : [ @@ -74,12 +76,6 @@ }, { "rel" : "bookmark", - "type" : "application/vnd.openstack.compute-v1.1+xml", - "href" : "http://servers.api.openstack.org/1234/servers/5678" - }, - { - "rel" : "bookmark", - "type" : "application/vnd.openstack.compute-v1.1+json", "href" : "http://servers.api.openstack.org/1234/servers/56789" } ]