Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow inherited DelegatingConverter to be processed #104

Open
petitgros opened this issue Feb 12, 2024 · 1 comment
Open

Allow inherited DelegatingConverter to be processed #104

petitgros opened this issue Feb 12, 2024 · 1 comment

Comments

@petitgros
Copy link

petitgros commented Feb 12, 2024

Related to #101

Hi,

I am trying to modify the annotation processor to support custom Converter interface but I don't know how to process DelegatingConverter by inheritance.

New code in ConverterMapperProcessor:

delegatingConverterDescriptors =
        annotations.stream()
            .filter(ConverterMapperProcessor::isDelegatingConverterAnnotation)
            .map(roundEnv::getElementsAnnotatedWith)
            .flatMap(Set::stream)
            .map(ExecutableElement.class::cast)
            // Do not generate delegate without Mapper annotation on class
            .filter(annotatedMethod -> annotatedMethod.getEnclosingElement().getAnnotationMirrors().stream().anyMatch(x -> x.getAnnotationType().toString().equals(MAPPER)))
            .map(annotatedMethod -> new DelegatingConverterDescriptor(annotatedMethod, processingEnv))
            .collect(toList());

Custom converter:

public interface BaseMapper<S, T> extends Converter<S, T> {

    @Nullable
    T convert(@NonNull S source, @Context CycleAvoidingMappingContext context);

    @Nullable
    @Override
    @Named("baseConvert")
    default T convert(@NonNull S source) {
        return convert(source, new CycleAvoidingMappingContext());
    }

    // Annotation is not processed
    @DelegatingConverter
    @InheritInverseConfiguration
    default S invertConvert(T source) {
        return invertConvert(source, new CycleAvoidingMappingContext());
    }

    S invertConvert(T source, @Context CycleAvoidingMappingContext context);
}

Mapper:

@Mapper(config = MapperConfig.class)
public abstract class CarMapper implements BaseMapper<Car, CarDto> {

    // Required annotation to have delegate generated by processor
    @DelegatingConverter
    @Override
    public Car invertConvert(CarDto source) {
        return BaseMapper.super.invertConvert(source);
    }
}

Delegate:

@Component
public class  CarDtoToCarConverter implements Converter<CarDto, Car> {
  private  CarMapper delegateMapper;

  public CarDtoToCarConverter(@Autowired final CarMapper delegateMapper) {
    this.delegateMapper = delegateMapper;
  }

  @Override
  public Car convert(final CarDto source) {
    return delegateMapper.invertConvert(source);
  }
}

Wanted mapper:

@Mapper(config = MapperConfig.class)
public abstract class CarMapper implements BaseMapper<Car, CarDto> {
    // Nothing to override
}

Thanks

@Chessray
Copy link
Collaborator

Logically speaking, the second portion (generating the Delegating Converter) would need to happen inside the Processor for the @Mapper annotation. This goes a bit against how we're doing things at the moment. Not sure whether this is feasible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants