added nested json unwrapping

This commit is contained in:
Adrian Cole 2011-02-05 11:54:32 -08:00
parent 37d5533028
commit f1a878f016
5 changed files with 106 additions and 3 deletions

View File

@ -0,0 +1,55 @@
/**
*
* 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.http.functions;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.http.HttpResponse;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
*/
@Singleton
public class UnwrapOnlyNestedJsonValue<T> implements Function<HttpResponse, T> {
private final ParseJson<Map<String, Map<String, T>>> json;
@Inject
UnwrapOnlyNestedJsonValue(ParseJson<Map<String, Map<String, T>>> json) {
this.json = json;
}
@Override
public T apply(HttpResponse arg0) {
Map<String, Map<String, T>> map = json.apply(arg0);
if (map == null || map.size() == 0)
return null;
Map<String, T> map1 = Iterables.getOnlyElement(map.values());
if (map1 == null || map1.size() == 0)
return null;
return Iterables.getOnlyElement(map1.values());
}
}

View File

@ -35,4 +35,19 @@ import java.lang.annotation.Target;
@Target(METHOD)
@Retention(RUNTIME)
public @interface Unwrap {
/**
* level to unwrap.
*
* ex. if default (1)
*
* { "foo" :"bar" } becomes "bar"
*
* ex. if (2)
*
* { "foo" : {"bar" : "baz} } becomes "baz"
*
* @return nestingLevel
*/
int depth() default 1;
}

View File

@ -87,6 +87,7 @@ import org.jclouds.http.functions.ReturnInputStream;
import org.jclouds.http.functions.ReturnStringIf2xx;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
import org.jclouds.http.options.HttpRequestOptions;
import org.jclouds.http.utils.ModifyRequest;
@ -783,10 +784,17 @@ public class RestAnnotationProcessor<T> {
returnVal = method.getGenericReturnType();
}
ParameterizedType parserType;
if (method.isAnnotationPresent(Unwrap.class))
parserType = Types.newParameterizedType(UnwrapOnlyJsonValue.class, returnVal);
else
if (method.isAnnotationPresent(Unwrap.class)) {
int nestingLevel = method.getAnnotation(Unwrap.class).depth();
if (nestingLevel == 1)
parserType = Types.newParameterizedType(UnwrapOnlyJsonValue.class, returnVal);
else if (nestingLevel == 2)
parserType = Types.newParameterizedType(UnwrapOnlyNestedJsonValue.class, returnVal);
else
throw new IllegalStateException("nesting level " + nestingLevel + " not yet supported for @Unwrap");
} else {
parserType = Types.newParameterizedType(ParseJson.class, returnVal);
}
return (Key<? extends Function<HttpResponse, ?>>) Key.get(parserType);
} else if (method.getReturnType().equals(String.class)
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureStringLiteral)) {

View File

@ -168,6 +168,9 @@ swift.propertiesbuilder=org.jclouds.openstack.swift.SwiftPropertiesBuilder
cloudfiles.contextbuilder=org.jclouds.cloudfiles.CloudFilesContextBuilder
cloudfiles.propertiesbuilder=org.jclouds.openstack.swift.SwiftPropertiesBuilder
cloudstack.contextbuilder=org.jclouds.cloudstack.CloudStackContextBuilder
cloudstack.propertiesbuilder=org.jclouds.cloudstack.CloudStackPropertiesBuilder
cloudfiles-us.contextbuilder=org.jclouds.cloudfiles.CloudFilesContextBuilder
cloudfiles-us.propertiesbuilder=org.jclouds.rackspace.cloudfiles.CloudFilesUSPropertiesBuilder

View File

@ -97,6 +97,7 @@ import org.jclouds.http.functions.ReturnInputStream;
import org.jclouds.http.functions.ReturnStringIf2xx;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
import org.jclouds.http.internal.PayloadEnclosingImpl;
import org.jclouds.http.options.BaseHttpRequestOptions;
import org.jclouds.http.options.GetOptions;
@ -764,6 +765,12 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<? extends Set<String>> testUnwrap4();
@GET
@Path("/")
@Unwrap(depth = 2)
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<? extends Set<String>> testUnwrapDepth2();
@Target( { ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("ROWDY")
@ -933,6 +940,21 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
ImmutableSet.of("0.7.0", "0.7.1"));
}
@SuppressWarnings("unchecked")
public void testUnwrapDepth2() throws SecurityException, NoSuchMethodException, IOException {
Method method = TestPut.class.getMethod("testUnwrapDepth2");
HttpRequest request = factory(TestPut.class).createRequest(method);
assertResponseParserClassEquals(method, request, UnwrapOnlyNestedJsonValue.class);
// now test that it works!
Function<HttpResponse, Map<String, String>> parser = (Function<HttpResponse, Map<String, String>>) RestAnnotationProcessor
.createResponseParser(parserFactory, injector, method, request);
assertEquals(parser.apply(new HttpResponse(200, "ok",
newStringPayload("{\"runit\":{\"runit\":[\"0.7.0\",\"0.7.1\"]}}"))), ImmutableSet.of("0.7.0", "0.7.1"));
}
static class TestRequestFilter1 implements HttpRequestFilter {
public HttpRequest filter(HttpRequest request) throws HttpException {
return request;