mercredi 23 janvier 2019

Modify every field of a Multilevel Java Class

I have Java Classes which contains instances another java classes, String, List. I need to modify every field till the last level until we encounter String. e.g. If object in my first class is an Object type, then I need to modify each of the corresponding object field for each level. If it is a list, then I need to iterate every element and modify (if an object is encountered, modify all fields of the object)

public class ApiBaseResponse implements Encryptable{    
    private ApiActualResponse response;
    private List<String> randomList;
    private String randomStr;
}

public class ApiActualResponse implements Encryptable{

    private String data;
    private RandomObject object; // To show class may contain instance of another class
}

I was trying to do it via recursive reflection. My approach:

I will get all the fields in the object provided in argument,

if field is of user defined type, then call this method recursively.

if field is of list type, iterate list and call this method recursively for each element in list

if field is of String type, modify according to logic

public <T> T encryptAllFields(T data) {

    try {
        if(data == null) {
            return data;
        }
        if(Encryptable.class.isAssignableFrom(data.getClass())){
            Field[] fields =  data.getClass().getDeclaredFields();
            for(Field field: fields){
                field.setAccessible(true);                    
                field.set(data, encryptAllFields(field.get(field.get(data))));
                field.setAccessible(false);
            }
        } else if(List.class.isAssignableFrom(data.getClass())){
            List listData = ((List)data);
            for(int i=0; i<listData.size(); i++){
                listData.set(i, encryptAllFields(listData.get(i)));
            }
        } else if(String.class.isAssignableFrom(data.getClass())){
            data = encryptAndEncode(String.valueOf(data));
        } else {
            throw new ValidationException("NON_ENCRYPTABLE_FIELD_FOUND");
        }

        return data;

    } catch (Exception ex) {
        log.error("Error during encryption of field: ", ex);
        throw new EncryptionException(ex);
    }


}

If initially the fields are

{
 "randomStr":"abc"
 "randomList":[{ "ABC", "abc"}]
 "response":{
           "data":"data",
           "object": {
                         "random":"abc"
                     }
       }
 }

After processing,

{
 "randomStr":"def"
 "randomList":[{ "DEF", "def"}]
 "response":{
           "data":"gbib",
           "object": {
                         "random":"def"
                     }
       }
 }

Any other approach is welcome.

I don't want to put method in every class I write that encrypts all the fields inside it and hence so on.





Aucun commentaire:

Enregistrer un commentaire