mirror of https://github.com/apache/jclouds.git
deepened unwrapping of json to include only value in list
This commit is contained in:
parent
f1a878f016
commit
6f545c0277
|
@ -142,7 +142,7 @@ public class SimpleDateFormatDateService implements DateService {
|
||||||
public static final Pattern NANOS_TO_MILLIS_PATTERN = Pattern
|
public static final Pattern NANOS_TO_MILLIS_PATTERN = Pattern
|
||||||
.compile(".*[0-9][0-9][0-9][0-9][0-9][0-9]");
|
.compile(".*[0-9][0-9][0-9][0-9][0-9][0-9]");
|
||||||
|
|
||||||
public static final Pattern TZ_PATTERN = Pattern.compile(".*[+-][0-9][0-9]:[0-9][0-9]");
|
public static final Pattern TZ_PATTERN = Pattern.compile(".*[+-][0-9][0-9]:?[0-9][0-9]");
|
||||||
|
|
||||||
private String trimNanosToMillis(String toParse) {
|
private String trimNanosToMillis(String toParse) {
|
||||||
if (NANOS_TO_MILLIS_PATTERN.matcher(toParse).matches())
|
if (NANOS_TO_MILLIS_PATTERN.matcher(toParse).matches())
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.Set;
|
||||||
|
|
||||||
|
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 UnwrapOnlyNestedJsonValueInSet<T> implements Function<HttpResponse, T> {
|
||||||
|
|
||||||
|
private final UnwrapOnlyNestedJsonValue<Set<T>> json;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
UnwrapOnlyNestedJsonValueInSet(UnwrapOnlyNestedJsonValue<Set<T>> json) {
|
||||||
|
this.json = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T apply(HttpResponse arg0) {
|
||||||
|
Set<T> set = json.apply(arg0);
|
||||||
|
if (set == null || set.size() == 0)
|
||||||
|
return null;
|
||||||
|
return Iterables.getOnlyElement(set);
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,9 +24,10 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unwraps the only value in the json reponse
|
* Unwraps the only value in a nested json reponse
|
||||||
*
|
*
|
||||||
* ex. { "foo" :"bar" } becomes "bar"
|
* ex. { "foo" :"bar" } becomes "bar"
|
||||||
*
|
*
|
||||||
|
@ -44,10 +45,27 @@ public @interface Unwrap {
|
||||||
*
|
*
|
||||||
* ex. if (2)
|
* ex. if (2)
|
||||||
*
|
*
|
||||||
* { "foo" : {"bar" : "baz} } becomes "baz"
|
* { "foo" : {"bar" : ["baz"]} } becomes ["baz"]
|
||||||
*
|
*
|
||||||
* @return nestingLevel
|
* @return nestingLevel
|
||||||
*/
|
*/
|
||||||
int depth() default 1;
|
int depth() default 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* final collection type
|
||||||
|
*
|
||||||
|
* ex. if depth(2), edgeCollection(Map.class)
|
||||||
|
*
|
||||||
|
* { "foo" : {"bar" : ["baz"]} } becomes ["baz"]
|
||||||
|
*
|
||||||
|
* ex. if depth(3), edgeCollection(Set.class)
|
||||||
|
*
|
||||||
|
* { "foo" : {"bar" : ["baz"]} } becomes "baz"
|
||||||
|
*
|
||||||
|
* <h4>Note</h4> only Map and Set are valid
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Class<?> edgeCollection() default Map.class;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,7 @@ import org.jclouds.http.functions.ReturnStringIf2xx;
|
||||||
import org.jclouds.http.functions.ReturnTrueIf2xx;
|
import org.jclouds.http.functions.ReturnTrueIf2xx;
|
||||||
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
|
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
|
||||||
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
|
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
|
||||||
|
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValueInSet;
|
||||||
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
|
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
|
||||||
import org.jclouds.http.options.HttpRequestOptions;
|
import org.jclouds.http.options.HttpRequestOptions;
|
||||||
import org.jclouds.http.utils.ModifyRequest;
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
|
@ -785,13 +786,17 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
ParameterizedType parserType;
|
ParameterizedType parserType;
|
||||||
if (method.isAnnotationPresent(Unwrap.class)) {
|
if (method.isAnnotationPresent(Unwrap.class)) {
|
||||||
int nestingLevel = method.getAnnotation(Unwrap.class).depth();
|
int depth = method.getAnnotation(Unwrap.class).depth();
|
||||||
if (nestingLevel == 1)
|
Class edgeCollection = method.getAnnotation(Unwrap.class).edgeCollection();
|
||||||
|
if (depth == 1 && edgeCollection == Map.class)
|
||||||
parserType = Types.newParameterizedType(UnwrapOnlyJsonValue.class, returnVal);
|
parserType = Types.newParameterizedType(UnwrapOnlyJsonValue.class, returnVal);
|
||||||
else if (nestingLevel == 2)
|
else if (depth == 2 && edgeCollection == Map.class)
|
||||||
parserType = Types.newParameterizedType(UnwrapOnlyNestedJsonValue.class, returnVal);
|
parserType = Types.newParameterizedType(UnwrapOnlyNestedJsonValue.class, returnVal);
|
||||||
|
else if (depth == 3 && edgeCollection == Set.class)
|
||||||
|
parserType = Types.newParameterizedType(UnwrapOnlyNestedJsonValueInSet.class, returnVal);
|
||||||
else
|
else
|
||||||
throw new IllegalStateException("nesting level " + nestingLevel + " not yet supported for @Unwrap");
|
throw new IllegalStateException(String.format(
|
||||||
|
"depth(%d) edgeCollection(%s) not yet supported for @Unwrap", depth, edgeCollection));
|
||||||
} else {
|
} else {
|
||||||
parserType = Types.newParameterizedType(ParseJson.class, returnVal);
|
parserType = Types.newParameterizedType(ParseJson.class, returnVal);
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,7 @@ import org.jclouds.http.functions.ReturnStringIf2xx;
|
||||||
import org.jclouds.http.functions.ReturnTrueIf2xx;
|
import org.jclouds.http.functions.ReturnTrueIf2xx;
|
||||||
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
|
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
|
||||||
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
|
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
|
||||||
|
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValueInSet;
|
||||||
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
import org.jclouds.http.internal.PayloadEnclosingImpl;
|
||||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||||
import org.jclouds.http.options.GetOptions;
|
import org.jclouds.http.options.GetOptions;
|
||||||
|
@ -771,6 +772,12 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
ListenableFuture<? extends Set<String>> testUnwrapDepth2();
|
ListenableFuture<? extends Set<String>> testUnwrapDepth2();
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/")
|
||||||
|
@Unwrap(depth = 3, edgeCollection = Set.class)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
ListenableFuture<String> testUnwrapDepth3();
|
||||||
|
|
||||||
@Target( { ElementType.METHOD })
|
@Target( { ElementType.METHOD })
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@HttpMethod("ROWDY")
|
@HttpMethod("ROWDY")
|
||||||
|
@ -955,6 +962,50 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
||||||
newStringPayload("{\"runit\":{\"runit\":[\"0.7.0\",\"0.7.1\"]}}"))), ImmutableSet.of("0.7.0", "0.7.1"));
|
newStringPayload("{\"runit\":{\"runit\":[\"0.7.0\",\"0.7.1\"]}}"))), ImmutableSet.of("0.7.0", "0.7.1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testUnwrapDepth3() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
Method method = TestPut.class.getMethod("testUnwrapDepth3");
|
||||||
|
HttpRequest request = factory(TestPut.class).createRequest(method);
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, request, UnwrapOnlyNestedJsonValueInSet.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.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testUnwrapDepth3None() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
Method method = TestPut.class.getMethod("testUnwrapDepth3");
|
||||||
|
HttpRequest request = factory(TestPut.class).createRequest(method);
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, request, UnwrapOnlyNestedJsonValueInSet.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\":[]}}"))), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testUnwrapDepth3TooMany() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
Method method = TestPut.class.getMethod("testUnwrapDepth3");
|
||||||
|
HttpRequest request = factory(TestPut.class).createRequest(method);
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, request, UnwrapOnlyNestedJsonValueInSet.class);
|
||||||
|
// now test that it works!
|
||||||
|
|
||||||
|
Function<HttpResponse, Map<String, String>> parser = (Function<HttpResponse, Map<String, String>>) RestAnnotationProcessor
|
||||||
|
.createResponseParser(parserFactory, injector, method, request);
|
||||||
|
|
||||||
|
parser.apply(new HttpResponse(200, "ok", newStringPayload("{\"runit\":{\"runit\":[\"0.7.0\",\"0.7.1\"]}}")));
|
||||||
|
}
|
||||||
|
|
||||||
static class TestRequestFilter1 implements HttpRequestFilter {
|
static class TestRequestFilter1 implements HttpRequestFilter {
|
||||||
public HttpRequest filter(HttpRequest request) throws HttpException {
|
public HttpRequest filter(HttpRequest request) throws HttpException {
|
||||||
return request;
|
return request;
|
||||||
|
|
Loading…
Reference in New Issue