• No results found

Constraints on Enumerated Types

In document Archetype Definition Language ADL 2 (Page 57-143)

4.5 Constraints on Primitive Types

4.5.10 Constraints on Enumerated Types

Enumeration types in the reference model are assumed to have the semantics defined in UML and mainstream programming languages, i.e. to be a distinct type based on a primitive type, normally Integer or String. Each such type consists of a set of values from the domain of its underlying type,

1. http://www.ihtsdo.org/

thus, a set of Integer, String or other primitive values. Each of these values is assumed to be named in the manner of a symbolic constant. Although stricly speaking UML doesn’t require an enumerated type to be based on an underlying primitive type, programming languages do, hence the assumption here that values from the domain of such a type are involved.

In ADL, constraints on enumerated types are represented by constraints on the underlying primitive values. The following example shows 2 constraints on an attribute of the type PROPORTION_KIND

from the openEHR Reference Model.

ITEM_TREE[id4] { items {

ELEMENT[id5] occurrences {0..1} matches {-- test enum 1 value {

DV_PROPORTION[id6] {

numerator {|0.0..1.0|; 0.0}

type {1} -- pk_unitary }

} }

ELEMENT[id7] {-- test enum 2 value {

DV_PROPORTION[id8] {

numerator {|0.0..1.0|; 0.0}

type {2, 3} -- pk_percent, pk_fraction }

} } } }

PROPORTION_KIND is defined as {pk_ratio = 0; pk_unitary = 1; pk_percent = 2;

pk_fraction = 3; pk_integer_fraction = 4}. Modelling tools are relied on to visualise enumer-ation constraints in a suitable way, by inferring the type based on inspection of the reference model on which the archetype is based.

Various coded syntax rules have been defined for the cADL syntax, for use by parser and compiler authors. These can be found on at the GitHub location

https://github.com/openEHR/adl-resources/blob/master/messages/ADL/adl_syntax_errors.txt. The state of this file at the issue of this document is as follows.

["SUNK"] = <"Syntax error (unknown cause)">

["SARID"] = <"Syntax error in artefact identification clause; expecting archetype id (format = model_issuer-package-class.concept.version)">

["SASID"] = <"Syntax error in 'specialise' clause; expecting parent archetype id (model_issuer-ref_model-model_class.concept.version)">

["SACO"] = <"Syntax error in 'concept' clause; expecting TERM_CODE reference">

["SALA"] = <"Syntax error in language section">

["SALAN"] = <"Syntax error no language section found">

["SADS"] = <"Syntax error in description section">

["SADF"] = <"Syntax error in definition section">

["SAIV"] = <"Syntax error in invariant section">

["SAON"] = <"Syntax error in terminology section">

["SAAN"] = <"Syntax error in annotations section">

["SDSF"] = <"Syntax error: differential syntax not allowed in top-level archetype">

["SDINV"] = <"Syntax error: invalid ODIN section; error: $1">

["SCCOG"] = <"Syntax error: expecting a new node definition, primitive node definition, 'use' path, or 'archetype' reference">

["SUAID"] = <"Syntax error: expecting [archetype_id] in use_archetype statement">

["SUAIDI"] = <"Syntax error: invalid archetype id $1">

["SOCCF"] = <"Syntax error: expecting an 'occurrences expression', e.g. 'occurrences matches {n..m}'">

["SUNPA"] = <"Syntax error: expecting absolute path in use_node statement">

["SCOAT"] = <"Syntax error: expecting attribute definition(s)">

["SUAS"] = <"Syntax error: error after 'use_archetype' keyword; expecting Object node definition">

["SCAS"] = <"Syntax error: expecting a 'any' node, 'leaf' node, or new node definition">

["SINVS"] = <"Syntax error: illegal invariant expression at identifier $1">

["SEXPT"] = <"Syntax error: expecting absolute path after exists keyword">

["SEXLSG"] = <"Syntax error: existence single value must be 0 or 1">

["SEXLU1"] = <"Syntax error: existence upper limit must be 0 or 1 when lower limit is 0">

["SEXLU2"] = <"Syntax error: existence upper limit must be 1 when lower limit is 1">

["SEXLMG"] = <"Syntax error: existence must be one of 0..0, 0..1, or 1..1">

["SCIAV"] = <"Syntax error: invalid assumed value; must be an integer">

["SCDUAV"] = <"Syntax error: invalid assumed value; must be an ISO8601 duration">

["SCSAV"] = <"Syntax error: invalid assumed value; must be a string">

["SCBAV"] = <"Syntax error: invalid assumed value; must be a 'True' or 'False'">

["SCOAV"] = <"Syntax error: invalid assumed value; must be an ordinal integer value">

["SCDPT"] = <"Syntax error: invalid date constraint pattern '$1'; allowed patterns: $2">

["SCTPT"] = <"Syntax error: invalid time constraint pattern '$1'; allowed patterns: $2">

["SCDTPT"] = <"Syntax error: invalid date/time constraint pattern '$1';

allowed patterns: $2">

["SCDUPT"] = <"Syntax error: invalid duration constraint pattern '$1'; legal pattern: P[Y|y][M|m][W|w][D|d][T[H|h][M|m][S|s]] or P[W|w]

[/duration_interval]">

["SCSRE"] = <"Syntax error: regular expression compile error '$1' is not a valid regular expression">

["STCCP"] = <"Syntax error: invalid term code constraint pattern '$1': $2">

["STCDC"] = <"Syntax error: duplicate code(s) found in code list">

["STCAC"] = <"Syntax error: assumed value code $1 not found in code list">

["STCNT"] = <"Syntax error: terminology not specified">

5 Assertions

5.1 Overview

This section describes the assertion sub-language of archetypes. Assertions are used in archetype

“slot” clauses in the cADL definition section, and in the rules section. The following simple assertion in the rules section of an archetype says that the speed in kilometres of some node is related to the speed-in-miles by a factor of 1.6:

validity: /speed[id2]/kilometres[id14]/magnitude = /speed[id4]/miles[id14]/magnitude * 1.6

5.1.1 Requirements

Assertions are needed in archetypes to express rules in two locations in an archetype. In an archetype slot, assertions can be stated to control what archetypes are allowed in the slot, as shown in the fol-lowing example:

CLUSTER[id3] occurrences matches {0..1} matches {-- Detail items cardinality matches {0..*; unordered} matches {

allow_archetype CLUSTER[id9] occurrences matches {0..1} matches { include

archetype_id/value matches {/openEHR-EHR-CLUSTER.exam-.+\.v1/}

} } }

In the above, the statement following the include keyword expresses a condition on the value found at the path archetype_id/value, using the familiar ADL matches operator, and a regular expression on archetype identifiers. Most slot statements are of this kind, with some requiring slightly more com-plex expressions. See section 4.3.10 on page 38 for more details.

The main requirement for assertions in archetypes is for expressing rules that cannot be expressed uding the standard cADL syntax. Types of rules include:

constraints involving more than one node in an archetype, such as a rule stating that the sum of the five 0-2 value scores in an Apgar test (heartrate, breathing, muscle tone, reflex, col-our) correspond to the Apgar total, recorded in a sixth node;

rules involving predefined variables such as ‘current date’;

rules involving query results from a data or knowledge context, allowing values such as

‘patient date of birth’ to be referenced.

The semantic requirements are for expressions including arithmetic, boolean, and relational opera-tors, some functions, quantifier operaopera-tors, a notion of operator precedence, parentheses, constant val-ues, and certain kinds of variables. However, there is no requirement for procedural semantics, type declarations or many of the other complexities of full-blown programming languages.

5.1.2 Design Basis

The archetype assertion language is a small language of its own. Formally it is a reduced first-order predicate logic language with various operators. It has similarities with OMG’s OCL (Object Con-straint Language) syntax, and is also similar to the assertion syntax which has been used in the Object-Z [14] and Eiffel [12] languages and tools for over a decade (see Sowa [15], Hein [8], Kilov &

Ross [9] for an explanation of predicate logic in information modelling). None of these languages has been used directly, for reasons including:

OCL has a complex type system, and includes some undecidable procedural semantics;

none have adequate variable referencing mechanisms, such as to paths and external queries;

they are too powerful, and would introduce unnecessary complexity into archetypes and templates.

There are also similarities with other languages developed in the health arena for expressing ‘medical logic’ (Arden), guidelines (GLIF and many others) and decision support (GELLO and many others).

These languages were not directly used either, for reasons including:

none have a path referencing mechanism;

some are too procedural (Arden, GLIF);

current versions of some of these languages have been made specific to the HL7v3 RIM, a particular model of health information designed for message representation (GLIF 3.x, GELLO);

all in their published form are too powerful for the needs identified here.

The design approach used here was to create a small concrete syntax allowing for a core subset of first-order predicate logic, which could easily be parsed into a typical parse-tree form, defined in the openEHR Archetype Object Model. Many different variations on syntax elements are possible (as evidenced by the many formal logic syntaxes used in mathematics and computing theory); the ele-ments used here were chosen for ease of expression using normal kebyoard characters and intuitive-ness.

5.2 Keywords

The syntax of the invariant section is a subset of first-order predicate logic. In it, the following key-words can be used:

exists, for_all,

and, or, xor, not, implies

true, false

Symbol equivalents for some of the above are given in the following table.

Textual Rendering

Symbolic

Rendering Meaning

matches, is_in  Set membership, “p is in P”

exists  Existential quantifier, “there exists ...”

for_all  Universal quantifier, “for all x...”

implies  Material implication, “p implies q”, or “if p then q”

and  Logical conjunction, “p and q”

or  Logical disjunction, “p or q”

xor  Exclusive or, “only one of p or q”

not, ~  Negation, “not p”

5.3 Typing

The assertion language is fully typed. All operators, variables and constants have either assumed or declared type signatures.

5.4 Operators

Assertion expressions can include arithmetic, relational and boolean operators, plus the existential and universal quantifiers.

5.4.1 Arithmetic Operators

The supported arithmetic operators are as follows:

addition: + subtraction: -multiplication: * division: / exponent: ^

modulo division: % -- remainder after integer division

5.4.2 Equality Operators

The supported equality operators are as follows:

equality: = inequality: !=

The semantics of these operators are of value comparison.

5.4.3 Relational Operators

The supported relational operators are as follows:

less than: <

less than or equal: <=

greater than: >

greater than or equal: >=

The semantics of these operators are of value comparison on entities of Comparable types (see openEHR Support IM, Assumed Types section). All generate a Boolean result.

5.4.4 Boolean Operators

The supported boolean operators are as follows:

not: not and: and xor: xor

implies: implies

set membership: matches, is_in

The boolean operators also have symbolic equivalents shown earlier. All boolean operators take Boolean operands and generate a Boolean result. The not operator can be applied as a prefix operator to all operators returning a boolean result.

5.4.5 Quantifiers

The two standard logical quantifier operators are supported:

existential quantifier: exists universal quantifier: for_all

These operators also have the usual symbolic equivalents shown earlier. The exists operator can be used on an variable, including paths referring to a node or value within an archetype. The for_all

operator can be applied to sets and lists, such as referred to by a path to a multiply-valued attribute.

5.4.6 Functions

The following functions are supported:

sum (x, y, ....): equivalent to x + y + ....

mean (x, y, ...): the mean (average) value of x, y, ...

max (x, y, ...): the maximum value among x, y, ...

min (x, y, ...): the minimum value among x, y, ...

All of the above functions have the signature func(Real, ...):Real, but will also perform as though having the signature func(Integer, ...):Integer, due to automatic numeric type promo-tion/demotion rules.

Other functions may be added in the future.

5.5 Operands

Operands in an assertion expression are typed and are of four kinds, as described in the following sub-sections.

5.5.1 Constants

Constant values are of any primitive type defined in the openEHR Support IM Assumed Types, and expressed according in the ODIN syntax (see the ODIN specification), i.e.:

Character, e.g. ‘x’;

String, e.g. “this is a string”;

Boolean, e.g. True, False;

Integer, e.g. 5;

Real, e.g. 5.2;

ISO8601_DATE, e.g. 2004-08-12;

ISO8601_TIME, e.g. 12:00:59;

ISO8601_DATE_TIME, e.g. 2004-08-12T12:00:59;

ISO8601_DURATION, e.g. P39W;

URI, e.g. http://en.wikipedia.org/wiki/Everest;

coded term, e.g. [snomed_ct::2004950];

Intervals of any numeric type, according to ODIN syntax e.g. |70..130|;

List of any primitive type, e.g. “string1”, “string2”, “string3”;

5.5.2 Object References

A reference to an object in data, including a leaf value, is expressed using an archetype path. All such paths are absolute (i.e. contain a leading ‘/’) and are understood to be with respect to the root of the current archetype. References to archetype nodes have the type defined at the relevant point in the underlying reference model. Examples include:

/data[id2]/items[id3]/value[id35]/value -- Date of initial onset; type ISO8601_DATE

To Be Continued:

5.5.3 Built-in Variables

A small number of built-in variables are available for use in assertions, and are referred to using a ‘$’

symbol, for example $current_date. Built-in variables defined include:

$current_date: ISO8601_DATE

$current_time: ISO8601_TIME

$current_date_time: ISO8601_DATE_TIME

$current_year: Integer

$current_month: Integer

5.5.4 Archetype-defined Variables

Variables may be declared within the rules section of an archetype. This is done using the following syntax:

$var_name:Type ::= expression

This facility can be used to equate a variable name to a path, e.g. the following equates the variable

$diagnosis to the code at the path contianing the diagnosis (e.g. in the openEHR-EHR-EVALUA-TION.problem-diagnosis.v1 archetype):

$diagnosis:CODE_PHRASE ::= /data/items[id2.1]/value/defining_code

The variable can then be used instead of the path in subsequent expressions.

5.5.5 External Queries

An expression referring to an externally defined query, possibly including arguments, may be defined using the variable declaration syntax. The general pattern is as follows:

$varname:Type ::= query(context, query_name, arg1, arg2, ...)

Examples include:

$date_of_birth:ISO8601_DATE ::= query(“ehr”, “date_of_birth”)

$has_diabetes:Boolean ::= query(“ehr”, “has_diagnosis”,

“snomed_ct::1234567”)

$is_female:Boolean ::= query(“ehr”, “is_female”)

Any number of arguments can be included.

Query Contexts

Query Names

5.6 Precedence and Parentheses

To Be Continued:

5.7 Conditions

Example....

$is_female implies exists /path/to/xxx

5.8 Natural Language Issues

xx

6 ADL Paths

6.1 Overview

The notion of paths is integral to ADL, and a common path syntax is used to reference nodes in both ODIN and cADL sections of an archetype. The same path syntax works for both, because both ODIN and cADL have an alternating object/attribute structure. However, the interpretation of path expres-sions in ODIN and cADL differs slightly; the differences are explained in the ODIN and cADL sec-tions of this document. This section describes only the common syntax and semantics.

The general form of the path syntax is as follows (see syntax section below for full specification):

path: [‘/’] path_segment { ‘/’ path_segment }+

path_segment: attr_name [ ‘[’ object_id ‘]’ ]

Essentially, ADL paths consist of segments separated by slashes (‘/’), where each segment is an attribute name with optional object identifier predicate, indicated by brackets (‘[]’).

ADL Paths are formed from an alternation of segments made up of an attribute name and optional object node identifier predicate, separated by slash (‘/’) characters. Node identifiers are delimited by brackets (i.e. []).

Similarly to paths used in file systems, ADL paths are either absolute or relative, with the former being indicated by a leading slash.

Paths are absolute or relative with respect to the document in which they are men-tioned. Absolute paths commence with an initial slash (‘/’) character.

The ADL path syntax also supports the concept of “movable” path patterns, i.e. paths that can be used to find a section anywhere in a hierarchy that matches the path pattern. Path patterns are indicated with a leading double slash (“//”) as in Xpath.

Path patterns are absolute or relative with respect to the document in which they are mentioned. Absolute paths commence with an initial slash (‘/’) character.

6.2 Relationship with W3C Xpath

The ADL path syntax is semantically a subset of the Xpath query language, with a few syntactic shortcuts to reduce the verbosity of the most common cases. Xpath differentiates between “children”

and “attributes” items of an object due to the difference in XML between Elements (true sub-objects) and Attributes (tag-embedded primitive values). In ADL, as with any pure object formalism, there is no such distinction, and all subparts of any object are referenced in the manner of Xpath chil-dren; in particular, in the Xpath abbreviated syntax, the key child:: does not need to be used.

ADL does not distinguish attributes from children, and also assumes the node_id attribute. Thus, the following expressions are legal for cADL structures:

items[1] -- the first member of ‘items’

items[systolic] -- the member of ‘items’ with meaning ‘systolic’

items[id1] -- the member of ‘items’ with node id ‘id1’

The Xpath equivalents are:

items[1] -- the first member of ‘items’

items[meaning() = ‘systolic’]-- the member of ‘items’ for which the meaning() function evaluates to “systolic”

items[@archetype_node_id = ‘id1’]-- the member of ‘items’ with key ‘id1’

In the above, meaning() is a notional function is defined for Xpath in openEHR, which returns the rubric for the node_id of the current node. Such paths are only for display purposes, and paths used for computing always use the ‘at’ codes, e.g. items[id1], for which the Xpath equivalent is

items[@node_id = ‘id1’].

The ADL movable path pattern is a direct analogue of the Xpath syntax abbreviation for the

‘descendant’ axis.

7 Default Values

7.1 Overview

In ADL 2, it is possible to specify a default value for any object node. This almost always limited to use in templates, since default values are usually specific to local contexts or use cases. However they may validly be used in any archetype.

Within a template, a default value can be defined to support the situation where only one value is pos-sible for a data item due to the specific nature of the template. For example, a blood pressure arche-type may allow a number of possible values for ‘patient position’, such as ‘lying’, and ‘sitting’,

‘standing’. When used in a hospital, the patient will usually be lying so a default value for this can be set, as shown in the following example:

/data[id2]/events[id6]/state[id7]/items[id8]/value { DV_CODED_TEXT {

_default {

(DV_CODED_TEXT)

defining_code = [snomedct::163033001]> -- lying BP

} } }

Default values are expressed in ODIN syntax, since they are instances of objects, rather than being constraints. They are introduced using a pseudo-attribute ‘_default’, which is detected by the com-piler as being a meta-attribute. The example above only sets the default value, but it could have also modified the constraint on the value object as well, as in the following version (where the standing blood pressure possibility from the archetype has been removed):

/data[id2]/events[id6]/state[id7]/items[id8]/value { DV_CODED_TEXT {

defining_code { [snomedct::

163033001, -- lying blood pressure 163035008] -- sitting blood pressure }

_default {

(DV_CODED_TEXT)

defining_code = [snomed::163033001]> -- lying BP

} } }

Default values can be set in the same way on container objects, such that one or more container objects distinguished by node identifier or name (if renaming has been used in the template) within the same container can have a default value assigned to them.

To Be Continued: example

A default value is either of the same type as specified by the corresponding archetype node (rm_type_name attribute) or any subtype allowed by the reference model.

8 ADL - Archetype Definition Language

8.1 Introduction

This section describes whole ADL artefacts. The relationship of the cADL-encoded definition sec-tion and the ODIN-encoded terminology section is discussed in detail. In this section, only standard ADL (i.e. the standard cADL constructs and types described so far) is assumed.

Some syntax valdity rules are defined, but validity in general is defined by the rules stated in the AOM specification, which can be checked by a compiler as soon as an AOM structure is parsed from an ADL document (or other serialsiation format).

The general structure of ADL artefacts is as follows:

(([flat] archetype | template | template_overlay) | operational_template) (qualifiers)

id

[specialize parent_id]

language ODIN description

ODIN definition

cADL [rules

assertions]

terminology ODIN [annotations

ODIN]

[revision_history ODIN]

An ADL source template has the structure (‘template’ keyword; must be specialised):

[flat] template (qualifiers) id

specialize parent_id language

ODIN description

ODIN definition

cADL [rules

assertions]

terminology ODIN [annotations

ODIN]

[revision_history ODIN section]

An ADL template overlay has the structure shown below (‘template_overlay’ keyword, must be spe-cialised; minimal sections):

template_overlay (qualifiers) id

specialize parent_id definition

cADL terminology

ODIN

The structure of an operational template expressed in native ADL is as follows (‘operational_template’ keyword; full flattened structure, including component_ontologies section):

operational_template (qualifiers) template_id

language ODIN description

ODIN definition

cADL [rules

assertions]

terminology ODIN [annotations

ODIN]

component_ontologies ODIN

8.2 File-naming Convention

8.2 File-naming Convention

In document Archetype Definition Language ADL 2 (Page 57-143)

Related documents