Java Articles

Advertisement

Java Getting Annotation Attributes Example

by Ram Satish

Share

In this article, we will see how to extract annotation attributes. An annotation attribute is like a non-void method that has no parameters. An attribute can itself be another annotation.

Let’s first define an annotation.

Define Annotations

Below is a simple annotation that represents a programming language. You can specify the default values using default. The attributes are declared just the way we define methods in an interface. Attribute scriptingLang() is a nested annotation that again returns an annotation.

Lang:

Advertisement
package com.javarticles.annotations;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface Lang {
String[] value() default {};
String[] name() default {};
String ver() default "";
boolean backwardCompatible() default true;
Class<?>[] classes() default {};
ScriptingLang[] scriptingLang() default {@ScriptingLang("Groovy")};
}

Here is the definition of scripting language annotation.

ScriptingLang:

package com.javarticles.annotations;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface ScriptingLang {
String[] value() default {"Groovy"};
String ver() default "";
}

classes attribute returns an array of Class type. We will use the below classes when we get to the usage of annotation.
A:

package com.javarticles.annotations;

public class A {
}

B:

package com.javarticles.annotations;

public class B {
}

Getting Annotation Attributes

In the below main class, we use annotation @Lang and define the attributes. Attribute scriptingLang returns an array of nested annotations.
Few things to note about:

  1. Before we start reading the attributes, we need to first get the annotation Annotation annotation = AnnotationAttributesExample.class.getDeclaredAnnotation(Lang.class)
  2. Attributes are like methods so to get the attributes use: Method[] methods = annotation.annotationType().getDeclaredMethods();
  3. Annotation attributes are methods without any parameter and they always return something. if (method.getParameterTypes().length == 0 && method.getReturnType() != void.class) { //get the attribute value }
  4. Next we need to get the attribute value. Object value = method.invoke(annotation);
  5. Finally, we convert the attribute value to a simpler type. For example, if the attribute type is Class, we return class name. If it is a nested annotation, we further parse the annotation to get the attributes as Map

AnnotationAttributesExample:

package com.javarticles.annotations;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.LinkedHashMap;

@Lang(name = "Java", ver = "1.8", scriptingLang =
{@ScriptingLang(value="Jython", ver="2.5.2"), @ScriptingLang(value="Groovy", ver="2.4")},
backwardCompatible = false, classes = {A.class, B.class })
public class AnnotationAttributesExample {
public static void main(String[] args) {
Annotation annotation = AnnotationAttributesExample.class
.getDeclaredAnnotation(Lang.class);
LinkedHashMap<String, Object> attributes = getAnnotationAttributesAsMap(
annotation, true, true);
printAttributes(attributes);
}

static void printAttributes(LinkedHashMap<String, Object> attributes) {
for (String key : attributes.keySet()) {
Object value = attributes.get(key);
if (String[].class.isInstance(value)) {
value = Arrays.asList((String[]) value);
}
if (LinkedHashMap[].class.isInstance(value)) {
LinkedHashMap<String, Object>[] nestedAttrbutes = (LinkedHashMap<String, Object>[]) value;
for (LinkedHashMap<String, Object> nestedAttributeMap : nestedAttrbutes) {
printAttributes(nestedAttributeMap);
}
} else {
System.out.println(key + "->" + value);
}
}
}

public static LinkedHashMap<String, Object> getAnnotationAttributesAsMap(
Annotation annotation, boolean classValuesAsString,
boolean nestedAnnotationsAsMap) {

LinkedHashMap<String, Object> attrs = new LinkedHashMap<String, Object>();
Method[] methods = annotation.annotationType().getDeclaredMethods();
for (Method method : methods) {
if (method.getParameterTypes().length == 0
&& method.getReturnType() != void.class) {
try {
Object value = method.invoke(annotation);
attrs.put(
method.getName(),
extractAttributeValue(value, classValuesAsString,
nestedAnnotationsAsMap));
} catch (Exception ex) {
throw new IllegalStateException(
"Could not obtain annotation attribute values", ex);
}
}
}
return attrs;
}

static Object extractAttributeValue(Object value, boolean classValuesAsString,
boolean nestedAnnotationsAsMap) {
if (classValuesAsString) {
if (value instanceof Class) {
value = ((Class<?>) value).getName();
} else if (value instanceof Class[]) {
Class<?>[] clazzArray = (Class[]) value;
String[] newValue = new String[clazzArray.length];
for (int i = 0; i < clazzArray.length; i++) {
newValue[i]= clazzArray[i].getName();
}
value = newValue;
}
}
if (nestedAnnotationsAsMap && value instanceof Annotation) {
return getAnnotationAttributesAsMap((Annotation) value,
classValuesAsString, true);
} else if (nestedAnnotationsAsMap && value instanceof Annotation[]) {
Annotation[] nestedAnnotations = (Annotation[]) value;
LinkedHashMap<String, Object>[] mappedAnnotations = new LinkedHashMap[nestedAnnotations.length];
for (int i = 0; i < nestedAnnotations.length; i++) {
mappedAnnotations[i]= getAnnotationAttributesAsMap(
nestedAnnotations[i], classValuesAsString, true);
}
return mappedAnnotations;
} else {
return value;
}
}
}

We print the extracted attributes.

Output:

name->[Java]
value->[]
classes->[com.javarticles.annotations.A, com.javarticles.annotations.B]
backwardCompatible->false
ver->1.8
value->[Jython]
ver->2.5.2
value->[Groovy]
ver->2.4

Download the source code

This was an example about getting annotation attributes.

You can download the source code here: javaGetAnnotationAttributesExample.zip

Share

Advertisement

Related

Advertisement

Latest

Advertisement