MapStruct: отфильтровать список перед отображением - PullRequest
0 голосов
/ 29 марта 2019

Я видел этот вопрос, заданный в другом месте, но не совсем в том же контексте и без ответа, который подходит для нашего варианта использования.

Предположим, у меня есть поле списка в исходном объекте:

List<MySourceElement> mySourceList;

и соответствующее поле назначения:

List<MyTargetElement> myTargetList;

Я просто хочу иметь возможность фильтровать элементы в исходном mySourceList по некоторому атрибуту MySourceElement, прежде чем будет выполнен стандартный преобразователь для mySourceList для сопоставления с myTargetList.

Предположим, что MySourceElement имеет логический атрибут isValid, а наш предикат фильтра просто (isValid == true) и что MyTargetElement не имеет соответствующего логического значения.

Я испробовал несколько подходов, включая @DecoratedWith и qualBy:

  1. @ DecoratedWith стал слишком сложным / сложным с внедрением Guice для такого простого случая использования, и эта функция также указана в документации MapStruct как экспериментальная с jsr330.

  2. qualBy не работал (т.е. я не смог заставить mapstruct применить метод qualBy в реализации).

Квалифицированный метод был что-то вроде:

@FilterForValid    
public List<MySourceElement> filterForValid(List<MySourceElement> mySourceElement) {
    ... implementation ...
}

И моя декларация картографа была такой:

@Mapping(source = "mySourceList", target = "myTargetList", qualifiedBy = FilterForValid.class)
Target sourceToTarget(Source source);

Я хотел реализацию для квалифицированных, например:

target.withMyTargetList( 
    mySourceListToMyTargetList(filterUtil.filterForValid(source.getMySourceList)));    

Вместо того, чтобы получить квалифицированную работу, я был бы рад выяснить, как использовать @BeforeMapping для этого, но мне не было ясно, как я это сделаю из документации, тем более что для всех намерений и целей исходный объект следует считать неизменным.

Буду признателен за любые рекомендации относительно самого простого и предпочтительного способа фильтрации коллекций в сочетании с вызовом картографа таким образом.

1 Ответ

1 голос
/ 29 марта 2019

Существует запрошенная функция mapstruct / mapstruct # 1610 , которая позволила бы использовать встроенную поддержку для чего-то подобного здесь.Сказав это, подход для решения этой проблемы будет использовать аннотацию @Context.Ваш картограф может выглядеть так:

@Mapper
public interface MyMapper {


    Target map(Source source, @Context Predicate<MySourceElement> predicate);

    default List<MySourceElement> mapAndFilter(List<MySourceElement> list, @Context Predicate<MySourceElement> predicate) {
        List<MySourceElement> newList = new ArrayList<>();
        for(MySourceElement el : list) {
            if (predicate.test(el)) {
                newList.add(map(el));
            }
        }

        return newList;
    }

    MySourceElement map(MySourceElement el);
}
...