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
@@ -24,7 +25,6 @@ internal object RuleEngineAnalyzer {
2425 ENV_VAR_ENROLLMENT_DATE ,
2526 ENV_VAR_ENROLLMENT_ID ,
2627 ENV_VAR_ENROLLMENT_STATUS ,
27- ENV_VAR_INCIDENT_DATE ,
2828 ENV_VAR_TEI_COUNT ,
2929 )
3030
@@ -34,47 +34,62 @@ internal object RuleEngineAnalyzer {
3434 ): RuleContextRequirements {
3535 val byName = variables.associateBy { it.name }
3636 val hasNonCalculatedVariables = variables.any { it !is RuleVariableCalculatedValue }
37+ val acc = RequirementsAccumulator (byName)
3738
39+ for (rule in rules) {
40+ if (acc.isComplete) break
41+ for (expr in rule.expressions()) {
42+ acc.processEnvVars(expr)
43+ if (hasNonCalculatedVariables) acc.processVarNames(expr)
44+ acc.processOrgUnitGroups(expr)
45+ }
46+ }
47+
48+ return acc.toRequirements()
49+ }
50+
51+ private fun Rule.expressions (): List <Expression > = buildList {
52+ conditionExpression.getOrNull()?.let { add(it) }
53+ actions.forEach { action -> action.dataExpression.getOrNull()?.let { add(it) } }
54+ }
55+
56+ private class RequirementsAccumulator (private val byName : Map <String , RuleVariable >) {
3857 var needsAllEvents = false
3958 var needsEnrollment = false
4059 var needsDataValues = false
4160 var needsAttributes = false
4261 var needsOrgUnitGroups = false
4362
44- for (rule in rules) {
45- if (needsAllEvents && needsEnrollment && needsDataValues && needsAttributes && needsOrgUnitGroups) break
63+ val isComplete get() = needsAllEvents && needsEnrollment && needsDataValues && needsAttributes && needsOrgUnitGroups
4664
47- val expressions = buildList {
48- rule.conditionExpression.getOrNull()?.let { add(it) }
49- rule.actions.forEach { action -> action.dataExpression.getOrNull()?.let { add(it) } }
65+ fun processEnvVars (expr : Expression ) {
66+ if (needsAllEvents && needsEnrollment) return
67+ for (envVar in expr.collectProgramVariablesNames()) {
68+ if (! needsAllEvents) needsAllEvents = envVar in MULTI_EVENT_ENV_VARS
69+ if (! needsEnrollment) needsEnrollment = envVar in ENROLLMENT_ENV_VARS
70+ if (needsAllEvents && needsEnrollment) break
5071 }
72+ }
5173
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()
74+ fun processVarNames (expr : Expression ) {
75+ if (needsAllEvents && needsDataValues && needsAttributes) return
76+ for (name in expr.collectProgramRuleVariableNames()) {
77+ val v = byName[name]
78+ val isMultiEvent = v is RuleVariableNewestEvent || v is RuleVariableNewestStageEvent || v is RuleVariablePreviousEvent
79+ if (! needsAllEvents) needsAllEvents = isMultiEvent
80+ if (! needsDataValues) needsDataValues = isMultiEvent || v is RuleVariableCurrentEvent
81+ if (! needsAttributes) needsAttributes = v is RuleVariableAttribute
82+ if (! needsEnrollment) needsEnrollment = needsAttributes
83+ if (needsAllEvents && needsDataValues && needsAttributes) break
7584 }
7685 }
7786
78- return RuleContextRequirements (needsAllEvents, needsEnrollment, needsDataValues, needsAttributes, needsOrgUnitGroups)
87+ fun processOrgUnitGroups (expr : Expression ) {
88+ if (! needsOrgUnitGroups) needsOrgUnitGroups = expr.collectInOrgUnitGroups().isNotEmpty()
89+ }
90+
91+ fun toRequirements () = RuleContextRequirements (
92+ needsAllEvents, needsEnrollment, needsDataValues, needsAttributes, needsOrgUnitGroups,
93+ )
7994 }
8095}
0 commit comments