11package org.hisp.dhis.rules.engine
22
3+ import org.hisp.dhis.lib.expression.Expression
34import org.hisp.dhis.rules.api.RuleContextRequirements
45import org.hisp.dhis.rules.models.Rule
56import org.hisp.dhis.rules.models.RuleVariable
@@ -14,7 +15,6 @@ import org.hisp.dhis.rules.utils.RuleEngineUtils.ENV_VAR_ENROLLMENT_DATE
1415import org.hisp.dhis.rules.utils.RuleEngineUtils.ENV_VAR_ENROLLMENT_ID
1516import org.hisp.dhis.rules.utils.RuleEngineUtils.ENV_VAR_ENROLLMENT_STATUS
1617import org.hisp.dhis.rules.utils.RuleEngineUtils.ENV_VAR_EVENT_COUNT
17- import org.hisp.dhis.rules.utils.RuleEngineUtils.ENV_VAR_INCIDENT_DATE
1818import org.hisp.dhis.rules.utils.RuleEngineUtils.ENV_VAR_TEI_COUNT
1919
2020internal object RuleEngineAnalyzer {
@@ -24,7 +24,6 @@ internal object RuleEngineAnalyzer {
2424 ENV_VAR_ENROLLMENT_DATE ,
2525 ENV_VAR_ENROLLMENT_ID ,
2626 ENV_VAR_ENROLLMENT_STATUS ,
27- ENV_VAR_INCIDENT_DATE ,
2827 ENV_VAR_TEI_COUNT ,
2928 )
3029
@@ -34,47 +33,62 @@ internal object RuleEngineAnalyzer {
3433 ): RuleContextRequirements {
3534 val byName = variables.associateBy { it.name }
3635 val hasNonCalculatedVariables = variables.any { it !is RuleVariableCalculatedValue }
36+ val acc = RequirementsAccumulator (byName)
3737
38+ for (rule in rules) {
39+ if (acc.isComplete) break
40+ for (expr in rule.expressions()) {
41+ acc.processEnvVars(expr)
42+ if (hasNonCalculatedVariables) acc.processVarNames(expr)
43+ acc.processOrgUnitGroups(expr)
44+ }
45+ }
46+
47+ return acc.toRequirements()
48+ }
49+
50+ private fun Rule.expressions (): List <Expression > = buildList {
51+ conditionExpression.getOrNull()?.let { add(it) }
52+ actions.forEach { action -> action.dataExpression.getOrNull()?.let { add(it) } }
53+ }
54+
55+ private class RequirementsAccumulator (private val byName : Map <String , RuleVariable >) {
3856 var needsAllEvents = false
3957 var needsEnrollment = false
4058 var needsDataValues = false
4159 var needsAttributes = false
4260 var needsOrgUnitGroups = false
4361
44- for (rule in rules) {
45- if (needsAllEvents && needsEnrollment && needsDataValues && needsAttributes && needsOrgUnitGroups) break
62+ val isComplete get() = needsAllEvents && needsEnrollment && needsDataValues && needsAttributes && needsOrgUnitGroups
4663
47- val expressions = buildList {
48- rule.conditionExpression.getOrNull()?.let { add(it) }
49- rule.actions.forEach { action -> action.dataExpression.getOrNull()?.let { add(it) } }
64+ fun processEnvVars (expr : Expression ) {
65+ if (needsAllEvents && needsEnrollment) return
66+ for (envVar in expr.collectProgramVariablesNames()) {
67+ needsAllEvents = needsAllEvents || envVar in MULTI_EVENT_ENV_VARS
68+ needsEnrollment = needsEnrollment || envVar in ENROLLMENT_ENV_VARS
69+ if (needsAllEvents && needsEnrollment) break
5070 }
71+ }
5172
52- for (expr in expressions) {
53- if (! needsAllEvents || ! needsEnrollment) {
54- for (envVar in expr.collectProgramVariablesNames()) {
55- needsAllEvents = needsAllEvents || envVar in MULTI_EVENT_ENV_VARS
56- needsEnrollment = needsEnrollment || envVar in ENROLLMENT_ENV_VARS
57- if (needsAllEvents && needsEnrollment) break
58- }
59- }
60-
61- if (hasNonCalculatedVariables && (! needsAllEvents || ! needsDataValues || ! needsAttributes)) {
62- for (name in expr.collectProgramRuleVariableNames()) {
63- val v = byName[name]
64- val isMultiEvent = v is RuleVariableNewestEvent || v is RuleVariableNewestStageEvent || v is RuleVariablePreviousEvent
65- needsAllEvents = needsAllEvents || isMultiEvent
66- needsDataValues = needsDataValues || isMultiEvent || v is RuleVariableCurrentEvent
67- needsAttributes = needsAttributes || v is RuleVariableAttribute
68- needsEnrollment = needsEnrollment || needsAttributes
69- if (needsAllEvents && needsDataValues && needsAttributes) break
70- }
71- }
72-
73-
74- needsOrgUnitGroups = needsOrgUnitGroups || expr.collectInOrgUnitGroups().isNotEmpty()
73+ fun processVarNames (expr : Expression ) {
74+ if (needsAllEvents && needsDataValues && needsAttributes) return
75+ for (name in expr.collectProgramRuleVariableNames()) {
76+ val v = byName[name]
77+ val isMultiEvent = v is RuleVariableNewestEvent || v is RuleVariableNewestStageEvent || v is RuleVariablePreviousEvent
78+ needsAllEvents = needsAllEvents || isMultiEvent
79+ needsDataValues = needsDataValues || isMultiEvent || v is RuleVariableCurrentEvent
80+ needsAttributes = needsAttributes || v is RuleVariableAttribute
81+ needsEnrollment = needsEnrollment || needsAttributes
82+ if (needsAllEvents && needsDataValues && needsAttributes) break
7583 }
7684 }
7785
78- return RuleContextRequirements (needsAllEvents, needsEnrollment, needsDataValues, needsAttributes, needsOrgUnitGroups)
86+ fun processOrgUnitGroups (expr : Expression ) {
87+ if (! needsOrgUnitGroups) needsOrgUnitGroups = expr.collectInOrgUnitGroups().isNotEmpty()
88+ }
89+
90+ fun toRequirements () = RuleContextRequirements (
91+ needsAllEvents, needsEnrollment, needsDataValues, needsAttributes, needsOrgUnitGroups,
92+ )
7993 }
8094}
0 commit comments