Basics

Keywords

The following keywords are recognised in cADL:

  • matches, ~matches, is_in, ~is_in

  • occurrences, existence, cardinality

  • ordered, unordered, unique

  • use_node, allow_archetype

  • include, exclude

  • before , after

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

Textual
Rendering
Symbolic
Rendering
Meaning

matches

Set membership, "p is in P"

not, ~

Negation, "not p"

*

Infinity, 'any number of…​'

Block / Node Structure

cADL constraints are written in a block-structured style, similar to block-structured programming languages like C. A typical block resembles the following (the recurring pattern /.+/ is a regular expression matching a non-empty string):

  • at-coded ADL2

  • id-coded ADL2

    PERSON[at0000] ∈ {
        name ∈ {
            PERSON_NAME[at0001] ∈ {
                forenames cardinality ∈ {1..*} ∈ {/.+/}
                family_name ∈ {/.+/}
                title ∈ {"Dr", "Miss", "Mrs", "Mr"}
            }
        }
        addresses cardinality ∈ {1..*} ∈ {
            LOCATION_ADDRESS[at0002] ∈ {
                street_number existence ∈ {0..1} ∈ {/.+/}
                street_name ∈ {/.+/}
                locality ∈ {/.+/}
                post_code ∈ {/.+/}
                state ∈ {/.+/}
                country ∈ {/.+/}
            }
        }
    }
    PERSON[id1] ∈ {
        name ∈ {
            PERSON_NAME[id2] ∈ {
                forenames cardinality ∈ {1..*} ∈ {/.+/}
                family_name ∈ {/.+/}
                title ∈ {"Dr", "Miss", "Mrs", "Mr"}
            }
        }
        addresses cardinality ∈ {1..*} ∈ {
            LOCATION_ADDRESS[id3] ∈ {
                street_number existence ∈ {0..1} ∈ {/.+/}
                street_name ∈ {/.+/}
                locality ∈ {/.+/}
                post_code ∈ {/.+/}
                state ∈ {/.+/}
                country ∈ {/.+/}
            }
        }
    }

In the above, each block is introduced by an identifier (shown in blue) from an information model. The identifiers alternate between type-names (upper case in this example, or 'camel' case) and type attribute names (lower case). Here, 'type-name' indicates the name of a type, which may be a class name, or may be a derived generic type name. An 'attribute name' is the name of an attribute in the inheritance-flattened form of a type, i.e. may be be defined in an ancestor class of the class to which the type-name most directly corresponds.

Blocks introduced by a type name are known as object blocks or object nodes, while those introduced by an attribute name are attribute blocks or attribute nodes.

The block identifier is followed by the ∈ operator (equivalent text keyword: matches or is_in ) followed by an open brace, is the start of a 'block', which continues until the closing matching brace (normally visually indented to match the line at the beginning of the block).

  • at-coded ADL2

  • id-coded ADL2

    PERSON[at0000] ∈ {                  -- OBJECT block 1 ------------+
        name ∈ {                            -- attribute block A ---+ |
            PERSON_NAME[at0001] ∈ { ... }       -- OBJECT block 2   + |
        }                                  -------------------------+ |
    }                                   ------------------------------+
    PERSON[id1] ∈ {                     -- OBJECT block 1 ------------+
        name ∈ {                            -- attribute block A ---+ |
            PERSON_NAME[id2] ∈ { ... }          -- OBJECT block 2   + |
        }                                  -------------------------+ |
    }                                   ------------------------------+

An object block or node can be thought of as a constraint matching a set of instances conforming to the type which introduces the block.

The example above expresses a constraint on an instance of the type PERSON ; the constraint is expressed by everything inside the PERSON block. The two blocks at the next level define constraints on properties of PERSON , in this case name and addresses. Each of these constraints is expressed in turn by the next level containing constraints on further types, and so on. The general structure is therefore a recursive nesting of constraints on types, followed by constraints on attributes (of that type), followed by types (being the types of the attribute under which it appears) until leaf nodes are reached.

A cADL text is a structure of alternating object and attribute blocks each introduced respectively by type names and attribute names from an underlying information model.

Comments

In a cADL text, comments are defined as follows:

Comments are indicated by the leader characters '--'. Multi-line comments are achieved using the '--' leader on each line where the comment continues.

The Underlying Information Model

Identifiers in cADL texts correspond to entities - types and attributes - in an information model. The latter is typically an object-oriented model, but may just as easily be an entity-relationship model or any other typed model of information. A UML model compatible with the example above is shown in UML Model of Person. Note that there can be more than one model compatible with a given fragment of cADL syntax, and in particular, there are usually more properties and classes in the reference model than are mentioned in the cADL constraints. In other words, a cADL text includes constraints only for those parts of a model that are useful or meaningful to constrain.

AM example demographics
Figure 1. UML Model of Person

Constraints expressed in cADL cannot invalidate those from the information model. For example, the PERSON.family_name attribute is mandatory in the model in the above PERSON model, so it is not valid to express a constraint allowing the attribute to be optional. In general, a cADL archetype can only further constrain an existing information model. However, it must be remembered that for very generic models consisting of only a few classes and a lot of optionality, this rule is not so much a limitation as a way of adding meaning to information. Thus, for a demographic information model which has only the types PARTY and PERSON, one can write cADL which defines the concepts of entities such as COMPANY , EMPLOYEE , PROFESSIONAL , and so on, in terms of constraints on the types available in the information model.

This general approach can be used to express constraints for instances of any information model. The following example shows how to express a constraint on the value property of an ELEMENT class to be a DV_QUANTITY with a suitable range for expressing blood pressure.

  • at-coded ADL2

  • id-coded ADL2

    ELEMENT[at0009] matches {          -- diastolic blood pressure
        value matches {
            DV_QUANTITY[at9071] matches {
                magnitude matches {|0..1000|}
                property matches {"pressure"}
                units matches {"mm[Hg]"}
            }
        }
    }
    ELEMENT[id10] matches {          -- diastolic blood pressure
        value matches {
            DV_QUANTITY[id11] matches {
                magnitude matches {|0..1000|}
                property matches {"pressure"}
                units matches {"mm[Hg]"}
            }
        }
    }

In this specification, the terms underlying information model and reference model are equivalent and refer to the information model on which a cADL text is based.

Information Model Identifiers

Identifiers from the underlying information model are used to introduce all cADL nodes. Identifiers obey the same rules as in ODIN: type names commence with an upper case letter, while attribute and function names commence with a lower case letter. In cADL, names of types and the name of any property (i.e. attribute or parameterless function) can be used.

A type name is any identifier with an initial upper case letter, followed by any combination of letters, digits and underscores. A generic type name (including nested forms) additionally may include commas, angle brackets and spaces, and must be syntactically correct as per the OMG UML 2.x specification or higher. An attribute name is any identifier with an initial lower case letter, followed by any combination of letters, digits and underscores. Any convention that obeys this rule is allowed.

Type identifiers are shown in this document in all uppercase, e.g. PERSON , while attribute identifiers are shown in all lowercase, e.g. home_address . In both cases, underscores are used to represent word breaks. This convention is used to improve the readability of this document, and other conventions may be used, such as the common programmer’s mixed-case convention exemplified by Person and homeAddress. The convention chosen for any particular cADL document should be based on that used in the underlying information model.

Node Identifier and Coding Systems

Node identifier codes appear after all type identifiers in a cADL text.

ADL 2.4 introduces support for a choice of node identifier coding systems, in order to facilitate transition from ADL1 to ADL2:

  • the at-code coding system, identical to that used for ADL1, mandatory to be used in openEHR Reference Model (RM) environments.

  • the id-code coding system, as originally introduced in ADL2.

Each coding system has a different node-naming and numbering convention:

  • For at-coded archetypes, node identifiers take the form of an at-code in brackets, e.g. [at0002]. The at-code of a root object in a structure is always at0000, or for specialised archetypes, at0000.1, at0000.1.1 etc.

  • For id-coded archetypes, node identifiers take the form of an id-code in brackets, e.g. [id3]. The id-code of a root object in a structure is always id1, or for specialised archetypes, id1.1, id1.1.1 etc.

The rules and use of node identifiers are described in more detail below in the [_node_identifiers] and [_node_identifier_codes] sections.

The matches Operator

The matches or is_in operator deserves special mention, since it is the key operator in cADL. This operator can be understood mathematically as set membership. When it occurs between an identifier and a block delimited by braces, the meaning is: the set of values allowed for the entity referred to by the name (either an object, or parts of an object - attributes) is specified between the braces. What appears between any matching pair of braces can be thought of as a specification for a set of values. Since blocks can be nested, this approach to specifying values can be understood in terms of nested sets, or in terms of a value space for instances of a type. Thus, in the following example, the matches operator links the name of an entity to a linear value space (i.e. a list), consisting of all words ending in 'ion'.

    aaa matches {/\w*ion[\s\n\t ]/} -- the set of words ending in 'ion'

The following example links the name of a type XXX with a hierarchical value space.

  • at-coded ADL2

  • id-coded ADL2

    XXX[at0001] matches {
        xxx_attr1 matches {
            YYY[at0002] matches {
                yyy_attr1 matches {0..3}
            }
        }
        xxx_attr2 matches {
            ZZZ[at0003] matches {
                zzz_attr1 matches {>1992-12-01}
            }
        }
    }
    XXX[id2] matches {
        xxx_attr1 matches {
            YYY[id3] matches {
                yyy_attr1 matches {0..3}
            }
        }
        xxx_attr2 matches {
            ZZZ[id4] matches {
                zzz_attr1 matches {>1992-12-01}
            }
        }
    }

The meaning of the syntax above is: data matching the constraints consists of an instance of type XXX , or any subtype allowed by the underlying information model, for which the value of attribute aaa is of type YYY , or any subtype allowed by the underlying information model, and so on, recursively until leaf level constraints are reached.

Occasionally the matches operator needs to be used in the negative, usually at a leaf block. Any of the following can be used to constrain the value space of the attribute aaa to any number except 5:

    aaa ~matches {5}
    aaa ~is_in {5}
    aaa ∉ {5}

The choice of whether to use matches or is_in is a matter of taste and background; those with a mathematical background will probably prefer is_in , while those with a data processing background may prefer matches .

Natural Language

cADL is completely independent of all natural languages. The only potential exception is where constraints include literal values from some language, and this is easily and routinely avoided by the use of separate language and terminology definitions, as used in ADL archetypes. However, for the purposes of readability, comments in English have been included in this document to aid the reader. In real cADL documents, comments are generated from the archetype terminology in the language of the locale.