Сопоставьте коллекцию с параметром с mapstruct

Чтобы сопоставить определенный объект с mapstruct, мне нужна специальная пост-обработка, для которой необходим дополнительный параметр:

@Mapper
public abstract class AlertConfigActionMapper {

    @Mappings({ @Mapping(target = "label", ignore = true)})
    public abstract AlertConfigActionTO map (AlertConfigAction action, Locale userLanguage);

    @AfterMapping
    public void setLabel (AlertConfigAction  action, @MappingTarget AlertConfigActionTO to, Locale userLanguage) {
        for (AlertConfigActionLabel label : action.getAlertConfigActionLabels()) {
            if (label.getLanguage().equals(userLanguage)) {
                to.setLabel(label.getLabel());
                break;
            } else if (label.getLanguage().equals(Locale.ENGLISH)) {
                to.setLabel(label.getLabel());
            }
        }

    }
}

Это работает отлично. Проблема начинается, когда я добавляю следующий метод к этому картографу:

public abstract ArrayList<AlertConfigActionTO> mapList (List<AlertConfigAction> actions, Locale userLanguage);

Мне нужно передать этот параметр (userLanguage), но mapstruct, похоже, "сломается" в этом случае: я генерирую следующий код для этой части (что естественно дает ошибку компиляции):

@Override
public List<AlertConfigActionTO> mapList(List<AlertConfigAction> actions, Locale userLanguage) {
    if ( actions == null && userLanguage == null ) {
        return null;
    }

    List<AlertConfigActionTO> list = new List<AlertConfigActionTO>();

    return list;
}

Я уверен, что это связано с параметром, так как если я удалю его (из всех методов сопоставления), тогда метод mapList будет сгенерирован правильно.

Что нужно сделать для разрешения пользовательских параметров в этом случае?

Ответы

Ответ 1

То, что вы описали, пока невозможно. Не могли бы вы открыть запрос функции в нашем отслеживании проблем? Мы должны предоставлять средства обозначения параметров как своего рода "контекста", который передается по стеку вызовов.

В настоящее время вы можете взглянуть на использование ThreadLocal, которое вы установили перед вызовом процедуры сопоставления и которую вы получаете при настройке после сопоставления. Это не изящно - и вам нужно очистить локальную нить, чтобы избежать утечек памяти, но это должно сделать трюк.

Ответ 2

Я не думаю, что это возможно. По крайней мере, не так. Проблема в том, что вы готовите интерфейс/абстрактный класс, а отдых выполняется движком. И этот движок ожидает методов с одним параметром... Есть декораторы, но они идут одинаково. Я бы попытался ввести язык. Создайте bean, отметьте его как область сеанса и узнайте. С помощью Spring вы должны использовать ScopedProxyMode для этого... Не знаете, как это происходит с CDI.

Другой вариант более обходчив, тогда решение - может быть, AlertConfigAction может передать эту информацию?

Ответ 3

Я знаю, что этот вопрос довольно старый, но я столкнулся с этой проблемой, и начиная с версии 1.2 mapstruct, вы можете решить ее, используя @Context

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

public abstract ArrayList<AlertConfigActionTO> mapList (List<AlertConfigAction> actions, @Context Locale userLanguage);

Теперь вам просто необходимо добавить еще одно неабстрактное отображение:

public AlertConfigActionTO mapConcrete (AlertConfigAction action, @Context Locale userLanguage){
      return map (action, userLanguage);
}