Having an issue converting java to kotlin for some...
# announcements
s
Having an issue converting java to kotlin for some things with some advanced generics and co/contravariances We have this AbstractProjector
Copy code
public abstract class AbstractProjector<ID extends Serializable, DTO extends AbstractView, DAO extends AbstractViewDao> {
    protected final JpaRepository<DAO, ID> repository;
    protected final Function<DAO, DTO> toDto;
    protected final Function<DTO, DAO> toDao;

    protected AbstractProjector(JpaRepository<DAO, ID> repository,
                                Function<DAO, DTO> toDtoFunction,
                                Function<DTO, DAO> toDaoFunction) {
        this.repository = repository;
        this.toDto = toDtoFunction;
        this.toDao = toDaoFunction;
    }
...
that is used like this:
Copy code
public class WorkItemProjector extends AbstractProjector<WorkItemId, WorkItemView, WorkItemViewDao> {
    @Autowired
    public WorkItemProjector(WorkItemViewRepository repository) {
        super(repository, WorkItemViewDao::toDto, WorkItemViewDao::toDao);
    }
...
}
Here is the repository:
Copy code
interface WorkItemViewRepository : JpaRepository<WorkItemViewDao?, WorkItemId?> {...}
Here is the
WorkItemView
and
WorkItemViewDao
Copy code
data class WorkItemView(
    val workItemId: WorkItemId,
    val decisionId: SomeId,
    val appId: SomeId,
    override var tenantId: TenantId,
    val workItemStatus: WorkItemListType? = null
) : AbstractView, Serializable

@Entity(name = "…")
@Table(name = "…")
data class WorkItemViewDao(
    @Id var workItemId: WorkItemId,
    @AttributeOverrides(AttributeOverride(name = "id", column = Column(name = "…")))
    var decisionId: SomeId,
    @AttributeOverrides(AttributeOverride(name = "id", column = Column(name = "…")))
    var appId: SomeId,
    override var tenantId: TenantId,
    @Type(type = "Json", parameters = arrayOf(Parameter(name = "type", value = "…")))
    @Column(name = "data") var workItemView: WorkItemView
) : AbstractViewDao {
    companion object {
        @JvmStatic
        fun toDao(view: WorkItemView) = WorkItemViewDao(view.workItemId, view.decisionId, view.appId, view.tenantId, view)

        @JvmStatic
        fun toDto(dao: WorkItemViewDao?) = dao?.workItemView
    }
}
When converting this to Kotlin, you can guess the issue. AbstractProjector
Copy code
abstract class AbstractProjector<ID : Serializable?, DTO : AbstractView?, DAO : AbstractViewDao?> protected constructor(
    protected val repository: JpaRepository<DAO, ID>,
    protected val toDto: (DAO) -> DTO,
    protected val toDao: (DTO) -> DAO
) {..}
WorkItemProjector
Copy code
class WorkItemProjector(repository: WorkItemViewRepository) :
    AbstractProjector<WorkItemId?, WorkItemView?, WorkItemViewDao?>(
        repository,
        WorkItemViewDao::toDto,
        WorkItemViewDao::toDao
    ) {…}
and the issue is show in an image below. Here are some of the function signatures (in
AbstractProjector
) that demonstrate how I can’t effectively split this into multiple interfaces with different
out/in
variances (I think)
Copy code
protected fun save(tenantId: TenantId?, viewCreator: () -> DTO) {
protected fun conditionallyUpdate(viewId: ID, proceedWithUpdate: (DTO) -> Unit, viewUpdater: (DTO) -> DTO) {
protected fun update(viewId: ID, viewUpdater: (DTO) -> DTO) {
protected fun update(daoSupplier: Supplier<DAO>, viewUpdater: (DTO) -> DTO) {
protected fun updateDao(viewId: ID, viewUpdater: (DAO) -> DAO) {
protected fun delete(viewId: ID) {
private fun update(viewDao: DAO, viewUpdater: (DTO) -> DTO) {
Any clue on this would be great.