Kotlin + GIZMO should be compatible
From https://github.com/TimefoldAI/timefold-solver/discussions/531:
@PlanningSolution
class MySolution {
@get:PlanningEntityCollectionProperty
var itemList: List<Item> = listOf()
...
I get the error
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.IllegalStateException: Member (itemList) of class (com.acme.model.MySolution) is not public and domainAccessType is GIZMO. Maybe put the annotations onto the public getter of the field. Maybe use domainAccessType REFLECTION instead of GIZMO. [in thread "main"]
which is irritating, because the annotation is on the getter, as it explicitly has the Kotlin prefix get:.
But you're right: This isn't an issue with Gizmo itself, it originates in Timefold. I didn't put much thought to it at the time, but instead went for the public fields approach, as it only affected a few properties in my model. It seems that GizmoSolutionOrEntityDescriptor creates a GizmoMemberDescriptor for both the getters and the fields, and when iterating over them, it fails at the first field because Modifier.isPublic() returns false.
A possible workaround is using a custom SolutionCloner. The easiest way is probably to use a Kotlin data classes as PlanningSolution and PlanningEntities:
@PlanningSolution(solutionCloner = MySolutionCloner::class)
data class MySolution(
@get:PlanningEntityCollectionProperty
var itemList: List<Item> = listOf()
...
and implement a SolutionCloner that delegates to the data classes' copy() methods:
class MySolutionCloner: SolutionCloner<MySolution> {
override fun cloneSolution(solution: MySolution) = solution.copy(itemList = solution.itemList.map { it.copy() })
}
Make sure that the @ProblemFact* @PlanningEntity* and @PlanningScore annotations are bound to the public getter via @get:.