Package com.tngtech.archunit.core.domain
Class JavaAnnotation<OWNER extends HasDescription>
java.lang.Object
com.tngtech.archunit.core.domain.JavaAnnotation<OWNER>
- Type Parameters:
OWNER
- The type of the closest "parent" of this annotation. If this annotation is annotated on a class or member, it is that class or member. If this annotation is a member of another annotation, it is that annotation.
- All Implemented Interfaces:
HasDescription
,HasOwner<OWNER>
,HasType
public final class JavaAnnotation<OWNER extends HasDescription> extends java.lang.Object implements HasType, HasOwner<OWNER>, HasDescription
Represents an imported annotation on an annotated object like a class or a method. To be
independent of the classpath, all properties of this annotation are just stored as a simple
key value pairs. I.e. if you consider
NOTE
----------
ArchUnit holds the annotation in a classpath independent representation, i.e. some types will be mapped, when the access is proxied. Consider
@MyAnnotation(name = "some name", anAttribute = 7)
class MyClass {}
this annotation will be imported storing the association
name → "some name"
anAttribute → 7
Properties will be made available via get(String)
, e.g.
myAnnotation.get("anAttribute")
will return the value 7. Since this behavior is inconvenient (loss of type safety),
there is another approach to retrieve these values, if the annotation can
be resolved on the classpath. It's then possible to access a simple proxy
MyAnnotation moreConvenient = myAnnotation.as(MyAnnotation.class);
moreConvenient.anAttribute(); // → returns 7
----------NOTE
----------
ArchUnit holds the annotation in a classpath independent representation, i.e. some types will be mapped, when the access is proxied. Consider
@SomeAnnotation(type = String.class)
class MyClass {}
Accesses to 'type' will be different for the proxied version:
someAnnotation.get("type"); // → returns JavaClass{String}
someAnnotation.as(SomeAnnotation.class).type(); // → returns String.class
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
JavaAnnotation.DefaultParameterVisitor
Default implementation ofJavaAnnotation.ParameterVisitor
implementing a no-op behavior, i.e.static interface
JavaAnnotation.ParameterVisitor
A Visitor (compareaccept(ParameterVisitor)
) offering possibilities to specify behavior when various types ofgetProperties()
are encountered.
The list of declared methods is exhaustive, thus any legal parameter type of anAnnotation
is represented by the respectivevisit
-method.Nested classes/interfaces inherited from interface com.tngtech.archunit.core.domain.properties.HasOwner
HasOwner.Functions, HasOwner.Predicates
Nested classes/interfaces inherited from interface com.tngtech.archunit.core.domain.properties.HasType
HasType.Functions, HasType.Predicates
-
Method Summary
Modifier and Type Method Description void
accept(JavaAnnotation.ParameterVisitor parameterVisitor)
Simple implementation of the Visitor pattern (compare e.g.<A extends java.lang.annotation.Annotation>
Aas(java.lang.Class<A> annotationType)
Returns a compile safe proxied version of the respectiveJavaAnnotation
.Optional<java.lang.Object>
get(java.lang.String propertyName)
Returns the value of the property with the given name, i.e.CanBeAnnotated
getAnnotatedElement()
Returns either the element annotated with thisJavaAnnotation
(a class or member) or in case this annotation is an annotation parameter, the element annotated with an annotation that transitively declares this annotation as an annotation parameter.java.lang.String
getDescription()
java.lang.Object
getExplicitlyDeclaredProperty(java.lang.String propertyName)
OWNER
getOwner()
Compare documentation ofOWNER
onJavaAnnotation
java.util.Map<java.lang.String,java.lang.Object>
getProperties()
JavaClass
getRawType()
JavaType
getType()
boolean
hasExplicitlyDeclaredProperty(java.lang.String propertyName)
Returnstrue
, if and only if the value of this property has been explicitly declared within the annotation declaration.java.lang.String
toString()
Optional<java.lang.Object>
tryGetExplicitlyDeclaredProperty(java.lang.String propertyName)
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
-
Method Details
-
getType
-
getRawType
- Specified by:
getRawType
in interfaceHasType
-
getOwner
Compare documentation ofOWNER
onJavaAnnotation
- Specified by:
getOwner
in interfaceHasOwner<OWNER extends HasDescription>
- Returns:
- The "owner" of this object, compare
HasOwner
-
getAnnotatedElement
Returns either the element annotated with thisJavaAnnotation
(a class or member) or in case this annotation is an annotation parameter, the element annotated with an annotation that transitively declares this annotation as an annotation parameter.
Example:
For case(1)@SomeAnnotation class SomeClass {} (2) class SomeClass { @SomeAnnotation SomeField someField; } (3)@ComplexAnnotation(param = @SomeAnnotation) class SomeClass {}
(1)
the result ofsomeAnnotation.getAnnotatedElement()
would beSomeClass
, for case(2)
the result ofsomeAnnotation.getAnnotatedElement()
would besomeField
and for(3)
the result ofsomeAnnotation.getAnnotatedElement()
would also beSomeClass
, even though@SomeAnnotation
is a parameter of@ComplexAnnotation
.- Returns:
- The closest element traversing up the tree, that can be annotated
-
get
Returns the value of the property with the given name, i.e. the result of the method with the property name of the representedAnnotation
. E.g. for
the results will be@SomeAnnotation(value = "someString", types = {SomeType.class, AnotherType.class}) class SomeAnnotatedClass {}
This method will return ansomeAnnotation.get("value") → "someString" someAnnotation.get("types") → [JavaClass{SomeType}, JavaClass{AnotherType}]
explicitly declared property
, or the default value for the given property as a fallback.- Parameters:
propertyName
- The name of the annotation property, i.e. the declared method name- Returns:
- the value of the given property, where the result type is more precisely
- Class<?> → JavaClass{clazz}
- Class<?>[] → [JavaClass{clazz},...]
- Enum → JavaEnumConstant
- Enum[] → [JavaEnumConstant,...]
- Annotation → JavaAnnotation
- Annotation[] → [JavaAnnotation,...]
- anyOtherType → anyOtherType
-
hasExplicitlyDeclaredProperty
@PublicAPI(usage=ACCESS) public boolean hasExplicitlyDeclaredProperty(java.lang.String propertyName)Returnstrue
, if and only if the value of this property has been explicitly declared within the annotation declaration. E.g.
The opposite is a non-explicitly declared property, e.g.@SomeAnnotation(prop = "explicitly declared") class SomeClass {}
Where the property@interface SomeAnnotationWithDefault { String prop() default "default"; } @SomeAnnotationWithDefault class SomeClass {}
prop
has the implicit default value"default"
, but no explicitly declared value.- Parameters:
propertyName
- The name of the annotation property, i.e. the declared method name- Returns:
true
, if and only if the value of this property has been explicitly declared
-
getExplicitlyDeclaredProperty
@PublicAPI(usage=ACCESS) public java.lang.Object getExplicitlyDeclaredProperty(java.lang.String propertyName)- Parameters:
propertyName
- The name of the annotation property, i.e. the declared method name- Returns:
- the same value as
get(String)
, if the property is explicitly declared (comparehasExplicitlyDeclaredProperty(String)
);
throws an exception if the property has not been explicitly declared (i.e. falls back to a default value)
-
tryGetExplicitlyDeclaredProperty
@PublicAPI(usage=ACCESS) public Optional<java.lang.Object> tryGetExplicitlyDeclaredProperty(java.lang.String propertyName)- Parameters:
propertyName
- The name of the annotation property, i.e. the declared method name- Returns:
- the same value as
get(String)
, if the property is explicitly declared (comparehasExplicitlyDeclaredProperty(String)
), otherwiseOptional.absent()
-
getProperties
- Returns:
- a map containing all [property → value], where each value correlates to
get(String property)
-
accept
Simple implementation of the Visitor pattern (compare e.g. https://en.wikipedia.org/wiki/Visitor_pattern).
While it is fairly convenient to analyse aJavaAnnotation
that is on the classpath (e.g. by usingas(Class)
), it is quite tedious to do so for aJavaAnnotation
not on the classpath (i.e. viagetProperties()
).
accept(ParameterVisitor)
offers an alternative by taking away traversal and casting logic when analysing potentially unknownJavaAnnotations
of different parameter structures.
Whether using this method or performing casting operations ongetProperties()
might depend on the use case. For a known annotation where only a single known parameter is relevant, a solution like
might be completely sufficient. However an analysis like "all class parameters of all annotations in packageString value = (String) knownJavaAnnotation.get("value").get()
foo.bar
should implement a certain interface" (or potentially nested annotations), this might not be an easily readable approach.accept(ParameterVisitor)
makes this use case fairly trivial:
FurthermoreunknownJavaAnnotation.accept(new DefaultParameterVisitor() { @Override public void visitClass(String propertyName, JavaClass javaClass) { // do whatever check on the class parameter javaClass } });
JavaAnnotation.ParameterVisitor
does exactly specify which cases can occur forJavaAnnotation
parameters without the need to introspect and cast the values. In case traversal into nestedJavaAnnotations
is necessary, this also becomes quite simple:
unknownJavaAnnotation.accept(new DefaultParameterVisitor() { // parameter handling logic @Override public void visitAnnotation(String propertyName, JavaAnnotation<?> nestedAnnotation) { nestedAnnotation.accept(this); } });
- Parameters:
parameterVisitor
- A visitor which allows to implement behavior for different types of annotation parameters
-
as
@PublicAPI(usage=ACCESS) public <A extends java.lang.annotation.Annotation> A as(java.lang.Class<A> annotationType)Returns a compile safe proxied version of the respectiveJavaAnnotation
. In other words, the result ofas(MyAnnotation.class)
will be of typeMyAnnotation
and allow property access in a compile safe manner. For this to work the respective
including all referred parameter types must be on the classpath or anAnnotation
Exception
will be thrown. Furthermore the respectiveJavaAnnotation
must actually be an import of the passed parameterannotationType
or aRuntimeException
will likely occur.- Type Parameters:
A
- The type of the importedAnnotation
backing thisJavaAnnotation
- Parameters:
annotationType
- Any type implementingAnnotation
- Returns:
- A compile safe proxy of type
JavaAnnotation
-
getDescription
public java.lang.String getDescription()- Specified by:
getDescription
in interfaceHasDescription
-
toString
public java.lang.String toString()- Overrides:
toString
in classjava.lang.Object
-