FHIR Chat · Help with slicing on an extension value · shorthand

Stream: shorthand

Topic: Help with slicing on an extension value


view this post on Zulip Jean Duteau (Sep 28 2021 at 15:12):

Okay, I need help from the big guns -> Help me @Chris Moesel , you're my only hope!

I'm trying to slice Claim.careTeam on a boolean value in an extension. Here is the thread where Grahame has been trying to help: https://chat.fhir.org/#narrow/stream/179252-IG-creation/topic/How.20to.20slice.20on.20the.20value.20of.20an.20extension. Basically, it appears that whatever I'm doing, SUSHI is taking my FSH file and not creating a proper differential. Here is the repository: https://github.com/HL7/davinci-pas

I declare the extension on Claim.careTeam:

* careTeam MS
* careTeam.extension contains CareTeamClaimScope named careTeamClaimScope 1..1 MS

And then I slice careTeam on the value of the extension:

* careTeam ^slicing.discriminator.type = #value
* careTeam ^slicing.discriminator.path = "extension('http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope').value as Boolean"
* careTeam ^slicing.rules = #open
* careTeam ^slicing.description = "Slice based on whether the care team member belongs to the overall claim or to an individual claim item."
* careTeam contains OverallClaimMember 0..14 and ItemClaimMember 0..10
* careTeam[OverallClaimMember].extension contains CareTeamClaimScope named careTeamScope 1..1 MS
* careTeam[OverallClaimMember].extension[careTeamClaimScope].valueBoolean = true (exactly)
* careTeam[ItemClaimMember].extension contains CareTeamClaimScope named careTeamScope 1..1 MS
* careTeam[ItemClaimMember].extension[careTeamClaimScope].valueBoolean = false (exactly)

Here is what Grahame said about the slicing:

so the problem is around how slicing works. I'm pretty what I'm about to say is on record, but I can't find it :-(
the base slice defines the constraints that apply to all the slices. The validator will test the rules in the base slice first, then match the slices, and then apply the rules in the slice
but the snapshot generator does not replicate the constraints in the slice into each of the slices. That would be multiple inheritance, and we don't do that
usually, it doesn't matter, since the validator tests both
but you've found a case where it does: you have to manually redeclare the extension constraint in the slice, since the discriminator refers to it

That is why I added the xxx.extension contains XXX in each of the slices. But that still isn't enough as I'm still getting an error and Grahame then said:

so I don't think that the differential has changed in a meaningful way . The differential in profile http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-claim says:

Claim.careTeam sliced by the value of the extension http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope
Claim.careTeam.extension sliced by URL
one care team claim scope extension which is extension http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope
Then it defines the first slice:

Claim.careTeam:OverallClaimMember
Claim.careTeam:OverallClaimMember.extension - 2..*
Claim.careTeam:OverallClaimMember.extension:careTeamClaimScope - defines the named slice
Claim.careTeam:OverallClaimMember.extension:careTeamClaimScope.valueBoolean - fixes the value to true
But... see what I wrote above:

the snapshot generator does not replicate the constraints in the slice into each of the slices

so when it goes to process the first slice, nothing ever says that the extension careTeamClaimScope is actually the extension http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope

Is there something that I'm doing wrong in how I'm declaring the extension in the slices? Is this just something SUSHI can't convert?

view this post on Zulip Chris Moesel (Sep 29 2021 at 19:43):

I need to look into this more, but on first glance my guess is that SUSHI recognizes that the extension is already declared in the "base slice" (as Grahame referred to it), and thinks that since it is in that base slice, it does not need to be repeated in each individual slice -- because it's not actually a diff from the base slice. SUSHI tries really hard not to put anything into the differential that isn't actually different -- so even if you manually code it up in FSH, SUSHI says "Dude, that's not necessary. Let me clean that up for you."

This is just my guess though. I'd need to dig deeper to confirm.

view this post on Zulip Chris Moesel (Oct 13 2021 at 22:05):

Thanks for your patience, @Jean Duteau. I've looked into this a bit more and have a better idea what is going on.

Case 1: In the case where you did not redeclare the extensions on the individual careTeam slices, SUSHI did not redeclare them for you because it only outputs the differences in the slice vs the base. So we know why we're not seeing the extensions in the slices there.

Case 2: If you redeclare the extensions on each slice and use the same slice name as in the base (careTeamClaimScope), then SUSHI spits a warning at you about declaring a slice name that already exists. But since what you declared is exactly the same as the base, SUSHI still omits it in the differential since it is not different from the base. We end up w/ the same output as Case 1 above.

Case 3: If you redeclare the extensions on each slice and use a different slice name (careTeamScope, not careTeamClaimScope), then SUSHI does actually produce a differential w/ the extensions declared in that careTeamScope slice of the extension element. But note that it is treated as a different extension slice, which is also 1..1. So now you have the base requiring 1..1 careTeamClaimScope extension slice and the careTeam slices each also requiring 1..1 careTeamScope extension slice. SUSHI sees two extension slices, each declared as 1..1, and then thinks it should bump the overall extension cardinality to 2..*. (This is starting to get confusing, isn't it?). Now... in your example, after redeclaring the extension slices as careTeamScope, you then set the fixed value on the careTeamClaimScope extension slice (the one from the base, not from the slice) -- and the validator thinks the value is not fixed in the careTeam slice now since it doesn't know what the base extension slice is. (Yup, still confusing, but it makes sense if you think it through). You can actually fix this by changing the lines that fix the extension's value to use the careTeamScope slice instead of the careTeamClaimScope slice. BUT... you still end up w/ the error due to SUSHI marking the base extension as 2..*.

view this post on Zulip Chris Moesel (Oct 13 2021 at 22:39):

Oh. And there was one more issue. In the discriminator, you had value as Boolean, but Boolean is not a valid FHIR type -- it needs to be value as boolean (although I think you can get away with just value actually).

view this post on Zulip Chris Moesel (Oct 13 2021 at 22:47):

So... I expect you're looking for a solution ;-). I actually have one for you! SUSHI applies rules top-down. When it creates slices, it starts each slice as a clone of the base element being sliced -- and the diff is generated from that. In other words, the diff is based on the state of the base element at the time the slice was created. So... we can use that to our advantage here. So to make everything happy, here is what you need to do:

  • Move the * careTeam.extension contains... rule to the end of the definition (after you declare the careTeam slices)
  • Use consistent slice names across the base and slices (e.g., name them all careTeamClaimScope)
  • Fix the discriminator to use as boolean instead of as Boolean

You should end up w/ a set of rules something like this:

* careTeam MS
* careTeam ^slicing.discriminator.type = #value
* careTeam ^slicing.discriminator.path = "extension('http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope').value as boolean"
* careTeam ^slicing.rules = #open
* careTeam ^slicing.description = "Slice based on whether the care team member belongs to the overall claim or to an individual claim item."
* careTeam contains OverallClaimMember 0..14 and ItemClaimMember 0..10
* careTeam[OverallClaimMember].extension contains CareTeamClaimScope named careTeamClaimScope 1..1 MS
* careTeam[OverallClaimMember].extension[careTeamClaimScope].valueBoolean = true (exactly)
* careTeam[ItemClaimMember].extension contains CareTeamClaimScope named careTeamClaimScope 1..1 MS
* careTeam[ItemClaimMember].extension[careTeamClaimScope].valueBoolean = false (exactly)
// Apply this last so that slices above don't treat it as an inherited constraint and suppress it from the differential
* careTeam.extension contains CareTeamClaimScope named careTeamClaimScope 1..1 MS

I'll also pipe in on that other thread and try to determine what things should be redeclared in slices (and when) so that in the future you don't need to resort to these rule-ordering tricks.

view this post on Zulip Jean Duteau (Oct 14 2021 at 15:21):

woo hoo! success! now I can just fix my 64 warnings from terminology and examples :)

view this post on Zulip Chris Moesel (Nov 12 2021 at 20:52):

Hey @Jean Duteau. We've improved SUSHI's handling of this in SUSHI 2.2.0. Now your original FSH should work without needing to do the rule-order hack I suggested before. All constraints from the base element are mirrored into the slice when the slice is created.


Last updated: Apr 12 2022 at 19:14 UTC