how to map generics objects with Orika?

我们两清 提交于 2019-12-10 11:29:40

问题


I am using Orika 1.4.5, and i want to make my BidirectionalConverter to map PaginatedResponse<T> to PaginatedResponse<S> and viceversa.

The PaginatedResponse class is as follows:

public class PaginatedResponse<T> {

    private List<T> items;
    private List<Sorting> orderBy;
    private PagingResponse paging;

    public PaginatedResponse(List<T> items, List<Sorting> orderBy, PagingResponse paging) {
        this.items = items;
        this.orderBy = orderBy;
        this.paging = paging;
    }

    // Getters
}

So i want that my PaginatedResponseCovnerter takes all map calls where conversion is PaginatedResponse<Something> object1 to PaginatedResponse<OtherSomething> object2, and i want that object1 and object2 have same orderBy and paging attributes. So i try doings this:

public class PaginatedResponseConverter<T, S>
    extends BidirectionalConverter<PaginatedResponse<T>, PaginatedResponse<S>>
    implements MapperAware {

    private MapperFacade mapper;
    private T clazz1;
    private S clazz2;

    public PaginatedResponseConverter(T clazz1, S clazz2) {
        this.clazz1 = clazz1;
        this.clazz2 = clazz2;
    }

    @Override
    public void setMapper(Mapper mapper) {
        this.mapper = (MapperFacade) mapper;
    }


    @Override
    @SuppressWarnings("unchecked")
    public PaginatedResponse<S> convertTo(PaginatedResponse<T> source, Type<PaginatedResponse<S>> destinationType) {
        System.out.println("ConverTo");
        PagingResponse paging = source.getPaging();
        List<Sorting> sortings = source.getOrderBy();
        List<S> items = (List<S>) this.mapper.mapAsList(source.getItems(), this.clazz2.getClass());
        return new PaginatedResponse<S>(items, sortings, paging);
    }


    @Override
    @SuppressWarnings("unchecked")
    public PaginatedResponse<T> convertFrom(PaginatedResponse<S> source, Type<PaginatedResponse<T>> destinationType) {
        // The same upside down
    }
}

But the problem with this is that i have to register this custom converter with generics arguments , and these are not always the same. I want that if i try to convert from PaginatedResponse<SomeClass1> to PaginatedResponse<SomeClass2> be the same that PaginatedResponse<AnotherClass1> to PaginatedResponse<AnotherClass2>, and by the way, i cannot do this:

converterFactory.registerConverter(new PaginatedResponseConverter<Object, Object>(Object.class, Object.class));

because by this way all PaginatedResponse calls will get into PaginatedResponseConverter but i dont know the real type from the classes, so when it goes inside the converTo or convertFrom method, that need the exact class of the generic argument to do the mapAsList() method

Can you help me with this?


回答1:


There is this solution based on Orika's TypeBuilder that creates Type-s that store their type arguments.

My code will map a PaginatedResponse<Source> to a PaginatedResponse<Dest1> and then to a PaginatedResponse<Dest2>. If you don't mind some generic warnings, here it goes:

Driver class:

public static void main(String[] args) {
    MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
    ConverterFactory converterFactory = mapperFactory.getConverterFactory();
    converterFactory.registerConverter(new PaginatedToPaginatedConverter());

    PaginatedResponse<Source> sourcePaginatedResponse = createSourceObject();
    MapperFacade mapper = mapperFactory.getMapperFacade();

    PaginatedResponse dest1PaginatedResponse = mapper.map(sourcePaginatedResponse,
            new TypeBuilder<PaginatedResponse<Source>>(){}.build(),
            new TypeBuilder<PaginatedResponse<Dest1>>(){}.build());

    PaginatedResponse dest2PaginatedResponse = mapper.map(sourcePaginatedResponse,
            new TypeBuilder<PaginatedResponse<Source>>(){}.build(),
            new TypeBuilder<PaginatedResponse<Dest2>>(){}.build());
}

Converter, observe that I did not bother to generify PaginatedResponse, instead I overrode canConvert:

public class PaginatedToPaginatedConverter extends BidirectionalConverter<PaginatedResponse, PaginatedResponse> {

    public PaginatedResponse convertTo(PaginatedResponse paginatedResponse, Type<PaginatedResponse> destinationType) {
        PaginatedResponse dest = new PaginatedResponse();
        dest.setItems(mapperFacade.mapAsList(paginatedResponse.getItems(),
                ((Type) destinationType.getActualTypeArguments()[0]).getRawType()));
        dest.setOrderBy(mapperFacade.mapAsList(paginatedResponse.getOrderBy(), Sorting.class));
        dest.setPaging(mapperFacade.map(paginatedResponse.getPaging(), PagingResponse.class));
        return dest;
    }

    public PaginatedResponse convertFrom(PaginatedResponse paginatedResponse, Type<PaginatedResponse> destinationType) {
        return null;
    }

    @Override
    public boolean canConvert(Type<?> sourceType, Type<?> destinationType) {
        return sourceType.getRawType().equals(PaginatedResponse.class)
                && destinationType.getRawType().equals(PaginatedResponse.class);
    }
}


来源:https://stackoverflow.com/questions/29615401/how-to-map-generics-objects-with-orika

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!