diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngine.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngine.kt deleted file mode 100644 index b1ff34fc..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngine.kt +++ /dev/null @@ -1,120 +0,0 @@ -package org.hisp.dhis.rules - -import org.hisp.dhis.lib.expression.Expression -import org.hisp.dhis.lib.expression.spi.IllegalExpressionException -import org.hisp.dhis.lib.expression.spi.ParseException -import org.hisp.dhis.lib.expression.spi.ValueType -import org.hisp.dhis.rules.models.* - -data class RuleEngine( - val executionContext: RuleEngineContext, - val events: List = emptyList(), - val enrollment: org.hisp.dhis.rules.models.RuleEnrollment? = null, - val triggerEnvironment: TriggerEnvironment? = TriggerEnvironment.SERVER) { - - fun evaluate(ruleEvent: RuleEvent): List { - return evaluate(ruleEvent, executionContext.rules) - } - - fun evaluate(ruleEvent: RuleEvent, rulesToEvaluate: List): List { - val valueMap = RuleVariableValueMapBuilder.target(ruleEvent) - .ruleVariables(executionContext.ruleVariables) - .ruleEnrollment(enrollment) - .triggerEnvironment(triggerEnvironment) - .ruleEvents(events) - .constantValueMap(executionContext.constantsValues) - .build() - return RuleEngineExecution(ruleEvent, null, rulesToEvaluate, valueMap, executionContext.supplementaryData).execute() - } - - fun evaluate(ruleEnrollment: org.hisp.dhis.rules.models.RuleEnrollment, - rulesToEvaluate: List): List { - val valueMap = RuleVariableValueMapBuilder.target(ruleEnrollment) - .ruleVariables(executionContext.ruleVariables) - .triggerEnvironment(triggerEnvironment) - .ruleEvents(events) - .constantValueMap(executionContext.constantsValues) - .build() - return RuleEngineExecution(null, ruleEnrollment, rulesToEvaluate, valueMap, executionContext.supplementaryData).execute() - } - - fun evaluate(): List { - val valueMap = RuleVariableValueMapBuilder.target() - .ruleVariables(executionContext.ruleVariables) - .ruleEnrollment(enrollment) - .triggerEnvironment(triggerEnvironment) - .ruleEvents(events) - .constantValueMap(executionContext.constantsValues) - .multipleBuild() - return RuleEngineMultipleExecution(executionContext.rules, valueMap, - executionContext.supplementaryData).execute() - } - - fun evaluate( ruleEnrollment: org.hisp.dhis.rules.models.RuleEnrollment): List { - return evaluate(ruleEnrollment, executionContext.rules) - } - - fun evaluate(expression: String): RuleValidationResult { - // Rule condition expression should be evaluated against Boolean - return getExpressionDescription(expression, Expression.Mode.RULE_ENGINE_CONDITION) - } - - fun evaluateDataFieldExpression(expression: String): RuleValidationResult { - // Rule action data field field should be evaluated against all i.e Boolean, String, Date and Numerical value - return getExpressionDescription(expression, Expression.Mode.RULE_ENGINE_ACTION) - } - - private fun getExpressionDescription(expression: String, mode: Expression.Mode): RuleValidationResult { - return try { - val validationMap: MutableMap = HashMap() - val dataItemStore = executionContext.dataItemStore - for ((key, value) in dataItemStore!!) { - validationMap[key] = value.valueType.toValueType() - } - Expression(expression, mode, false).validate(validationMap) - val displayNames: MutableMap = HashMap() - for ((key, value) in dataItemStore) { - displayNames[key] = value.displayName - } - val description = Expression(expression, mode, false).describe(displayNames) - RuleValidationResult(valid = true, description = description) - } catch (ex: IllegalExpressionException) { - RuleValidationResult( - valid = false, - exception = RuleEngineValidationException(ex), - errorMessage = ex.message - ) - } catch (ex: ParseException) { - RuleValidationResult( - valid = false, - exception = RuleEngineValidationException(ex), - errorMessage = ex.message - ) - } - } - - @Deprecated("use data copy") - class Builder internal constructor(private val ruleEngineContext: RuleEngineContext) { - private var ruleEvents: List = emptyList() - private var ruleEnrollment: org.hisp.dhis.rules.models.RuleEnrollment? = null - private var triggerEnvironment: TriggerEnvironment? = null - fun events(ruleEvents: List): Builder { - this.ruleEvents = ruleEvents - return this - } - - fun enrollment(ruleEnrollment: org.hisp.dhis.rules.models.RuleEnrollment): Builder { - this.ruleEnrollment = ruleEnrollment - return this - } - - fun triggerEnvironment(triggerEnvironment: TriggerEnvironment): Builder { - this.triggerEnvironment = triggerEnvironment - return this - } - - fun build(): RuleEngine { - return RuleEngine(ruleEngineContext, ruleEvents, ruleEnrollment, triggerEnvironment) - } - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineContext.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineContext.kt deleted file mode 100644 index 84226c90..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineContext.kt +++ /dev/null @@ -1,13 +0,0 @@ -package org.hisp.dhis.rules - -import org.hisp.dhis.rules.models.Rule -import org.hisp.dhis.rules.models.RuleVariable - -data class RuleEngineContext( - val rules: List, - val ruleVariables: List, - val supplementaryData: Map> = emptyMap(), - val constantsValues: Map = emptyMap(), - val ruleEngineIntent: RuleEngineIntent = RuleEngineIntent.EVALUATION, - val dataItemStore: Map = emptyMap() -) diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineExecution.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineExecution.kt deleted file mode 100644 index 808c74ca..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineExecution.kt +++ /dev/null @@ -1,28 +0,0 @@ -package org.hisp.dhis.rules - -import org.hisp.dhis.rules.models.* - - -internal data class RuleEngineExecution( - val event: RuleEvent?, - val enrollment: org.hisp.dhis.rules.models.RuleEnrollment?, - val rules: List, - val valueMap: MutableMap, - val supplementaryData: Map> -) { - fun execute(): List { - if (event != null) { - return RuleConditionEvaluator().getRuleEffects( - TrackerObjectType.EVENT, event.event, valueMap, - supplementaryData, rules - ) - } - if (enrollment != null) { - return RuleConditionEvaluator().getRuleEffects( - TrackerObjectType.ENROLLMENT, enrollment.enrollment, valueMap, - supplementaryData, rules - ) - } - throw IllegalStateException("event and enrollment were null") - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineFilter.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineFilter.kt deleted file mode 100644 index 74e25324..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineFilter.kt +++ /dev/null @@ -1,70 +0,0 @@ -package org.hisp.dhis.rules - -import org.hisp.dhis.rules.models.* - -/* -* Copyright (c) 2004-2021, University of Oslo -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* Neither the name of the HISP project nor the names of its contributors may -* be used to endorse or promote products derived from this software without -* specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - fun filterRules(rules: List, ruleEnrollment: org.hisp.dhis.rules.models.RuleEnrollment?): List { - val filteredRules: MutableList = mutableListOf() - for (rule in rules) { - val programStage: String? = rule.programStage - if (programStage.isNullOrEmpty()) { - val ruleActions = filterActionRules( - rule.actions, - AttributeType.TRACKED_ENTITY_ATTRIBUTE - ) - filteredRules.add(rule.copy(actions = ruleActions)) - } - } - return filteredRules - } - - fun filterRules(rules: List, ruleEvent: org.hisp.dhis.rules.models.RuleEvent): List { - val filteredRules: MutableList = mutableListOf() - for (rule in rules) { - val programStage: String? = rule.programStage - if (programStage.isNullOrEmpty() || programStage == ruleEvent.programStage) { - val ruleActions = filterActionRules( - rule.actions, - AttributeType.DATA_ELEMENT - ) - filteredRules.add(rule.copy(actions = ruleActions)) - } - } - return filteredRules - } - - private fun filterActionRules(ruleActions: List, attributeType: org.hisp.dhis.rules.models.AttributeType): List { - val filteredRuleActions: MutableList = mutableListOf() - for (ruleAction in ruleActions) { - if (ruleAction !is RuleActionAttribute || ruleAction.attributeType() == attributeType || ruleAction.attributeType() == org.hisp.dhis.rules.models.AttributeType.UNKNOWN) { - filteredRuleActions.add(ruleAction) - } - } - return filteredRuleActions - } diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineIntent.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineIntent.kt deleted file mode 100644 index 0086c653..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineIntent.kt +++ /dev/null @@ -1,36 +0,0 @@ -package org.hisp.dhis.rules -/* - * Copyright (c) 2004-2020, University of Oslo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the name of the HISP project nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @author Zubair Asghar - */ -enum class RuleEngineIntent { - EVALUATION, - DESCRIPTION -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineMultipleExecution.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineMultipleExecution.kt deleted file mode 100644 index 4dacc1ba..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleEngineMultipleExecution.kt +++ /dev/null @@ -1,42 +0,0 @@ -package org.hisp.dhis.rules - -import org.hisp.dhis.rules.models.Rule -import org.hisp.dhis.rules.models.RuleEffects -import org.hisp.dhis.rules.models.TrackerObjectType - -internal data class RuleEngineMultipleExecution( - val rules: List, - val ruleVariableValueMap: RuleVariableValueMap, - val supplementaryData: Map> -) { - fun execute(): List { - val ruleEffects: MutableList = ArrayList() - for ((enrollment, value) in ruleVariableValueMap - .enrollmentMap) { - val enrollmentRuleEffects = RuleConditionEvaluator() - .getEvaluatedAndErrorRuleEffects( - TrackerObjectType.ENROLLMENT, enrollment.enrollment, value, - supplementaryData, filterRules(rules, enrollment) - ) - ruleEffects.add( - RuleEffects( - TrackerObjectType.ENROLLMENT, enrollment.enrollment, - enrollmentRuleEffects - ) - ) - } - for ((event, value) in ruleVariableValueMap - .eventMap) { - ruleEffects.add( - RuleEffects( - TrackerObjectType.EVENT, event.event, - RuleConditionEvaluator().getEvaluatedAndErrorRuleEffects( - TrackerObjectType.EVENT, event.event, value, - supplementaryData, filterRules(rules, event) - ) - ) - ) - } - return ruleEffects - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleExpressionEvaluator.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/RuleExpressionEvaluator.kt deleted file mode 100644 index 98f430f9..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleExpressionEvaluator.kt +++ /dev/null @@ -1,6 +0,0 @@ -package org.hisp.dhis.rules - -fun interface RuleExpressionEvaluator { - - fun evaluate(expression: String): String -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/DataItem.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/api/DataItem.kt similarity index 87% rename from src/commonMain/kotlin/org/hisp/dhis/rules/DataItem.kt rename to src/commonMain/kotlin/org/hisp/dhis/rules/api/DataItem.kt index 601ceea5..3c54ded0 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/DataItem.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/api/DataItem.kt @@ -1,4 +1,4 @@ -package org.hisp.dhis.rules +package org.hisp.dhis.rules.api /** * Class is place holder for program rule variable, Constant and program environment variable display name and type. diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/api/EnvironmentVariables.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/api/EnvironmentVariables.kt new file mode 100644 index 00000000..165dac95 --- /dev/null +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/api/EnvironmentVariables.kt @@ -0,0 +1,27 @@ +package org.hisp.dhis.rules.api + +import org.hisp.dhis.rules.utils.RuleEngineUtils + +object EnvironmentVariables { + val ENV_VARIABLES = mapOf( + Pair(RuleEngineUtils.ENV_VAR_COMPLETED_DATE, ItemValueType.DATE), + Pair(RuleEngineUtils.ENV_VAR_CURRENT_DATE, ItemValueType.DATE), + Pair(RuleEngineUtils.ENV_VAR_EVENT_DATE, ItemValueType.DATE), + Pair(RuleEngineUtils.ENV_VAR_INCIDENT_DATE, ItemValueType.DATE), + Pair(RuleEngineUtils.ENV_VAR_ENROLLMENT_DATE, ItemValueType.DATE), + Pair(RuleEngineUtils.ENV_VAR_DUE_DATE, ItemValueType.DATE), + Pair(RuleEngineUtils.ENV_VAR_EVENT_COUNT, ItemValueType.NUMBER), + Pair(RuleEngineUtils.ENV_VAR_TEI_COUNT, ItemValueType.NUMBER), + Pair(RuleEngineUtils.ENV_VAR_ENROLLMENT_COUNT, ItemValueType.NUMBER), + Pair(RuleEngineUtils.ENV_VAR_EVENT_ID, ItemValueType.NUMBER), + Pair(RuleEngineUtils.ENV_VAR_PROGRAM_STAGE_ID, ItemValueType.NUMBER), + Pair(RuleEngineUtils.ENV_VAR_ENROLLMENT_ID, ItemValueType.NUMBER), + Pair(RuleEngineUtils.ENV_VAR_ENROLLMENT_STATUS, ItemValueType.TEXT), + Pair(RuleEngineUtils.ENV_VAR_EVENT_STATUS, ItemValueType.TEXT), + Pair(RuleEngineUtils.ENV_VAR_OU, ItemValueType.TEXT), + Pair(RuleEngineUtils.ENV_VAR_OU_CODE, ItemValueType.TEXT), + Pair(RuleEngineUtils.ENV_VAR_ENVIRONMENT, ItemValueType.TEXT), + Pair(RuleEngineUtils.ENV_VAR_PROGRAM_NAME, ItemValueType.TEXT), + Pair(RuleEngineUtils.ENV_VAR_PROGRAM_STAGE_NAME, ItemValueType.TEXT) + ) +} \ No newline at end of file diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/ItemValueType.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/api/ItemValueType.kt similarity index 98% rename from src/commonMain/kotlin/org/hisp/dhis/rules/ItemValueType.kt rename to src/commonMain/kotlin/org/hisp/dhis/rules/api/ItemValueType.kt index c1a75343..f9fdf634 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/ItemValueType.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/api/ItemValueType.kt @@ -1,4 +1,4 @@ -package org.hisp.dhis.rules +package org.hisp.dhis.rules.api import org.hisp.dhis.lib.expression.spi.ValueType diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/api/RuleEngine.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/api/RuleEngine.kt new file mode 100644 index 00000000..d2e5852a --- /dev/null +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/api/RuleEngine.kt @@ -0,0 +1,20 @@ +package org.hisp.dhis.rules.api + +import org.hisp.dhis.rules.engine.DefaultRuleEngine +import org.hisp.dhis.rules.models.* +import kotlin.jvm.JvmStatic + +interface RuleEngine { + fun validate(expression: String, dataItemStore: Map): RuleValidationResult + fun validateDataFieldExpression(expression: String, dataItemStore: Map): RuleValidationResult + fun evaluateAll(enrollmentTarget: RuleEnrollment?, eventsTarget: List, executionContext: RuleEngineContext): List + fun evaluate(target: RuleEnrollment, ruleEvents: List, executionContext: RuleEngineContext): List + fun evaluate(target: RuleEvent, ruleEnrollment: RuleEnrollment?, ruleEvents: List, executionContext: RuleEngineContext): List + + companion object { + @JvmStatic + fun getInstance(): RuleEngine { + return DefaultRuleEngine() + } + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/api/RuleEngineContext.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/api/RuleEngineContext.kt new file mode 100644 index 00000000..e28895cd --- /dev/null +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/api/RuleEngineContext.kt @@ -0,0 +1,13 @@ +package org.hisp.dhis.rules.api + +import org.hisp.dhis.rules.models.Rule +import org.hisp.dhis.rules.models.RuleEnrollment +import org.hisp.dhis.rules.models.RuleEvent +import org.hisp.dhis.rules.models.RuleVariable + +data class RuleEngineContext( + val rules: List, + val ruleVariables: List = emptyList(), + val supplementaryData: Map> = emptyMap(), + val constantsValues: Map = emptyMap() +) diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/engine/DefaultRuleEngine.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/DefaultRuleEngine.kt new file mode 100644 index 00000000..bf2d4f7b --- /dev/null +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/DefaultRuleEngine.kt @@ -0,0 +1,83 @@ +package org.hisp.dhis.rules.engine + +import org.hisp.dhis.lib.expression.Expression +import org.hisp.dhis.lib.expression.spi.IllegalExpressionException +import org.hisp.dhis.lib.expression.spi.ParseException +import org.hisp.dhis.lib.expression.spi.ValueType +import org.hisp.dhis.rules.api.DataItem +import org.hisp.dhis.rules.api.RuleEngine +import org.hisp.dhis.rules.api.RuleEngineContext +import org.hisp.dhis.rules.models.* + +internal class DefaultRuleEngine: RuleEngine { + override fun evaluate(target: RuleEvent, ruleEnrollment: RuleEnrollment?, ruleEvents: List, executionContext: RuleEngineContext): List { + val valueMap = RuleVariableValueMapBuilder.target(target) + .ruleVariables(executionContext.ruleVariables) + .ruleEnrollment(ruleEnrollment) + .triggerEnvironment(TriggerEnvironment.SERVER) + .ruleEvents(ruleEvents) + .constantValueMap(executionContext.constantsValues) + .build() + return RuleConditionEvaluator().getRuleEffects( + TrackerObjectType.EVENT, target.event, valueMap, + executionContext.supplementaryData, executionContext.rules + ) + } + + override fun evaluate(target: RuleEnrollment, ruleEvents: List, executionContext: RuleEngineContext): List { + val valueMap = RuleVariableValueMapBuilder.target(target) + .ruleVariables(executionContext.ruleVariables) + .triggerEnvironment(TriggerEnvironment.SERVER) + .ruleEvents(ruleEvents) + .constantValueMap(executionContext.constantsValues) + .build() + return RuleConditionEvaluator().getRuleEffects( + TrackerObjectType.ENROLLMENT, target.enrollment, valueMap, + executionContext.supplementaryData, executionContext.rules + ) + } + + override fun evaluateAll(enrollmentTarget: RuleEnrollment?, eventsTarget: List, executionContext: RuleEngineContext): List { + val valueMap = RuleVariableValueMapBuilder.target() + .ruleVariables(executionContext.ruleVariables) + .ruleEnrollment(enrollmentTarget) + .triggerEnvironment(TriggerEnvironment.SERVER) + .ruleEvents(eventsTarget) + .constantValueMap(executionContext.constantsValues) + .multipleBuild() + return RuleEngineMultipleExecution().execute(executionContext.rules, valueMap, + executionContext.supplementaryData) + } + + override fun validate(expression: String, dataItemStore: Map): RuleValidationResult { + // Rule condition expression should be evaluated against Boolean + return getExpressionDescription(expression, Expression.Mode.RULE_ENGINE_CONDITION, dataItemStore) + } + + override fun validateDataFieldExpression(expression: String, dataItemStore: Map): RuleValidationResult { + // Rule action data field should be evaluated against all i.e Boolean, String, Date and Numerical value + return getExpressionDescription(expression, Expression.Mode.RULE_ENGINE_ACTION, dataItemStore) + } + + private fun getExpressionDescription(expression: String, mode: Expression.Mode, dataItemStore: Map): RuleValidationResult { + return try { + val validationMap: Map = dataItemStore.mapValues { e -> e.value.valueType.toValueType() } + Expression(expression, mode, false).validate(validationMap) + val displayNames: Map = dataItemStore.mapValues { e -> e.value.displayName } + val description = Expression(expression, mode, false).describe(displayNames) + RuleValidationResult(valid = true, description = description) + } catch (ex: IllegalExpressionException) { + RuleValidationResult( + valid = false, + exception = RuleEngineValidationException(ex), + errorMessage = ex.message + ) + } catch (ex: ParseException) { + RuleValidationResult( + valid = false, + exception = RuleEngineValidationException(ex), + errorMessage = ex.message + ) + } + } +} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleConditionEvaluator.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleConditionEvaluator.kt similarity index 77% rename from src/commonMain/kotlin/org/hisp/dhis/rules/RuleConditionEvaluator.kt rename to src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleConditionEvaluator.kt index 1547ed39..4b6eaf4f 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleConditionEvaluator.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleConditionEvaluator.kt @@ -1,14 +1,17 @@ -package org.hisp.dhis.rules +package org.hisp.dhis.rules.engine import org.hisp.dhis.lib.expression.Expression import org.hisp.dhis.lib.expression.spi.ExpressionData import org.hisp.dhis.lib.expression.spi.IllegalExpressionException +import org.hisp.dhis.rules.createLogger +import org.hisp.dhis.rules.models.Rule import org.hisp.dhis.rules.models.* -import org.hisp.dhis.rules.models.RuleEvaluationResult.Companion.errorRule -import org.hisp.dhis.rules.models.RuleEvaluationResult.Companion.evaluatedResult -import org.hisp.dhis.rules.models.RuleEvaluationResult.Companion.notEvaluatedResult +import org.hisp.dhis.rules.engine.RuleEvaluationResult.Companion.errorRule +import org.hisp.dhis.rules.engine.RuleEvaluationResult.Companion.evaluatedResult +import org.hisp.dhis.rules.engine.RuleEvaluationResult.Companion.notEvaluatedResult +import org.hisp.dhis.rules.utils.unwrapVariableName -class RuleConditionEvaluator { +internal class RuleConditionEvaluator { fun getEvaluatedAndErrorRuleEffects( targetType: TrackerObjectType, targetUid: String, @@ -16,11 +19,9 @@ class RuleConditionEvaluator { supplementaryData: Map>, rules: List ): List { - val ruleEffects: MutableList = ArrayList() - for ((_, ruleEffects1) in getRuleEvaluationResults(targetType, targetUid, valueMap, supplementaryData, rules)) { - ruleEffects.addAll(ruleEffects1) - } - return ruleEffects + val ruleEvaluationResults = getRuleEvaluationResults(targetType, targetUid, valueMap, supplementaryData, rules) + return ruleEvaluationResults + .flatMap { result -> result.ruleEffects } } fun getRuleEffects( @@ -30,19 +31,16 @@ class RuleConditionEvaluator { supplementaryData: Map>, rules: List ): List { - val ruleEffects: MutableList = ArrayList() - for ((_, ruleEffects1, _, error) in getRuleEvaluationResults( + val ruleEvaluationResults = getRuleEvaluationResults( targetType, targetUid, valueMap, supplementaryData, rules - )) { - if (!error) { - ruleEffects.addAll(ruleEffects1) - } - } - return ruleEffects + ) + return ruleEvaluationResults + .filter { result -> !result.error } + .flatMap { result -> result.ruleEffects } } fun getRuleEvaluationResults( @@ -67,12 +65,11 @@ class RuleConditionEvaluator { try { //Check if action is assigning value to calculated variable if (isAssignToCalculatedValue(action)) { - val (_, content, _, data) = action as RuleActionAssign updateValueMap( - unwrapVariableName(content), + unwrapVariableName(action.content()!!), RuleVariableValue( RuleValueType.TEXT, - process(data, valueMap, supplementaryData, Expression.Mode.RULE_ENGINE_ACTION), + process(action.data, valueMap, supplementaryData, Expression.Mode.RULE_ENGINE_ACTION), listOf(), null ), @@ -105,7 +102,7 @@ class RuleConditionEvaluator { } private fun addRuleErrorResult( - rule: Rule, ruleAction: org.hisp.dhis.rules.models.RuleAction?, e: Exception, targetType: TrackerObjectType, + rule: Rule, ruleAction: RuleAction?, e: Exception, targetType: TrackerObjectType, targetUid: String, ruleEvaluationResults: MutableList ) { val errorMessage: String @@ -140,10 +137,7 @@ class RuleConditionEvaluator { condition: String?, valueMap: Map, supplementaryData: Map>, mode: Expression.Mode ): String { - if (condition==null) { - return "" - } - if (condition.isEmpty()) { + if (condition==null || condition.isEmpty()) { return "" } val expression = Expression(condition, mode, false) @@ -168,8 +162,8 @@ class RuleConditionEvaluator { } else result } - private fun isAssignToCalculatedValue(ruleAction: org.hisp.dhis.rules.models.RuleAction): Boolean { - return ruleAction is RuleActionAssign && ruleAction.field.isEmpty() + private fun isAssignToCalculatedValue(ruleAction: RuleAction): Boolean { + return ruleAction.type == "ASSIGN" && ruleAction.field() == null } private fun updateValueMap( @@ -182,23 +176,24 @@ class RuleConditionEvaluator { private fun create( rule: Rule, - ruleAction: org.hisp.dhis.rules.models.RuleAction, + ruleAction: RuleAction, valueMap: MutableMap, supplementaryData: Map> ): RuleEffect { - if (ruleAction is RuleActionAssign) { - val data = process(ruleAction.data(), valueMap, supplementaryData, Expression.Mode.RULE_ENGINE_ACTION) - updateValueMap(ruleAction.field, RuleVariableValue(RuleValueType.TEXT, data, listOf(), null), valueMap) - return if (data == null || data.isEmpty()) { + if (ruleAction.type == "ASSIGN") { + val data = process(ruleAction.data, valueMap, supplementaryData, Expression.Mode.RULE_ENGINE_ACTION) + updateValueMap(ruleAction.field()!!, RuleVariableValue(RuleValueType.TEXT, data, listOf(), null), valueMap) + return if (data.isEmpty()) { RuleEffect(rule.uid, ruleAction, null) } else { RuleEffect(rule.uid, ruleAction, data) } } + val data = if (!ruleAction.data.isNullOrEmpty()) process(ruleAction.data, valueMap, supplementaryData, Expression.Mode.RULE_ENGINE_ACTION) else "" return RuleEffect( rule.uid, ruleAction, - process(ruleAction.data(), valueMap, supplementaryData, Expression.Mode.RULE_ENGINE_ACTION) + data ) } diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleEngineMultipleExecution.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleEngineMultipleExecution.kt new file mode 100644 index 00000000..efcfbf03 --- /dev/null +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleEngineMultipleExecution.kt @@ -0,0 +1,76 @@ +package org.hisp.dhis.rules.engine + +import org.hisp.dhis.rules.models.Rule +import org.hisp.dhis.rules.models.* + +internal class RuleEngineMultipleExecution { + fun execute(rules: List, ruleVariableValueMap: RuleVariableValueMap, + supplementaryData: Map>): List { + val ruleEffects: MutableList = ArrayList() + for ((enrollment, value) in ruleVariableValueMap.enrollmentMap) { + val enrollmentRuleEffects = RuleConditionEvaluator() + .getEvaluatedAndErrorRuleEffects( + TrackerObjectType.ENROLLMENT, enrollment.enrollment, value, + supplementaryData, filterRules(rules) + ) + ruleEffects.add( + RuleEffects( + TrackerObjectType.ENROLLMENT, enrollment.enrollment, + enrollmentRuleEffects + ) + ) + } + for ((event, value) in ruleVariableValueMap.eventMap) { + ruleEffects.add( + RuleEffects( + TrackerObjectType.EVENT, event.event, + RuleConditionEvaluator().getEvaluatedAndErrorRuleEffects( + TrackerObjectType.EVENT, event.event, value, + supplementaryData, filterRules(rules, event) + ) + ) + ) + } + return ruleEffects + } + + private fun filterRules(rules: List): List { + val filteredRules: MutableList = mutableListOf() + for (rule in rules) { + val programStage: String? = rule.programStage + if (programStage.isNullOrEmpty()) { + val ruleActions = filterActionRules( + rule.actions, + AttributeType.TRACKED_ENTITY_ATTRIBUTE + ) + filteredRules.add(rule.copy(actions = ruleActions)) + } + } + return filteredRules + } + + private fun filterRules(rules: List, ruleEvent: RuleEvent): List { + val filteredRules: MutableList = mutableListOf() + for (rule in rules) { + val programStage: String? = rule.programStage + if (programStage.isNullOrEmpty() || programStage == ruleEvent.programStage) { + val ruleActions = filterActionRules( + rule.actions, + AttributeType.DATA_ELEMENT + ) + filteredRules.add(rule.copy(actions = ruleActions)) + } + } + return filteredRules + } + + private fun filterActionRules(ruleActions: List, attributeType: AttributeType): List { + val filteredRuleActions: MutableList = mutableListOf() + for (ruleAction in ruleActions) { + if (ruleAction.attributeType() == null || ruleAction.attributeType() == attributeType.name || ruleAction.attributeType() == AttributeType.UNKNOWN.name) { + filteredRuleActions.add(ruleAction) + } + } + return filteredRuleActions + } +} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleEvaluationResult.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleEvaluationResult.kt similarity index 75% rename from src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleEvaluationResult.kt rename to src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleEvaluationResult.kt index 9535f1fe..b20385a0 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleEvaluationResult.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleEvaluationResult.kt @@ -1,6 +1,10 @@ -package org.hisp.dhis.rules.models +package org.hisp.dhis.rules.engine -data class RuleEvaluationResult( +import org.hisp.dhis.rules.models.Rule +import org.hisp.dhis.rules.models.RuleAction +import org.hisp.dhis.rules.models.RuleEffect + +internal data class RuleEvaluationResult( val rule: Rule, val ruleEffects: List, val evaluatedAs: Boolean, @@ -19,7 +23,7 @@ data class RuleEvaluationResult( val effects = listOf( RuleEffect( rule.uid, - RuleActionError(errorMessage), + RuleAction(errorMessage, "ERROR"), errorMessage ) ) diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleVariableValue.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleVariableValue.kt similarity index 62% rename from src/commonMain/kotlin/org/hisp/dhis/rules/RuleVariableValue.kt rename to src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleVariableValue.kt index 197f9350..ee6c7c2e 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleVariableValue.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleVariableValue.kt @@ -1,11 +1,11 @@ -package org.hisp.dhis.rules +package org.hisp.dhis.rules.engine import org.hisp.dhis.lib.expression.spi.ValueType import org.hisp.dhis.lib.expression.spi.VariableValue import org.hisp.dhis.rules.models.RuleValueType data class RuleVariableValue( - val type: org.hisp.dhis.rules.models.RuleValueType, + val type: RuleValueType, val value: String? = null, val candidates: List = listOf(), val eventDate: String? = null @@ -16,9 +16,9 @@ data class RuleVariableValue( private fun valueType(): ValueType { return when (type) { - org.hisp.dhis.rules.models.RuleValueType.DATE -> ValueType.DATE - org.hisp.dhis.rules.models.RuleValueType.NUMERIC -> ValueType.NUMBER - org.hisp.dhis.rules.models.RuleValueType.BOOLEAN -> ValueType.BOOLEAN + RuleValueType.DATE -> ValueType.DATE + RuleValueType.NUMERIC -> ValueType.NUMBER + RuleValueType.BOOLEAN -> ValueType.BOOLEAN else -> ValueType.STRING } } diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleVariableValueMap.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleVariableValueMap.kt similarity index 74% rename from src/commonMain/kotlin/org/hisp/dhis/rules/RuleVariableValueMap.kt rename to src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleVariableValueMap.kt index 5d96852c..e83fe523 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleVariableValueMap.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleVariableValueMap.kt @@ -1,8 +1,8 @@ -package org.hisp.dhis.rules +package org.hisp.dhis.rules.engine import org.hisp.dhis.rules.models.RuleEvent -data class RuleVariableValueMap( +internal data class RuleVariableValueMap( val enrollmentMap: Map>, val eventMap: Map> ) \ No newline at end of file diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleVariableValueMapBuilder.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleVariableValueMapBuilder.kt similarity index 82% rename from src/commonMain/kotlin/org/hisp/dhis/rules/RuleVariableValueMapBuilder.kt rename to src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleVariableValueMapBuilder.kt index e0058d7b..636d75da 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/RuleVariableValueMapBuilder.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleVariableValueMapBuilder.kt @@ -1,29 +1,23 @@ -package org.hisp.dhis.rules +package org.hisp.dhis.rules.engine import kotlinx.datetime.LocalDate +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toLocalDateTime import org.hisp.dhis.rules.models.* import org.hisp.dhis.rules.utils.RuleEngineUtils +import org.hisp.dhis.rules.utils.currentDate import kotlin.collections.ArrayList import kotlin.collections.HashMap -class RuleVariableValueMapBuilder private constructor() { - private val allConstantValues: MutableMap - - private val ruleVariables: MutableList - - private val ruleEvents: MutableList - var ruleEnrollment: org.hisp.dhis.rules.models.RuleEnrollment? = null +internal class RuleVariableValueMapBuilder private constructor() { + val allConstantValues: MutableMap = HashMap() + val ruleVariables: MutableList = ArrayList() + val ruleEvents: MutableList = ArrayList() + var ruleEnrollment: RuleEnrollment? = null var ruleEvent: RuleEvent? = null private var triggerEnvironment: TriggerEnvironment? = null - init { - // collections used for construction of resulting variable value map - ruleVariables = ArrayList() - ruleEvents = ArrayList() - allConstantValues = HashMap() - } - - private constructor(ruleEnrollment: org.hisp.dhis.rules.models.RuleEnrollment) : this() { + private constructor(ruleEnrollment: RuleEnrollment) : this() { // enrollment is the target this.ruleEnrollment = ruleEnrollment @@ -34,13 +28,13 @@ class RuleVariableValueMapBuilder private constructor() { // event is the target this.ruleEvent = ruleEvent } - - fun ruleVariables(ruleVariables: List?): RuleVariableValueMapBuilder { - this.ruleVariables.addAll(ruleVariables!!) + + fun ruleVariables(ruleVariables: List): RuleVariableValueMapBuilder { + this.ruleVariables.addAll(ruleVariables) return this } - fun ruleEnrollment(ruleEnrollment: org.hisp.dhis.rules.models.RuleEnrollment?): RuleVariableValueMapBuilder { + fun ruleEnrollment(ruleEnrollment: RuleEnrollment?): RuleVariableValueMapBuilder { check(this.ruleEnrollment == null) { "It seems that enrollment has been set as target " + "already. It can't be used as a part of execution context." @@ -64,8 +58,8 @@ class RuleVariableValueMapBuilder private constructor() { return this } - fun constantValueMap(constantValues: Map?): RuleVariableValueMapBuilder { - allConstantValues.putAll(constantValues!!) + fun constantValueMap(constantValues: Map): RuleVariableValueMapBuilder { + allConstantValues.putAll(constantValues) return this } @@ -85,7 +79,7 @@ class RuleVariableValueMapBuilder private constructor() { } fun multipleBuild(): RuleVariableValueMap { - val enrollmentMap: MutableMap> = HashMap() + val enrollmentMap: MutableMap> = HashMap() if (ruleEnrollment != null) { enrollmentMap[ruleEnrollment!!] = build() } @@ -111,8 +105,8 @@ class RuleVariableValueMapBuilder private constructor() { return false } - private fun buildCurrentEventValues(): Map { - val currentEventValues: MutableMap = HashMap() + private fun buildCurrentEventValues(): Map { + val currentEventValues: MutableMap = HashMap() if (ruleEvent != null) { for (index in ruleEvent!!.dataValues.indices) { val ruleDataValue = ruleEvent!!.dataValues[index] @@ -122,8 +116,8 @@ class RuleVariableValueMapBuilder private constructor() { return currentEventValues } - private fun buildCurrentEnrollmentValues(): Map { - val currentEnrollmentValues: MutableMap = HashMap() + private fun buildCurrentEnrollmentValues(): Map { + val currentEnrollmentValues: MutableMap = HashMap() if (ruleEnrollment != null) { val ruleAttributeValues = ruleEnrollment!!.attributeValues for (attributeValue in ruleAttributeValues) { @@ -133,8 +127,8 @@ class RuleVariableValueMapBuilder private constructor() { return currentEnrollmentValues } - private fun buildAllEventValues(): Map> { - val allEventsValues: MutableMap> = HashMap() + private fun buildAllEventValues(): Map> { + val allEventsValues: MutableMap> = HashMap() val events: MutableList = ArrayList(ruleEvents) if (ruleEvent != null) { // target event should be among the list of all @@ -153,11 +147,11 @@ class RuleVariableValueMapBuilder private constructor() { // push new list if it is not there for the given data element if (!allEventsValues.containsKey(ruleDataValue.dataElement)) { - allEventsValues[ruleDataValue.dataElement] = ArrayList(events.size) //NOPMD + allEventsValues[ruleDataValue.dataElement] = ArrayList(events.size) } // append data value to the list - allEventsValues[ruleDataValue.dataElement]!!.add(ruleDataValue) + allEventsValues[ruleDataValue.dataElement]?.add(ruleDataValue) } } return allEventsValues @@ -189,7 +183,7 @@ class RuleVariableValueMapBuilder private constructor() { currentDate.toString() ) } - if (!ruleEvents.isEmpty()) { + if (ruleEvents.isNotEmpty()) { valueMap[RuleEngineUtils.ENV_VAR_EVENT_COUNT] = RuleVariableValue( RuleValueType.NUMERIC, ruleEvents.size.toString(), listOf(ruleEvents.size.toString()), currentDate.toString() @@ -232,10 +226,9 @@ class RuleVariableValueMapBuilder private constructor() { RuleVariableValue(RuleValueType.TEXT, organisationUnitCode) } if (ruleEvent != null) { - val eventDate = ruleEvent!!.eventDate + val eventDate = ruleEvent!!.eventDate.toLocalDateTime(TimeZone.currentSystemDefault()).date.toString() valueMap[RuleEngineUtils.ENV_VAR_EVENT_DATE] = RuleVariableValue( - RuleValueType.TEXT, eventDate.toString(), - listOf(eventDate.toString()), currentDate.toString() + RuleValueType.TEXT, eventDate, listOf(eventDate), currentDate.toString() ) if (ruleEvent!!.dueDate != null) { val dueDate = ruleEvent!!.dueDate @@ -295,14 +288,14 @@ class RuleVariableValueMapBuilder private constructor() { val currentEventValues = buildCurrentEventValues() for (ruleVariable in ruleVariables) { valueMap.putAll( - ruleVariable.createValues(this, allEventValues, currentEnrollmentValues, currentEventValues) + ruleVariable.createValues(ruleEvent, allEventValues, currentEnrollmentValues, currentEventValues) ) } return valueMap } companion object { - fun target(ruleEnrollment: org.hisp.dhis.rules.models.RuleEnrollment): RuleVariableValueMapBuilder { + fun target(ruleEnrollment: RuleEnrollment): RuleVariableValueMapBuilder { return RuleVariableValueMapBuilder(ruleEnrollment) } diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/Option.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/Option.kt similarity index 70% rename from src/commonMain/kotlin/org/hisp/dhis/rules/Option.kt rename to src/commonMain/kotlin/org/hisp/dhis/rules/models/Option.kt index 7e5a9576..51eae686 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/Option.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/models/Option.kt @@ -1,4 +1,4 @@ -package org.hisp.dhis.rules +package org.hisp.dhis.rules.models /** * @author rajazubair diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleAction.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleAction.kt index 70b7a858..f85a01f4 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleAction.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleAction.kt @@ -1,5 +1,19 @@ package org.hisp.dhis.rules.models -fun interface RuleAction { - fun data(): String? -} +data class RuleAction( + val data: String?, + val type: String, + val values: Map = emptyMap() +){ + fun content():String? { + return values["content"] + } + + fun field():String? { + return values["field"] + } + + fun attributeType():String? { + return values["attributeType"] + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionAssign.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionAssign.kt deleted file mode 100644 index 4a869628..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionAssign.kt +++ /dev/null @@ -1,41 +0,0 @@ -package org.hisp.dhis.rules.models - -data class RuleActionAssign( - val field: String, - val content: String, - val attributeType2: AttributeType, - val data2: String -) : RuleActionAttribute { - companion object { - fun create( - content: String?, - data: String, field: String?, attributeType: AttributeType? - ): RuleActionAssign { - require(!(content == null && field == null)) { - "Either content or field " + - "parameters must be not null." - } - return RuleActionAssign( - field ?: "", content ?: "", attributeType ?: AttributeType.UNKNOWN, data - - ) - } - - fun create(content: String?, data: String, field: String?): RuleActionAssign { - return create( - content, - data, - field, - AttributeType.UNKNOWN - ) - } - } - - override fun attributeType(): AttributeType { - return attributeType2 - } - - override fun data(): String { - return data2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionAttribute.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionAttribute.kt deleted file mode 100644 index 7a289a2e..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionAttribute.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.hisp.dhis.rules.models - -interface RuleActionAttribute : RuleAction { - fun attributeType(): AttributeType -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionCreateEvent.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionCreateEvent.kt deleted file mode 100644 index 9e55b931..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionCreateEvent.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.hisp.dhis.rules.models - -data class RuleActionCreateEvent( - val programStage: String, - val content: String = "", - val data2: String = "" -) : RuleAction { - override fun data(): String { - return data2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionError.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionError.kt deleted file mode 100644 index 010ed2e5..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionError.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.hisp.dhis.rules.models - -data class RuleActionError(val data2: String) : RuleAction { - override fun data(): String { - return data2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideField.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideField.kt deleted file mode 100644 index 78bc57b3..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideField.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.hisp.dhis.rules.models - -/** - * @param data - * @param attributeType - * @param content a message to show to user - * when a target field is hidden. - * @param field uid of the target field to hide. - * It can be both dataElement and trackedEntityAttribute. - */ -data class RuleActionHideField( - val field: String, - val content: String = "", - val attributeType2: AttributeType = AttributeType.UNKNOWN, - val data2: String = "" -) : RuleActionAttribute { - override fun data(): String { - return data2 - } - - override fun attributeType(): AttributeType { - return attributeType2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideOption.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideOption.kt deleted file mode 100644 index a91ec6ef..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideOption.kt +++ /dev/null @@ -1,25 +0,0 @@ -package org.hisp.dhis.rules.models - -/** - * @param data - * @param attributeType - * @param content a message to show to user - * when a target option is hidden. - * @param option uid of the target option to hide. - * @param field uid of the target field to hide. - */ -data class RuleActionHideOption( - val field: String, - val option: String, - val content: String = "", - val attributeType2: AttributeType = AttributeType.UNKNOWN, - val data2: String = "" -) : RuleActionAttribute { - override fun data(): String { - return data2 - } - - override fun attributeType(): AttributeType { - return attributeType2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideOptionGroup.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideOptionGroup.kt deleted file mode 100644 index f7e40f1f..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideOptionGroup.kt +++ /dev/null @@ -1,25 +0,0 @@ -package org.hisp.dhis.rules.models - -/** - * @param data - * @param attributeType - * @param content a message to show to user - * when a target option is hidden. - * @param optionGroup uid of the target option group to hide. - * @param field uid of the target field to hide options. - */ -data class RuleActionHideOptionGroup( - val field: String, - val optionGroup: String, - val content: String = "", - val attributeType2: AttributeType = AttributeType.UNKNOWN, - val data2: String = "" -) : RuleActionAttribute { - override fun data(): String { - return data2 - } - - override fun attributeType(): AttributeType { - return attributeType2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideProgramStage.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideProgramStage.kt deleted file mode 100644 index 2b38d7e8..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideProgramStage.kt +++ /dev/null @@ -1,10 +0,0 @@ -package org.hisp.dhis.rules.models - -data class RuleActionHideProgramStage( - val programStage: String, - val data2: String = "" -) : RuleAction { - override fun data(): String { - return data2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideSection.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideSection.kt deleted file mode 100644 index 701ef23f..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionHideSection.kt +++ /dev/null @@ -1,10 +0,0 @@ -package org.hisp.dhis.rules.models - -data class RuleActionHideSection( - val programStageSection: String, - val data2: String = "" -) : RuleAction { - override fun data(): String { - return data2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionMessage.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionMessage.kt deleted file mode 100644 index 018c4823..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionMessage.kt +++ /dev/null @@ -1,43 +0,0 @@ -package org.hisp.dhis.rules.models - -data class RuleActionMessage( - val type: Type, - val field: String = "", - val content: String = "", - val attributeType2: AttributeType = AttributeType.UNKNOWN, - val data2: String = "" -) : RuleActionAttribute { - enum class Type { - WARNING_ON_COMPILATION, - ERROR_ON_COMPILATION, - SHOW_WARNING, - SHOW_ERROR - } - - companion object { - /* - On Completion - */ - fun create( - content: String?, - data: String?, field: String?, attributeType: AttributeType?, type: Type - ): RuleActionMessage { - require(!(content == null && data == null && field == null)) { - "Content, data and field" + - " must not be null at the same time" - } - return RuleActionMessage( - type, field ?: "", content ?: "", - attributeType ?: AttributeType.UNKNOWN, data ?: "" - ) - } - } - - override fun attributeType(): AttributeType { - return attributeType2 - } - - override fun data(): String { - return data2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionScheduleMessage.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionScheduleMessage.kt deleted file mode 100644 index 76dea60a..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionScheduleMessage.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.hisp.dhis.rules.models - -/* -* Copyright (c) 2004-2018, University of Oslo -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* Neither the name of the HISP project nor the names of its contributors may -* be used to endorse or promote products derived from this software without -* specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -data class RuleActionScheduleMessage( - val notification: String, - val data2: String? -) : RuleAction { - override fun data(): String? { - return data2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionSendMessage.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionSendMessage.kt deleted file mode 100644 index 061813a5..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionSendMessage.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.hisp.dhis.rules.models - -/* -* Copyright (c) 2004-2017, University of Oslo -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* Neither the name of the HISP project nor the names of its contributors may -* be used to endorse or promote products derived from this software without -* specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -data class RuleActionSendMessage( - val notification: String, - val data2: String? -) : RuleAction { - override fun data(): String? { - return data2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionSetMandatoryField.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionSetMandatoryField.kt deleted file mode 100644 index 677e7d0c..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionSetMandatoryField.kt +++ /dev/null @@ -1,15 +0,0 @@ -package org.hisp.dhis.rules.models - -data class RuleActionSetMandatoryField( - val field: String, - val attributeType2: AttributeType = AttributeType.UNKNOWN, - val data2: String = "" -) : RuleActionAttribute { - override fun data(): String { - return data2 - } - - override fun attributeType(): AttributeType { - return attributeType2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionShowOptionGroup.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionShowOptionGroup.kt deleted file mode 100644 index b06d780c..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionShowOptionGroup.kt +++ /dev/null @@ -1,25 +0,0 @@ -package org.hisp.dhis.rules.models - -/** - * @param data - * @param attributeType - * @param content a message to show to user - * when a option group is shown. - * @param optionGroup uid of the target option group to show. - * @param field uid of the field of option group to show. - */ -data class RuleActionShowOptionGroup( - val field: String, - val optionGroup: String, - val content: String = "", - val attributeType2: AttributeType = AttributeType.UNKNOWN, - val data2: String = "" -) : RuleActionAttribute { - override fun data(): String { - return data2 - } - - override fun attributeType(): AttributeType { - return attributeType2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionText.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionText.kt deleted file mode 100644 index de9676ee..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionText.kt +++ /dev/null @@ -1,57 +0,0 @@ -package org.hisp.dhis.rules.models - -/** - * - * @param data dynamic data which can be potentially - * generated by the RuleEngine. - * @param content a static content which will - * be shown to the user. - * @param location location of where the result of this - * action must be rendered: can be either 'feedback' - * or 'program indicator' widget. - */ -data class RuleActionText( - val type: Type, - val data2: String, - val content: String, - val location: String -) : RuleAction { - enum class Type { - DISPLAYTEXT, - DISPLAYKEYVALUEPAIR - } - - companion object { - const val LOCATION_FEEDBACK_WIDGET = "feedback" - const val LOCATION_INDICATOR_WIDGET = "indicators" - fun createForFeedback( - type: Type, - content: String?, data: String? - ): RuleActionText { - require(!(content == null && data == null)) { "Both content and data must not be null" } - return RuleActionText( - type, - data ?: "", - content ?: "", - LOCATION_FEEDBACK_WIDGET - ) - } - - fun createForIndicators( - type: Type, - content: String?, data: String? - ): RuleActionText { - require(!(content == null && data == null)) { "Both content and data must not be null" } - return RuleActionText( - type, - data ?: "", - content ?: "", - LOCATION_INDICATOR_WIDGET - ) - } - } - - override fun data(): String { - return data2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionUnsupported.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionUnsupported.kt deleted file mode 100644 index 8a0ae1d2..00000000 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleActionUnsupported.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.hisp.dhis.rules.models - -/** - * @param data - * @param content a message to show to user - * when an actionType is not supported - * @param actionValueType name of the unsupported action. - */ - -data class RuleActionUnsupported( - val content: String, - val actionValueType: String, - val data2: String -) : RuleAction { - override fun data(): String { - return data2 - } -} diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleDataValue.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleDataValue.kt index 9fe395ac..d5969f77 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleDataValue.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleDataValue.kt @@ -1,9 +1,9 @@ package org.hisp.dhis.rules.models -import kotlinx.datetime.LocalDate +import kotlinx.datetime.Instant data class RuleDataValue( - val eventDate: LocalDate, + val eventDate: Instant, val programStage: String, val dataElement: String, val value: String diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleEnrollment.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleEnrollment.kt index 0f592ed0..6976a637 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleEnrollment.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleEnrollment.kt @@ -7,10 +7,10 @@ data class RuleEnrollment( val programName: String, val incidentDate: LocalDate, val enrollmentDate: LocalDate, - val status: org.hisp.dhis.rules.models.RuleEnrollment.Status, + val status: Status, val organisationUnit: String, val organisationUnitCode: String, - val attributeValues: List + val attributeValues: List ) { enum class Status { ACTIVE, diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleEvent.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleEvent.kt index 20613171..3dfc934a 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleEvent.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleEvent.kt @@ -1,5 +1,6 @@ package org.hisp.dhis.rules.models +import kotlinx.datetime.Instant import kotlinx.datetime.LocalDate data class RuleEvent( @@ -7,7 +8,7 @@ data class RuleEvent( val programStage: String, val programStageName: String, val status: Status, - val eventDate: LocalDate, + val eventDate: Instant, val dueDate: LocalDate?, val completedDate: LocalDate?, val organisationUnit: String, diff --git a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleVariable.kt b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleVariable.kt index 301eef6c..9013a37c 100644 --- a/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleVariable.kt +++ b/src/commonMain/kotlin/org/hisp/dhis/rules/models/RuleVariable.kt @@ -1,13 +1,12 @@ package org.hisp.dhis.rules.models -import org.hisp.dhis.rules.Option -import org.hisp.dhis.rules.RuleVariableValue -import org.hisp.dhis.rules.RuleVariableValueMapBuilder +import org.hisp.dhis.rules.engine.RuleVariableValue +import org.hisp.dhis.rules.engine.RuleVariableValueMapBuilder interface RuleVariable { - fun options(): List