All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.itangcent.common.text.ScriptEngineTemplateEvaluator.kt Maven / Gradle / Ivy

package com.itangcent.common.text

import com.itangcent.common.utils.GsonUtils
import java.util.regex.Pattern
import javax.script.ScriptContext
import javax.script.ScriptEngine
import javax.script.ScriptEngineManager
import javax.script.SimpleScriptContext

abstract class ScriptEngineTemplateEvaluator : TemplateEvaluator {

    protected val scriptEngine: ScriptEngine by lazy {
        buildScriptEngine().also { initScripEngine(it) }
    }

    private fun buildScriptEngine(): ScriptEngine {
        val manager = ScriptEngineManager()
        return manager.getEngineByName(scriptType())
    }

    abstract fun scriptType(): String

    open fun initScripEngine(scriptEngine: ScriptEngine) {
    }

    override fun eval(str: String): Any? {
        return try {
            scriptEngine.eval(str)?.toString()
        } catch (e: Exception) {
            null
        }
    }
}

abstract class ScriptEngineTemplateEvaluatorWithSuperTemplateEvaluator(private val templateEvaluator: TemplateEvaluator) :
    ScriptEngineTemplateEvaluator() {

    private val scriptContext: ScriptContext by lazy {
        TemplateEvaluatorScriptContext(templateEvaluator)
    }

    override fun eval(str: String): Any? {
        return try {
            scriptEngine.eval(str, scriptContext)?.toString()
        } catch (e: Exception) {
            scriptContext.getAttribute("a")
            null
        }
    }
}

private class TemplateEvaluatorScriptContext(private val templateEvaluator: TemplateEvaluator) : SimpleScriptContext() {
    override fun getAttribute(name: String?): Any? {
        super.getAttribute(name)?.let { return it }
        return name?.takeIf { !it.startsWith("#jsr223") }?.let { templateEvaluator.eval(it)?.resolveNumeric() }
    }

    override fun getAttribute(name: String?, scope: Int): Any? {
        super.getAttribute(name, scope)?.let { return it }
        return name?.takeIf { !it.startsWith("#jsr223") }?.let { templateEvaluator.eval(it)?.resolveNumeric() }
    }

    override fun getAttributesScope(name: String?): Int {
        val scope = super.getAttributesScope(name)
        if (scope != -1 || name == null || name.startsWith("#jsr223")) {
            return scope
        }
        if (templateEvaluator.eval(name) != null) {
            return GLOBAL_SCOPE
        }
        return scope
    }

    private fun Any.resolveNumeric(): Any {
        if (this is String) {
            try {
                if (NUMERIC_PATTERN.matcher(this).matches()) {
                    return if (this.contains('.')) {
                        this.toDouble()
                    } else {
                        this.toLong()
                    }
                } else if (TRUE_OR_FALSE.contains(this)) {
                    return this.toBoolean()
                } else if (this.startsWith("{") && this.endsWith("}")) {
                    return GsonUtils.fromJson(this, Map::class)
                } else if (this.startsWith("[") && this.endsWith("]")) {
                    return GsonUtils.fromJson(this, List::class)
                }
            } catch (ignore: Exception) {
            }
        }
        return this
    }

    companion object {
        private val NUMERIC_PATTERN = Pattern.compile("^[\\-0-9][0-9]*(.[0-9]+)?\$")
        private val TRUE_OR_FALSE = arrayOf("true", "false")
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy