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

Non-constructor val properties #29

Open
shrralis opened this issue Oct 15, 2023 · 1 comment
Open

Non-constructor val properties #29

shrralis opened this issue Oct 15, 2023 · 1 comment

Comments

@shrralis
Copy link

I have a situation when my DTO has a val field declared in its constructor and my Entity has the same val field but it is not defined in its constructor.
The problem is, that field is being omitted and not handled in any way.

data class DTO(
    val a: String,
    val b: String,
    val field: MutableSet<String>,
)

class Entity(
    val a: String,
    val b: String,
) {
    val field: MutableSet<String> = mutableSetOf()
}

@Konverter
@KComponent
interface EntityConverter {

    @Konvert(
        mappings = [
            Mapping(target = "field", expression = "doSomething()"),
        ],
    )
    fun convertToEntity(dto: DTO): Entity
}

The problem is that the result implementation of the converter doesn't handle that field at all, it fills only constructor properties:

@Component
public object EntityConverterImpl : EntityConverter {
    @GeneratedKonverter(priority = 5_000)
    override fun convertToEntity(dto: DTO): Entity = Entity(
        a = dto.a,
        b = dto.b,
    )
}

I believe the problem is that field is immutable (val) but what do we do in such cases?
Is there any functionality like MapStruct's AfterMapping?
Or is there a way to fill that field using .addAll()?

@shrralis
Copy link
Author

I believe it would be possible to declare a default fun in the Konverter, like:

@Konverter
@KComponent
interface EntityConverter {

    @Konvert(
        mappings = [
            Mapping(target = "field", expression = "doSomething()"),
        ],
    )
    fun convertToEntity(dto: DTO): Entity

    fun convertFully(dto: DTO) = convertToEntity(dto).apply { field.addAll(dto.field) }
}

But it seems to be redundant since the whole interface has 2 available functions and it would confuse people.
I'd prefer to have something like:

@Konverter
@KComponent
interface EntityConverter {

    @Konvert(
        mappings = [
            Mapping(target = "field", expression = "doSomething()"),
        ],
        afterKonvert = "it.fillCollections(dto)", // <-- where `it` is a result Entity and `dto` is the function's param
    )
    fun convertToEntity(dto: DTO): Entity

    fun Entity.fillCollections(dto: DTO): Unit {
        this.field.addAll(dto.field)
    }
}

Is this considerable?

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

1 participant