vendredi 26 mai 2017

Find attribute of specific type in nested objects

I often have to deal with DTOs that contains other DTOs and I'd like to scan one object's attributes (and their own attributes, recursively) and retrieve every accessible object of class Bingo in the whole hierarchy.

For example, when I have the following :

public static class Bingo {
    // the one I want to get
}

public static class Foo {
    private Bar bar;
    private Bingo bingo;
    private List<Bingo> bingos;

    // getters & setters
}

public static class Bar {

    private Bingo bingo;

    // getters & setters
}

I'd like to get all instances of Bingo found in attributes of my Foo object, including the ones in the Bar object and the List.

Is there a library conveniently doing that ?

A more complete test case (using a bit of JUnit) :

public static class Bingo {
    private final int id;

    public Bingo(int in_id) {
        id = in_id;
    }

    @Override
    public String toString() {
        return "Bingo#"+String.valueOf(id);
    }

}

public static class BingoWrapper {

    private Bingo bingo;

    public Bingo getBingo() {
        return bingo;
    }

    public void setBingo(Bingo in_bingo) {
        bingo = in_bingo;
    }
}

public static class BingoFactory {

    private final List<Bingo> ALL_BINGOS = new ArrayList<>();
    private int sequence = 0;

    public Bingo createBingo(){
        Bingo l_bingo = new Bingo(sequence++);
        ALL_BINGOS.add(l_bingo);
        return l_bingo;
    }

    public BingoWrapper createBingoWrapper(){
        BingoWrapper l_bar = new BingoWrapper();
        l_bar.setBingo(createBingo());
        return l_bar;
    }

    public List<Bingo> getAllBingos(){
        return ALL_BINGOS.stream().collect(Collectors.toList());
    }

}

public static class Foo {

    private Bingo bingo;
    private BingoWrapper wrapper;
    private Bingo[] array;
    private Collection<Object> collection;
    private Map<Object,Object> map;

    public Bingo getBingo() {
        return bingo;
    }
    public void setBingo(Bingo in_bingo) {
        bingo = in_bingo;
    }
    public BingoWrapper getWrapper() {
        return wrapper;
    }
    public void setWrapper(BingoWrapper in_bar) {
        wrapper = in_bar;
    }
    public Bingo[] getArray() {
        return array;
    }
    public void setArray(Bingo[] in_array) {
        array = in_array;
    }
    public Collection<Object> getCollection() {
        return collection;
    }
    public void setCollection(Collection<Object> in_collection) {
        collection = in_collection;
    }
    public Map<Object, Object> getMap() {
        return map;
    }
    public void setMap(Map<Object, Object> in_map) {
        map = in_map;
    }
}

@Test
public void test(){
    BingoFactory l_bingoFactory = new BingoFactory();

    Foo l_foo = new Foo();
    l_foo.setBingo(l_bingoFactory.createBingo());                  // one in a field
    l_foo.setWrapper(l_bingoFactory.createBingoWrapper());         // one in a field of a field

    l_foo.setArray(new Bingo[]{l_bingoFactory.createBingo()});     // one in an array in a field

    l_foo.setCollection(Arrays.asList(
            l_bingoFactory.createBingo(),                          // one in Collection in a field
            l_bingoFactory.createBingoWrapper()));                 // one in a field of an item in a Collection in a field

    Map<Object,Object> l_map = new HashMap<>();
    l_foo.setMap(l_map);
    l_map.put("key", l_bingoFactory.createBingo());                // one as a key in a Map in a field
    l_map.put(l_bingoFactory.createBingo(), "value");              // one as a value in a Map in a field
    l_map.put("keyAgain", l_bingoFactory.createBingoWrapper());    // one wrapped in a value in a Map in a Field 
    l_map.put(l_bingoFactory.createBingoWrapper(), "valueAgain");  // one wrapped in a key in a Map in a field 

    List<Bingo> l_found = BeanUtils.scanObjectForType(l_foo, Bingo.class);   // Magic happens here

    System.out.println(l_found);                                   // for debug
    Assert.assertTrue(l_found.containsAll(l_bingoFactory.getAllBingos())); // I want them ALL
}





Aucun commentaire:

Enregistrer un commentaire