Simple DSL for providing data

This commit is contained in:
Shadowfacts 2017-08-05 13:41:24 -04:00
parent 86de475391
commit fe378f453d
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
2 changed files with 30 additions and 17 deletions

View File

@ -35,7 +35,7 @@ _result.toString()
ScriptEngineManager() ScriptEngineManager()
} }
fun render(template: String, data: Map<String, Any>, dumpGeneratedScript: File? = null): String { fun render(template: String, dumpGeneratedScript: File? = null, dataProvider: DataProviderContext.() -> Unit): String {
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
var template = template var template = template
template = template.replace("$", "\${'$'}") template = template.replace("$", "\${'$'}")
@ -64,34 +64,47 @@ _result.toString()
writeText(script) writeText(script)
} }
return eval(script, data) as String val data = DataProviderContext()
data.dataProvider()
return eval(script, data.map) as String
} }
fun render(template: File, data: Map<String, Any>, dumpGeneratedScript: File? = null): String { fun render(template: File, dumpGeneratedScript: File? = null, dataProvider: DataProviderContext.() -> Unit): String {
return render(template.readText(), data, dumpGeneratedScript) return render(template.readText(), dumpGeneratedScript, dataProvider)
} }
internal fun eval(script: String, data: Map<String, Any> = mapOf()): Any? { internal fun eval(script: String, data: Map<String, TypedValue> = mapOf()): Any? {
val engine = manager.getEngineByExtension("kts") val engine = manager.getEngineByExtension("kts")
val bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE) val bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE)
bindings.putAll(data) bindings.putAll(data)
// Hack to allow data to be accessed by name from template instead of via bindings map // Hack to allow data to be accessed by name from template instead of via bindings map
val unwrapBindings = data.keys.map { val unwrapBindings = data.keys.map {
val value = data[it]!! val type = data[it]!!.type
if (value is Value) { "val $it = (bindings[\"$it\"] as net.shadowfacts.ekt.EKT.TypedValue).value as $type"
val type = value.type
"val $it = (bindings[\"$it\"] as net.shadowfacts.ekt.EKT.Value).value as $type"
} else {
val type = value::class.qualifiedName
"val $it = bindings[\"$it\"] as $type"
}
}.joinToString("\n") }.joinToString("\n")
engine.eval(unwrapBindings) engine.eval(unwrapBindings)
return engine.eval(script) return engine.eval(script)
} }
data class Value(val value: Any, val type: String) class DataProviderContext {
internal val map = mutableMapOf<String, TypedValue>()
infix fun String.to(value: Any) {
if (value is TypedValue) {
map[this] = value
} else {
map[this] = TypedValue(value, value::class.qualifiedName!!)
}
}
infix fun Any.asType(type: String): TypedValue {
return TypedValue(this, type)
}
}
data class TypedValue(val value: Any, val type: String)
} }

View File

@ -6,9 +6,9 @@ import java.io.File
* @author shadowfacts * @author shadowfacts
*/ */
fun main(args: Array<String>) { fun main(args: Array<String>) {
val res = EKT.render(File("template.ekt"), mapOf( val res = EKT.render(File("template.ekt"), dumpGeneratedScript = File("script.kts")) {
"list" to EKT.Value(listOf(1, 2, 3), "List<String>") "list" to (listOf(1, 2, 3) asType "List<Int>")
), dumpGeneratedScript = File("script.kts")) }
File("result.txt").apply { File("result.txt").apply {
if (!exists()) createNewFile() if (!exists()) createNewFile()