New ADL/AOM proposals to solve some old problems

In openEHR we use custom syntax in archetypes to express ordinal constraints, quantity constraints and coded text constraints - i..e constraints on what are probably the most ubiquitous data types in health.

I have been mulling over feedback from previous debates here and in CIMI about the ‘undesirability’ of this syntax.

I have posted some new ideas on how to solve this here.

The executive summary is:

  • let’s treat ‘code’ as a built in type, like a Date or a Uri; this then makes an AOM type that constrains this trivial;

  • ADL can be augmented in a generic way to enable tuples to be constrained, which would better solve the Quantity constraint problem

  • The Ordinal constraint syntax would be replaced by a combination of both of the above.

Feedback welcome.

  • thomas

Very interesting thoughts Tom!

My initial impression of the proposal is very positive. If I understand things correctly this will enable shorter and more readable serializations not only in ADL but also in other formalisms.

If we consider ADL being a DSL mainly targeted for constraining health-related RMs then simplifications towards that goal are welcome.

The only potential catch is implementation issues. Have you already tried implementing a parser for this in some language? (If so, please provide a link.) I guess the suggestion could make some implementation parts easier and some a bit trickier.

Best regards,
Erik Sundvall
LiO: erik.sundvall@lio.se http://www.lio.se/Verksamheter/IT-centrum/
LiU: erik.sundvall@liu.se http://www.imt.liu.se/~erisu/

P.s. [/daydreaming] It might be interesting to connect a future updated AOM 1.5 in Java with (de)serialization using Jackson, see https://github.com/FasterXML Jackson already supports several highly configurable serialization format options, perhaps ADL or ODIN databindings would be possible too :wink: RM bindings might be a more interesting use case than AM bindings though…

well actually I am thinking of ADL as a domain-independent formalism. Today we do have some health-IT oriented extras, but that would disappear with the proposal I am making here, and would be replaced by a) a built-in type (essentially a special kind of string) representing a terminology code, and b) the tuple constraint capability. Although the former may look like a health IT specific, I would argue that it is applicable in any industry, where there is any kind of coding going on. That surely has to be increasing. I haven’t done anything in the ADL parser to support this, but I think it will be easy to handle for leaf level tuples. For tuples of complex objects, it will probably be harder, but I think that is of less utility anyway. The main annoyance will be re-processing existing archetypes on the fly, but that’s life… Before I do any work on it, I think it would be useful to get more feedback. - thomas

As you know, I'm not a big fan of domain types, so take my comments
with a grain of salt :wink:
I understand that back in the day when archetypes were hand crafted
domain types could serve a purpose. But in my opinion ADL should not
be written by hand nowadays. Tools should be the ones that 'hide' the
'verboseness' and provide the user with a simple interface to simulate
domain types if you want/need that. Also, the difference in file size
is negligible (if archetypes pass from 16kb to 20kb I wouldn't worry
that much...).
If you ask me I would get rid of them completely and make ADL
completely model agnostic.

This is why I can agree with the second point completely: There you
are making ADL better, more powerful.
But I see a problem with the first point as it still requires an
external definition of the 'mappings' between how we understand codes
in each one of the standards (and which information we can constraint
about them). With this new syntax, can we constraint mappings between
codes? ( How do I say that I don't want to allow the mappings in
certain coded text?) and what about the code qualifiers? What if your
RM defines another kind of attribute for codes interesting to be put
into the archetypes but not supported by this code syntax?
If both visions (codes as a type and codes as a full structure)
coexist then we have the same problem as we have now (or worse).

PS: BTW, by definition a leaf constraint type (the new proposed
'C_TERMINOLOGY_CODE' or whatever) does not have node id, I don't see
how one would be able to define alternatives of codes from different
terminologies or specialize that...
PPS: ...which is the exact same problem that domain types have (as
they also lack node id)

PPPS: How you define an AQL filter over a domain type?

I’m not worried about size, up to a point. But there some truisms about formalisms - the main one is that if the context free grammar of a formalism only has a complicated way to do something, then any structural representation will also be complicated. Additionally, if it’s complicated to express a simple thing in the formalism, it’s probable that no users or developers understand it clearly. Consider these dichotomies: well that’s true, but it’s already true for types like Date, Time, DateTime and Duration. Note that a Datetime with timezone has 7 pieces of information in it, and a lot of implied validity rules. Is it a leaf type or a complex type? We just use ISO8601 strings for all of these, and let other tools work out the obvious mappings between various RMs with TS (HL7), DATE/TIME types (openEHR), XSD gXXX types (FHIR), and so on. Proposing the idea of a ‘terminology code’ made up of a terminology id and a code or code-phrase (as a string expressed in e.g. the SNOMED CT Compositional grammar) as a built-in type doesn’t seem a great leap in the semantic age. I’m not exactly sure what constraint you want to express here: can you be more precise? well in openEHR we have always modelled code terms as syntax, not a complex model of qualifiers. See the CODE_PHRASE type. it depends on what are trying to do. The ‘normal’ thing that 90% of archetypes need to do is this: ELEMENT[at0021] occurrences matches {0..1} matches { – Certainty value matches { DV_CODED_TEXT matches { defining_code matches { [local:: at0022, – Suspected at0023, – Probable at0024] – Confirmed } } } } If this is written without the ‘custom syntax’ then you have: ELEMENT[at0021] occurrences matches {0..1} matches { – Certainty value matches { DV_CODED_TEXT matches { defining_code matches { CODE_PHRASE matches { terminology matches { TERMINOLOGY_ID matches { value matches {“local”} } code_string matches { “at0022”, – Suspected “at0023”, – Probable “at0024” – Confirmed } } } } } } Either way, there is no at-codes on the possibilities, and there’s no need. Of course, you can always do this: ELEMENT[at0021] occurrences matches {0..1} matches { – Certainty value matches { DV_CODED_TEXT [atNNNN] matches { defining_code matches { … } } DV_CODED_TEXT [atNNNN] matches { defining_code matches { … } } } } which might possibly make sense in some situation. - thomas

How do you define an AQL filter over a date time? Well, ok, it’s not quite as simple as that. With a coded term type (in particular) you want operators like ‘in set’, ‘in subsumption’, and ‘in subset’. But why do we see this as being specific to health? - thomas

As you know, I'm not a big fan of domain types, so take my comments
with a grain of salt :wink:
I understand that back in the day when archetypes were hand crafted
domain types could serve a purpose. But in my opinion ADL should not
be written by hand nowadays. Tools should be the ones that 'hide' the
'verboseness' and provide the user with a simple interface to simulate
domain types if you want/need that. Also, the difference in file size
is negligible (if archetypes pass from 16kb to 20kb I wouldn't worry
that much...).
If you ask me I would get rid of them completely and make ADL
completely model agnostic.

I'm not worried about size, up to a point. But there some truisms about
formalisms - the main one is that if the context free grammar of a formalism
only has a complicated way to do something, then any structural
representation will also be complicated. Additionally, if it's complicated
to express a simple thing in the formalism, it's probable that no users or
developers understand it clearly.

Consider these dichotomies:

OWL (readable) v RDF (hideous)
JSON (simplistic, but readable) v XML (hard to read, tricky inheritance
model, tricky containment semantics, ...)
Ruby / Python (readable, according the young generation at least :wink: v C++
(much harder than it should be)
Ecore syntax (human readable and computable) v XMI (no need to say anything
here).

One thing we can learn from this is that where clear abstract syntaxes are
not found, there you find confusion.

"readability" seems like a too subjective measure, and depends mostly
of the person/program writing it on the first place.

This is why I can agree with the second point completely: There you
are making ADL better, more powerful.
But I see a problem with the first point as it still requires an
external definition of the 'mappings' between how we understand codes
in each one of the standards (and which information we can constraint
about them).

well that's true, but it's already true for types like Date, Time, DateTime
and Duration. Note that a Datetime with timezone has 7 pieces of
information in it, and a lot of implied validity rules. Is it a leaf type or
a complex type? We just use ISO8601 strings for all of these, and let other
tools work out the obvious mappings between various RMs with TS (HL7),
DATE/TIME types (openEHR), XSD gXXX types (FHIR), and so on.

Dates are mostly represented as strings with more or less
restrictions. The classes to represent the codes are more complicated
than that (codes, terminology, mapping(s), qualifiers, etc)

Proposing the idea of a 'terminology code' made up of a terminology id and a
code or code-phrase (as a string expressed in e.g. the SNOMED CT
Compositional grammar) as a built-in type doesn't seem a great leap in the
semantic age.

With this new syntax, can we constraint mappings between
codes? ( How do I say that I don't want to allow the mappings in
certain coded text?)

I'm not exactly sure what constraint you want to express here: can you be
more precise?

Have a template or specialized archetype that the codes in my target
system will have exactly one mapping (from a standard terminology to a
local one, for example)

and what about the code qualifiers? What if your
RM defines another kind of attribute for codes interesting to be put
into the archetypes but not supported by this code syntax?
If both visions (codes as a type and codes as a full structure)
coexist then we have the same problem as we have now (or worse).

well in openEHR we have always modelled code terms as syntax, not a complex
model of qualifiers. See the CODE_PHRASE type.

I know how openEHR does it, but others may or may not model it like that.

PS: BTW, by definition a leaf constraint type (the new proposed
'C_TERMINOLOGY_CODE' or whatever) does not have node id, I don't see
how one would be able to define alternatives of codes from different
terminologies or specialize that...
PPS: ...which is the exact same problem that domain types have (as
they also lack node id)

it depends on what are trying to do. The 'normal' thing that 90% of
archetypes need to do is this:

                            ELEMENT[at0021] occurrences matches {0..1}
matches { -- Certainty
                                value matches {
                                    DV_CODED_TEXT matches {
                                        defining_code matches {
                                            [local::
                                            at0022, -- Suspected
                                            at0023, -- Probable
                                            at0024] -- Confirmed
                                        }
                                    }
                                }
                            }

If this is written without the 'custom syntax' then you have:

                            ELEMENT[at0021] occurrences matches {0..1}
matches { -- Certainty
                                value matches {
                                    DV_CODED_TEXT matches {
                                        defining_code matches {
                                            CODE_PHRASE matches {
                                                terminology matches {
                                                    TERMINOLOGY_ID matches {
                                                        value matches
{"local"}
                                                    }
                                                code_string matches {
                                                    "at0022", --
Suspected
                                                    "at0023", --
Probable
                                                    "at0024" -- Confirmed
                                               }
                                            }
                                        }
                                    }
                                }
                            }

Either way, there is no at-codes on the possibilities, and there's no need.

Of course, you can always do this:

                            ELEMENT[at0021] occurrences matches {0..1}
matches { -- Certainty
                                value matches {
                                    DV_CODED_TEXT [atNNNN] matches {
                                        defining_code matches {
                                            ...
                                        }
                                    }
                                    DV_CODED_TEXT [atNNNN] matches {
                                        defining_code matches {
                                            ...
                                        }
                                    }
                                }
                            }

which might possibly make sense in some situation.

- thomas

Sure, you can make alternatives of coded_text, the domain type here is
the codePhrase...

I think this could be a perfect valid example (ignore random codes)

defining_code existence matches {1..1} matches {
                                                    [SNOMED-CT::
                                                    123456,
                                                    11234561,
                                                    1002123456,
                                                    61234563,
                                                    98752;
                                                    233233]
                                                    [LOINC::
                                                    72693-5,
                                                    1234-5,
                                                    3254-8,
                                                    6548-1,
                                                    44563-7;
                                                    3254-8]
                                                    [local::
                                                    at1000,
                                                    at1001,
                                                    at1002,
                                                    at1003,
                                                    at1014;
                                                    at1001]
                                                }

You cannot define a node id for each defining code. But specializing
it should be allowed (define a subset of the parent seems like an
obvious thing to do on codephrases)

The same thing applies to C_DV_QUANTITY for example

ELEMENT[at1005] occurrences matches {0..1} matches { -- Tilt
(degrees and radian)
                                        value existence matches {1..1}
matches {
                                            C_DV_QUANTITY <
                                                property = <[openehr::497]>
                                                list = <
                                                    ["1"] = <
                                                        units = <"°">
                                                        magnitude =
<|-90.0..90.0|>
                                                        precision = <|0|>
                                                    >
                                                >
                                              >
                                             C_DV_QUANTITY <
                                                property = <[openehr::497]>
                                                list = <
                                                    ["1"] = <
                                                        units = <"c">
                                                        magnitude =
<|-2PI..2PI|>
                                                        precision = <|0|>
                                                    >
                                                >
                                              >
                                        }
                                    }

C_DV_QUANTITY[atXXXX]<...> is not correct.
And looking at the example, after all this years I have yet to find a
good explanation of why domain types can have things like "property"
which cannot be defined in standard ADL

You can generate operations to deal with domain types, but then AQL
would be openEHR specific (you can call it OQL then). What I say is
that generating a path to specify a filter (and accessing it) is
direct when the domain type has been expanded, and not so easy if you
take it as it is. If you get the expanded path each time then the user
won't be able to tell where the AQL path comes from (it'll have
attributes he doesn't know about). I only see disadvantages working
with domain types in AQL.

You can generate operations to deal with domain types, but then AQL
would be openEHR specific (you can call it OQL then). What I say is

Diego,

there is nothing openEHR-specific today in AQL, and allowing more complex primitive types like dates or codes or URIs doesn't change that. It will work just as well with any reference model from any industry. So I don't get your point here.

that generating a path to specify a filter (and accessing it) is
direct when the domain type has been expanded, and not so easy if you
take it as it is. If you get the expanded path each time then the user
won't be able to tell where the AQL path comes from (it'll have
attributes he doesn't know about). I only see disadvantages working
with domain types in AQL.

but in that case you should be arguing that we should remove the Date/Time types and URIs etc. It's true, we can just limit ourselves to Integer / Real / String / Character / Boolean / Binary, but... why? It's just making life needlessly difficult as far as I can see.

- thomas

Consider these dichotomies:

OWL (readable) v RDF (hideous)
JSON (simplistic, but readable) v XML (hard to read, tricky inheritance
model, tricky containment semantics, ...)
Ruby / Python (readable, according the young generation at least :wink: v C++
(much harder than it should be)
Ecore syntax (human readable and computable) v XMI (no need to say anything
here).

One thing we can learn from this is that where clear abstract syntaxes are
not found, there you find confusion.

"readability" seems like a too subjective measure, and depends mostly
of the person/program writing it on the first place.

Nevertheless, the unreadable examples from the list above are all infamous for their difficulty of learning, difficulty of understanding, complexity, and for being things everyone wants to (and eventually does) replace. It's not by accident that this happens.

This is why I can agree with the second point completely: There you
are making ADL better, more powerful.
But I see a problem with the first point as it still requires an
external definition of the 'mappings' between how we understand codes
in each one of the standards (and which information we can constraint
about them).

well that's true, but it's already true for types like Date, Time, DateTime
and Duration. Note that a Datetime with timezone has 7 pieces of
information in it, and a lot of implied validity rules. Is it a leaf type or
a complex type? We just use ISO8601 strings for all of these, and let other
tools work out the obvious mappings between various RMs with TS (HL7),
DATE/TIME types (openEHR), XSD gXXX types (FHIR), and so on.

Dates are mostly represented as strings with more or less
restrictions. The classes to represent the codes are more complicated
than that (codes, terminology, mapping(s), qualifiers, etc)

only if you think it has to be a class model. But in fact, 99% of all codes on the planet are just single codes. A small number have some qualifiers / modifiers, and the standard way to do this in both the ontology and terminology communities is with different kinds of syntax - either OWL-based or IHTSDO based. CLass models always fail in this area, because they can never predict what new things terminology code phrases need to be able to represent.

I am not saying that you could not keep using the explicit CODED_TERM model-based approach as well, just that it's getting in the way 99% of the time.

I'm not exactly sure what constraint you want to express here: can you be
more precise?

Have a template or specialized archetype that the codes in my target
system will have exactly one mapping (from a standard terminology to a
local one, for example)

well the normal way to do that is with terminology bindings. The following example would be a pretty dangerous thing to do, especially in health, and in any case, it would be hard to find any real world example that could look like this, because LOINC and SNOMED-CT don't really overlap or code for the same things at all. The better way to do that is definitely with bindings.

Sure, you can make alternatives of coded_text, the domain type here is
the codePhrase...

I think this could be a perfect valid example (ignore random codes)

defining_code existence matches {1..1} matches {
                                                     [SNOMED-CT::
                                                     123456,
                                                     11234561,
                                                     1002123456,
                                                     61234563,
                                                     98752;
                                                     233233]
                                                     [LOINC::
                                                     72693-5,
                                                     1234-5,
                                                     3254-8,
                                                     6548-1,
                                                     44563-7;
                                                     3254-8]
                                                     [local::
                                                     at1000,
                                                     at1001,
                                                     at1002,
                                                     at1003,
                                                     at1014;
                                                     at1001]
                                                 }

You cannot define a node id for each defining code. But specializing
it should be allowed (define a subset of the parent seems like an
obvious thing to do on codephrases)

The same thing applies to C_DV_QUANTITY for example

ELEMENT[at1005] occurrences matches {0..1} matches { -- Tilt
(degrees and radian)
                                         value existence matches {1..1}
matches {
                                             C_DV_QUANTITY <
                                                 property = <[openehr::497]>
                                                 list = <
                                                     ["1"] = <
                                                         units = <"°">
                                                         magnitude =
<|-90.0..90.0|>
                                                         precision = <|0|>
                                                     >
                                                 >
                                               >
                                              C_DV_QUANTITY <
                                                 property = <[openehr::497]>
                                                 list = <
                                                     ["1"] = <
                                                         units = <"c">
                                                         magnitude =
<|-2PI..2PI|>
                                                         precision = <|0|>
                                                     >
                                                 >
                                               >
                                         }
                                     }

  C_DV_QUANTITY[atXXXX]<...> is not correct.

actually, you can set at-codes on the DV_QUANTITY blocks above, but it's kind of ugly. But the proposals I am suggesting make all this go away.

And looking at the example, after all this years I have yet to find a
good explanation of why domain types can have things like "property"
which cannot be defined in standard ADL

it's very simple: with a plug-in constrainer type, you can have all kinds of special constraining attributes that are not in the RM at all. E.g. here 'property' is not actually a property of DV_QUANTITY (arguably it should be but that's another argument).

Similar thing happens with things like C_STRING - there is the regex and the list way of constraining a String value. There is nothing called 'pattern' in the String type.

- thomas

You can generate operations to deal with domain types, but then AQL
would be openEHR specific (you can call it OQL then). What I say is

Diego,

there is nothing openEHR-specific today in AQL, and allowing more complex
primitive types like dates or codes or URIs doesn't change that. It will
work just as well with any reference model from any industry. So I don't get
your point here.

I'm not saying there is something openEHR specific right now in AQL,
I'm just saying that including additional requirements to deal with
domain types would make more difficult the implementation of a AQL
engine, and the queries generated this way ("domain type"-based
queries if you want) only would work in a environment ready to use
domain types.
My whole point is, domain types will give you more headaches in the
long run (problems with specialization, AQL, mapping, etc.) than
benefits.

that generating a path to specify a filter (and accessing it) is
direct when the domain type has been expanded, and not so easy if you
take it as it is. If you get the expanded path each time then the user
won't be able to tell where the AQL path comes from (it'll have
attributes he doesn't know about). I only see disadvantages working
with domain types in AQL.

but in that case you should be arguing that we should remove the Date/Time
types and URIs etc. It's true, we can just limit ourselves to Integer / Real
/ String / Character / Boolean / Binary, but... why? It's just making life
needlessly difficult as far as I can see.

Implied semantics will give you problem always (again, talking about
paths). The advantage of date/time & uris over codes is that the
former are strings which can be treated with convenient functions.
Codes would depend on the underlying archetype reference model to be
interpreted correctly.

Consider these dichotomies:

OWL (readable) v RDF (hideous)
JSON (simplistic, but readable) v XML (hard to read, tricky inheritance
model, tricky containment semantics, ...)
Ruby / Python (readable, according the young generation at least :wink: v
C++
(much harder than it should be)
Ecore syntax (human readable and computable) v XMI (no need to say
anything
here).

One thing we can learn from this is that where clear abstract syntaxes
are
not found, there you find confusion.

"readability" seems like a too subjective measure, and depends mostly
of the person/program writing it on the first place.

Nevertheless, the unreadable examples from the list above are all infamous
for their difficulty of learning, difficulty of understanding, complexity,
and for being things everyone wants to (and eventually does) replace. It's
not by accident that this happens.

I disagree, everything has a place in this world. You would not be
programing in eiffel it that wasn't the case ;D

This is why I can agree with the second point completely: There you
are making ADL better, more powerful.
But I see a problem with the first point as it still requires an
external definition of the 'mappings' between how we understand codes
in each one of the standards (and which information we can constraint
about them).

well that's true, but it's already true for types like Date, Time,
DateTime
and Duration. Note that a Datetime with timezone has 7 pieces of
information in it, and a lot of implied validity rules. Is it a leaf type
or
a complex type? We just use ISO8601 strings for all of these, and let
other
tools work out the obvious mappings between various RMs with TS (HL7),
DATE/TIME types (openEHR), XSD gXXX types (FHIR), and so on.

Dates are mostly represented as strings with more or less
restrictions. The classes to represent the codes are more complicated
than that (codes, terminology, mapping(s), qualifiers, etc)

only if you think it has to be a class model. But in fact, 99% of all codes
on the planet are just single codes. A small number have some qualifiers /
modifiers, and the standard way to do this in both the ontology and
terminology communities is with different kinds of syntax - either OWL-based
or IHTSDO based. CLass models always fail in this area, because they can
never predict what new things terminology code phrases need to be able to
represent.

I am not saying that you could not keep using the explicit CODED_TERM
model-based approach as well, just that it's getting in the way 99% of the
time.

If getting in the way means write 5 lines instead of 1 then I give you that.
I don't really see which is the big gain of this

        CODED_TEXT matches {[local: at0111, at0012, at0013, at0014, at0015]}

over making it completely generic and leaving headaches behind with this

CODED_TEXT matches {
            terminology_id matches {
                TERMINOLOGY_ID matches {
                    value matches {"local"}
                }
            }
            code matches {"at0111", "at0012", "at0013", "at0014", "at0015"}
        }

I'm not exactly sure what constraint you want to express here: can you be
more precise?

Have a template or specialized archetype that the codes in my target
system will have exactly one mapping (from a standard terminology to a
local one, for example)

well the normal way to do that is with terminology bindings. The following
example would be a pretty dangerous thing to do, especially in health, and
in any case, it would be hard to find any real world example that could look
like this, because LOINC and SNOMED-CT don't really overlap or code for the
same things at all. The better way to do that is definitely with bindings.

Was a quick example, if you one a little more real take SNOMED and
RxNorm for example. Something like "valid medications for a given
disease".
I don't really think that the requirement could be done with bindings
by the way. If I have in my an object that supports codes with
mappings then archetyping that to require one and only one mapping is
trivial in ADL.

Sure, you can make alternatives of coded_text, the domain type here is
the codePhrase...

I think this could be a perfect valid example (ignore random codes)

defining_code existence matches {1..1} matches {
                                                     [SNOMED-CT::
                                                     123456,
                                                     11234561,
                                                     1002123456,
                                                     61234563,
                                                     98752;
                                                     233233]
                                                     [LOINC::
                                                     72693-5,
                                                     1234-5,
                                                     3254-8,
                                                     6548-1,
                                                     44563-7;
                                                     3254-8]
                                                     [local::
                                                     at1000,
                                                     at1001,
                                                     at1002,
                                                     at1003,
                                                     at1014;
                                                     at1001]
                                                 }

You cannot define a node id for each defining code. But specializing
it should be allowed (define a subset of the parent seems like an
obvious thing to do on codephrases)

The same thing applies to C_DV_QUANTITY for example

ELEMENT[at1005] occurrences matches {0..1} matches { -- Tilt
(degrees and radian)
                                         value existence matches {1..1}
matches {
                                             C_DV_QUANTITY <
                                                 property =
<[openehr::497]>
                                                 list = <
                                                     ["1"] = <
                                                         units = <"°">
                                                         magnitude =
<|-90.0..90.0|>
                                                         precision = <|0|>
                                                     >
                                                 >
                                               >
                                              C_DV_QUANTITY <
                                                 property =
<[openehr::497]>
                                                 list = <
                                                     ["1"] = <
                                                         units = <"c">
                                                         magnitude =
<|-2PI..2PI|>
                                                         precision = <|0|>
                                                     >
                                                 >
                                               >
                                         }
                                     }

  C_DV_QUANTITY[atXXXX]<...> is not correct.

actually, you can set at-codes on the DV_QUANTITY blocks above, but it's
kind of ugly. But the proposals I am suggesting make all this go away.

I'm curious how. codePhrase can also have a node id? Some domain types
can and others can't?

And looking at the example, after all this years I have yet to find a
good explanation of why domain types can have things like "property"
which cannot be defined in standard ADL

it's very simple: with a plug-in constrainer type, you can have all kinds of
special constraining attributes that are not in the RM at all. E.g. here
'property' is not actually a property of DV_QUANTITY (arguably it should be
but that's another argument).

Similar thing happens with things like C_STRING - there is the regex and the
list way of constraining a String value. There is nothing called 'pattern'
in the String type.

Well, doesn't feel the same way. I would use a binding to a local
openEHR terminology to represent 'property' instead of putting that on
a attribute.

Hi Tom,

Is the intention that the new data type TERMINOLOGY_CODE also can contain a post-coordinated code so it, for example, can contain a expression in SNOMED CT compositional grammar? (See www.snomed.org/tig?t=rfg_expression_scg for more details about SNOMED CT compositional grammar.)

Greetings

Mikael

yes exactly. Technically I suppose it should be called TERMINOLOGY_CODE_PHRASE or TERMINOLOGY_CODE_STRING or something like that. It’s the same idea as the openEHR CODE_PHRASE, the point here is to have an AOM type that is minimal, and just can represent a basic constrainable terminology code idea, and be easily mapped to actual RMs. - thomas

Hi Tom,

That sounds really nice.

Regards

Mikael