Jordi
Jordi

Reputation: 23277

Mapstruct: one source field to several multiple target fields

public class ExtensionTarget {

    private StringType valueString;
    private BooleanType valueBoolean;
    private CodeableConcept valueCodeableConcept;
    
}

public class ExtensionSource {

    private Type value;
    
}

where StringType, BooleanType and CodeableConcept inherit from Type.

Currently, I'm using this mapper in to make this mapping:

@Mapper(
    uses = { TypeMapper.class }
)
public interface ExtensionMapper {

    ExtensionTarget fhirToMpi(ExtensionSource fhirType);
}

public abstract class TypeMapper {
    
    private final StringTypeMapper stringTypeMapper = Mappers.getMapper(StringTypeMapper.class);
    private final BooleanTypeMapper booleanTypeMapper = Mappers.getMapper(BooleanTypeMapper.class);
    private final CodeableConceptMapper codeableConceptMapper = Mappers.getMapper(CodeableConceptMapper.class);

    public Type fhirToMpi(org.hl7.fhir.r4.model.Type fhirType) {
        if (fhirType instanceof CodeableConcept) {
            return this.codeableConceptMapper.fhirToMpi((CodeableConcept)fhirType);
        } else if (fhirType instanceof StringType) {
            return this.stringTypeMapper.fhirToMpi((StringType)fhirType);
        } else if (fhirType instanceof BooleanType) {
            return this.booleanTypeMapper.fhirToMpi((BooleanType)fhirType);
        }
        return null;
    }

}

Is there any other more elegant way to get it?

Upvotes: 0

Views: 1761

Answers (1)

Filip
Filip

Reputation: 21471

Currently there is no elegant way to achieve what you are looking for. However, soon, like really soon we are going to release MapStruct 1.5.Beta2 that will have your request implemented as part of this PR.

In a nutshell once 1.5.Beta2 is out you can do the following:

@Mapper(uses = {
        StringTypeMapper.class,
        BooleanTypeMapper.class,
        CodeableConceptMapper.class,
    })
public interface TypeMapper {
    

    @SubclassMapping(target = CodeableConcept.class, source = org.hl7.fhir.r4.model.CodeableConcept.class)
    @SubclassMapping(target = StringType.class, source = org.hl7.fhir.r4.model.StringType.class)
    @SubclassMapping(target = BooleanType.class, source = org.hl7.fhir.r4.model.BooleanType.class)
    Type fhirToMpi(org.hl7.fhir.r4.model.Type fhirType);
}

I assumed that your sub classes are in the same package as your source type. In addition to that there will also be SubclassExhaustiveStrategy that can control how a mapping between non defined types should happen.

i.e. if there is no valid constructor for the target type or it is abstract. The current possibilities are:

  • COMPILE_ERROR - Basically the exactly what happens now if you try to do this
  • RUNTIME_EXCEPTION - There will be a runtime IllegalArgumentException thrown

In your example you return null. This is a valid option as well. I would suggest you to create an issue in the MapStruct tracker to add this functionality if you need it.

Upvotes: 1

Related Questions