Skip to content

Instantly share code, notes, and snippets.

@j-didi
Last active June 11, 2020 21:23
Show Gist options
  • Save j-didi/a18c65a42b0c0c28f255df76c618fc3b to your computer and use it in GitHub Desktop.
Save j-didi/a18c65a42b0c0c28f255df76c618fc3b to your computer and use it in GitHub Desktop.
Kotlin Domain Specific Language using reflections, infix and aggregation
import com.google.gson.GsonBuilder
import kotlin.reflect.KMutableProperty
import kotlin.reflect.full.memberProperties
//Enum and properties to better infix semantic
private const val Terminal = 0
enum class LogTarget(val value: Int) {
TERMINAL(0);
companion object {
fun fromInt(value: Int) = values().first { it.value == value }
}
}
//Data classes
data class PersonalInfo(
val name: String,
val email: String,
val phone: String,
val cpf: String
)
data class Address(
val cep: String,
val uf: String,
val city: String,
val district: String,
val street: String,
val number: String? = null,
val complement: String? = null
)
data class Account(
var id: Int,
var personalInfo: PersonalInfo? = null,
var address: Address? = null
) {
//Infix with reflection and aggregation
infix fun<TEntity> add(field: TEntity) where TEntity : Any {
Account::class.memberProperties
.filter{ it.name.equals(field::class.simpleName, true) }
.filterIsInstance<KMutableProperty<*>>()
.forEach { it.setter.call(this, field) }
}
//Formatted json log
infix fun logTo(target: Int) {
val logTarget = LogTarget.fromInt(target)
val gson = GsonBuilder().setPrettyPrinting().create()
val json: String = gson.toJson(this)
//Implement other targets
when(logTarget) {
LogTarget.TERMINAL -> println(json)
}
}
}
//Clean domain flow
fun main() {
val account = Account(1)
val personalInfo = PersonalInfo(
name = "Jefferson Didi Silva",
email = "didi@gmail.com",
phone = "4002-8922",
cpf = "000.000.000-00"
)
val address = Address(
cep = "24466-970",
uf = "RJ",
city = "São Gonçalo",
street = "Rod. Niterói - Manilha",
district = "Boa Vista",
number = "100"
)
account add personalInfo
account add address
account logTo Terminal
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment