Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypedElementOnSourceNode throws StructuralTypeException on .value for "complex" logical model data type #1606

Closed
alexzautke opened this issue Jan 26, 2021 · 5 comments · Fixed by #1623
Assignees

Comments

@alexzautke
Copy link
Member

alexzautke commented Jan 26, 2021

Describe the bug
In (C)-CDA or other logical models an element within an ITypedElement tree might have a value even if the InstanceType of this element is "complex", e.g. when the InstanceType is a LogicalModel datatype with a .value child (+ "xmlAttr" for ElementDefinition.representation). In the 1.9 version of the SDK, accessing such value only worked because we tested it only with data type uris beginning with "http". This bypassed a check in TypedElementOnSourceNode to see if the element contained a primitive value (the type name always began with a lower case char). Due to the new tryMapFhirPrimitiveTypeToSystemType mapping, this trick no longer works. An StructuralTypeException is thrown before we can even check if the type is a logical model data type.

To Reproduce
See unit test TestValueAttrRepresentationLogicalModelDataType in Hl7.FhirPath.Tests.ElementNodeTests (Branch: fix/1606-typedelementonsourcenode-logical-model-data-type)

Expected behavior
TypedElementOnSourceNode should return the value of the .value child as in version 1.9.0 and earlier.

Version used:

  • FHIR Version: [STU3]
  • Version: [2.0.2]
@joelemaltais
Copy link

joelemaltais commented Jan 27, 2021

This is the last issue blocking the release of the FHIR Mapper based on this version of the SDK - unless we release without CDA Support.

@ewoutkramer
Copy link
Member

ewoutkramer commented Feb 4, 2021

In the 1.9 version of the SDK, accessing such value only worked because we tested it only with data type uris beginning with "http". This bypassed a check in TypedElementOnSourceNode to see if the element contained a primitive value

That's interesting how a bug actually was a feature. For laughs, here's the 1.9 version of the code, which determines whether the InstanceType is a primitive:

if (!Primitives.IsPrimitive(InstanceType))
{
    raiseTypeError($"Since type {InstanceType} is not a primitive, it cannot have a value", Source, location: Source.Location);
    return null;
}

// Type might still be a custom "primitive" type for logical models
if (Uri.IsWellFormedUriString(InstanceType, UriKind.Absolute))
{    

Primitives.IsPrimitive() wasn't really that smart, it just checked whether the first letter of the type is lower case. So, because logical types start with http:// and the h is a lower case, the code would go on and proceed to the check for a logical model type.

I am not surprised this "feature" disappeared when I rewrote this code for 2.0 😄

@ewoutkramer
Copy link
Member

ewoutkramer commented Feb 4, 2021

The story continues.

So, even with this code bypassed, an interesting issue surfaced. Take a look at the bit of code that tries to figure out the actual primitive used by the logical model. It does this by figuring out the type of the value element of the instance type encountered:

// Type might still be a custom "primitive" type for logical models
if (Uri.IsWellFormedUriString(InstanceType, UriKind.Absolute))
{
     var summary = Provider.Provide(InstanceType);
     var valueType = summary?.GetElements().FirstOrDefault(e => 
               e.ElementName.Equals("value"))?.Type.FirstOrDefault()?.GetTypeName();
     if (!P.Any.TryGetSystemTypeByName(valueType, out ts))
                        throw new InvalidOperationException($"Cannot figure out what the primitive type is jadajada....");
}

So, in the given example, it encounters a logical type that represents the v3 TEL datatype (and so, the actual InstanceType is http://hl7.org/fhir/StructureDefinition/TEL here). Now, the code resolves this and looks for the value element within the definition of the TEL datatype. It will find the /FHIR/ datatype uri.

And then, of course, this still fails. Because in the rewrite I had assumed that CDA types express their value members in System types, not FHIR types (because, hey, you're CDA, not FHIR).

Is this expected?

For now, I'll make it work like 1.9, so, I'll interpret the datatype as a FHIR primitive not a System primitive.

@alexzautke
Copy link
Member Author

Oh that bit I missed. Yes, it should be a FHIR primitive. The StructureDefinitions for CCDA are not generated by us (at least for now) and the Java tooling is not working with system types at that level. When we switch to system types here, we can discuss this in a new feature request ticket.

@ewoutkramer
Copy link
Member

Thanks for the excellent bug report + fix branch by the way, that saved my hours of trying to replicate this....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants