Add support for custom @Rule annotations

pull/26/head
richdouglasevans 9 years ago
parent b684602e5a
commit b64a807051

@ -93,7 +93,7 @@ class RuleDefinitionValidator {
} }
private boolean isRuleClassWellDefined(final Object rule) { private boolean isRuleClassWellDefined(final Object rule) {
return rule.getClass().isAnnotationPresent(Rule.class); return Utils.isAnnotationPresent(Rule.class, rule.getClass());
} }
private boolean isConditionMethodWellDefined(final Method method) { private boolean isConditionMethodWellDefined(final Method method) {

@ -146,7 +146,7 @@ class RuleProxy implements InvocationHandler {
} }
private Rule getRuleAnnotation() { private Rule getRuleAnnotation() {
return getTargetClass().getAnnotation(Rule.class); return Utils.findAnnotation(Rule.class, getTargetClass());
} }
private String getRuleName() { private String getRuleName() {

@ -1,5 +1,6 @@
package org.easyrules.util; package org.easyrules.util;
import java.lang.annotation.Annotation;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
@ -74,6 +75,32 @@ public final class Utils {
return interfaces; return interfaces;
} }
@SuppressWarnings("unchecked")
public static <A extends Annotation> A findAnnotation(
final Class<? extends Annotation> targetAnnotation, final Class annotatedType) {
checkNotNull(targetAnnotation, "targetAnnotation");
checkNotNull(annotatedType, "annotatedType");
Annotation foundAnnotation = annotatedType.getAnnotation(targetAnnotation);
if (foundAnnotation == null) {
for (Annotation annotation : annotatedType.getAnnotations()) {
Class<? extends Annotation> annotationType = annotation.annotationType();
if (annotationType.isAnnotationPresent(targetAnnotation)) {
foundAnnotation = annotationType.getAnnotation(targetAnnotation);
break;
}
}
}
return (A) foundAnnotation;
}
public static boolean isAnnotationPresent(
final Class<? extends Annotation> targetAnnotation, final Class annotatedType) {
return findAnnotation(targetAnnotation, annotatedType) != null;
}
public static void checkNotNull(final Object argument, final String argumentName) { public static void checkNotNull(final Object argument, final String argumentName) {
if (argument == null) { if (argument == null) {
throw new IllegalArgumentException(format("The %s must not be null", argumentName)); throw new IllegalArgumentException(format("The %s must not be null", argumentName));

@ -0,0 +1,14 @@
package org.easyrules.annotation;
@MetaRule
public class AnnotatedRuleWithMetaRuleAnnotation {
@Condition
public boolean when() {
return true;
}
@Action
public void then() throws Exception {
}
}

@ -0,0 +1,12 @@
package org.easyrules.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Rule
public @interface MetaRule {
}

@ -22,6 +22,11 @@ public class RuleDefinitionValidatorTest {
ruleDefinitionValidator.validateRuleDefinition(new Object()); ruleDefinitionValidator.validateRuleDefinition(new Object());
} }
@Test
public void withCustomAnnotationThatIsItselfAnnotatedWithTheRuleAnnotation() throws Throwable {
ruleDefinitionValidator.validateRuleDefinition(new AnnotatedRuleWithMetaRuleAnnotation());
}
/* /*
* Conditions methods tests * Conditions methods tests
*/ */

@ -0,0 +1,20 @@
package org.easyrules.core;
import org.easyrules.annotation.AnnotatedRuleWithMetaRuleAnnotation;
import org.easyrules.api.Rule;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
public class RuleProxyTest {
@Test
public void proxyingHappensEvenWhenRuleIsAnnotatedWithMetaRuleAnnotation() {
AnnotatedRuleWithMetaRuleAnnotation rule1 = new AnnotatedRuleWithMetaRuleAnnotation();
Rule rule = RuleProxy.asRule(rule1);
assertNotNull(rule.getDescription());
assertNotNull(rule.getName());
}
}

@ -0,0 +1,72 @@
package org.easyrules.util;
import org.junit.Test;
import java.lang.annotation.*;
import static org.junit.Assert.*;
public class UtilsTest {
@Test
public void findAnnotationWithClassWhereAnnotationIsPresent() {
Annotation foo = Utils.findAnnotation(Foo.class, AnnotationIsPresent.class);
assertCorrectAnnotationIsFound(Foo.class, foo);
}
@Test
public void findAnnotationWithClassWhereAnnotationIsPresentViaMetaAnnotation() {
Annotation foo = Utils.findAnnotation(Foo.class, AnnotationIsPresentViaMetaAnnotation.class);
assertCorrectAnnotationIsFound(Foo.class, foo);
}
@Test
public void findAnnotationWithClassWhereAnnotationIsNotPresent() {
Annotation foo = Utils.findAnnotation(Foo.class, Object.class);
assertNull(foo);
}
@Test
public void isAnnotationPresentWithClassWhereAnnotationIsPresent() {
assertTrue(Utils.isAnnotationPresent(Foo.class, AnnotationIsPresent.class));
}
@Test
public void isAnnotationPresentWithClassWhereAnnotationIsPresentViaMetaAnnotation() {
assertTrue(Utils.isAnnotationPresent(Foo.class, AnnotationIsPresentViaMetaAnnotation.class));
}
@Test
public void isAnnotationPresentWithClassWhereAnnotationIsNotPresent() {
assertFalse(Utils.isAnnotationPresent(Foo.class, Object.class));
}
private static void assertCorrectAnnotationIsFound(
Class expectedAnnotationType, Annotation actualAnnotation) {
assertNotNull(actualAnnotation);
assertEquals(expectedAnnotationType, actualAnnotation.annotationType());
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
private @interface Foo {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Foo
private @interface MetaFoo {
}
@Foo
private static final class AnnotationIsPresent {
}
@MetaFoo
private static final class AnnotationIsPresentViaMetaAnnotation {
}
}
Loading…
Cancel
Save