-
Notifications
You must be signed in to change notification settings - Fork 0
Add FHIR Type to fromFHIR function signature #46
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't fully reviewed/tested, but have a few questions...
@@ -1740,7 +1747,8 @@ function generateFromFHIRAssignment(field, fhirElement, fhirElementPath, shrElem | |||
if (shrType.isPrimitive && !isExtension) { | |||
rhs = fhirPathString; | |||
} else { | |||
rhs = `FHIRHelper.createInstanceFromFHIR('${shrType.fqn}', ${fhirPathString}, shrId, allEntries, mappedResources, referencesOut, ${isExtension})`; | |||
const fhirType = fhirElement.type[0].code; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it safe to assume that the type at index 0
is the right type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. Off the top of my head I'm not sure of all the reasons that a FHIR element might have multiple types, but if this was originally a choice type like value[x]
then it's been pre-processed so that it appears to be a single choice with a single type, and that's the use case where this is most relevant.
Not conclusive proof, but running through the current spec there are no instances where there is a second type available to choose here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Yes, if we've already handled [x]
types before this then I think that should be fine.
@@ -41,15 +41,16 @@ function generateFactory(namespaces) { | |||
cw.blComment(() => { | |||
cw.ln('Create an instance of a class from its FHIR representation.') | |||
.ln('@param {Object} fhir - The element data in FHIR format (use `{}` and provide `type` for a blank instance)') | |||
.ln(`@param {string} [type] - The (optional) type of the element (e.g., 'http://standardhealthrecord.org/spec/shr/demographics/PersonOfRecord'). This is only used if the type cannot be extracted from the JSON.`) | |||
.ln(`@param {string} fhirType - the type of the FHIR object that was passed in, in case not otherwise identifiable from the object itself`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is fhirType
optional? I noticed you pass in null
for it in some of the cases above. So it seems it must be optional? The shrType
below explicitly states that it is optional (in the description).
Also note that in jsdoc, you can indicate a parameter is optional by surrounding it in [
]
. See: https://jsdoc.app/tags-param.html#optional-parameters-and-default-values
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I see you did use the [
]
jsdoc syntax in the namespace factory... so I guess you knew. Maybe you missed it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think I first learned I could do that between here and the namespace factory. For consistency I'll change the namespace factory comment to remove the brackets. Technically whether it's optional or not will depend on the individual class, since most classes won't use it but some will require it.
I just thought of a good test case for this, so I will plan to add that today as well. Following along the example in the description above, mock out the |
@dehall -- OK. I was planning to review and merge this today, so let me know when it is ready. |
@cmoesel ready for review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good, tests pass, but I'd suggest one change for consistency. See individual comment for details.
createInstanceFromFHIR: function(key, value, shrId, allEntries=[], mappedResources={}, referencesOut=[], asExtension=false) { | ||
if (Array.isArray(value)) { | ||
return value.map(v => FHIRHelper.createInstanceFromFHIR(key, v, shrId, allEntries, mappedResources, referencesOut, asExtension)); | ||
createInstanceFromFHIR: function(shrType, fhir, fhirType, shrId, allEntries=[], mappedResources={}, referencesOut=[], asExtension=false) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code has three basic implementations of functions called createInstanceFromFHIR
: this one, a high-level one generated on ObjectFactory
, and one on each NamespaceFactory
.
The latter two have signature:
function(fhir, fhirType, shrType, shrId=uuid(), allEntries=[], mappedResources={}, referencesOut=[], asExtension=false)
But this one has signature:
function(shrType, fhir, fhirType, shrId, allEntries=[], mappedResources={}, referencesOut=[], asExtension=false)
Note that they are almost exactly the same except for the order of the first three arguments. Ideally, there should be consistency between all of them in order to avoid stupid and unintentional mistakes (probably to be made by me).
So... can we either change this signature to match the others or change the others to match this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the other locations to match this one, I think it's fewer code changes and in simpler places, plus the ordering feels more consistent with how createInstanceFromFHIR('ns.Class', fhir, ...)
turns into Class.fromFHIR(fhir, ....)
.
Also I updated the comments for shrType
similarly to the above, originally they said "optional" but it can be required depending on other parameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
Adds FHIR type to the fromFHIR function signature, as a foundation for future changes to address #35. One solution referenced there uses the approach that the "receiving" function, such as shr.base.Reason.fromFHIR in that example, uses a lookup to figure out what the incoming data is. After some thought that seems potentially error-prone, because the "sending" function should in theory always know what the type of everything actually is.
Where this is most valuable is in cases like Observation which has many different options for value[x]. This proposed approach would result in something like this:
And then DataValue.fromFHIR can reference the given type to know what to do with the given object.
Note that nothing actually uses this yet, that fix will have to come later as I find more time. The intent for now is just that this will make manual fixes easier, so only the function signature being correctly aligned is needed right now.