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

com.yandex.div.evaluable.EvaluableException.kt Maven / Gradle / Ivy

Go to download

DivKit is an open source Server-Driven UI (SDUI) framework. SDUI is a an emerging technique that leverage the server to build the user interfaces of their mobile app.

There is a newer version: 30.27.0
Show newest version
package com.yandex.div.evaluable

import com.yandex.div.evaluable.internal.Token
import org.json.JSONArray
import org.json.JSONObject

internal const val REASON_DIVISION_BY_ZERO = "Division by zero is not supported."
internal const val REASON_EMPTY_ARGUMENT_LIST = "Function requires non empty argument list."
internal const val REASON_INTEGER_OVERFLOW = "Integer overflow."
internal const val REASON_OUT_OF_BOUNDS = "Indexes are out of bounds."
internal const val REASON_INDEXES_ORDER = "Indexes should be in ascending order."
internal const val REASON_CONVERT_TO_INTEGER = "Unable to convert value to Integer."
internal const val REASON_CONVERT_TO_NUMBER = "Unable to convert value to Number."
internal const val REASON_CONVERT_TO_BOOLEAN = "Unable to convert value to Boolean."
internal const val REASON_CONVERT_TO_COLOR = "Unable to convert value to Color, expected format #AARRGGBB."
internal const val REASON_CONVERT_TO_URL = "Unable to convert value to Url."
internal const val REASON_OUT_OF_RANGE = "Value out of range 0..1."

open class EvaluableException(
    message: String,
    cause: Exception? = null
) : RuntimeException(message, cause)

class TokenizingException(
    message: String,
    cause: Exception? = null
) : EvaluableException(message, cause)

class MissingVariableException(
    val variableName: String,
    cause: Exception? = null
) : EvaluableException("Variable '${variableName}' is missing.", cause)

class IntegerOverflow(
        val expression: String,
        cause: Exception? = null
) : EvaluableException("Failed to evaluate [$expression]. $REASON_INTEGER_OVERFLOW", cause)

internal fun throwExceptionOnEvaluationFailed(
    expression: String,
    reason: String,
    cause: Exception? = null
): Nothing = throw EvaluableException("Failed to evaluate [$expression]. $reason", cause)

internal fun throwExceptionOnFunctionEvaluationFailed(
    name: String,
    args: List,
    reason: String,
    cause: Exception? = null
): Nothing = throwExceptionOnEvaluationFailed(functionToMessageFormat(name, args), reason, cause)

internal fun throwExceptionOnMethodEvaluationFailed(
    name: String,
    args: List,
    reason: String,
    cause: Exception? = null
): Nothing = throwExceptionOnEvaluationFailed(methodToMessageFormat(name, args), reason, cause)


internal fun functionToMessageFormat(name: String, args: List): String {
    return args.joinToString(prefix = "${name}(", postfix = ")") {
        it.toMessageFormat()
    }
}

internal fun methodToMessageFormat(name: String, args: List): String {
    return if (args.size > 1) {
        args.subList(1, args.size).joinToString(prefix = "${args.first()}.$name(", postfix = ")", separator = ",")
    } else "$name()"
}

internal fun throwExceptionOnEvaluationFailed(
    operator: Token.Operator.Binary,
    left: Any,
    right: Any,
): Nothing {
    val evaluable = "${left.toMessageFormat()} $operator ${right.toMessageFormat()}"
    val typesMessage = if (left.javaClass != right.javaClass) {
        "different types: ${EvaluableType.of(left).typeName} and ${EvaluableType.of(right).typeName}"
    } else {
        "${EvaluableType.of(left).typeName} type"
    }
    throwExceptionOnEvaluationFailed(
        evaluable,
        "Operator '$operator' cannot be applied to $typesMessage."
    )
}

internal fun List.toMessageFormat(): String {
    return this.joinToString(", ") {
        it.toMessageFormat()
    }
}

internal fun Any.toMessageFormat(): String {
    return when (this) {
        is JSONArray -> ""
        is JSONObject -> ""
        is String -> "'$this'"
        else -> toString()
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy