Add Types.nextAnnotations

This commit is contained in:
Eric Cochran
2017-01-30 23:27:10 -08:00
parent ed164fd806
commit 05b594a26c
2 changed files with 69 additions and 6 deletions

View File

@@ -28,9 +28,12 @@ import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType; import java.lang.reflect.WildcardType;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Properties; import java.util.Properties;
import java.util.Set;
/** Factory methods for types. */ /** Factory methods for types. */
public final class Types { public final class Types {
@@ -39,6 +42,29 @@ public final class Types {
private Types() { private Types() {
} }
/**
* Checks if {@code annotations} contains {@code jsonQualifier}.
* Returns the subset of {@code annotations} without {@code jsonQualifier}, or null if {@code
* annotations} does not contain {@code jsonQualifier}.
*/
public static Set<? extends Annotation> nextAnnotations(Set<? extends Annotation> annotations,
Class<? extends Annotation> jsonQualifier) {
if (!jsonQualifier.isAnnotationPresent(JsonQualifier.class)) {
throw new IllegalArgumentException(jsonQualifier + " is not a JsonQualifier.");
}
if (annotations.isEmpty()) {
return null;
}
for (Annotation annotation : annotations) {
if (jsonQualifier.equals(annotation.annotationType())) {
Set<Annotation> delegateAnnotations = new LinkedHashSet<>(annotations);
delegateAnnotations.remove(annotation);
return Collections.unmodifiableSet(delegateAnnotations);
}
}
return null;
}
/** /**
* Returns a new parameterized type, applying {@code typeArguments} to {@code rawType}. Use this * Returns a new parameterized type, applying {@code typeArguments} to {@code rawType}. Use this
* method if {@code rawType} is not enclosed in another type. * method if {@code rawType} is not enclosed in another type.

View File

@@ -15,13 +15,17 @@
*/ */
package com.squareup.moshi; package com.squareup.moshi;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set;
import org.junit.Test; import org.junit.Test;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
@@ -29,6 +33,44 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
public final class TypesTest { public final class TypesTest {
@Retention(RUNTIME) @JsonQualifier @interface TestQualifier {
}
@Retention(RUNTIME) @JsonQualifier @interface AnotherTestQualifier {
}
@Retention(RUNTIME) @interface TestAnnotation {
}
@TestQualifier private Object hasTestQualifier;
@Test public void nextAnnotationsRequiresJsonAnnotation() throws Exception {
try {
Types.nextAnnotations(Collections.<Annotation>emptySet(), TestAnnotation.class);
fail();
} catch (IllegalArgumentException expected) {
assertThat(expected).hasMessage(
"interface com.squareup.moshi.TypesTest$TestAnnotation is not a JsonQualifier.");
}
}
@Test public void nextAnnotationsDoesNotContainReturnsNull() throws Exception {
Set<? extends Annotation> annotations =
Collections.singleton(Types.createJsonQualifierImplementation(AnotherTestQualifier.class));
assertThat(Types.nextAnnotations(annotations, TestQualifier.class)).isNull();
assertThat(
Types.nextAnnotations(Collections.<Annotation>emptySet(), TestQualifier.class)).isNull();
}
@Test public void nextAnnotationsReturnsDelegateAnnotations() throws Exception {
Set<Annotation> annotations = new LinkedHashSet<>(2);
annotations.add(Types.createJsonQualifierImplementation(TestQualifier.class));
annotations.add(Types.createJsonQualifierImplementation(AnotherTestQualifier.class));
Set<AnotherTestQualifier> expected =
Collections.singleton(Types.createJsonQualifierImplementation(AnotherTestQualifier.class));
assertThat(Types.nextAnnotations(Collections.unmodifiableSet(annotations), TestQualifier.class))
.isEqualTo(expected);
}
@Test public void newParameterizedType() throws Exception { @Test public void newParameterizedType() throws Exception {
// List<A>. List is a top-level class. // List<A>. List is a top-level class.
@@ -149,16 +191,11 @@ public final class TypesTest {
@Test public void createJsonQualifierImplementation() throws Exception { @Test public void createJsonQualifierImplementation() throws Exception {
TestQualifier actual = Types.createJsonQualifierImplementation(TestQualifier.class); TestQualifier actual = Types.createJsonQualifierImplementation(TestQualifier.class);
TestQualifier expected = TestQualifier expected =
(TestQualifier) TypesTest.class.getDeclaredField("unused").getAnnotations()[0]; (TestQualifier) TypesTest.class.getDeclaredField("hasTestQualifier").getAnnotations()[0];
assertThat(actual.annotationType()).isEqualTo(TestQualifier.class); assertThat(actual.annotationType()).isEqualTo(TestQualifier.class);
assertThat(actual).isEqualTo(expected); assertThat(actual).isEqualTo(expected);
assertThat(actual).isNotEqualTo(null); assertThat(actual).isNotEqualTo(null);
assertThat(actual.hashCode()).isEqualTo(expected.hashCode()); assertThat(actual.hashCode()).isEqualTo(expected.hashCode());
assertThat(actual.getClass()).isNotEqualTo(TestQualifier.class); assertThat(actual.getClass()).isNotEqualTo(TestQualifier.class);
} }
@TestQualifier private static Object unused;
@Retention(RUNTIME) @JsonQualifier @interface TestQualifier {
}
} }