Conditional occurrences and existence

One of the long-standing requirements for archetypes is to enable a kind of constraint that allows certain data items to be made mandatory or prohibited based on the value of another data item. Two common examples are often cited:

  • if gender is male, prohibit any items (e.g. previous pregnancies) that are female only.
  • if tobacco use /= none, tobacco use details is required.

Currently, the way to express this kind of constraint is with an expression in the rule section, of the following form

/data[id2]/items[id3]/value[id18] /= [at17] implies exists /data[id2]/items[id8]

-- substance use status /= 'never used' implies existence of use details CLUSTER

Such expressions may be considered somewhat obscure since they have to be separately evaluated to determine the full validity of the data. This implies the existence of an expression processor to fully evaluate data against an archetype. 

An alternative approach is being looked at by the Activity Based Design (ABD) group at Intermountain Healthcare, whereby dependency conditions such as this are expressed inline. The ABD group has its own syntax and constructs for this, which are not directly replicatable in ADL, but the general approach appears worth considering from the point of view of clarity. To take the above example, one way to express it, with an augmented ADL syntax could be:

definition
	EVALUATION[id1] matches {	-- Substance Use Summary
		data matches {
			ITEM_TREE[id2] matches {
				items cardinality matches {1..*; unordered} matches {
					ELEMENT[id6] occurrences matches {0..1} matches {...}	-- Substance
					ELEMENT[id3] occurrences matches {0..1} matches {	-- Usage Status
						value matches {
							DV_CODED_TEXT[id18] matches {
								defining_code matches {[ac1]}		-- Usage Status
							}
						}
					}
					CLUSTER[id8] -- Consumption summary
						occurrences matches 										-- ********
							(/data[id2]/items[id3]/value[id18] /= [at17]) {1..*}    -- at17 is 'never used'
							{0..*} 													-- default is 0..* occurrences
					matches {
						items matches {
							ELEMENT[id9] occurrences matches {0..1} matches {	-- Form
								value matches {
									DV_TEXT[id19] 
								}
							}
							ELEMENT[id16] occurrences matches {0..1} matches {...}	-- Method of use
							ELEMENT[id10] occurrences matches {0..1} matches {...}	-- Date commenced
							ELEMENT[id11] occurrences matches {0..1} matches {...}	-- Age commenced
							ELEMENT[id12] occurrences matches {0..1} matches {...}	-- Date ceased
							ELEMENT[id13] occurrences matches {0..1} matches {...}	-- Age ceased
							ELEMENT[id14] occurrences matches {0..1} matches {...}	-- Comment
						}
					}
					allow_archetype CLUSTER[id15] matches {	-- Cessation attempts
						include
							archetype_id/value matches {/openEHR-EHR-CLUSTER\.cessation_attempts\.v1/}
					}
				}
			}
		}
	}

The new constraint is shown on the starred line. Here, alternative occurrences constraints are listed either with a 'guard' condition in parentheses, or else a default constraint (the final one).

This same scheme could also be used for the existence constraint. A slightly more general form would allow more than one guarded constraint depending on different values of another node, prior to the default.

The potential advantage of such an approach is that it ties the occurrences of a subtree to the values of its determining data item from elsewhere in the archetype. The disadvantage is a) somewhat ugly ADL and b) it complicates the AOM, since 'occurrences' is currently a simple attribute of type MULTIPLICITY_INTERVAL in C_OBJECT.

A related alternative may be to revert to stating an additional constraint in the rules section, but in the same way as above, i.e.:

definition
	EVALUATION[id1] matches {	-- Substance Use Summary
		data matches {
			ITEM_TREE[id2] matches {
				items cardinality matches {1..*; unordered} matches {
					ELEMENT[id6] occurrences matches {0..1} matches {...}	-- Substance
					ELEMENT[id3] occurrences matches {0..1} matches {...}	-- Usage Status
					CLUSTER[id8] occurrences matches {0..*} matches {-- Consumption summary
						items matches {
							ELEMENT[id9] occurrences matches {0..1} matches {...}	-- Form
							ELEMENT[id16] occurrences matches {0..1} matches {...}	-- Method of use
							ELEMENT[id10] occurrences matches {0..1} matches {...}	-- Date commenced
							ELEMENT[id11] occurrences matches {0..1} matches {...}	-- Age commenced
							ELEMENT[id12] occurrences matches {0..1} matches {...}	-- Date ceased
							ELEMENT[id13] occurrences matches {0..1} matches {...}	-- Age ceased
							ELEMENT[id14] occurrences matches {0..1} matches {...}	-- Comment
						}
					}
					allow_archetype CLUSTER[id15] matches {...}
				}
			}
		}
	}
 
rules
	/data[id2]/items[id8] 
		occurrences matches
				(/data[id2]/items[id3]/value[id18] /= [at17]) {1..*}    -- at17 is 'never used'
			{0..*} 													-- default is 0..* occurrences

This approach preserves the original simplicity of the ADL/AOM structure, and treats the tighter constraint as a rule that is attached to the /data[id2]/items[id8]  (consumption summary) path, rather than being just a rule in a set of rules. The advantages here are that changes to the AOM are in the rules section rather than in C_OBJECT. A disadvantage is that it would be in theory possible to write contradicting constraints, which require more validation complexity to detect.