Skip to content
Advertisement

MapStruct. Mapping fields of list element by expression

Good afternoon! There is an object that contains field as type List, is it possible to set each (some) field of type T, by values generated in the annotation by the expression parameter?

For example:

Target object:

public class CustomList<T extends CustomEntity> extends CustomEntity {
    
    private List<T> field;
    
    public CustomList() {
        field = new ArrayList();
    }
}

Mapper interface:

@Mapper
public interface Mapper {
    @Mapping(target = "java(field.foreach(f -> f.getId))", expression = "java(UUID.randomUUID().toString())")
    CustomList<SomeObject> map (Object object);
}

How can such an idea be implemented? In the documentation, I found only examples with 1:1 mapping.

Edited:

Also, i try to use this:

public class IterableNonIntegrableUtil {

  @SetElements
  public CustomList<SomeObject> map(Object object) {
    CustomList<SomeObject> customList= new CustomList<>();
    customList.getField()
        .forEach(item -> item.setUid(UUID.randomUUID().toString()));
    return customList;
  }}




@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface SetElements{}



Mapper interface:
@Mapper(uses = IterableNonIntegrableUtil.class)
    public interface Mapper {
        @Mapping(target = "field", souce = "object", 
qualifiedBy=SetElements.class)
        CustomList<SomeObject> map (Object object);}

But in this case i have some error with Qualifier.

Advertisement

Answer

It is possible by mapping the object to the same type:

CustomList<SomeObject> map(CustomList<SomeObject> src);

// in case you only want to set the ones that are null.
@Mapping(target = "someField1", default = "someValue")
@Mapping(target = "someField2", defaultExpression = "java(someMethod())")
// in case you always want to set the value.
@Mapping(target = "someField3", constant = "someValue")
@Mapping(target = "someField4", expression = "java(someMethod())")
SomeObject map(SomeObject src);

I myself would look into setting the default values at the point where you construct the object.

For example:

class SomeObject {
    private String someField;

    /**
      * When called with a null or a blank value, the default value will be restored.
      */
    void setSomeField(String value) {
        // there is probably an utility out there which can make this a one-liner.
        if (value != null && !value.isBlank()){
            someField = value;
        } else {
            someField = "defaultValue";
        }
    }
}
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement