diff --git a/core/src/main/java/org/jclouds/internal/ClassMethodArgs.java b/core/src/main/java/org/jclouds/internal/ClassMethodArgs.java index f01dc64ae8..5268e20540 100644 --- a/core/src/main/java/org/jclouds/internal/ClassMethodArgs.java +++ b/core/src/main/java/org/jclouds/internal/ClassMethodArgs.java @@ -22,6 +22,7 @@ import static com.google.common.base.Objects.equal; import static com.google.common.base.Preconditions.checkNotNull; import java.lang.reflect.Method; +import java.util.Arrays; import org.jclouds.javax.annotation.Nullable; @@ -134,6 +135,7 @@ public class ClassMethodArgs { } protected ToStringHelper string() { - return Objects.toStringHelper("").add("clazz", clazz).add("method", method).add("args", args); + return Objects.toStringHelper("").omitNullValues().add("clazz", clazz).add("method", method) + .add("args", args != null ? Arrays.asList(args) : null); } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/location/config/LocationModule.java b/core/src/main/java/org/jclouds/location/config/LocationModule.java index 089b62f06a..fc9f597448 100644 --- a/core/src/main/java/org/jclouds/location/config/LocationModule.java +++ b/core/src/main/java/org/jclouds/location/config/LocationModule.java @@ -145,7 +145,12 @@ public class LocationModule extends AbstractModule { public Set apply(Set input) { return Sets.filter(input, filter); } - + + @Override + public String toString() { + return "filterStrings(" + filter + ")"; + } + } @Provides diff --git a/core/src/main/java/org/jclouds/location/predicates/fromconfig/AnyOrConfiguredRegionId.java b/core/src/main/java/org/jclouds/location/predicates/fromconfig/AnyOrConfiguredRegionId.java index 5b1aa2d93f..4e5f2a0d23 100644 --- a/core/src/main/java/org/jclouds/location/predicates/fromconfig/AnyOrConfiguredRegionId.java +++ b/core/src/main/java/org/jclouds/location/predicates/fromconfig/AnyOrConfiguredRegionId.java @@ -52,5 +52,10 @@ public class AnyOrConfiguredRegionId implements RegionIdFilter { return true; return idsInConfig.contains(input); } + + @Override + public String toString() { + return "anyOrConfiguredRegionId(" + idsInConfigSupplier + ")"; + } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/location/predicates/fromconfig/AnyOrConfiguredZoneId.java b/core/src/main/java/org/jclouds/location/predicates/fromconfig/AnyOrConfiguredZoneId.java index 6dd68f3e84..7430167643 100644 --- a/core/src/main/java/org/jclouds/location/predicates/fromconfig/AnyOrConfiguredZoneId.java +++ b/core/src/main/java/org/jclouds/location/predicates/fromconfig/AnyOrConfiguredZoneId.java @@ -52,5 +52,10 @@ public class AnyOrConfiguredZoneId implements ZoneIdFilter { return true; return idsInConfig.contains(input); } + + @Override + public String toString() { + return "anyOrConfiguredZoneId(" + idsInConfigSupplier + ")"; + } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/location/suppliers/RegionIdToURISupplier.java b/core/src/main/java/org/jclouds/location/suppliers/RegionIdToURISupplier.java index ac7bc3815e..e8f42a55e6 100644 --- a/core/src/main/java/org/jclouds/location/suppliers/RegionIdToURISupplier.java +++ b/core/src/main/java/org/jclouds/location/suppliers/RegionIdToURISupplier.java @@ -20,6 +20,7 @@ package org.jclouds.location.suppliers; import java.net.URI; import java.util.Map; +import java.util.NoSuchElementException; import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.suppliers.fromconfig.RegionIdToURIFromConfigurationOrDefaultToProvider; @@ -44,9 +45,10 @@ public interface RegionIdToURISupplier extends Supplier> { } } + @Override + public String toString() { + return "splitConfigurationKey(" + configKey + ")"; + } + } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java index 0832a0544d..e8d4e9e68b 100644 --- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java +++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java @@ -48,6 +48,7 @@ import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.NoSuchElementException; import java.util.Set; import java.util.SortedSet; import java.util.concurrent.ExecutionException; @@ -435,6 +436,11 @@ public class RestAnnotationProcessor { requestBuilder.method(getHttpMethodOrConstantOrThrowException(method)); } + if (endpoint == null) { + throw new NoSuchElementException(String.format("no endpoint found for %s", + new ClassMethodArgs(method.getDeclaringClass(), method, args))); + } + requestBuilder.declaring(declaring) .javaMethod(method) .args(args) diff --git a/core/src/main/java/org/jclouds/util/Suppliers2.java b/core/src/main/java/org/jclouds/util/Suppliers2.java index bc9b80b350..0d02f6b334 100644 --- a/core/src/main/java/org/jclouds/util/Suppliers2.java +++ b/core/src/main/java/org/jclouds/util/Suppliers2.java @@ -25,11 +25,13 @@ import java.io.OutputStream; import java.io.Serializable; import java.util.Map; +import com.google.common.annotations.Beta; import com.google.common.base.Function; import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; +import com.google.common.base.Throwables; import com.google.common.collect.Iterables; import com.google.common.io.OutputSupplier; @@ -44,7 +46,8 @@ public class Suppliers2 { @Override public V apply(Map> input) { - return Iterables.getLast(input.values()).get(); + Supplier last = Iterables.getLast(input.values()); + return last.get(); } @Override @@ -82,6 +85,56 @@ public class Suppliers2 { }; } + /** + * returns the value of the first supplier, or the value of the fallback, if the unlessNull is + * null. + */ + @Beta + public static Supplier or(final Supplier unlessNull, final Supplier fallback) { + return new Supplier() { + + @Override + public T get() { + T val = unlessNull.get(); + if (val != null) + return val; + return fallback.get(); + } + + @Override + public String toString() { + return Objects.toStringHelper(this).add("unlessNull", unlessNull).add("fallback", fallback).toString(); + } + }; + } + + /** + * if a throwable of certain type is encountered on getting the first value, use the fallback. + */ + @Beta + public static Supplier onThrowable(final Supplier unlessThrowable, + final Class throwable, final Supplier fallback) { + return new Supplier() { + + @Override + public T get() { + try { + return unlessThrowable.get(); + } catch (Throwable t) { + if (Throwables2.getFirstThrowableOfType(t, throwable) != null) + return fallback.get(); + throw Throwables.propagate(t); + } + } + + @Override + public String toString() { + return Objects.toStringHelper(this).add("unlessThrowable", unlessThrowable) + .add("throwable", throwable.getSimpleName()).add("fallback", fallback).toString(); + } + }; + } + // only here until guava compose gives a toString! // http://code.google.com/p/guava-libraries/issues/detail?id=1052 public static Supplier compose(Function function, Supplier supplier) { diff --git a/core/src/test/java/org/jclouds/util/Suppliers2Test.java b/core/src/test/java/org/jclouds/util/Suppliers2Test.java index 6ff27ccbff..612bd5f963 100644 --- a/core/src/test/java/org/jclouds/util/Suppliers2Test.java +++ b/core/src/test/java/org/jclouds/util/Suppliers2Test.java @@ -18,25 +18,13 @@ */ package org.jclouds.util; -import static com.google.common.base.Preconditions.checkNotNull; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertSame; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; +import java.util.NoSuchElementException; import org.testng.annotations.Test; -import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableMap; @@ -45,15 +33,66 @@ public class Suppliers2Test { @Test public void testGetLastValueInMap() { - assertEquals(Suppliers2 - . getLastValueInMap( - Suppliers.>> ofInstance(ImmutableMap.of("foo", Suppliers - .ofInstance("bar")))).get(), "bar"); + assertEquals( + Suppliers2. getLastValueInMap( + Suppliers.>> ofInstance(ImmutableMap.of("foo", + Suppliers.ofInstance("bar")))).get(), "bar"); } @Test public void testOfInstanceFunction() { assertEquals(Suppliers2.ofInstanceFunction().apply("foo").get(), "foo"); } + + @Test + public void testOrWhenFirstNull() { + assertEquals(Suppliers2.or(Suppliers. ofInstance(null), Suppliers.ofInstance("foo")).get(), "foo"); + } + + @Test + public void testOrWhenFirstNotNull() { + assertEquals(Suppliers2.or(Suppliers. ofInstance("foo"), Suppliers.ofInstance("bar")).get(), "foo"); + } + + @Test + public void testOnThrowableWhenFirstThrowsMatchingException() { + assertEquals(Suppliers2.onThrowable(new Supplier() { + + @Override + public String get() { + throw new NoSuchElementException(); + } + + }, NoSuchElementException.class, Suppliers.ofInstance("foo")).get(), "foo"); + } + + @Test(expectedExceptions = RuntimeException.class) + public void testOnThrowableWhenFirstThrowsUnmatchingException() { + Suppliers2.onThrowable(new Supplier() { + + @Override + public String get() { + throw new RuntimeException(); + } + + }, NoSuchElementException.class, Suppliers.ofInstance("foo")).get(); + } + + @Test + public void testOnThrowableWhenFirstIsFine() { + assertEquals( + Suppliers2.onThrowable(Suppliers. ofInstance("foo"), NoSuchElementException.class, + Suppliers.ofInstance("bar")).get(), "foo"); + } + + @Test + public void testCombination() { + Supplier alternate = Suppliers.ofInstance("bar"); + Supplier or = Suppliers2.or(Suppliers. ofInstance("foo"), alternate); + Supplier combined = Suppliers2.onThrowable(or, NoSuchElementException.class, alternate); + + assertEquals(combined.get(), "foo"); + } + }