fee1good
fee1good

Reputation: 149

Map Enum field with MapStruct

I want to map 2 models, where each of them has almost the same enums. Let me show:

The first model has enum:

public enum EventSource {
  BETRADAR("SOURCE_BETRADAR"),
  BETGENIUS("SOURCE_BETGENIUS"),
  BETCONSTRUCT("SOURCE_BETCONSTRUCT"),
  MODEL("SOURCE_MODEL");

Second model has enum:

public enum SportEventSource implements ProtocolMessageEnum {
  SOURCE_UNKNOWN(0),
  SOURCE_BETRADAR(1),
  SOURCE_BETGENIUS(2),
  SOURCE_BETCONSTRUCT(3),
  UNRECOGNIZED(-1);

I have such custom mapping method:

@Named("eventSourceConverter")   
default EventSource eventSourceConverter(SportEventSource source) {
        switch (source) {
          case SOURCE_MODEL:
            return EventSource.MODEL;
          case SOURCE_BETCONSTRUCT:
            return EventSource.BETCONSTRUCT;
          case SOURCE_BETGENIUS:
            return EventSource.BETGENIUS;
          case SOURCE_BETRADAR:
            return EventSource.BETRADAR;
          default:
            return EventSource.MODEL;
        }   
}

And then I use:

  @Mapping(target = "mainSource", source = "source", qualifiedByName = "eventSourceConverter")
  AdapterCompetitor protoToModel(Competitor proto);

But get:

error: The following constants from the property "SportEventSource source" enum have no corresponding constant in the "*source*" enum and must be mapped via adding additional mappings: SOURCE_UNKNOWN, SOURCE_BETRADAR, SOURCE_BETGENIUS, SOURCE_BETCONSTRUCT, UNRECOGNIZED.
  AdapterCompetitor protoToModel(Competitor proto);

I've also created the enum mapper like:

  @ValueMappings({
      @ValueMapping(source = "SOURCE_BETRADAR", target = "BETRADAR"),
      @ValueMapping(source = "SOURCE_BETGENIUS", target = "BETGENIUS"),
      @ValueMapping(source = "SOURCE_BETCONSTRUCT", target = "BETCONSTRUCT"),
      @ValueMapping(source = "SOURCE_MODEL", target = "MODEL"),
      @ValueMapping(source = "SOURCE_UNKNOWN", target = "MODEL"),
      @ValueMapping(source = "UNRECOGNIZED", target = "MODEL")
  })
  EventSource eventSourceToSportEventSource(SportEventSource source);

But I don't need to have it separately, just want that enum field will be mapped within the internal mapping. Simply to say — when I do AdapterCompetitor protoToModel(Competitor proto) enum also should be mapped.

Thanks!

p.s. sorry for my eng, hope my questions make sense :)

Upvotes: 9

Views: 59288

Answers (3)

Sergey Yaushev
Sergey Yaushev

Reputation: 113

I think the most convenient way is just to make a default method in your mapper

default ProblemStatus problemStatusFromString(String status) {
    return ProblemStatus.get(status);
}

default String problemStatusToString(ProblemStatus problemStatus) {
    return problemStatus.getValue();
}

Upvotes: 3

Thomas Schmidt
Thomas Schmidt

Reputation: 1378

This can be achieved using @ValueMapping

Upvotes: 4

fee1good
fee1good

Reputation: 149

I used

@Mapper(componentModel = "spring")
public interface ConverterMapper {
  @Named("UnitValueConverter")
  default Long unitValueConverter(UInt64Value value) {
    return value.getValue();
  }

as an interface which contains all named mappers like above, and then I do

@Mapper(componentModel = "spring")
public interface EventMapper extends ConverterMapper

The issue was that I didn't add the @Mapper annotation to the ConverterMapper interface

Upvotes: -1

Related Questions