CodyK
CodyK

Reputation: 3657

Pull all fields with annotation (including fields inside an object in another and fields in inner classes)

Hi I am creating a custom Excel parsing marshaller tool, you can reference this: How can I call getter/setter for property marked with custom annotation?

What I need now is to be able to find all annotations, specifically how can I find ones that nested objects or inner classes, and then call that setter/getter.

For example:

public class MyOuterClass {
    private InnerClass innerObject;

    public void setInnerObject (InnerClass innerObject) {
        this.innerObject = innerObject;
    }

    public InnerClass getInnerObject() {
        return innerObject;
    }
}

and;

public class InnerClass {

    // I need to get this field and call its setter from the class passed in, so something like:
    // MyOuterClass outClass; outClass.getInnerObject.setFieldIWant("field")
    // OR outClass.getInnerObject.getFieldIWant
    // But have to be able to do at run time, having no knowledge of the class inside
    // This must also work for a nested class

    @ExcelColumn
    private String fieldIWant;

    public void setFieldIWant(String fieldIWant) {
        this.fieldIWant = fieldIWant;
    }

    public String getFieldIWant() {
        return fieldIWant;
    }
}

Upvotes: 3

Views: 6795

Answers (2)

Ceiling Gecko
Ceiling Gecko

Reputation: 3186

The following classes implement the AnnotatedElement interface:

  • AccessibleObject
  • Class
  • Constructor
  • Field
  • Method
  • Package

On object instances of said classes you can then call the:

<object>.isAnnotationPresent(Class<? extends Annotation> annotationClass)

method in which you specify the annotation you wish to check for.

So in your case the method call for @ExcelColumn would look like:

<object>.isAnnotationPresent(ExcelColumn.class)

Then you can just use reflection to iterate over the fields/methods etc. of the object you wish to check and call .isAnnotationPresent method on each of them to check whether they have the said annotation or not.

So if you want to do some magic on fields (and nested fields) you could create a method like so:

public void doMagicToFields(Object someObject){
    // Get all declared fields.
    Field[] fields = someObject.getClass().getDeclaredFields();
    for(Field field: fields){
        // If the field is annotated by @ExcelColumn
        if(field.isAnnotationPresent(ExcelColumn.class){
            // If the field is a String (add more checks as needed)
            if(String.class.equals(field.getType()){
                // Set the fields value to "myValue" in case of String.
                field.set(someObject, "myValue");
            }
            // Recursive call to check the nested fields of this field object.
            doMagicToFields(
                // We actually get the field object here.
                field.get(someObject)
            );
        }

    }
}

Upvotes: 6

davegarred
davegarred

Reputation: 36

To find inner classes MyOuterClass.class.getClasses() will get you started, but will only give you one level of visibility. You'll need to iterate through those inner classes (e.g., SomeInnerClass.class.getClasses()) to check if they have an inner class themselves.

Once you have your list of classes it's as simple as SomeClass.class.getMethods() to get a list of all methods.

for(Class<?> clazz : OuterClass.class.getClasses()) {
        for(Method method : clazz.getMethods()) {
            if(method.getAnnotation(ExcelColumn.class) != null) {
                System.out.println(clazz.getName() + "." + method.getName());
            }
        }
    }

Upvotes: 1

Related Questions