From d8d6a9519dc2eeb6a06c7c4074358ba70fdfc8fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luiz=20H=2E=20Rapat=C3=A3o?= Date: Sat, 4 Nov 2023 11:29:05 +0000 Subject: [PATCH] feat: add project documentation (#11) There is no behavior or functionality added in this change, it only adds method documentation to support developers to use the library. --- .../projects/ruleset/engine/Evaluator.kt | 13 +++ .../ruleset/engine/context/ContextFactory.kt | 46 +++++++++- .../ruleset/engine/types/Expression.kt | 20 ++++- .../ruleset/engine/types/OnFailure.kt | 8 ++ .../projects/ruleset/engine/types/Operator.kt | 12 +++ .../engine/types/builder/BetweenBuilder.kt | 31 +++++++ .../engine/types/builder/ExpressionBuilder.kt | 84 +++++++++++++++++++ .../engine/types/builder/ExtensionBuilder.kt | 59 +++++++++++++ .../engine/types/builder/MatcherBuilder.kt | 21 +++++ .../ruleset/jackson/ExpressionMixin.kt | 6 ++ 10 files changed, 295 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/rapatao/projects/ruleset/engine/Evaluator.kt b/src/main/kotlin/com/rapatao/projects/ruleset/engine/Evaluator.kt index 0c46f7c..fd73fc2 100644 --- a/src/main/kotlin/com/rapatao/projects/ruleset/engine/Evaluator.kt +++ b/src/main/kotlin/com/rapatao/projects/ruleset/engine/Evaluator.kt @@ -7,10 +7,23 @@ import org.mozilla.javascript.Context import org.mozilla.javascript.Script import org.mozilla.javascript.ScriptableObject +/** + * The Evaluator class is used to evaluate a given rule expression against input data. + * + * @property contextFactory The factory used to create a context for evaluating the expressions. + * Defaults to ContextFactory(). + */ class Evaluator( val contextFactory: ContextFactory = ContextFactory(), ) { + /** + * Evaluates the given rule expression against the provided input data. + * + * @param rule The expression to be evaluated. + * @param inputData The input data to be used in the evaluation. + * @return `true` if the rule expression evaluates to `true`, `false` otherwise. + */ fun evaluate(rule: Expression, inputData: Any): Boolean { return contextFactory.call(inputData) { context, scope -> val processIsTrue = rule.takeIf { v -> v.parseable() }?.processExpression(context, scope) ?: true diff --git a/src/main/kotlin/com/rapatao/projects/ruleset/engine/context/ContextFactory.kt b/src/main/kotlin/com/rapatao/projects/ruleset/engine/context/ContextFactory.kt index 2d58346..2f1b0ad 100644 --- a/src/main/kotlin/com/rapatao/projects/ruleset/engine/context/ContextFactory.kt +++ b/src/main/kotlin/com/rapatao/projects/ruleset/engine/context/ContextFactory.kt @@ -6,11 +6,27 @@ import org.mozilla.javascript.Context import org.mozilla.javascript.ContextFactory import org.mozilla.javascript.ScriptableObject +/** + * A factory for creating JavaScript contexts with customizable options. + * + * @property optimizationLevel The optimization level for the context. Defaults to -1. + * @property wrapJavaPrimitives Determines if Java primitive values should be wrapped in their corresponding JavaScript + * wrapper objects. Defaults to false. + * @property languageVersion The language version of the JavaScript code to be executed in the context. + * Defaults to Context.VERSION_DEFAULT. + */ open class ContextFactory( val optimizationLevel: Int = -1, val wrapJavaPrimitives: Boolean = false, val languageVersion: Int = Context.VERSION_DEFAULT ) : ContextFactory() { + /** + * Check if the given feature is enabled in the context. + * + * @param cx the context in which to check the feature + * @param featureIndex the index of the feature to check + * @return true if the feature is enabled, false otherwise + */ override fun hasFeature(cx: Context, featureIndex: Int): Boolean { if (Context.FEATURE_ENABLE_JAVA_MAP_ACCESS == featureIndex) { return true @@ -19,6 +35,11 @@ open class ContextFactory( return super.hasFeature(cx, featureIndex) } + /** + * Creates and configures a new context for executing JavaScript code. + * + * @return The newly created context. + */ override fun makeContext(): Context { val context = super.makeContext() @@ -29,10 +50,20 @@ open class ContextFactory( return context } - fun call( + /** + * Executes the provided block of code with the given input data and returns a boolean value indicating + * the success or failure of the execution. + * + * @param inputData The input data to be used in the execution. + * @param block A lambda function that takes in a context and a scope as parameters and returns a boolean value. + * The context represents the context in which the execution takes place, and the scope represents + * the scope of the execution. + * @return The result of the execution. + */ + open fun call( inputData: Any, - block: (context: Context, scope: ScriptableObject) -> Boolean - ): Boolean { + block: (context: Context, scope: ScriptableObject) -> T + ): T { return this.call { context -> val scope = context.initSafeStandardObjects() @@ -42,7 +73,14 @@ open class ContextFactory( } } - private fun parseParameters( + /** + * Parses parameters and injects them into the given scope based on the input data. + * + * @param scope the scriptable object scope where the parameters will be injected + * @param context the context in which the parameters will be injected + * @param inputData the input data containing the parameters + */ + open fun parseParameters( scope: ScriptableObject, context: Context, inputData: Any, diff --git a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/Expression.kt b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/Expression.kt index 15ae9ca..c5148c6 100644 --- a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/Expression.kt +++ b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/Expression.kt @@ -1,5 +1,19 @@ package com.rapatao.projects.ruleset.engine.types +/** + * Represents an expression used in a logical query. + * + * An expression can consist of one or more sub-expressions and an operator. + * It can also specify the action to take if the expression fails. + * + * @property allMatch A list of sub-expressions that all must match. + * @property anyMatch A list of sub-expressions where at least one must match. + * @property noneMatch A list of sub-expressions where none must match. + * @property left The left operand of the expression. + * @property operator The operator to apply to the expression. + * @property right The right operand of the expression. + * @property onFailure The action to take if the expression fails. + */ data class Expression( val allMatch: List? = null, val anyMatch: List? = null, @@ -11,9 +25,13 @@ data class Expression( ) { fun operator() = operator fun onFailure() = onFailure - fun parseable(): Boolean = operator != null + /** + * Checks if the current object is valid. + * + * @return Boolean value indicating whether the object is valid. + */ fun isValid(): Boolean { val any = anyMatch?.map { it.isValid() }?.firstOrNull { !it } ?: true val none = noneMatch?.map { it.isValid() }?.firstOrNull { !it } ?: true diff --git a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/OnFailure.kt b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/OnFailure.kt index 16f8042..5ea9636 100644 --- a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/OnFailure.kt +++ b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/OnFailure.kt @@ -1,5 +1,13 @@ package com.rapatao.projects.ruleset.engine.types +/** + * Enum class representing the possible actions on failure. + * + * This enum class defines three choices that can be made when handling failures: + * - [FALSE]: Indicates that the failure should be considered as a false result. + * - [TRUE]: Indicates that the failure should be considered as a true result. + * - [THROW]: Indicates that an exception should be thrown when a failure occurs. + **/ enum class OnFailure { FALSE, TRUE, diff --git a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/Operator.kt b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/Operator.kt index 343ef3b..bbf61a3 100644 --- a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/Operator.kt +++ b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/Operator.kt @@ -1,5 +1,17 @@ package com.rapatao.projects.ruleset.engine.types +/** + * Enum class for different operators. + * + * This enum class represents various operators that can be used for comparison or evaluation operations. + * The available operators are: + * - EQUALS: Represents the equals operator (==). + * - NOT_EQUALS: Represents the not equals operator (!=). + * - GREATER_THAN: Represents the greater than operator (>). + * - GREATER_OR_EQUAL_THAN: Represents the greater than or equal to operator (>=). + * - LESS_THAN: Represents the less than operator (<). + * - LESS_OR_EQUAL_THAN: Represents the less than or equal to operator (<=). + */ enum class Operator { EQUALS, NOT_EQUALS, diff --git a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/BetweenBuilder.kt b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/BetweenBuilder.kt index 6cf2a0c..bc217cd 100644 --- a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/BetweenBuilder.kt +++ b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/BetweenBuilder.kt @@ -3,20 +3,51 @@ package com.rapatao.projects.ruleset.engine.types.builder import com.rapatao.projects.ruleset.engine.types.Expression import com.rapatao.projects.ruleset.engine.types.Operator +/** + * Creates a [BetweenBuilder] object to build a between condition. + * + * @param from The lower boundary value. + * @return A [BetweenBuilder] object to build the between condition. + */ infix fun Any.from(from: Any): BetweenBuilder = BetweenBuilder( left = this, from = from, operator = Operator.GREATER_THAN, ) +/** + * Creates a [BetweenBuilder] with the given left operand, starting value, and comparison operator + * + * @param from The starting value of the range, inclusive + * @return The [BetweenBuilder] instance for further chaining + */ infix fun Any.fromInclusive(from: Any): BetweenBuilder = BetweenBuilder( left = this, from = from, operator = Operator.GREATER_OR_EQUAL_THAN, ) +/** + * A builder class for constructing expressions representing a between condition. + * + * @property left The left operand of the condition. + * @property from The starting value of the range. + * @property operator The comparison operator for the condition. + */ data class BetweenBuilder(val left: Any, val from: Any, val operator: Operator) { + /** + * Creates a non-inclusive range expression using the given `to` value. + * + * @param to The upper bound value to compare against. + * @return A range expression. + */ infix fun to(to: Any): Expression = MatcherBuilder.allMatch( ExpressionBuilder.expression(left = left, operator = operator, right = from), ExpressionBuilder.expression(left = left, operator = Operator.LESS_THAN, right = to), ) + /** + * Creates an inclusive range expression using the given `to` value. + * + * @param to The upper bound of the range. + * @return A range expression + */ infix fun toInclusive(to: Any): Expression = MatcherBuilder.allMatch( ExpressionBuilder.expression(left = left, operator = operator, right = from), ExpressionBuilder.expression(left = left, operator = Operator.LESS_OR_EQUAL_THAN, right = to), diff --git a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/ExpressionBuilder.kt b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/ExpressionBuilder.kt index 78af1d0..8d64094 100644 --- a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/ExpressionBuilder.kt +++ b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/ExpressionBuilder.kt @@ -9,35 +9,119 @@ import com.rapatao.projects.ruleset.engine.types.Operator.LESS_OR_EQUAL_THAN import com.rapatao.projects.ruleset.engine.types.Operator.LESS_THAN import com.rapatao.projects.ruleset.engine.types.Operator.NOT_EQUALS +/** + * A utility class for building expressions using different operators. + */ object ExpressionBuilder { + /** + * Creates a new instance of [Builder] with the given [left] parameter. + * + * @param left the value to set as the left property of the [Builder] instance. + */ fun left(left: Any) = Builder(left) + /** + * Checks if the given expression evaluates to true. + * + * @param expression The expression to be evaluated. + * @return true if the expression evaluates to true, false otherwise. + */ fun isTrue(expression: Any) = left(expression).isTrue() + + /** + * Checks if the given expression evaluates to false. + * + * @param expression the expression to be evaluated + * @return true if the expression evaluates to false, false otherwise + */ fun isFalse(expression: Any) = left(expression).isFalse() + /** + * Creates an expression using the given left operand, operator, and right operand. + * + * @param left The left operand of the expression. + * @param operator The operator of the expression. + * @param right The right operand of the expression. + * @return The created expression. + */ fun expression(left: Any, operator: Operator, right: Any) = Expression( left = left, operator = operator, right = right ) + /** + * Represents a builder for creating expressions. + * + * @param left The left-hand side of the expression. + */ class Builder(private val left: Any) { + /** + * Creates an expression that represents the "equals to" comparison between the left operand and the right + * operand. + * + * @param right The right operand to compare. + * @return The expression representing the "equals to" comparison. + */ infix fun equalsTo(right: Any) = Expression(left = left, operator = EQUALS, right = right) + /** + * Creates an expression representing the inequality comparison between the left-hand side and the right-hand + * side. + * + * @param right The right-hand side of the comparison. + * @return A new expression representing the inequality comparison. + */ infix fun notEqualsTo(right: Any) = Expression(left = left, operator = NOT_EQUALS, right = right) + /** + * Creates an Expression object representing the greater-than comparison between the left operand and the right + * operand. + * + * @param right the right operand to compare with the left operand + * + * @return the Expression object representing the greater-than comparison + */ infix fun greaterThan(right: Any) = Expression(left = left, operator = GREATER_THAN, right = right) + /** + * Creates an expression that represents the "greater than or equal to" operation + * + * @param right the value to compare with + * @return an expression representing the "greater than or equal to" operation + */ infix fun greaterOrEqualThan(right: Any) = Expression(left = left, operator = GREATER_OR_EQUAL_THAN, right = right) + /** + * Creates an 'less than' expression with the specified 'right' value. + * + * @param right The right value of the expression. + * @return The created expression. + */ infix fun lessThan(right: Any) = Expression(left = left, operator = LESS_THAN, right = right) + /** + * Creates an expression that represents the less than or equal to operation. + * + * @param right The value to compare against the left operand. + * @return An Expression object representing the less than or equal to operation. + */ infix fun lessOrEqualThan(right: Any) = Expression(left = left, operator = LESS_OR_EQUAL_THAN, right = right) + /** + * Checks if the left operand represents a boolean with value true. + * + * @return The boolean expression representing if the condition is true. + */ fun isTrue() = Expression(left = left, operator = EQUALS, right = true) + /** + * Checks if the left operand represents a boolean with value false. + * + * @return The boolean expression representing if the condition is false. + */ fun isFalse() = Expression(left = left, operator = EQUALS, right = false) } } diff --git a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/ExtensionBuilder.kt b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/ExtensionBuilder.kt index 7fc1526..68c7e05 100644 --- a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/ExtensionBuilder.kt +++ b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/ExtensionBuilder.kt @@ -6,24 +6,83 @@ import com.rapatao.projects.ruleset.engine.types.builder.ExpressionBuilder.isFal import com.rapatao.projects.ruleset.engine.types.builder.ExpressionBuilder.isTrue import com.rapatao.projects.ruleset.engine.types.builder.ExpressionBuilder.left +/** + * Converts the receiver object to an instance of `Expression` if it is not already an `Expression`. + * + * @return The `Expression` instance representing the receiver object, or the receiver object itself + * if it is already an `Expression`. + */ fun Any.asExpression(): Expression = this.takeIf { it !is Expression }?.let { isTrue(it) } ?: this as Expression +/** + * Checks if the current value is considered to be "true". + * + * @return An [Expression] representing the current value. + */ fun Any.isTrue(): Expression = isTrue(this) +/** + * Checks if the given expression evaluates to false. + * + * @return True if the expression is false, false otherwise. + */ fun Any.isFalse(): Expression = isFalse(this) +/** + * Checks if the current object is equal to the given object using a custom equality expression. + * + * @param right The object to compare with. + * @return An expression representing the equality comparison between the current object and the given object. + */ infix fun Any.equalsTo(right: Any): Expression = left(this).equalsTo(right) +/** + * Compares this object with the specified [right] object for inequality. + * + * @param right The object to compare with this object. + * @return An [Expression] representing the inequality comparison result. + */ infix fun Any.notEqualsTo(right: Any): Expression = left(this).notEqualsTo(right) +/** + * Returns an expression representing the greater-than comparison between this value and the given value. + * + * @param from The value to compare against. + * @return An [Expression] representing the greater-than comparison. + */ infix fun Any.greaterThan(from: Any): Expression = left(this).greaterThan(from) +/** + * Compares two objects and returns an expression representing the "greater than or equal to" comparison. + * + * @param from The object to compare against. + * @return An expression representing the "greater than or equal to" comparison. + */ infix fun Any.greaterOrEqualThan(from: Any): Expression = left(this).greaterOrEqualThan(from) +/** + * Compares this object with the specified object and returns an expression representing the result + * of the less than comparison. + * + * @param from the object to compare with + * @return an expression representing the result of the less than comparison + */ infix fun Any.lessThan(from: Any): Expression = left(this).lessThan(from) +/** + * Checks if the current value is less than or equal to the provided value. + * + * @param from The value to compare against. + * @return An [Expression] representing the comparison expression. + */ infix fun Any.lessOrEqualThan(from: Any): Expression = left(this).lessOrEqualThan(from) +/** + * Applies the specified [OnFailure] behavior when evaluating the current [Expression] fails. + * + * @param use The behavior to be applied when evaluation fails. + * @return An [Expression] with the specified [OnFailure] behavior. + */ infix fun Expression.ifFail(use: OnFailure): Expression = Expression( left = this.left, operator = this.operator, right = this.right, onFailure = use, ) diff --git a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/MatcherBuilder.kt b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/MatcherBuilder.kt index 20ae26a..eee3547 100644 --- a/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/MatcherBuilder.kt +++ b/src/main/kotlin/com/rapatao/projects/ruleset/engine/types/builder/MatcherBuilder.kt @@ -2,16 +2,37 @@ package com.rapatao.projects.ruleset.engine.types.builder import com.rapatao.projects.ruleset.engine.types.Expression +/** + * The `MatcherBuilder` class provides static methods for building expressions using matchers. + */ object MatcherBuilder { + /** + * Creates an [Expression] that matches all provided matchers. + * + * @param matchers The matchers to be combined into a single expression. + * @return The created expression that matches all provided matchers. + */ fun allMatch(vararg matchers: Any): Expression = Expression( allMatch = matchers.map { it.asExpression() } ) + /** + * Creates an expression for verifying if any of the given matchers matches. + * + * @param matchers the matchers to be evaluated + * @return the expression representing the anyMatch operation + */ fun anyMatch(vararg matchers: Any) = Expression( anyMatch = matchers.map { it.asExpression() } ) + /** + * Creates an instance of [Expression] with [noneMatch] set to the provided [matchers]. + * + * @param matchers The matchers to check against. + * @return An instance of [Expression] with [noneMatch] set. + */ fun noneMatch(vararg matchers: Any) = Expression( noneMatch = matchers.map { it.asExpression() }, ) diff --git a/src/main/kotlin/com/rapatao/projects/ruleset/jackson/ExpressionMixin.kt b/src/main/kotlin/com/rapatao/projects/ruleset/jackson/ExpressionMixin.kt index 06307c3..98e3bdb 100644 --- a/src/main/kotlin/com/rapatao/projects/ruleset/jackson/ExpressionMixin.kt +++ b/src/main/kotlin/com/rapatao/projects/ruleset/jackson/ExpressionMixin.kt @@ -6,6 +6,12 @@ import com.fasterxml.jackson.annotation.JsonInclude import com.rapatao.projects.ruleset.engine.types.OnFailure import com.rapatao.projects.ruleset.engine.types.Operator +/** + * This interface represents a mixin for JSON serialization and deserialization of expressions. + * It provides methods for handling onFailure, operator, and validity of an expression. + * + * @JsonInclude(JsonInclude.Include.NON_DEFAULT) + */ @JsonInclude(JsonInclude.Include.NON_DEFAULT) interface ExpressionMixin {