Skip to content

Commit d4eceaa

Browse files
Code review fixes
1 parent ab7bc2f commit d4eceaa

2 files changed

Lines changed: 45 additions & 36 deletions

File tree

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.hisp.dhis.rules.engine
22

3+
import org.hisp.dhis.lib.expression.Expression
34
import org.hisp.dhis.rules.api.RuleContextRequirements
45
import org.hisp.dhis.rules.models.Rule
56
import org.hisp.dhis.rules.models.RuleVariable
@@ -14,7 +15,6 @@ import org.hisp.dhis.rules.utils.RuleEngineUtils.ENV_VAR_ENROLLMENT_DATE
1415
import org.hisp.dhis.rules.utils.RuleEngineUtils.ENV_VAR_ENROLLMENT_ID
1516
import org.hisp.dhis.rules.utils.RuleEngineUtils.ENV_VAR_ENROLLMENT_STATUS
1617
import org.hisp.dhis.rules.utils.RuleEngineUtils.ENV_VAR_EVENT_COUNT
17-
import org.hisp.dhis.rules.utils.RuleEngineUtils.ENV_VAR_INCIDENT_DATE
1818
import org.hisp.dhis.rules.utils.RuleEngineUtils.ENV_VAR_TEI_COUNT
1919

2020
internal 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
}

src/commonTest/kotlin/org/hisp/dhis/rules/RuleEngineAnalyzerTest.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,6 @@ class RuleEngineAnalyzerTest {
220220
assertTrue(analyze(listOf(rule("V{enrollment_status} == 'ACTIVE'"))).needsEnrollment)
221221
}
222222

223-
@Test
224-
fun incidentDateEnvVarTriggersNeedsEnrollment() {
225-
assertTrue(analyze(listOf(rule("V{incident_date} > '2020-01-01'"))).needsEnrollment)
226-
}
227-
228223
@Test
229224
fun teiCountEnvVarTriggersNeedsEnrollment() {
230225
assertTrue(analyze(listOf(rule("V{tei_count} > 0"))).needsEnrollment)

0 commit comments

Comments
 (0)