How to map multiple enums to string (and back) using their common property with MapStruct?

I have two enums with common property - id:

public enum AccessLevel {
    PUBLIC("public"),PRIVATE("private");
    private String id;
}

public enum Status {
    SUCCESS("success"),TIMEOUT("timeout");
    private String id;
}

And I need generic MapStruct mapping of such enums (without need to define mapping of every such enum).


Solution 1:

Yes, it's possible through @TargetType annotation. You need a common interface for such enums:

public interface IdEnum {
    String getId();
}

Then you need to be able to create enum of such interface instance by id:

static <T extends Enum<T> & IdEnum> T getById(Class<T> enumClass, String id) {
    for (T e : enumClass.getEnumConstants()) {
        if (e.getId().equals(id)) {
            return e;
        }
    }
    throw new IllegalArgumentException("No enum const " + enumClass.getName() + " for id '" + id + "'");
}

Then the generic Mapper may look like this (@TargetType annotation is the key to success):

public class IdEnumMapper {

    public <T extends Enum<T> & IdEnum> T mapToEnum(String value, @TargetType Class<T> idEnumClass) {
        return IdEnum.getById(idEnumClass, value);
    }

    public String mapToString(IdEnum idEnum) {
        return idEnum.getId();
    }
}

Just use it your mapper that maps a class that contains such enums:

@Mapper(uses = {IdEnumMapper.class})
public interface FilterMapper {
....