added means to supply default parameters to a MapBinder

This commit is contained in:
Adrian Cole 2010-08-24 10:45:27 -07:00
parent f2b074e2a5
commit e726d74a9d
3 changed files with 139 additions and 70 deletions

View File

@ -0,0 +1,46 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.rest.annotations;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.ws.rs.QueryParam;
/**
* Designates that default parameters will be added a map that builds the request entity.
*
* @see QueryParam
* @author Adrian Cole
*/
@Target( { TYPE, METHOD })
@Retention(RUNTIME)
public @interface MapPayloadParams {
public static final String NULL = "MAP_PAYLOAD_NULL";
String[] keys();
String[] values() default NULL;
}

View File

@ -111,6 +111,7 @@ import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.MapBinder; import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.MapPayloadParam; import org.jclouds.rest.annotations.MapPayloadParam;
import org.jclouds.rest.annotations.MapPayloadParams;
import org.jclouds.rest.annotations.MatrixParams; import org.jclouds.rest.annotations.MatrixParams;
import org.jclouds.rest.annotations.OverrideRequestFilters; import org.jclouds.rest.annotations.OverrideRequestFilters;
import org.jclouds.rest.annotations.ParamParser; import org.jclouds.rest.annotations.ParamParser;
@ -576,6 +577,17 @@ public class RestAnnotationProcessor<T> {
} }
} }
private void addMapPayload(Map<String, String> postParams, MapPayloadParams mapDefaults,
Collection<Entry<String, String>> tokenValues) {
for (int i = 0; i < mapDefaults.keys().length; i++) {
if (mapDefaults.values()[i].equals(MapPayloadParams.NULL)) {
postParams.put(mapDefaults.keys()[i], null);
} else {
postParams.put(mapDefaults.keys()[i], replaceTokens(mapDefaults.values()[i], tokenValues));
}
}
}
private void addQuery(Multimap<String, String> queryParams, QueryParams query, private void addQuery(Multimap<String, String> queryParams, QueryParams query,
Collection<Entry<String, String>> tokenValues) { Collection<Entry<String, String>> tokenValues) {
for (int i = 0; i < query.keys().length; i++) { for (int i = 0; i < query.keys().length; i++) {
@ -806,13 +818,12 @@ public class RestAnnotationProcessor<T> {
public void decorateRequest(GeneratedHttpRequest<T> request, Multimap<String, String> headers) { public void decorateRequest(GeneratedHttpRequest<T> request, Multimap<String, String> headers) {
org.jclouds.rest.MapBinder mapBinder = getMapPayloadBinderOrNull(request.getJavaMethod(), request.getArgs()); org.jclouds.rest.MapBinder mapBinder = getMapPayloadBinderOrNull(request.getJavaMethod(), request.getArgs());
Map<String, String> mapParams = buildPostParams(request.getJavaMethod(), request.getArgs());
// MapPayloadBinder is only useful if there are parameters. We guard here
// in case the
// MapPayloadBinder is also an PayloadBinder. If so, it can be used with
// or without
// parameters.
if (mapBinder != null) { if (mapBinder != null) {
Map<String, String> mapParams = buildPostParams(request.getJavaMethod(), request.getArgs());
if (request.getJavaMethod().isAnnotationPresent(MapPayloadParams.class)) {
MapPayloadParams params = request.getJavaMethod().getAnnotation(MapPayloadParams.class);
addMapPayload(mapParams, params, headers.entries());
}
mapBinder.bindToRequest(request, mapParams); mapBinder.bindToRequest(request, mapParams);
} else { } else {
OUTER: for (Entry<Integer, Set<Annotation>> entry : filterValues( OUTER: for (Entry<Integer, Set<Annotation>> entry : filterValues(

View File

@ -119,6 +119,7 @@ import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.MapBinder; import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.MapPayloadParam; import org.jclouds.rest.annotations.MapPayloadParam;
import org.jclouds.rest.annotations.MapPayloadParams;
import org.jclouds.rest.annotations.MatrixParams; import org.jclouds.rest.annotations.MatrixParams;
import org.jclouds.rest.annotations.OverrideRequestFilters; import org.jclouds.rest.annotations.OverrideRequestFilters;
import org.jclouds.rest.annotations.ParamParser; import org.jclouds.rest.annotations.ParamParser;
@ -534,25 +535,27 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
assertEquals(request.getMethod(), "POST"); assertEquals(request.getMethod(), "POST");
} }
public class TestPost { public interface TestPost {
@POST @POST
public void post(@Nullable @BinderParam(BindToStringPayload.class) String content) { void post(@Nullable @BinderParam(BindToStringPayload.class) String content);
}
@POST @POST
public void postAsJson(@BinderParam(BindToJsonPayload.class) String content) { public void postAsJson(@BinderParam(BindToJsonPayload.class) String content);
}
@POST @POST
@Path("{foo}") @Path("{foo}")
public void postWithPath(@PathParam("foo") @MapPayloadParam("fooble") String path, MapBinder content) { public void postWithPath(@PathParam("foo") @MapPayloadParam("fooble") String path, MapBinder content);
}
@POST @POST
@Path("{foo}") @Path("{foo}")
@MapBinder(BindToJsonPayload.class) @MapBinder(BindToJsonPayload.class)
public void postWithMethodBinder(@PathParam("foo") @MapPayloadParam("fooble") String path) { public void postWithMethodBinder(@PathParam("foo") @MapPayloadParam("fooble") String path);
}
@POST
@Path("{foo}")
@MapPayloadParams(keys = "rat", values = "atat")
@MapBinder(BindToJsonPayload.class)
public void postWithMethodBinderAndDefaults(@PathParam("foo") @MapPayloadParam("fooble") String path);
} }
public void testCreatePostRequest() throws SecurityException, NoSuchMethodException, IOException { public void testCreatePostRequest() throws SecurityException, NoSuchMethodException, IOException {
@ -606,6 +609,15 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
assertPayloadEquals(request, "{\"fooble\":\"data\"}", "application/json", false); assertPayloadEquals(request, "{\"fooble\":\"data\"}", "application/json", false);
} }
public void testCreatePostWithMethodBinderAndDefaults() throws SecurityException, NoSuchMethodException, IOException {
Method method = TestPost.class.getMethod("postWithMethodBinderAndDefaults", String.class);
HttpRequest request = factory(TestPost.class).createRequest(method, "data");
assertRequestLineEquals(request, "POST http://localhost:9999/data HTTP/1.1");
assertNonPayloadHeadersEqual(request, "");
assertPayloadEquals(request, "{\"fooble\":\"data\",\"rat\":\"atat\"}", "application/json", false);
}
static interface TestMultipartForm { static interface TestMultipartForm {
@POST @POST
void withStringPart(@PartParam(name = "fooble") String path); void withStringPart(@PartParam(name = "fooble") String path);