FHIR Chat · How to slice on the value of an extension · IG creation

Stream: IG creation

Topic: How to slice on the value of an extension


view this post on Zulip Jean Duteau (Sep 02 2021 at 23:56):

I have an extension that has a boolean value and I want to slice based on the true/false value. I've tried a number of different ways of expressing the discriminator and keep getting the following error:

Slicing cannot be evaluated: Unable to resolve discriminator in definitions: extension('http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope').value.ofType(boolean) (@char 1)

The extension is on the Claim.careTeam element and the slice is on the careTeam element (if that is important to know).

Can anyone provide the proper expression for this discriminator? Bonus points if you can explain why:

extension('blah').value

doesn't just work (where blah is the actual url of the extension).

view this post on Zulip Lloyd McKenzie (Sep 03 2021 at 16:38):

My guess is that the ofType bit isn't handled. Can the extension have a value other than boolean? If not, you can leave that bit off

view this post on Zulip Lloyd McKenzie (Sep 03 2021 at 16:39):

If that works, submit a Git issue against the validator for lack of support for ofType

view this post on Zulip Jean Duteau (Sep 03 2021 at 18:15):

I did try 'extension('url').value' and 'extension('url').valueBoolean. They both gave the same error as above.

view this post on Zulip Lloyd McKenzie (Sep 03 2021 at 18:22):

valueBoolean wouldn't be expected to work. You're doing a 'slice by value' and have a fixed value defined for your slices?

view this post on Zulip Jean Duteau (Sep 03 2021 at 18:37):

yes. the extension is a valueBoolean and I have one slice for 'true' and one slice for 'false'.

view this post on Zulip Jean Duteau (Sep 03 2021 at 18:38):

      {
        "id": "Claim.careTeam",
        "path": "Claim.careTeam",
        "slicing": {
          "discriminator": [
            {
              "type": "value",
              "path": "extension('http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope').value"
            }
          ],
          "rules": "open",
          "description": "Slice based on whether the care team member belongs to the overall claim or to an individual claim item."
        },
        "mustSupport": true
      },
      {
        "id": "Claim.careTeam:OverallClaimMember",
        "path": "Claim.careTeam",
        "sliceName": "OverallClaimMember",
        "min": 0,
        "max": "14"
      },
      {
        "id": "Claim.careTeam:OverallClaimMember.extension:careTeamClaimScope",
        "path": "Claim.careTeam.extension",
        "sliceName": "careTeamClaimScope"
      },
      {
        "id": "Claim.careTeam:OverallClaimMember.extension:careTeamClaimScope.valueBoolean",
        "path": "Claim.careTeam.extension.valueBoolean",
        "min": 0,
        "max": "1",
        "patternBoolean": true
      },

view this post on Zulip Lloyd McKenzie (Sep 04 2021 at 19:35):

The id should be ".value:valueBoolean" rather than ".valueBoolean". Similarly, the path should be ".value", not ".valueBoolean"

view this post on Zulip Jean Duteau (Sep 07 2021 at 13:41):

@Grahame Grieve I've worked with the Sushi team and Chris thinks that the slicing is correct. This might be a validator problem. I've checked in the code: https://github.com/HL7/davinci-pas. I'm unsure what to do to move this forward since I want to slice on the boolean value of an extension and the validator appears to not like that slicing discriminator.

view this post on Zulip Chris Moesel (Sep 07 2021 at 14:29):

@Lloyd McKenzie said:

The id should be ".value:valueBoolean" rather than ".valueBoolean". Similarly, the path should be ".value", not ".valueBoolean"

My understanding is that this shortcut syntax (valueBoolean) is allowed in the discriminator -- and we even see it used like this in some core FHIR profiles. When the IG Publisher processes it, it correctly converts the shortcut paths/ids to their standard variants (id value[x]:valueBoolean, path value[x]) in the snapshot. I have confirmed this myself.

view this post on Zulip Lloyd McKenzie (Sep 07 2021 at 15:00):

I know some tools support it. I'm not clear that it's "allowed". @Grahame Grieve?

view this post on Zulip Grahame Grieve (Sep 17 2021 at 02:24):

@Jean Duteau looking at this, I can improve the error to be more informative, and so I have. Now, I get this error:

Slicing cannot be evaluated: Unable to resolve discriminator extension('http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope').value found in the definitions because the extension http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope wasn't found in the profile http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-claim-update

view this post on Zulip Jean Duteau (Sep 17 2021 at 04:17):

so profile-claim-update has profile-claim as its parent. the careTeamClaimScope is found in profile-claim. profile-claim-update just puts constraints on supportingInfo and item.

view this post on Zulip Jean Duteau (Sep 17 2021 at 04:20):

when I look at the snapshot of profile-claim-update, the careTeamClaimScope extension is there:

      {
        "id": "Claim.careTeam.extension:careTeamClaimScope",
        "path": "Claim.careTeam.extension",
        "sliceName": "careTeamClaimScope",
        "short": "Extension",
        "definition": "A flag that indicates whether the care team applies to the entire claim or a single item.",
        "min": 1,
        "max": "1",
        "base": {
          "path": "Element.extension",
          "min": 0,
          "max": "*"
        },
        "type": [
          {
            "code": "Extension",
            "profile": [
              "http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope"
            ]
          }
        ],

view this post on Zulip Grahame Grieve (Sep 17 2021 at 04:28):

well, not so fast. here's an even more improved error message once I got to that same point:

view this post on Zulip Grahame Grieve (Sep 17 2021 at 04:28):

Slicing cannot be evaluated: Unable to resolve discriminator extension('http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope').value on Claim.careTeam:OverallClaimMember found in the definitions because the extension http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope wasn't found in the profile http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-claim-update

view this post on Zulip Jean Duteau (Sep 17 2021 at 04:31):

      {
        "id": "Claim.careTeam:OverallClaimMember",
        "extension": [
          {
            "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name",
            "valueString": "CareTeam"
          }
        ],
        "path": "Claim.careTeam",
        "sliceName": "OverallClaimMember",
        "short": "Members of the care team",
        "definition": "The members of the team who provided the products and services.",
        "requirements": "Common to identify the responsible and supporting practitioners.",
        "min": 0,
        "max": "14",
        "base": {
          "path": "Claim.careTeam",
          "min": 0,
          "max": "*"
        },
        "type": [
          {
            "code": "BackboneElement"
          }
        ],

view this post on Zulip Grahame Grieve (Sep 17 2021 at 04:35):

right. and then the extension inside it...

view this post on Zulip Grahame Grieve (Sep 17 2021 at 04:35):

{
        "id" : "Claim.careTeam:OverallClaimMember.extension:careTeamClaimScope",
        "path" : "Claim.careTeam.extension",
        "sliceName" : "careTeamClaimScope",
        "short" : "Extension",
        "definition" : "An Extension",
        "min" : 0,
        "max" : "*",
        "base" : {
          "path" : "Element.extension",
          "min" : 0,
          "max" : "*"
        },
        "type" : [
          {
            "code" : "Extension"
          }
        ],
        "constraint" : [
          {
            "key" : "ele-1",
            "severity" : "error",
            "human" : "All FHIR elements must have a @value or children",
            "expression" : "hasValue() or (children().count() > id.count())",
            "xpath" : "@value|f:*|h:div",
            "source" : "http://hl7.org/fhir/StructureDefinition/Element"
          },
          {
            "key" : "ext-1",
            "severity" : "error",
            "human" : "Must have either extensions or value[x], not both",
            "expression" : "extension.exists() != value.exists()",
            "xpath" : "exists(f:extension)!=exists(f:*[starts-with(local-name(.), \"value\")])",
            "source" : "http://hl7.org/fhir/StructureDefinition/Extension"
          }
        ],
        "isModifier" : false,
        "isSummary" : false
      },

view this post on Zulip Grahame Grieve (Sep 17 2021 at 04:35):

no profile, so no match

view this post on Zulip Grahame Grieve (Sep 17 2021 at 04:46):

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 :-(

view this post on Zulip Grahame Grieve (Sep 17 2021 at 04:46):

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

view this post on Zulip Grahame Grieve (Sep 17 2021 at 04:47):

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

view this post on Zulip Grahame Grieve (Sep 17 2021 at 04:47):

usually, it doesn't matter, since the validator tests both

view this post on Zulip Grahame Grieve (Sep 17 2021 at 04:48):

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

view this post on Zulip Jean Duteau (Sep 17 2021 at 04:59):

okay, i understand what that says, but I'm not sure how to accomplish it.

view this post on Zulip Grahame Grieve (Sep 17 2021 at 05:18):

profile the extension on the slice the same way you did it on the base

view this post on Zulip Jean Duteau (Sep 17 2021 at 05:38):

okay, had to do some FSH trickery, but I think I did that as I'm getting different errors now. will look into it...

view this post on Zulip Jean Duteau (Sep 17 2021 at 05:54):

okay, next question that is sort of related:
with the discriminator as

extension('http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope').value

I get an error that "...the discriminator XXX does not have fixed value, binding or existence assertions"

When I change it to be ...valueBoolean, I get a different error: "Unable to resolve discriminator in definitions: valueBoolean"

view this post on Zulip Grahame Grieve (Sep 17 2021 at 06:12):

well, commit that, and I'll have a look.

view this post on Zulip Jean Duteau (Sep 17 2021 at 13:23):

committed. thank you.

view this post on Zulip Jean Duteau (Sep 18 2021 at 20:01):

@Grahame Grieve whenever you get a chance...

view this post on Zulip Jean Duteau (Sep 27 2021 at 21:57):

@Grahame Grieve if you can let me know what I'm doing wrong, I'd like to finish getting this IG ready for publication. https://github.com/HL7/davinci-pas

view this post on Zulip Grahame Grieve (Sep 28 2021 at 03:58):

your expression is

extension('http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope').valueBoolean

view this post on Zulip Grahame Grieve (Sep 28 2021 at 03:58):

see https://hl7.org/fhir/fhirpath.html#polymorphism

view this post on Zulip Grahame Grieve (Sep 28 2021 at 03:59):

should be

extension('http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope').value as Boolean

view this post on Zulip Jean Duteau (Sep 28 2021 at 04:18):

okay, I had that at one time but changed it when I was getting the previous error. running a build to check...

view this post on Zulip Jean Duteau (Sep 28 2021 at 04:22):

that still gave me the same error:

Slicing cannot be evaluated: Could not match discriminator ([extension('http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope').value as Boolean]) for slice Claim.careTeam:OverallClaimMember in profile http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-claim-update - the discriminator [extension('http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-careTeamClaimScope').value as Boolean] does not have fixed value, binding or existence assertions

view this post on Zulip Grahame Grieve (Sep 28 2021 at 04:23):

well, it's progress. Commit that and I'll have another look

view this post on Zulip Jean Duteau (Sep 28 2021 at 04:30):

done

view this post on Zulip Grahame Grieve (Sep 28 2021 at 07:21):

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

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

@Grahame Grieve, thanks for the analysis of this. I've done some further analysis and posted my findings here.

While I provided Jean a work-around, it seems that the right solution is for SUSHI to redeclare extensions in each slice. Are there any other constraints or ElementDefinition fields that we also should redeclare (i.e. copy) from the base when people create slices of an element?

view this post on Zulip Grahame Grieve (Oct 17 2021 at 20:15):

I think pretty much everything

view this post on Zulip Chris Moesel (Oct 18 2021 at 12:30):

OK! That makes it pretty easy then. Thanks!

view this post on Zulip Chris Moesel (Nov 22 2021 at 19:31):

@Grahame Grieve -- we're working through the implications of what it means to redeclare "pretty much everything" from a slice base's differential to its individual slices. Having done some initial implementation, we're seeing a few things we want to ask about:

  • Does it make sense to redeclare the slice base's metadata like short, definition, comment, etc in each slice?
  • If a choice type is restricted to one type, but a type slice is used to further constrain the element, should the type slice also have the type in its differential? E.g.:
    • Observation.value[x] in the profile has "type": [{ "code": "Quantity" }]
    • If the profile also has an Observation.value[x]:valueQuantity element, should it also have "type": [{ "code": "Quantity" }] in its differential?
  • If a slice base has constraints on child elements (e.g., Observation.component.code has a contraint), then should the differential introduce Observation.component:SliceA.code just to redeclare that constraint?

view this post on Zulip Grahame Grieve (Nov 29 2021 at 04:50):

Does it make sense to redeclare the slice base's metadata like short, definition, comment, etc in each slice?

mostly, I think. it's hard to answer that without more context

If a choice type is restricted to one type, but a type slice is used to further constrain the element, should the type slice also have the type in its differential? E.g.:
Observation.value[x] in the profile has "type": [{ "code": "Quantity" }]
If the profile also has an Observation.value[x]:valueQuantity element, should it also have "type": [{ "code": "Quantity" }] in its differential?

I think so? Again, hard without context but this us about reprofiling?

If a slice base has constraints on child elements (e.g., Observation.component.code has a contraint), then should the differential introduce Observation.component:SliceA.code just to redeclare that constraint?

I think so? Again... hard to answer without context

view this post on Zulip Chris Moesel (Dec 02 2021 at 21:38):

Thanks for the responses, @Grahame Grieve. We've decided that for now we will address the immediate problem at hand -- which is that the validator needs extensions redeclared in slices in order to process discriminator paths that use the extension() function. Since slices conceptually inherit constraints from the base slice, we think its less disruptive now if we only redundantly declare the inherited constraints in cases where we know they cause problems otherwise. This will be in the next SUSHI release.


Last updated: Apr 12 2022 at 19:14 UTC