Дополнительное преобразование/отображение Orika во время выполнения

Я использую картограф Orika, чтобы избежать шаблонных конвертеров, и у меня есть интересная проблема. Чтобы упростить разработку, мне нужно создать аннотацию, которая будет определять, когда отображать значение, а когда оставить его как есть (не нуль или значение по умолчанию, а как есть).

Представьте, что у нас есть 2 класса:

class Dto {
    public int id;
    public String name;
}

class Entity {
    public int id;
    public String name;
}

Dto исходит от Front-end, и мы хотим сопоставить имя поля с сущностью, только если оно начинается с чего-то вроде:

if {dto.name.startsWith("A")}
    entity.name = dto.name;

И нам нужна подобная логика во многих классах - меняется только начальная строка.

Поэтому я хочу создать аннотацию @IfStartsWith(String startsWith) и сделать следующее:

class Entity{
    public int id;
    @IfStartsWith("A")
    public String name;
}

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

Здесь важно то, что я не могу использовать значение по умолчанию (нулевую или пустую строку), потому что мне нужно оставить целевое значение как есть, если проверка не пройдена. «Как есть» означает либо значение, которое находится в существующем целевом объекте, либо значение класса по умолчанию (установленное как public String name = "My name";).

Я знаю, как получить аннотации из полей, и теперь это работает, но есть вопросы:

Что следует использовать: преобразователь на уровне поля или настройку на уровне класса?

Есть ли какой-либо способ избежать отражения в настройке значения поля внутри этих настраиваемых преобразователей/сопоставителей?


person Viktor Molokanov    schedule 31.03.2019    source источник


Ответы (1)


Итак, мне удалось решить эту проблему (не сказать, что это красиво).

По сути, я обнаружил, что Орика не может «оставить» поле как есть. Если вы действительно выполняете сопоставление из поля в поле, значение будет установлено каким бы оно ни было.

Я читаю все поля, используя отражение, и выполняю следующую логику:

if field has no @IfStartsWith annotation 
then it's mapped as usual:
   classMapBuilder.fieldAToB(*).fieldBToA(*)
if field has custom annotation 
then I create a CustomMapper object that handles the logic.

Обратите внимание, что это настраиваемый преобразователь уровня класса.

Здесь важно то, что вы НЕ выполняете стандартное сопоставление (fieldAToB, default и другие). До кастомного маппера Орика даже не знала, что есть такое поле и его надо мапить. Пользовательский сопоставитель использует отражение (потому что я заранее не знаю, какое поле будет отображаться таким образом).

Надеюсь, это поможет кому-то.

person Viktor Molokanov    schedule 08.10.2019