Issue 76:

New interface annotation parsing:
1.  HttpRequestOptions can now be a vararg option.  While we only support one element at the moment, it can cut down on repetition.

ex.
public List<Stuff> listStuff();
public List<Stuff> listStuff(ListOptions options);

becomes
public List<Stuff> listStuff(ListOptions ... options);

This is especially important when attempting to limit the copy-pasting of annotations which are the same between slight deviations

2.  HttpRequestOptions can now create a path suffix.  Again, this is to cut down on redundancy in the api:

ex.
public List<Stuff> listStuff();
public List<Stuff> listStuff(ListOptions options);
@Path(/details)
public List<Stuff> listStuffDetails();
@Path(/details)
public List<Stuff> listStuffDetails(ListOptions options);

becomes
public List<Stuff> listStuff(ListOptions ... options);

where ListOptions contains withDetails option.

example usage:

  List<Server> servers = connection.listServers(withDetails());


git-svn-id: http://jclouds.googlecode.com/svn/trunk@1652 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-07-19 17:33:17 +00:00
parent 02b35f2cb0
commit 2b0eb5025a
4 changed files with 64 additions and 5 deletions

View File

@ -40,6 +40,7 @@ public class BaseHttpRequestOptions implements HttpRequestOptions {
protected Multimap<String, String> queryParameters = HashMultimap.create();
protected Multimap<String, String> headers = HashMultimap.create();
protected String entity;
protected String pathSuffix;
public String buildStringEntity() {
return entity;
@ -76,4 +77,8 @@ public class BaseHttpRequestOptions implements HttpRequestOptions {
return matrixParameters;
}
public String buildPathSuffix() {
return pathSuffix;
}
}

View File

@ -56,4 +56,6 @@ public interface HttpRequestOptions {
String buildStringEntity();
String buildPathSuffix();
}

View File

@ -54,6 +54,7 @@ import org.jclouds.http.functions.ParseSax.HandlerWithResult;
import org.jclouds.http.options.HttpRequestOptions;
import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
@ -128,13 +129,17 @@ public class JaxrsAnnotationProcessor {
}
private static final Class<? extends HttpRequestOptions[]> optionsVarArgsClass = new HttpRequestOptions[] {}
.getClass();
private final Map<Method, Set<Integer>> methodToIndexesOfOptions = new MapMaker()
.makeComputingMap(new Function<Method, Set<Integer>>() {
public Set<Integer> apply(final Method method) {
Set<Integer> toReturn = Sets.newHashSet();
for (int index = 0; index < method.getParameterTypes().length; index++) {
Class<?> type = method.getParameterTypes()[index];
if (HttpRequestOptions.class.isAssignableFrom(type))
if (HttpRequestOptions.class.isAssignableFrom(type)
|| optionsVarArgsClass.isAssignableFrom(type))
toReturn.add(index);
}
return toReturn;
@ -147,7 +152,8 @@ public class JaxrsAnnotationProcessor {
private final ParseSax.Factory parserFactory;
Function<HttpResponse, ?> createResponseParser(Method method) {
@VisibleForTesting
public Function<HttpResponse, ?> createResponseParser(Method method) {
Function<HttpResponse, ?> transformer;
Class<? extends HandlerWithResult<?>> handler = getXMLTransformerOrNull(method);
if (handler != null) {
@ -158,7 +164,8 @@ public class JaxrsAnnotationProcessor {
return transformer;
}
Function<Exception, ?> createExceptionParserOrNullIfNotFound(Method method) {
@VisibleForTesting
public Function<Exception, ?> createExceptionParserOrNullIfNotFound(Method method) {
ExceptionParser annotation = method.getAnnotation(ExceptionParser.class);
if (annotation != null) {
return injector.getInstance(annotation.value());
@ -227,6 +234,10 @@ public class JaxrsAnnotationProcessor {
for (Entry<String, String> matrix : options.buildMatrixParameters().entries()) {
builder.matrixParam(matrix.getKey(), matrix.getValue());
}
String pathSuffix = options.buildPathSuffix();
if (pathSuffix != null) {
builder.path(pathSuffix);
}
}
URI endPoint;
@ -444,7 +455,22 @@ public class JaxrsAnnotationProcessor {
private HttpRequestOptions findOptionsIn(Method method, Object[] args) {
for (int index : methodToIndexesOfOptions.get(method)) {
return (HttpRequestOptions) args[index];
if (args.length >= index + 1) {// accomodate varargs
if (optionsVarArgsClass.isAssignableFrom(args[index].getClass())) {
HttpRequestOptions[] options = (HttpRequestOptions[]) args[index];
if (options.length == 0) {
return null;
} else if (options.length == 1) {
return options[0];
} else {
throw new IllegalArgumentException(
"we currently do not support multiple varargs options in: "
+ method.getName());
}
} else {
return (HttpRequestOptions) args[index];
}
}
}
return null;
}

View File

@ -390,6 +390,13 @@ public class JaxrsAnnotationProcessorTest {
return null;
}
@GET
@VirtualHost
@Path("/{id}")
public Future<String> get(@PathParam("id") String id, HttpRequestOptions... options) {
return null;
}
@GET
@Path("/{id}")
@ResponseParser(ReturnStringIf200.class)
@ -435,6 +442,25 @@ public class JaxrsAnnotationProcessorTest {
}
}
public void testCreateGetVarArgOptionsThatProducesHeaders() throws SecurityException,
NoSuchMethodException {
DateTime date = new DateTime();
GetOptions options = GetOptions.Builder.ifModifiedSince(date);
HttpRequestOptions[] optionsHolder = new HttpRequestOptions[]{};
Method method = TestRequest.class.getMethod("get", String.class, optionsHolder.getClass());
URI endpoint = URI.create("http://localhost");
HttpRequest httpMethod = factory.create(TestRequest.class).createRequest(endpoint, method,
new Object[] { "1", options });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/1");
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
assertEquals(httpMethod.getHeaders().size(), 2);
assertEquals(httpMethod.getHeaders().get(HttpHeaders.HOST), Collections
.singletonList("localhost"));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.IF_MODIFIED_SINCE), Collections
.singletonList(dateService.rfc822DateFormat(date)));
}
public void testCreateGetOptionsThatProducesHeaders() throws SecurityException,
NoSuchMethodException {
DateTime date = new DateTime();