Skip to content

Commit

Permalink
JPA Id: adds support for method annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
jqno committed Dec 21, 2018
1 parent 8e26d92 commit b6eb0b1
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ private void visitFields(Set<Class<?>> types, AnnotationCache cache, TypeDescrip
f.getType().getDeclaredAnnotations()
.forEach(a -> cacheSupportedAnnotations(a, types, cache, addToCache, inheriting));
});
typeDescription.getDeclaredMethods()
.filter(m -> m.getName().startsWith("get"))
.forEach(m -> {
String methodName = m.getName();
String correspondingFieldName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
Consumer<Annotation> addToCache = a -> types.forEach(t -> cache.addFieldAnnotation(t, correspondingFieldName, a));

m.getDeclaredAnnotations()
.forEach(a -> cacheSupportedAnnotations(a, types, cache, addToCache, inheriting));
});
}

private void cacheSupportedAnnotations(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ public void succeed_whenEqualsBehavesLikeVersionedEntity_givenIdIsMarkedWithIdAn
.verify();
}

@Test
public void succeed_whenMethodsAreAnnotatedInsteadOfFields() {
EqualsVerifier.forClass(MethodAnnotatedBusinessKeyPerson.class)
.verify();
}

@Test
public void fail_whenIdFieldIsTheOnlyFieldUsed() {
expectFailure("Precondition: you can't use withOnlyTheseFields on a field marked @Id.", "Suppress Warning.SURROGATE_KEY if");
Expand Down Expand Up @@ -531,4 +537,37 @@ public boolean equals(Object obj) {
return Float.floatToIntBits(id);
}
}

static final class MethodAnnotatedBusinessKeyPerson {
private final UUID id;
private final String socialSecurity;
private final String name;
private final LocalDate birthdate;

public MethodAnnotatedBusinessKeyPerson(UUID id, String socialSecurity, String name, LocalDate birthdate) {
this.id = id;
this.socialSecurity = socialSecurity;
this.name = name;
this.birthdate = birthdate;
}

@Id public UUID getId() { return id; }
@NaturalId public String getSocialSecurity() { return socialSecurity; }
public String getName() { return name; }
public LocalDate getBirthdate() { return birthdate; }

@Override
public boolean equals(Object obj) {
if (!(obj instanceof MethodAnnotatedBusinessKeyPerson)) {
return false;
}
MethodAnnotatedBusinessKeyPerson other = (MethodAnnotatedBusinessKeyPerson)obj;
return Objects.equals(socialSecurity, other.socialSecurity);
}

@Override
public int hashCode() {
return Objects.hash(socialSecurity);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,22 +104,44 @@ public void findTypeUseClassAnnotationInField() {
assertFieldDoesNotHaveAnnotation(AnnotatedTypes.class, NO_RETENTION, TYPEUSE_CLASS_RETENTION);
}

@Test
public void findRuntimeAnnotationInMethod() {
build(AnnotatedMethods.class);

assertFieldHasAnnotation(AnnotatedMethods.class, RUNTIME_RETENTION, METHOD_RUNTIME_RETENTION);
assertFieldHasAnnotation(AnnotatedMethods.class, BOTH_RETENTIONS, METHOD_RUNTIME_RETENTION);
assertFieldDoesNotHaveAnnotation(AnnotatedMethods.class, CLASS_RETENTION, METHOD_RUNTIME_RETENTION);
assertFieldDoesNotHaveAnnotation(AnnotatedMethods.class, NO_RETENTION, METHOD_RUNTIME_RETENTION);
}

@Test
public void findClassAnnotationInMethod() {
build(AnnotatedMethods.class);

assertFieldHasAnnotation(AnnotatedMethods.class, CLASS_RETENTION, METHOD_CLASS_RETENTION);
assertFieldHasAnnotation(AnnotatedMethods.class, BOTH_RETENTIONS, METHOD_CLASS_RETENTION);
assertFieldDoesNotHaveAnnotation(AnnotatedMethods.class, RUNTIME_RETENTION, METHOD_CLASS_RETENTION);
assertFieldDoesNotHaveAnnotation(AnnotatedMethods.class, NO_RETENTION, METHOD_CLASS_RETENTION);
}

@Test
public void findPartialAnnotationName() {
build(AnnotatedWithRuntime.class, AnnotatedFields.class, AnnotatedTypes.class);
build(AnnotatedWithRuntime.class, AnnotatedFields.class, AnnotatedTypes.class, AnnotatedMethods.class);

assertTypeHasAnnotation(AnnotatedWithRuntime.class, TYPE_RUNTIME_RETENTION_PARTIAL_CLASSNAME);
assertFieldHasAnnotation(AnnotatedFields.class, RUNTIME_RETENTION, FIELD_RUNTIME_RETENTION_PARTIAL_CLASSNAME);
assertFieldHasAnnotation(AnnotatedTypes.class, RUNTIME_RETENTION, TYPEUSE_RUNTIME_RETENTION_PARTIAL_CLASSNAME);
assertFieldHasAnnotation(AnnotatedMethods.class, RUNTIME_RETENTION, METHOD_RUNTIME_RETENTION_PARTIAL_CLASSNAME);
}

@Test
public void findFullyQualifiedAnnotationName() {
build(AnnotatedWithRuntime.class, AnnotatedFields.class, AnnotatedTypes.class);
build(AnnotatedWithRuntime.class, AnnotatedFields.class, AnnotatedTypes.class, AnnotatedMethods.class);

assertTypeHasAnnotation(AnnotatedWithRuntime.class, TYPE_RUNTIME_RETENTION_CANONICAL_CLASSNAME);
assertFieldHasAnnotation(AnnotatedFields.class, RUNTIME_RETENTION, FIELD_RUNTIME_RETENTION_CANONICAL_CLASSNAME);
assertFieldHasAnnotation(AnnotatedTypes.class, RUNTIME_RETENTION, TYPEUSE_RUNTIME_RETENTION_CANONICAL_CLASSNAME);
assertFieldHasAnnotation(AnnotatedMethods.class, RUNTIME_RETENTION, METHOD_RUNTIME_RETENTION_CANONICAL_CLASSNAME);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package nl.jqno.equalsverifier.testhelpers.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface MethodAnnotationClassRetention {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package nl.jqno.equalsverifier.testhelpers.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodAnnotationRuntimeRetention {}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@ public enum TestSupportedAnnotations implements Annotation {
FIELD_CLASS_RETENTION(false, "nl.jqno.equalsverifier.testhelpers.annotations.FieldAnnotationClassRetention"),
TYPEUSE_RUNTIME_RETENTION(false, "nl.jqno.equalsverifier.testhelpers.annotations.TypeUseAnnotationRuntimeRetention"),
TYPEUSE_CLASS_RETENTION(false, "nl.jqno.equalsverifier.testhelpers.annotations.TypeUseAnnotationClassRetention"),
METHOD_RUNTIME_RETENTION(false, "nl.jqno.equalsverifier.testhelpers.annotations.MethodAnnotationRuntimeRetention"),
METHOD_CLASS_RETENTION(false, "nl.jqno.equalsverifier.testhelpers.annotations.MethodAnnotationClassRetention"),

TYPE_RUNTIME_RETENTION_PARTIAL_CLASSNAME(false, "TypeAnnotationRuntimeRetention"),
TYPE_RUNTIME_RETENTION_CANONICAL_CLASSNAME(false, TypeAnnotationRuntimeRetention.class.getCanonicalName()),
FIELD_RUNTIME_RETENTION_PARTIAL_CLASSNAME(false, "FieldAnnotationRuntimeRetention"),
FIELD_RUNTIME_RETENTION_CANONICAL_CLASSNAME(false, FieldAnnotationRuntimeRetention.class.getCanonicalName()),
TYPEUSE_RUNTIME_RETENTION_PARTIAL_CLASSNAME(false, "TypeUseAnnotationRuntimeRetention"),
TYPEUSE_RUNTIME_RETENTION_CANONICAL_CLASSNAME(false, TypeUseAnnotationRuntimeRetention.class.getCanonicalName()),
METHOD_RUNTIME_RETENTION_PARTIAL_CLASSNAME(false, "MethodAnnotationRuntimeRetention"),
METHOD_RUNTIME_RETENTION_CANONICAL_CLASSNAME(false, MethodAnnotationRuntimeRetention.class.getCanonicalName()),

TYPE_INHERITS(true, "TypeAnnotationInherits"),
TYPE_DOESNT_INHERIT(false, "TypeAnnotationDoesntInherit"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,25 @@ public static class AnnotatedTypes {
public int noRetention;
}

public static class AnnotatedMethods {
private int runtimeRetention;
private int classRetention;
private int bothRetentions;
private int noRetention;

@MethodAnnotationRuntimeRetention
public int getRuntimeRetention() { return runtimeRetention; }

@MethodAnnotationClassRetention
public int getClassRetention() { return classRetention; }

@MethodAnnotationRuntimeRetention
@MethodAnnotationClassRetention
public int getBothRetentions() { return bothRetentions; }

public int getNoRetention() { return noRetention; }
}

@TypeAnnotationInherits
@TypeAnnotationDoesntInherit
public static class SuperclassWithAnnotations {
Expand Down

0 comments on commit b6eb0b1

Please sign in to comment.