Merge pull request #237 from NightlyNexus/patch-1

Add Types.createJsonQualifierImplementation
This commit is contained in:
Jesse Wilson 2017-01-30 20:55:00 -05:00 committed by GitHub
commit 14a430cb58
3 changed files with 60 additions and 0 deletions

View file

@ -61,6 +61,11 @@ public final class Moshi {
return adapter(type, Util.NO_ANNOTATIONS);
}
public <T> JsonAdapter<T> adapter(Type type, Class<? extends Annotation> annotationType) {
return adapter(type,
Collections.singleton(Types.createJsonQualifierImplementation(annotationType)));
}
@SuppressWarnings("unchecked") // Factories are required to return only matching JsonAdapters.
public <T> JsonAdapter<T> adapter(Type type, Set<? extends Annotation> annotations) {
type = Types.canonicalize(type);

View file

@ -15,10 +15,14 @@
*/
package com.squareup.moshi;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
@ -137,6 +141,39 @@ public final class Types {
}
}
@SuppressWarnings("unchecked")
static <T extends Annotation> T createJsonQualifierImplementation(final Class<T> annotationType) {
if (!annotationType.isAnnotation()) {
throw new IllegalArgumentException(annotationType + " must be an annotation.");
}
if (!annotationType.isAnnotationPresent(JsonQualifier.class)) {
throw new IllegalArgumentException(annotationType + " must have @JsonQualifier.");
}
if (annotationType.getDeclaredMethods().length != 0) {
throw new IllegalArgumentException(annotationType + " must not declare methods.");
}
return (T) Proxy.newProxyInstance(annotationType.getClassLoader(),
new Class<?>[] { annotationType }, new InvocationHandler() {
@Override public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String methodName = method.getName();
switch (methodName) {
case "annotationType":
return annotationType;
case "equals":
Object o = args[0];
return annotationType.isInstance(o);
case "hashCode":
return 0;
case "toString":
return "@" + annotationType.getName() + "()";
default:
return method.invoke(proxy, args);
}
}
});
}
static boolean equal(Object a, Object b) {
return a == b || (a != null && a.equals(b));
}

View file

@ -15,6 +15,7 @@
*/
package com.squareup.moshi;
import java.lang.annotation.Retention;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
@ -23,6 +24,7 @@ import java.util.Map;
import java.util.Properties;
import org.junit.Test;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
@ -143,4 +145,20 @@ public final class TypesTest {
assertThat(Types.mapKeyAndValueTypes(StringIntegerMap.class, StringIntegerMap.class))
.containsExactly(String.class, Integer.class);
}
@Test public void createJsonQualifierImplementation() throws Exception {
TestQualifier actual = Types.createJsonQualifierImplementation(TestQualifier.class);
TestQualifier expected =
(TestQualifier) TypesTest.class.getDeclaredField("unused").getAnnotations()[0];
assertThat(actual.annotationType()).isEqualTo(TestQualifier.class);
assertThat(actual).isEqualTo(expected);
assertThat(actual).isNotEqualTo(null);
assertThat(actual.hashCode()).isEqualTo(expected.hashCode());
assertThat(actual.getClass()).isNotEqualTo(TestQualifier.class);
}
@TestQualifier private static Object unused;
@Retention(RUNTIME) @JsonQualifier @interface TestQualifier {
}
}