@Target(value=PARAMETER) @Retention(value=CLASS) public @interface Context
@
ObjectFactory
methods or @
BeforeMapping
/@
AfterMapping
methods when applicable and can thus be used in custom code.
The type of an @Context
parameter is also inspected for
@
BeforeMapping
/@
AfterMapping
methods, which are called on the provided context
parameter value if applicable.
Note: no null
checks are performed before calling before/after mapping methods or object
factory methods on @
Context
annotated parameters. The caller needs to make sure that no null
are passed in that case.
For generated code to call a method that is declared with @Context
parameters, the declaration of the mapping
method being generated needs to contain at least those (or assignable) @Context
parameters as well. MapStruct
will not create new instances of missing @Context
parameters nor will it pass null
instead.
Example 1: Using @Context
parameters for passing data down to hand-written property mapping
methods and @
BeforeMapping
methods:
// multiple @Context parameters can be added
public abstract CarDto toCar(Car car, @Context VehicleRegistration context, @Context Locale localeToUse);
protected OwnerManualDto translateOwnerManual(OwnerManual ownerManual, @Context Locale locale) {
// manually implemented logic to translate the OwnerManual with the given Locale
}
@BeforeMapping
protected void registerVehicle(Vehicle mappedVehicle, @Context VehicleRegistration context) {
context.register( mappedVehicle );
}
@BeforeMapping
protected void notCalled(Vehicle mappedVehicle, @Context DifferentMappingContextType context) {
// not called, because no context parameter of type DifferentMappingContextType is available
// within toCar(Car, VehicleRegistration, Locale)
}
// generates:
public CarDto toCar(Car car, VehicleRegistration context, Locale localeToUse) {
registerVehicle( car, context );
if ( car == null ) {
return null;
}
CarDto carDto = new CarDto();
carDto.setOwnerManual( translateOwnerManual( car.getOwnerManual(), localeToUse );
// more generated mapping code
return carDto;
}
Example 2: Using an @Context
parameter with a type that provides its own @
BeforeMapping
methods to handle cycles in Graph structures:
// type of the context parameter
public class CyclicGraphContext {
private Map<Object, Object> knownInstances = new IdentityHashMap<>();
@BeforeMapping
public <T extends NodeDto> T getMappedInstance(Object source, @TargetType Class<T> targetType) {
return (T) knownInstances.get( source );
}
@BeforeMapping
public void storeMappedInstance(Object source, @MappingTarget NodeDto target) {
knownInstances.put( source, target );
}
}
@Mapper
public interface GraphMapper {
NodeDto toNodeDto(Node node, @Context CyclicGraphContext cycleContext);
}
// generates:
public NodeDto toNodeDto(Node node, CyclicGraphContext cycleContext) {
NodeDto target = cycleContext.getMappedInstance( node, NodeDto.class );
if ( target != null ) {
return target;
}
if ( node == null ) {
return null;
}
NodeDto nodeDto = new NodeDto();
cycleContext.storeMappedInstance( node, nodeDto );
nodeDto.setParent( toNodeDto( node.getParent(), cycleContext ) );
List<NodeDto> list = nodeListToNodeDtoList( node.getChildren(), cycleContext );
if ( list != null ) {
nodeDto.setChildren( list );
}
// more mapping code
return nodeDto;
}
Example 3: Using @Context
parameters for creating an entity object by calling an
@
ObjectFactory
methods:
// type of the context parameter
public class ContextObjectFactory {
@PersistenceContext(unitName = "my-unit")
private EntityManager em;
@ObjectFactory
public Valve create( String id ) {
Query query = em.createNamedQuery("Valve.findById");
query.setParameter("id", id);
Valve result = query.getSingleResult();
if ( result != null ) {
result = new Valve( id );
}
return result;
}
}
@Mapper
public interface ContextWithObjectFactoryMapper {
Valve map(ValveDto dto, @Context ContextObjectFactory factory, String id);
}
// generates:
public class ContextWithObjectFactoryMapperImpl implements ContextWithObjectFactoryMapper {
@Override
public Valve map(ValveDto dto, ContextObjectFactory factory, String id) {
if ( dto == null ) {
return null;
}
Valve valve = factory.create( id );
valve.setOneWay( dto.isOneWay() );
return valve;
}
}
Copyright © 2012-2021 MapStruct Authors; All rights reserved. Released under the Apache Software License 2.0.