Try extracting the mapping logic into a separate @Component and use @Named, for example, to call the desired method.
@Mapper(componentModel = "spring", uses = ProductMapper.class)
public interface MainMapper {
@Mapping(source = ".", target = "product", qualifiedByName = "mapProduct")
Target map(SourceDto dto);
}
@Component
public class ProductSelector {
private final ProductMapper productMapper;
private final String desiredId = "curr"; // or inject it from config
public ProductSelector(ProductMapper productMapper) {
this.productMapper = productMapper;
}
@Named("mapProduct")
public Product mapProduct(SourceDto dto) {
return dto.getProducts().stream()
.filter(p -> desiredId.equals(p.getId()))
.findFirst()
.map(productMapper::toProduct)
.orElse(null); // or throw an exception
}
}
Alternatively, you can inject ProductMapper via constructor if you rewrite MainMapper as an abstract class:
@Mapper(componentModel = "spring")
public abstract class MainMapper {
@Autowired
protected ProductMapper productMapper;
@Mapping(source = ".", target = "product")
public Target map(SourceDto dto) {
ProductDto productDto = dto.getProducts().stream()
.filter(p -> p.getId().equals("curr"))
.findFirst()
.orElseThrow();
Product product = productMapper.toProduct(productDto);
Target target = new Target();
target.setProduct(product);
return target;
}
}