FHIR Chat · Structure Definition · implementers

Stream: implementers

Topic: Structure Definition


view this post on Zulip Chris Grenz (Apr 07 2016 at 15:13):

Quick ? - only HL7 can use StructureDefintion.derivation = specialization, correct? @Michel Rutten What are you doing with this in Forge?

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:18):

@Chris Grenz Forge is still based on FHIR DSTU2, whereas StructureDefinition.derivation was introduced in DSTU3. For new profiles, Forge currently initializes StructureDefinition.constrainedType to the selected base resource type.

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:19):

specialization seems intended for logical models (and core resources?)

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:20):

Seems like there's a lot of churn in that part of the SD with changed in kind/type/contextType etc.

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:20):

I'm struggling a bit to keep my tooling current! Right now, we're supporting 0.5, 1.0.x, and (soon) 1.4.

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:20):

Yes, we discussed some of these changes in Atlanta. in STU3 it should be more regular.

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:21):

Must've missed that discussion...

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:21):

We will upgrade all our tools (incl. Forge) to STU3 after the Montreal balloting rounds. Until then, we will stick to DSTU2.

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:22):

Also, really struggling with the benefit of elementdefintion.base. What was the motivation there?

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:22):

It allows tooling to quickly determine the original path of the associated base element.

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:24):

When would base.path != path?

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:24):

And cardinality, e.g. if base resource defines an element as 0...* then a code generator would generate a List property. If a derived profile constrains the element to 0..1, then a code generator would still need to generate a List property, in order for the derived class to be compatible with the base class. The ElementDefinition.base component specifically solves this problem.

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:24):

e.g. for choice elements, base path ends with "value[x]" where actual path ends with "valueString".

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:24):

OK...nice for XML to JSON for sure. That could just be a single flag though...

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:25):

So path="valueString" and base.path = "value[x]"?

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:25):

This information could be calculated by resolving the base resource profile or expanding the snapshot, but this is a costly operation.

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:25):

e.g. path = "Observation.value[x]", base.path = "Observation.valueString"

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:26):

Does base just go back one generation, or all the way back to the first appearance of the element?

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:26):

In Forge, I currently initialize all the element base components while opening/loading the resource. This ensures that other business logic can safely assume the information is present and correct.

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:27):

Good question... I'd have to think about that. I assume element.base refers to the path in the root profile, but I'm not sure - need to carefully look at an example.

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:28):

So Patient baseDefinition of Acme-Patient baseDefinition of Acme-Neuro-Patient.

  • Acme-Patient has path = "Patient.deceasedDatetime" (base.path = "Patient.deceased[x]")
  • Acme-Neuro-Patient as path="Patient.deceasedDatetime" for further constraint. What is base.path?

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:28):

According to the description, element.base.path always refers to a core structuredefinition without a StructureDefinition.base component.

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:29):

ElementDefinition.base.path: "The Path that identifies the base element - this matches the ElementDefinition.path for that element. Across FHIR, there is only one base definition of any element - that is, an element definition on a StructureDefinition without a StructureDefinition.base."

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:29):

So Acme-Neuro-Patient has the same base.path = "Patient.deceased[x]"

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:29):

OK...so the "most base" element definition. And element[x] is always "more base" than elementType.

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:29):

ok...fair enough!

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:29):

This makes sense, as this is the information that is useful in application logic.

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:30):

thanks!

view this post on Zulip Michel Rutten (Apr 07 2016 at 15:32):

np. FHIR should be crystal clear on these concepts, so it's important we discuss this.

view this post on Zulip Chris Grenz (Apr 07 2016 at 15:33):

Part of this is that there's getting to be some mental "inertia" for some of us! "Now what happened there?" frequently crosses my mind!

view this post on Zulip Grahame Grieve (Apr 11 2016 at 05:20):

base is really useful if a structure definition profiles a data type inline - just walks straight into it

view this post on Zulip Grahame Grieve (Apr 11 2016 at 05:21):

path = Observation.valueQuantity.unit, base = Quantity.unit

view this post on Zulip Grahame Grieve (Apr 11 2016 at 05:21):

It's on my task list to write up how the FHIR typing system works formally for the current build.

view this post on Zulip Grahame Grieve (Apr 11 2016 at 05:21):

or we can work through it when I come visit you ;-)

view this post on Zulip Chris Grenz (May 17 2016 at 17:49):

Right now, I think the general understanding is that snapshot and differential should be calculable from each other (round trip-able). Maybe should be a little clearer on this. Consider the need for a profiler to define a profile that includes only a particular set of extensions from an enterprise set (the profile uses the enterprise profile as its baseDefintion). For instance, a cardio service may define a profile of encounter that uses 5 of the 25 extensions defined by the enterprise.

Question is: how does the profiler enforce the limitation of only 5 extensions (not cardinality, 5 urls)? He can close the slicing and max=0 the 20 to be disallowed. But if/when the enterprise defines the 26th, it will appear in the cardio profile.

IF we allow definition by snapshot, it would be possible to explicitly limit the slices that appear, but the machinery gets a little wonky (snapshot is always a superset of all elements/sliced defined in the baseDefinition lineage). Is there a mechanism to meet this use case I'm missing?

view this post on Zulip Grahame Grieve (May 17 2016 at 19:38):

if you allow 5 and close, then why does it matter if another is defined somewhere else?

view this post on Zulip Chris Grenz (May 17 2016 at 19:38):

If it's added to your baseDefinition, you'll (forcibly) inherit it.

view this post on Zulip Grahame Grieve (May 17 2016 at 19:39):

why? you said, these 5, and closed it.

view this post on Zulip Chris Grenz (May 17 2016 at 20:50):

The base has extension.slicing.rule="open" and defines 25 extensions. My profile closes the extensions (extension.slicing.rule="closed") and max=0 all the ones I want to exclude. But if another appears in the base (the 26th), it will already be part of my closed slicing (by inheritance). There's no way to block that...

view this post on Zulip Michel Rutten (May 19 2016 at 14:40):

@Chris Grenz how about if the derived profile defines another extension slice with max = 0 and no url property. Since the extension slice discriminator is always the url (per definition), this "catch-all" constraint would match any remaining extensions that do not match any of the other extension slices, at least conceptually. If this constraint then specifies max = 0, it would explicitly suppress any implicitly inherited extensions from the base profile not matched by any of the other slices. Do you think this could work?

view this post on Zulip Chris Grenz (May 19 2016 at 14:43):

Yes, that would work. Do we state what happens when a discriminator isn't set? I think it should work as you describe...

view this post on Zulip Chris Grenz (May 19 2016 at 18:33):

@Michel Rutten maybe not now that I think about it. Only _one_ slice may apply to any instance. I don't think this means that a "catch all" is valid since both the catch all and the specific version would apply to an instance with a related slice definition. In other words, an extension slice with no fixedUri for @url would apply to all extension instances and therefore disallow any other slices.

view this post on Zulip Chris Grenz (May 19 2016 at 18:34):

What you *could* do though would be to define a type profile of extension where max=0 for the url element. But that would require slicing extension by @profile and not url.

view this post on Zulip Chris Grenz (May 19 2016 at 18:34):

And the discriminator for extension is fixed to url.

view this post on Zulip Michel Rutten (May 20 2016 at 11:34):

@Chris Grenz yes, that seems to be correct. My suggestion would require a change to the standard, in order to define the proposed interpretation and behavior as such. I was just thinking out loud about how to cover your use case. Your suggestion of using a type profile might also work, but slicing by profile can be (very) computationally intensive and might not be supported by many FHIR servers. So personally, I consider this to be an advanced technique that you should use only if there are not simple alternative ways to express the intended constraints.

view this post on Zulip Michel Rutten (May 20 2016 at 11:40):

Seems like the expressive power of SlicingRules are too limited to express the desired constraints of your use case. It somewhat resembles binding strength, through wich a profile author can limit binding overrides in a derived profile. Maybe we can expand the SlicingRules?

view this post on Zulip Chris Grenz (May 20 2016 at 13:42):

(deleted)

view this post on Zulip Chris Grenz (May 20 2016 at 13:43):

Would really like to come up with a way to express this without a major breaking change....

view this post on Zulip Chris Grenz (May 20 2016 at 13:53):

I may be that what I'm trying to do breaks the concept of polymorphic inheritance and shouldn't actually be allowed. There's no way in most object oriented languages for a sub-type to constrain changes on the super-type or, more precisely, for the sub-type to selectively decide what to inherit from the super-type.

view this post on Zulip Chris Grenz (May 20 2016 at 13:53):

But that's not exactly how the FHIR type system works either....

view this post on Zulip Chris Grenz (May 20 2016 at 13:55):

I like your suggestion of a "everything else" slice...a notation for that might be the least disruptive.

view this post on Zulip Chris Grenz (May 20 2016 at 13:56):

It makes parsing somewhat harder though since all other slices have to be exhausted before it would match...similar to evaluating the "closed" rule.

view this post on Zulip Chris Grenz (May 20 2016 at 13:57):

Sorry for the rambling....that won't actually work either since the slices actually *are* defined in the baseDefinition and would just inherit intact.

view this post on Zulip Michel Rutten (May 20 2016 at 15:15):

Hmm... you always come up with these interesting cases ;p I definitely agree that it is preferred to find a compatible solution that doesn't introduce any breaking changes. Just having a hard time to find one. In this case, if I understand correctly, you need to suppress the inheritance of (yet) unknown information from the base profile. However SliningRule = closed on your derived profile only applies to profiles that derive from the derived profile, i.e. downstream 3rd+ level profiles. It does not lImit the inheritance from the original base profile and therefore cannot protect against future additions to the base profile, right? Hence my feeling that in order to express this behavior, we might have to expand SlicingRule with yet another option, e.g. sealed or something.

view this post on Zulip Chris Grenz (May 20 2016 at 16:58):

The primary issue is that we define by differential. We can only define how the profile is different from the base. So, we'd need to be able to re-generalize base specializations, e.g. create a slice that encompasses a set (an open ended set!) of base slices. While my use case is real, it really feels like an architecturally unsound thing to do within the profile hierarchy.

view this post on Zulip Chris Grenz (May 20 2016 at 17:02):

An alternate might be a profile that requires conformance to another profile but doesn't inherit from it. Unfortunately I think I accidentally removed this possibility with GF#9814 when we removed type from the root element. While I don't *think* anyone was enforcing this, it would have been possible for a profile to set type.profile on the root element and therefore force conformance with another profile.

view this post on Zulip Chris Grenz (May 20 2016 at 17:04):

With this, I could create a profile that required conformance to anther profile (e.g. an enterprise Patient profile) without using that as a base.

view this post on Zulip Michel Rutten (May 23 2016 at 14:18):

@Chris Grenz There has been some discussion on supporting (the union of) multiple profiles. I specifically remember that Claude Nanjo would has requested support for this functionality. The idea being that instead of having a single-inheritance chain of profiles, you can combine/overlay/aggregate multiple separate profiles into one. This would allow a more composition-based / aspect-oriented profiling approach. However because of the complexity and calculation costs, we haven't even started to implement any of this (yet...). Note that in Forge, the element type profile textbox actually allows you to enter multiple profile urls (press enter to add another line), however Forge currently only validates the first type profile and ignores any remaining type profiles. And Grahame informed me that he is not about to implement support for this in his server.

view this post on Zulip Chris Grenz (May 23 2016 at 14:30):

I've thought about multiple inheritance as well and found it to be as distasteful as it was in programming languages. I would differentiate though between multiple inheritance and additional conformance constraints: each profile must only inherit from one profile, but they could state conformance to other profiles. This wouldn't cause the other profiles' content to be included. It would just state an additional (complex) constraint.

view this post on Zulip Grahame Grieve (May 23 2016 at 21:00):

we can calculate whether a profile is a constraint on another or whether it's consistent with another

view this post on Zulip Chris Grenz (May 23 2016 at 21:02):

Yes, but we can't use another profile as a constraint (such as we can do with individual element type profiles) to the whole profiled type.

view this post on Zulip Grahame Grieve (May 23 2016 at 21:12):

the first is - all instances that conform t profile A conform to profile B

view this post on Zulip Grahame Grieve (May 23 2016 at 21:12):

the second is - there are some instances that conform to both profiles

view this post on Zulip Grahame Grieve (May 23 2016 at 21:12):

agree that we should only try to deal with one explicit parent

view this post on Zulip Chris Grenz (May 23 2016 at 21:13):

So if I define an "Enterprise Patient" profile, could I (without inheriting from it) say that a conformant resource MUST also be DAF-Patient conformant?

view this post on Zulip Grahame Grieve (May 23 2016 at 21:15):

yes, by explicitly requiring that in your meta.profile. but not implicitly no

view this post on Zulip PS (Feb 11 2020 at 04:28):

How can we pass our own structure definition(In JSON or XML) to Hl7.Fhir.Specification (.net package provided by fire.ly) so that it can validate against the object?
Thanks

view this post on Zulip Grahame Grieve (Feb 11 2020 at 05:31):

you might get a quicker answer if you post this question to #dotnet

view this post on Zulip PS (Feb 11 2020 at 05:46):

Will do. Thanks

view this post on Zulip Radha Rajendran (Apr 08 2021 at 09:52):

Hello all,

Can anyone please share structure definition examples with minValue and maxValue ?
These fields are choice of datatype, so could not find the exact key name for this fields .

view this post on Zulip Lloyd McKenzie (Apr 08 2021 at 15:27):

Already asked and answered here: https://chat.fhir.org/#narrow/stream/179166-implementers/topic/StructureDefinition.20.20and.20unknown.20properties


Last updated: Apr 12 2022 at 19:14 UTC