-
Notifications
You must be signed in to change notification settings - Fork 43
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
Fish With Version #1275
Fish With Version #1275
Conversation
- Add support to FSHTank to fish with a version - Add helper function to determine if a version is set on a FSH definition, which can be used by the FSHTank fish() function - Add helper functions for fishing for best version - a version that matches or any version if match is not found - Replace most places where fishing was done without any version that was specified Note: this will need an updated FPL in order to have FHIRDefinitions fish correctly with a version
…nd for FishingUtils
…eck fishing for VS URL with version throws mismatch error
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.
Wow. This turned out to be pretty intense! But... we finally have a more consistent approach to handling versioned canonicals! Thank you!
I found a few things that I think can be improved and/or fixed and/or removed. But... this is looking very good!
src/export/ValueSetExporter.ts
Outdated
@@ -57,7 +57,7 @@ export class ValueSetExporter { | |||
if (component.from.system) { | |||
const systemParts = component.from.system.split('|'); | |||
const foundSystem = ( | |||
this.fisher.fishForMetadata(systemParts[0], Type.CodeSystem)?.url ?? | |||
this.fisher.fishForMetadata(component.from.system, Type.CodeSystem)?.url ?? |
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 see that this change makes it more consistent w/ the approach we take for value sets below -- so that's good.
I also see that if there is a version, we drop the version when there's a match but keep it when there isn't (value sets below does the same thing). I think this is one of those places where we want to keep the version when there is a match. I think we had decided, however, that these kinds of changes aren't necessarily in scope for this PR and can be deferred to another PR if we want.
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.
Now that I have your nifty regex replace in my back pocket, I don't mind doing it here. But I can also hold off for a separate PR if that's preferred.
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, wait, now I'm not sure if I agree we should keep the version. The version the author specified gets added to the composeElement.version
regardless of if we find a match on line 63. And because the foundSystem
variable does a final split('|')
and then only foundSystem[0]
is used later, the version is always spliced off and never added to composeElement.system
. So do we want to include the |version
on the system
property, as well as on the version
property?
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.
Oh, dang. You're right! For whatever reason, ValueSet.compose.include
splits the version off into its own element. And the system
element is uri
not canonical
. So, yep, we definitely do not want to attach the |version
. Good call!
test/export/InstanceExporter.test.ts
Outdated
const visibleSystem = new FshCodeSystem('Visible'); | ||
const visibleSystemVersion = new CaretValueRule(''); | ||
visibleSystemVersion.caretPath = 'url'; | ||
visibleSystemVersion.value = 'http://hl7.org/fhir/us/minimal/CodeSystem/Visible|1.0.0'; |
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 don't think a CodeSystem
definition would declare its url
with a version. The url
would be the version-less URL and the version
element would contain the version. E.g.
const visibleSystemUrl = new CaretValueRule('');
visibleSystemUrl.caretPath = 'url';
visibleSystemUrl.value = 'http://hl7.org/fhir/us/minimal/CodeSystem/Visible';
const visibleSystemVersion = new CaretValueRule('');
visibleSystemVersion.caretPath = 'version';
visibleSystemVersion.value = '1.0.0';
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 thought I had added this case because of a regression, but I'm not sure which repo without rerunning the regression. I believe this was also tied to this change, and updating to use the regex replace actually causes this test to fail. I guess it is worth keeping the test with the version caret value rule, so I'll update this!
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.
Included in 70e31fc
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.
Technically, CodeSystem.url
is a uri
, so you're not supposed to append a version to it. It even says:
URL should not contain | or # - these characters make processing canonical references problematic
So if someone is making a CodeSystem with a URL like that in a real IG, we shouldn't support it anyway.
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.
Oh! Well maybe I just invented that test case. It seems so specific so I thought I must have pulled it from somewhere, but maybe not. Well, it is no longer supported now!
…lify conditional statements
…signing to a primitive code/string/uri
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.
This looks very good! I ran a regression and got the same two regressions as you did. Upon studying them, however, I realized that they're assigning the value to a code
-- so while the system in the FSH is incorrect, it isn't actually used because primitive code
does not include the system. This means the assignment can still safely happen.
That being the case, I thought it would be more appropriate to detect that situation and warn on it rather than error -- and proceed with the assignment rather than skipping it. So that is what I've done in 3a9f3e9.
Now everything looks good to me and has my approval!
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.
This looks great, thank you! There's one slightly unusual thing that I noticed, but I don't think it necessarily needs to be changed, so I'm giving my approval.
src/fhirtypes/common.ts
Outdated
const codeSystem = fishInTankBestVersion(tank, value.system, Type.CodeSystem); | ||
const codeSystemMeta = fishForMetadataBestVersion(fisher, value.system, Type.CodeSystem); |
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.
This is not really a problem, but it's possible for each of these functions to separately log a warning for a version mismatch if the CodeSystem is retrieved from the package when fishing for metadata. Here's an example that can make this happen:
CodeSystem: BreakfastCS
* ^version = "1.0.0"
* #toast "Toast"
* #donut "Donut"
Instance: MyBreakfast
InstanceOf: Observation
* status = #final
* code = BreakfastCS|2.0.0#toast
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.
Ah, yeah. We technically need to do both fishes -- so the only way I can think of to avoid the double warning is to do the 2nd one based on whatever was actually returned by the first (rather than the original request). E.g.,:
const codeSystemMeta = fishForMetadataBestVersion(fisher, value.system, Type.CodeSystem);
if (codeSystemMeta) {
clone = cloneDeep(rule);
const assignedCode = getRuleValue(clone) as FshCode;
assignedCode.system = value.system.replace(/^[^|]+/, codeSystemMeta.url);
// Find the code system using the returned metadata to avoid duplicate warnings if version mismatches
const matchedCanonical = codeSystemMeta.url
? `${codeSystemMeta.url}${codeSystemMeta.version ? `|${codeSystemMeta.version}` : ''}`
: value.system;
const codeSystem = fishInTankBestVersion(tank, matchedCanonical, Type.CodeSystem);
if (codeSystem && (codeSystem instanceof FshCodeSystem || codeSystem instanceof Instance)) {
// if a local system was used, check to make sure the code is actually in that system
listUndefinedLocalCodes(codeSystem, [assignedCode.code], tank, rule);
}
}
@mint-thompson - I have this change locally and it does worth. Do you think I should push it up?
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 think so, yes. It's not too complicated, and it makes the output more consistent. Thank you!
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. Fixed in 858c75d. I also noticed that the warning messages did not log the source info -- so we'd say there was a mismatch, but it would be up to the author to find it in their FSH files. This didn't seem optimal, so I also updated it to pass along the source info and log that. It's in the same commit.
Also updates system lookup code for FSHCodes to avoid double-warning on mismatched version.
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. I've addressed the double-warning and source info logging. @mint-thompson - can you give it one more review?
src/fhirtypes/common.ts
Outdated
const codeSystem = fishInTankBestVersion(tank, value.system, Type.CodeSystem); | ||
const codeSystemMeta = fishForMetadataBestVersion(fisher, value.system, Type.CodeSystem); |
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. Fixed in 858c75d. I also noticed that the warning messages did not log the source info -- so we'd say there was a mismatch, but it would be up to the author to find it in their FSH files. This didn't seem optimal, so I also updated it to pass along the source info and log that. It's in the same commit.
This PR supports fishing for definitions with a version. This PR adds support for fishing with a specified version in the
FSHTank
and in thePackage
. Support for fishing with a specified version inFHIRDefinitions
is provided by FPL. There is an FPL PR with this support here.In addition to supporting fishing with a version, there are a number of places that SUSHI tries to fish for the version specified but is satisfied if any version is found, but logs a warning. To support this, three util functions are included:
fishForFHIRBestVersion
,fishForMetadataBestVersion
, andfishInTankBestVersion
. These functions will call eitherfishForFHIR
,fishForMetadata
, orfish
(in a Tank) first with the item and specified version. If nothing is found, they'll then try again without a version, and if a definition/metadata is found with a differing version, a warning is logged. I replaced the special case handling SUSHI was doing to slice off the version and check for discrepancies between versions with these functions where possible.To test this, you can use the FPL PR (until a release is ready and available directly in this PR) and link your local FPL to SUSHI. Then you can run the tests and test FSH projects locally.
I ran a full regression and found that two repos had regressions, HL7/vrdr and nightingaleproject/vital_records_fhir_messaging_ig, both with the same issue. Both repos specify a line similar to:
This line is setting a URL with a version as a system in a FSH code. Before, SUSHI was just fishing for this, didn't find a definition so didn't realize it was a ValueSet, checked that it was a valid URI, and successfully used the code system. In this branch, fishing with the version will work correctly and SUSHI will find a ValueSet definition for this definition, which is a problem, and it will throw a MismatchBindingTypeError and not set the value. I think this regression is actually the correct behavior for SUSHI now.
Note: this PR is marked as draft until a new version of FPL is released with support for fishing with versions so that the FHIR Definitions fishing works correctly.FPL v.0.3.0 is used now, so this is no longer draft!