Skip to content

Commit e4ea99c

Browse files
perf: Collect orgUnitGroups in RuleContextRequirements [DHIS2-21245]
1 parent dd9769c commit e4ea99c

5 files changed

Lines changed: 55 additions & 5 deletions

File tree

api/rule-engine.api

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,15 @@ public final class org/hisp/dhis/rules/api/ItemValueType : java/lang/Enum {
6565

6666
public final class org/hisp/dhis/rules/api/RuleContextRequirements {
6767
public static final field Companion Lorg/hisp/dhis/rules/api/RuleContextRequirements$Companion;
68-
public fun <init> (Z)V
68+
public fun <init> (ZLjava/util/Set;)V
69+
public synthetic fun <init> (ZLjava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
6970
public final fun component1 ()Z
70-
public final fun copy (Z)Lorg/hisp/dhis/rules/api/RuleContextRequirements;
71-
public static synthetic fun copy$default (Lorg/hisp/dhis/rules/api/RuleContextRequirements;ZILjava/lang/Object;)Lorg/hisp/dhis/rules/api/RuleContextRequirements;
71+
public final fun component2 ()Ljava/util/Set;
72+
public final fun copy (ZLjava/util/Set;)Lorg/hisp/dhis/rules/api/RuleContextRequirements;
73+
public static synthetic fun copy$default (Lorg/hisp/dhis/rules/api/RuleContextRequirements;ZLjava/util/Set;ILjava/lang/Object;)Lorg/hisp/dhis/rules/api/RuleContextRequirements;
7274
public fun equals (Ljava/lang/Object;)Z
7375
public final fun getNeedsAllEvents ()Z
76+
public final fun getOrgUnitGroups ()Ljava/util/Set;
7477
public fun hashCode ()I
7578
public fun toString ()Ljava/lang/String;
7679
}

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ apiCompatibility ="0.17.0"
77
kotlinxDatetime = "0.7.1"
88
kotlinJsWrappers = "1.0.0-pre.830"
99
slf4jApi = "1.7.36"
10-
expressionParser = "1.4.0"
10+
expressionParser = "1.4.1"
1111

1212
[libraries]
1313
kotlin-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }

src/commonMain/kotlin/org/hisp/dhis/rules/api/RuleContextRequirements.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package org.hisp.dhis.rules.api
22

3+
import kotlin.js.JsExport
4+
5+
@JsExport
36
data class RuleContextRequirements(
47
val needsAllEvents: Boolean,
8+
val orgUnitGroups: Set<String> = emptySet(),
59
) {
610
companion object {
711
val NONE = RuleContextRequirements(needsAllEvents = false)

src/commonMain/kotlin/org/hisp/dhis/rules/engine/RuleEngineAnalyzer.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ internal object RuleEngineAnalyzer {
3030
}
3131
}
3232

33+
val orgUnitGroups = mutableSetOf<String>()
34+
35+
for (rule in rules) {
36+
rule.conditionExpression.getOrNull()?.let { orgUnitGroups += it.collectInOrgUnitGroups() }
37+
for (action in rule.actions) {
38+
action.dataExpression.getOrNull()?.let { orgUnitGroups += it.collectInOrgUnitGroups() }
39+
}
40+
}
41+
3342
val byName = variables.associateBy { it.name }
3443
val needsAllEvents = envVars.any { it in MULTI_EVENT_ENV_VARS } ||
3544
referencedVarNames.any { name ->
@@ -39,6 +48,6 @@ internal object RuleEngineAnalyzer {
3948
v is RuleVariablePreviousEvent
4049
}
4150

42-
return RuleContextRequirements(needsAllEvents)
51+
return RuleContextRequirements(needsAllEvents, orgUnitGroups)
4352
}
4453
}

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,40 @@ class RuleEngineAnalyzerTest {
148148
assertFalse(RuleContextRequirements.NONE.needsAllEvents)
149149
}
150150

151+
// --- orgUnitGroups collection ---
152+
153+
@Test
154+
fun orgUnitGroupInConditionIsCollected() {
155+
val rules = listOf(rule("d2:inOrgUnitGroup('GroupA')"))
156+
val result = RuleEngineAnalyzer.analyzeContextRequirements(rules, emptyList())
157+
assertEquals(setOf("GroupA"), result.orgUnitGroups)
158+
}
159+
160+
@Test
161+
fun orgUnitGroupInActionDataIsCollected() {
162+
val rules = listOf(rule("true", "d2:inOrgUnitGroup('GroupB')"))
163+
val result = RuleEngineAnalyzer.analyzeContextRequirements(rules, emptyList())
164+
assertEquals(setOf("GroupB"), result.orgUnitGroups)
165+
}
166+
167+
@Test
168+
fun multipleOrgUnitGroupsAcrossRulesAreCollected() {
169+
val rules = listOf(
170+
rule("d2:inOrgUnitGroup('GroupA')"),
171+
rule("true", "d2:inOrgUnitGroup('GroupB')"),
172+
rule("d2:inOrgUnitGroup('GroupA') || d2:inOrgUnitGroup('GroupC')"),
173+
)
174+
val result = RuleEngineAnalyzer.analyzeContextRequirements(rules, emptyList())
175+
assertEquals(setOf("GroupA", "GroupB", "GroupC"), result.orgUnitGroups)
176+
}
177+
178+
@Test
179+
fun noOrgUnitGroupReturnsEmptySet() {
180+
val rules = listOf(rule("#{score} > 5"))
181+
val result = RuleEngineAnalyzer.analyzeContextRequirements(rules, emptyList())
182+
assertTrue(result.orgUnitGroups.isEmpty())
183+
}
184+
151185
// --- RuleEngine interface delegation ---
152186

153187
@Test

0 commit comments

Comments
 (0)