Skip to content

Method with @Condition acts strange when applying to source  #3459

@foxii-cn

Description

@foxii-cn

Expected behavior

when @Condition annotated method's parameter type is same to mapping source

    DTO toDto(E entity);

    @Condition
    default boolean isEntityAvailable(E entity) {
        if (entity == null) {
            return false;
        }
        return Persistence.getPersistenceUtil().isLoaded(entity);
    }

hope to generate something like

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        if ( !isEntityAvailable( entity ) ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
        subCategoryDto.id( entity.getId() );
        subCategoryDto.name( entity.getName() );
        subCategoryDto.nick( entity.getNick() );
        return SubCategoryDto.build();
    }

or just ignore it

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
        subCategoryDto.id( entity.getId() );
        subCategoryDto.name( entity.getName() );
        subCategoryDto.nick( entity.getNick() );
        return SubCategoryDto.build();
    }

Actual behavior

but now I got this

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();

        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.id( entity.getId() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.name( entity.getName() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.nick( entity.getNick() );
        }

        return SubCategoryDto.build();
    }

Steps to reproduce the problem

using JPA with Mapstruct
I have a base interface:

public interface EntityMapper<DTO extends EntityDto, E extends BasicEntity> {
    E toEntity(DTO dto);

    DTO toDto(E entity);

    // try to avoid JPA lazy loading issue
    // and this one worked well
    @Condition
    default boolean isCollectionAvailable(Collection<E> collection) {
        if (collection == null) {
            return false;
        }
        return Persistence.getPersistenceUtil().isLoaded(collection);
    }

    // try to avoid JPA lazy loading issue
    // got problem with this
    @Condition
    default boolean isEntityAvailable(E entity) {
        if (entity == null) {
            return false;
        }
        return Persistence.getPersistenceUtil().isLoaded(entity);
    }

    @MapperConfig(mappingControl = DeepClone.class,
                  mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_ALL_FROM_CONFIG)
    interface Config {
    }
}

and entity mappers:

@Mapper(config = EntityMapper.Config.class, uses = {SubCategoryMapper.class})
public interface ParentCategoryMapper extends EntityMapper<ParentCategoryDto, ParentCategory> {
}

@Mapper(config = EntityMapper.Config.class, uses = {ParentCategoryMapper.class})
public interface SubCategoryMapper extends EntityMapper<SubCategoryDto, SubCategory> {
}

and then I got this:

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
        // Calling isEntityAvailable() so much times does not make any sense.
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.id( entity.getId() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.name( entity.getName() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.nick( entity.getNick() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.theOrder( entity.getTheOrder() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.icon( entity.getIcon() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.link( entity.getLink() );
        }
        // this is right
        if ( ParentCategoryMapper.isEntityAvailable( entity.getParentCategory() ) ) {
            subCategoryDto.parentCategory( ParentCategoryMapper.toDto( entity.getParentCategory() ) );
        }
        return SubCategoryDto.build();
    }

and what I want is:

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        if ( !isEntityAvailable( entity ) ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
        subCategoryDto.id( entity.getId() );
        subCategoryDto.name( entity.getName() );
        subCategoryDto.nick( entity.getNick() );
        subCategoryDto.theOrder( entity.getTheOrder() );
        subCategoryDto.icon( entity.getIcon() );
        subCategoryDto.link( entity.getLink() );
        if ( ParentCategoryMapper.isEntityAvailable( entity.getParentCategory() ) ) {
            subCategoryDto.parentCategory( ParentCategoryMapper.toDto( entity.getParentCategory() ) );
        }
        return SubCategoryDto.build();
    }

MapStruct Version

MapStruct 1.6.0.Beta1

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions