FHIR Chat · pattern discriminators and pattern[x]/binding · conformance

Stream: conformance

Topic: pattern discriminators and pattern[x]/binding


view this post on Zulip Chris Moesel (Jul 06 2020 at 20:18):

According to the R4 spec for discriminators:

Each slice must use the element definition for the element(s) in the discriminator(s) to ensure that the slices are clearly differentiated by assigning an appropriate value domain, depending on the discriminator type. If the type is value, or pattern, then the element definition must use either:

  • ElementDefinition.fixed[x], or
  • ElementDefinition.pattern[x], or
  • if the element has a terminology binding, a required binding with a Value Set that enumerates the list of possible codes in the value set ("extensional definition")

I take this to mean that if a discriminator type is pattern then the element pointed to by the discriminator path must have either a pattern[x] or binding property directly on it (and maybe a fixed[x] would be OK - not sure).

But... I've found that the IG Publisher doesn't seem to care. The following FSH produces no errors or warnings in the IG Publisher:

CodeSystem: ExampleComponentCS
Id: example-component-cs
* #foo "Foo" "Foo"
* #bar "Bar" "Bar"
* #boo "Boo" "Boo"
* #far "Far" "Far"

ValueSet: BooFarVS
Id: boo-far-vs
* ExampleComponentCS#boo "Boo"
* ExampleComponentCS#far "Far"

Profile: PractitionerBadSlicing
Parent: Practitioner
* identifier ^slicing.rules = #open
* identifier ^slicing.discriminator.type = #pattern
* identifier ^slicing.discriminator.path = "$this" // <-- $this
* identifier contains foo 0..1 and bar 0..1 and booFar 0..2
* identifier[foo].type = ExampleComponentCS#foo    // <-- NOT on $this
* identifier[bar].type = ExampleComponentCS#bar    // <-- NOT on $this
* identifier[booFar].type from BooFarVS            // <-- NOT on $this

I expected some flack from the publisher because the identifier discriminator type is pattern and the path is $this -- but the pattern[x] and binding are not on identifier (which is $this), but rather are on identifier.type.

Am I misunderstanding? Are patterns and binding on nested elements (below the discriminator path) valid for discrimination on? Or is the IG Publisher just not flagging this even though it is invalid?

view this post on Zulip Grahame Grieve (Jul 08 2020 at 01:37):

well, I think it looks wrong, and I would've expected an error. how can I reproduce this?

view this post on Zulip Chris Moesel (Jul 08 2020 at 02:37):

Is a standalone StructureDefinition that demonstrates it good enough? Or do you prefer a whole buildable IG? And if you think this is a bug, then I should file it in Jira, right?

view this post on Zulip Grahame Grieve (Jul 08 2020 at 04:22):

filing it with Jira is good. Ideally, I'll a structure definition and a valid and an invalid example. then I can add it to the unit tests

view this post on Zulip Igor Sirkovich (Jul 08 2020 at 05:10):

I'm just wondering if $this pattern slicing above would work in case slices are defined on different sub-elements of identifier, e.g. the last 3 lines would be:

  • identifier[foo].type = ExampleComponentCS#foo
  • identifier[bar].system = http://myidsystem.com/bar
  • identifier[booFar].type from BooFarVS

Alternatively, would this require slicing on discriminator=type and re-slicing on discriminator=system?
Is this a valid scenario generally speaking?

view this post on Zulip Chris Moesel (Jul 08 2020 at 13:26):

Issue filed here: https://jira.hl7.org/browse/FHIR-27927

view this post on Zulip Chris Moesel (Jul 08 2020 at 13:31):

@Igor Sirkovich -- I think there needs to be a constraint on the direct element the discriminator path points to (based on my reading of the spec). So you would probably need a patternIdentifier that specifies the type and system for that to work. If constraints on sub-path elements also counted for discrimination then I'm not sure why we would ever discriminate on anything other than $this.

view this post on Zulip Igor Sirkovich (Jul 08 2020 at 13:45):

Thank you @Chris Moesel

Would the following definition work in this case? I'm just trying to ensure I understand your explanation.

* identifier ^slicing.rules = #open
* identifier ^slicing.discriminator.type = #pattern
* identifier ^slicing.discriminator.path = "$this"
* identifier contains foo 0..1 and bar 0..1 and booFar 0..2
* identifier[foo].type = ExampleComponentCS#foo
* identifier[bar].system = http://myidsystem.com/bar
* identifier[booFar].type from BooFarVS

Chris Moesel said:

Igor Sirkovich -- I think there needs to be a constraint on the direct element the discriminator path points to (based on my reading of the spec). So you would probably need a patternIdentifier that specifies the type and system for that to work. If constraints on sub-path elements also counted for discrimination then I'm not sure why we would ever discriminate on anything other than $this.

view this post on Zulip Chris Moesel (Jul 08 2020 at 13:58):

Hi @Igor Sirkovich -- no, I don't think so. The FSH above says to discriminate by pattern on $this -- which is identifier. So I think there should be a patternIdentifier constraint on the identifier element in each slice. Instead that FSH produces the following constraints:

  • patternCodeableConcept on identifier.type (in foo slice)
  • patternUri on identifier.system (in bar slice)
  • binding on identifier.type (in booFar slice)

It's also not quite correct because the slices are not mutually exclusive. For example, if an identifier had a type that matched the foo slice and a system that matched the bar slice, it's ambiguous which slice it belongs to.

view this post on Zulip Chris Moesel (Jul 08 2020 at 14:22):

Also note that right now... SUSHI only supports patterns on arbitrary datatypes by using caret syntax. Fixing my original example to use patterns on identifier you'd need to do this:

Profile: PractitionerBadSlicing
Parent: Practitioner
* identifier ^slicing.rules = #open
* identifier ^slicing.discriminator.type = #pattern
* identifier ^slicing.discriminator.path = "$this"
* identifier contains foo 0..1 and bar 0..1 and booFar 0..2
* identifier[foo] ^patternIdentifier.type = ExampleComponentCS#foo
* identifier[bar] ^patternIdentifier.type = ExampleComponentCS#bar
* identifier[booFar].type from BooFarVS // <-- This is actually still wrong, but there's no way to apply it at the `identifier` level

FSH supports another way, but it's not yet supported in SUSHI

Instance: FooIdentifier
InstanceOf: Identifier
Usage: #inline
* type = ExampleComponentCS#foo

Instance: BarIdentifier
InstanceOf: Identifier
Usage: #inline
* type = ExampleComponentCS#foo

Profile: PractitionerBadSlicing
Parent: Practitioner
* identifier ^slicing.rules = #open
* identifier ^slicing.discriminator.type = #pattern
* identifier ^slicing.discriminator.path = "$this"
* identifier contains foo 0..1 and bar 0..1 and booFar 0..2
* identifier[foo] = FooIdentifier
* identifier[bar] = BarIdentifier
* identifier[booFar].type from BooFarVS // <-- This is actually still wrong, but there's no way to apply it at the `identifier` level

EDIT: Actually, it's pretty much impossible to fix it for the VS constraint (since we can pop it up a level and we can't represent it in patternIdentifier. So I had to edit that out.

view this post on Zulip Igor Sirkovich (Jul 09 2020 at 00:32):

Thank you @Chris Moesel. This is super helpful. Complex slicing is always a lot of fun :)

view this post on Zulip Igor Sirkovich (Jul 09 2020 at 00:35):

Just a thought: any chance the following might work?

* identifier[booFar] ^patternIdentifier.type from BooFarVS

I've never seen this, so I assume it's not valid, but probably worth checking.

view this post on Zulip Chris Moesel (Jul 09 2020 at 03:06):

I don't think there is a way to say that something in a pattern[x] should be bound to a value set. binding is a property on ElementDefinition, as is pattern[x] -- so they're at the same level, making it difficult to apply one to the other. Although pattern[x] allows you to specify values from a child path (via the pattern itself), I think binding can only be applies to the exact element it is on (no child paths).

It's hard to explain, and I feel like I'm probably not saying it very well, but hopefully that is helpful anyway!


Last updated: Apr 12 2022 at 19:14 UTC