Created
April 19, 2018 09:05
-
-
Save jaumard/1fd1ccc9db0374cb5d08f047414a6bc8 to your computer and use it in GitHub Desktop.
Problem with kotlin generics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data class CustomerPersonalInfo(val memberNumber: String, | |
val name: String, | |
val surname: String, | |
val taxId: Int) { | |
private constructor(builder: Builder) : this(builder.memberNumber, | |
builder.name, | |
builder.surname, | |
builder.taxId) | |
class Builder { | |
var memberNumber: String = "" | |
private set | |
lateinit var name: String | |
private set | |
lateinit var surname: String | |
private set | |
var taxId = 0 | |
private set | |
fun withMemberNumber(memberNumber: String) = apply { this.memberNumber = memberNumber } | |
fun withName(name: String) = apply { this.name = name } | |
fun withSurname(surname: String) = apply { this.surname = surname } | |
fun withTaxId(taxId: Int) = apply { this.taxId = taxId } | |
fun build() = CustomerPersonalInfo(this) | |
} | |
} | |
data class FormFieldDefinition(val fieldName: String) | |
class FormField<T>(var value: T, var name: String) | |
interface PersonalInfoFormFieldAccessor<T> { | |
private inline fun <reified T : Any> getGenericType() = T::class | |
fun getFormField(formFieldDefinition: FormFieldDefinition): FormField<T> | |
fun setValueToBuilder(builder: CustomerPersonalInfo.Builder, value: T) | |
fun accept(visitor: PersonalInfoFormFieldVisitor) | |
fun getValueFromPersonalInfo(personalInfo: CustomerPersonalInfo): T | |
} | |
abstract class PersonalInfoFormFieldVisitor { | |
open fun visitString(accessor: PersonalInfoFormFieldAccessor<String>?) { | |
//to implement when override | |
} | |
open fun getString(accessor: PersonalInfoFormFieldAccessor<String>?): String { | |
return "" | |
} | |
open fun visitInt(personalInfoFormFieldAccessor: PersonalInfoFormFieldAccessor<Int>?) { | |
//to implement | |
} | |
} | |
class PersonalInfoFormFieldAccessors { | |
companion object { | |
const val FIRST_NAME = "firstName" | |
const val TAX_ID = "taxIdentificationNumber" | |
} | |
val accessors = mutableMapOf<String, PersonalInfoFormFieldAccessor<*>>() | |
init { | |
initAccessors() | |
} | |
private fun initAccessors() { | |
accessors[FIRST_NAME] = object : PersonalInfoFormFieldAccessor<String> { | |
override fun getValueFromPersonalInfo(personalInfo: CustomerPersonalInfo): String { | |
return personalInfo.surname | |
} | |
override fun accept(visitor: PersonalInfoFormFieldVisitor) { | |
visitor.visitString(this) | |
} | |
override fun getFormField(formFieldDefinition: FormFieldDefinition): FormField<String> { | |
return FormField("test", FIRST_NAME) | |
} | |
override fun setValueToBuilder(builder: CustomerPersonalInfo.Builder, value: String) { | |
builder.withSurname(value) | |
} | |
} | |
accessors[TAX_ID] = object : PersonalInfoFormFieldAccessor<Int> { | |
override fun getValueFromPersonalInfo(personalInfo: CustomerPersonalInfo): Int { | |
return personalInfo.taxId | |
} | |
override fun accept(visitor: PersonalInfoFormFieldVisitor) { | |
visitor.visitInt(this) | |
} | |
override fun getFormField(formFieldDefinition: FormFieldDefinition): FormField<Int> { | |
return FormField(1, TAX_ID) | |
} | |
override fun setValueToBuilder(builder: CustomerPersonalInfo.Builder, value: Int) { | |
builder.withTaxId(value) | |
} | |
} | |
} | |
} | |
class PersonalInfoFormDefinition(formFieldDefinitions: List<FormFieldDefinition>, | |
personalInfoAccessors: PersonalInfoFormFieldAccessors) { | |
private val fields: List<FormField<*>> | |
private val accessors = personalInfoAccessors.accessors | |
init { | |
fields = formFieldDefinitions.mapNotNull { | |
getFormField(it) | |
}.toList() | |
} | |
fun getFields(): List<FormField<*>> { | |
return fields | |
} | |
fun getPopulatedFields(personalInfo: CustomerPersonalInfo?): List<FormField<*>> { | |
return if (personalInfo == null) { | |
fields | |
} else { | |
fields.forEach { field -> | |
val fieldAccessor = accessors[field.name] | |
fieldAccessor?.accept(object : PersonalInfoFormFieldVisitor() { | |
override fun visitString(accessor: PersonalInfoFormFieldAccessor<String>?) { | |
field.value = accessor?.getValueFromPersonalInfo(personalInfo) | |
} | |
}) | |
} | |
fields | |
} | |
} | |
fun getPersonalInfo(): CustomerPersonalInfo { | |
val builder = CustomerPersonalInfo.Builder() | |
for (field in fields) { | |
accessors[field.name]!!.setValueToBuilder(builder, field.value) | |
} | |
return builder.build() | |
} | |
private fun getFormField(formFieldDefinition: FormFieldDefinition): FormField<*>? { | |
val fieldAccessor = accessors[formFieldDefinition.fieldName] | |
return fieldAccessor?.getFormField(formFieldDefinition) | |
} | |
} | |
fun main(args: Array<String>) { | |
//nothing to do | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment