mercredi 9 septembre 2015

Reflection nested method invocations

I'm trying to transform an object to a flat representation. I'm not talking CSV or toString method.

The properties I'm interested in are annotated with a @Field annotation. The value of the annotation will be used to match to a transformation map(not shown here) that will determine how a property will be transformed.

I was able to come up with a piece of code that uses reflection. It creates a fieldName->Method map. For example, given the Client class below, the Map will have 'name' pointing to a Method object that corresponds to the getName() - see below. Then I can invoke the appropriate method on any instance of the Client class for any property.

How do I deal with nested properties. For example, given the Currency class below, how do I get a Method object that will call Client.accounts[1].currency.code?

public class Client{

    @Field( value = "name")
    public String getName(){...}

    @Field( value = "accounts" )
    public List<Account> getAccounts(){...}
}

public class Account{

    @Field( value = "acctNum")
    public Long getAcctNum(){...}

    @Field( value = "currency" )
    public Currency getCurrency(){...}
}

public class Currency{
    @Field( value = "code" )
    public String getCode(){...}
}

First I'm creating a map of fieldName to Method. Something that I plan to do only once, and then reuse for object instances.

Map<String, Method> fieldMap = new HashMap();
for( Method method : Client.class.getDeclaredMethods() ){
    Annotation annotation = method.getAnnotation(com.acme.Field.class);
    if( annotation == null) {
        continue;
    }

    com.acme.Field fieldMapping = (com.acme.mapping.Field) annotation;
    String fieldName = fieldMapping.value();
    fieldMap.put(fieldName, method);
}

Here's how I plan to reuse it

Client client = new Client();
for( Map.Entry<String, Method> entry : fieldMap.entrySet() ){
    System.out.println(entry.getKey()+" -> "+entry.getValue().invoke(client, null));
}





Aucun commentaire:

Enregistrer un commentaire