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

cc.unitmesh.prompt.validate.StringValidator.kt Maven / Gradle / Ivy

package cc.unitmesh.prompt.validate

/**
 * This class represents a string validation expression that evaluates to a boolean value, determining whether subsequent
 * statements should be executed or not.
 */
class StringValidator(val expression: String, override val input: String) : Validator {
    override fun validate(): Boolean {
        val expr = parseExpression(expression)
        val left = expr.left
        val right = expr.right
        val operator = expr.operator

        return when (operator) {
            CompareType.EQUALS -> input == right
            CompareType.NOT_EQUALS -> input != right
            CompareType.CONTAINS -> input.contains(right)
            CompareType.STARTS_WITH -> input.startsWith(right)
            CompareType.ENDS_WITH -> input.endsWith(right)
            CompareType.GREATER_THAN -> input.length > right.toInt()
            CompareType.LESS_THAN -> input.length < right.toInt()
            CompareType.PROPERTY_ACCESS -> {
                val propertyAccess = parsePropertyAccess(left)
                when (propertyAccess.operator) {
                    AccessType.LENGTH -> input.length == right.toInt()
                    AccessType.UPPER_CASE -> input.uppercase() == right
                    AccessType.LOWER_CASE -> input.lowercase() == right
                }
            }
        }
    }

    private fun parseExpression(expression: String): CompareExpr {
        // split expression to char and convert
        val chars = expression.toCharArray()
        val tokens = mutableListOf()
        val sb = StringBuilder()
        var isInQuote = false
        for (c in chars) {
            when {
                c == '"' || c == '\'' -> {
                    isInQuote = !isInQuote
                }
                isInQuote -> {
                    sb.append(c)
                    continue
                }
                c == ' ' -> {
                    if (sb.isNotEmpty()) {
                        tokens.add(sb.toString())
                        sb.clear()
                    }
                }
                else -> {
                    sb.append(c)
                }
            }
        }

        if (sb.isNotEmpty()) {
            tokens.add(sb.toString())
        }

        val left = tokens[0]
        val operator = when (tokens[1]) {
            "==" -> CompareType.EQUALS
            "!=" -> CompareType.NOT_EQUALS
            "contains" -> CompareType.CONTAINS
            "startsWith" -> CompareType.STARTS_WITH
            "endsWith" -> CompareType.ENDS_WITH
            "length" -> CompareType.PROPERTY_ACCESS
            "uppercase" -> CompareType.PROPERTY_ACCESS
            "lowercase" -> CompareType.PROPERTY_ACCESS
            ">" -> CompareType.GREATER_THAN
            "<" -> CompareType.LESS_THAN
            else -> throw Exception("Unsupported operator ${tokens[1]}")
        }
        val right = tokens[2]
        // if right is String, remove double quote
        if (right.startsWith("\"") && right.endsWith("\"")) {
            return CompareExpr(left, operator, right.substring(1, right.length - 1))
        }

        return CompareExpr(left, operator, right)
    }

    private fun parsePropertyAccess(expression: String): PropertyAccess {
        val chars = expression.toCharArray()
        val tokens = mutableListOf()
        val sb = StringBuilder()
        for (c in chars) {
            when (c) {
                '.' -> {
                    if (sb.isNotEmpty()) {
                        tokens.add(sb.toString())
                        sb.clear()
                    }
                }
                else -> {
                    sb.append(c)
                }
            }
        }

        if (sb.isNotEmpty()) {
            tokens.add(sb.toString())
        }

        val propertyName = tokens[0]
        val operator = when (tokens[1]) {
            "length" -> AccessType.LENGTH
            "uppercase" -> AccessType.UPPER_CASE
            "lowercase" -> AccessType.LOWER_CASE
            else -> throw Exception("Unsupported operator ${tokens[1]}")
        }
        val value = tokens[2]
        return PropertyAccess(propertyName, operator, value)
    }
}

data class CompareExpr(val left: String, val operator: CompareType, val right: String)

enum class CompareType {
    EQUALS,
    NOT_EQUALS,
    CONTAINS,
    STARTS_WITH,
    ENDS_WITH,
    GREATER_THAN,
    LESS_THAN,
    PROPERTY_ACCESS,
}

data class PropertyAccess(val propertyName: String, val operator: AccessType, val value: String)

enum class AccessType {
    LENGTH,
    UPPER_CASE,
    LOWER_CASE,
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy