Closed frankadrian314159 closed 2 years ago
I've read through the code and I've found something that seems odd to me. In the BundleTerminologyProvider.initialize() method, in the valueSetIndex HashTable, the collection of expanded Codes are stored under the value set's url as the key. However, in the .expand() method, the expanded codes are being looked up in the valueSetIndex under the value set's id as the key. This will only work if the value set's getId() and getUrl() methods return the same values, something that seems unlikely. In fact, if the getUrl method depends on the existence of a url property on the ValueSet resource, it may fail because the url is an optional property.
The reason why the tests are not failing is that with all of the tests, the value of id is set up using a .withId call, but instead of passing in the value set's id, you pass in the url. This ensures the id (which is then set to the url) matches the url.
Hi @frankadrian314159!
CQL and FHIR represent the version-independent identifiers of the ValueSets differently. The VersionedIdentifier (A CQL concept, not a FHIR concept - it doesn't even have a url property) calls that the "id", while FHIR calls it the "url". That's why the tests map one to the other. The indexing happens in terms of the VersionedIdentifier id, because that's how the CQL engine sees and requests that. Does that make sense?
I'll take a look at the other issue where the ValueSet isn't being correctly located.
Hi JP. Your explanation makes sense.
I will say, however, that in this case ValueSetUtil.getUrl (which is what the ValueSet's expansion is stored under in the initialize method) returns a String of the form com:zzz:valueset:20785a* (the FHIR url for the ValueSet), while the String that I am using as the identifier (and the expand method tries to use for lookup) is 20785a (the FHIR id for the ValueSet) This mismatch is the cause of the failure to locate the value set expansion.
Am I using the wrong identifier for the value set? Is one supposed to use the FHIR url as the identifier for the versioned identifier or should it be the FHIR id? What happens if the ValueSet's FHIR url does not exist (it is optional)?
*the :zzz: emoji is supposed to be zzz. Stupid emojis.
Yes, for FHIR-based CQL you'd generally use the URL. Here's some example CQL to show how it's done: https://github.com/cqframework/ecqm-content-r4-2022/blob/master/input/cql/DischargedonAntithromboticTherapyFHIR4.cql#L10-L13
And here's the relevant specification for CQL used in Quality Measures: https://build.fhir.org/ig/HL7/cqf-measures/using-cql.html#conformance-requirement-4-7
Thank you, JP. As far as I'm concerned, you can close out this issue.
I cloned the cql-evaluator repository about 3 days ago and built the project. I ran into this IllegalArgumentException, which I do not believe is a valid error. In order to make sure that this was not specific to version 1.4.6, I re-cloned and rebuilt the cql-evaluator this morning. I now have version 2.1.0 of the cql-evaluator and this issue still remains.
A test file named Test2.cql.txt (.txt because github's file attacher will not take a .cql file) is attached Test2.cql.txt. When I run this file in the evaluator (using the command line java -jar evaluator-2.1.0.jar cql -lu . -ln Test2 --terminology-url=vocabulary\valueset -fv R4 -c "Unfiltered=Add Medical API Rule 1" -mu \Users\fadrian\Projects\cql-test\input\tests), execution succeeds as I expect, giving the output:
test=org.opencds.cqf.cql.engine.runtime.ValueSet@4cbd03e7 testA=[Procedure(id=2B70A37918AAA2E54240A967896F7B95-46319170-PRCDR), Procedure(id=4C00C4C21FED574151AE7B63D6A42070-46319170-PRCDR), Procedure(id=981F2D079317C4D7CE85003DE2EFE81B-46319170-PRCDR), Procedure(id=DF9172F3F6B0B6CC7F633AB28C04F894-46319170-PRCDR), Procedure(id=2B70A37918AAA2E54240A967896F7B95-46319170-PRCDR), Procedure(id=4C00C4C21FED574151AE7B63D6A42070-46319170-PRCDR), Procedure(id=981F2D079317C4D7CE85003DE2EFE81B-46319170-PRCDR), Procedure(id=DF9172F3F6B0B6CC7F633AB28C04F894-46319170-PRCDR)]
This demonstrates that things seem to be set up properly for execution and that, under normal circumstances, the system can locate ValueSet 20785a and the Procedures it will be asking for in testC.
I then uncomment testC and its dependency, test3. Instead of returning results for test and testA and an empty list (which is what I expect) for testC, I get the following traceback:
org.opencds.cqf.cql.engine.exception.CqlException: java.lang.IllegalArgumentException: Unable to locate ValueSet 20785 at org.opencds.cqf.cql.engine.elm.execution.Executable.evaluate(Executable.java:33) at org.opencds.cqf.cql.engine.elm.execution.FunctionRefEvaluator.internalEvaluate(FunctionRefEvaluator.java:33) at org.opencds.cqf.cql.engine.elm.execution.Executable.evaluate(Executable.java:14) at org.opencds.cqf.cql.engine.elm.execution.ExpressionDefEvaluator.internalEvaluate(ExpressionDefEvaluator.java:19) at org.opencds.cqf.cql.engine.elm.execution.Executable.evaluate(Executable.java:14) at org.opencds.cqf.cql.engine.execution.CqlEngine.evaluateExpressions(CqlEngine.java:191) at org.opencds.cqf.cql.engine.execution.CqlEngine.evaluate(CqlEngine.java:169) at org.opencds.cqf.cql.engine.execution.CqlEngine.evaluate(CqlEngine.java:148) at org.opencds.cqf.cql.evaluator.CqlEvaluator.evaluate(CqlEvaluator.java:89) at org.opencds.cqf.cql.evaluator.CqlEvaluator.evaluate(CqlEvaluator.java:76) at org.opencds.cqf.cql.evaluator.cli.command.CqlCommand.call(CqlCommand.java:159) at org.opencds.cqf.cql.evaluator.cli.command.CqlCommand.call(CqlCommand.java:33) at picocli.CommandLine.executeUserObject(CommandLine.java:1953) at picocli.CommandLine.access$1300(CommandLine.java:145) at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2352) at picocli.CommandLine$RunLast.handle(CommandLine.java:2346) at picocli.CommandLine$RunLast.handle(CommandLine.java:2311) at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2179) at picocli.CommandLine.execute(CommandLine.java:2078) at org.opencds.cqf.cql.evaluator.cli.Main.run(Main.java:19) at org.opencds.cqf.cql.evaluator.cli.Main.main(Main.java:12) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) Caused by: java.lang.IllegalArgumentException: Unable to locate ValueSet 20785 at org.opencds.cqf.cql.evaluator.engine.terminology.BundleTerminologyProvider.expand(BundleTerminologyProvider.java:87) at org.opencds.cqf.cql.evaluator.engine.terminology.PrivateCachingTerminologyProviderDecorator.expand(PrivateCachingTerminologyProviderDecorator.java:47) at org.opencds.cqf.cql.evaluator.engine.terminology.PrivateCachingTerminologyProviderDecorator.in(PrivateCachingTerminologyProviderDecorator.java:25) at org.opencds.cqf.cql.evaluator.engine.retrieve.BundleRetrieveProvider.anyCodeInValueSet(BundleRetrieveProvider.java:89) at org.opencds.cqf.cql.evaluator.engine.retrieve.BundleRetrieveProvider.filterByTerminology(BundleRetrieveProvider.java:151) at org.opencds.cqf.cql.evaluator.engine.retrieve.BundleRetrieveProvider.retrieve(BundleRetrieveProvider.java:56) at org.opencds.cqf.cql.evaluator.engine.retrieve.PriorityRetrieveProvider.retrieve(PriorityRetrieveProvider.java:28) at org.opencds.cqf.cql.engine.data.CompositeDataProvider.retrieve(CompositeDataProvider.java:96) at org.opencds.cqf.cql.engine.elm.execution.RetrieveEvaluator.internalEvaluate(RetrieveEvaluator.java:57) at org.opencds.cqf.cql.engine.elm.execution.Executable.evaluate(Executable.java:14) ... 28 more
which states that the engine is now unable to locate ValueSet 20785a. This is the same traceback that I got in the previous version of the evaluator (generally speaking) in that the BundleTerminologyProvider seems to throw an IllegalArgumentException in this situation.
There are two potential issues here - either there is something that the evaluator code is expecting and not finding which is not required in a value set, or the bundle file is malformed in some way. As such, I have also attached the valueset bundle file 20785a.json.txt so you can assure yourselves that this is a valid JSON file containing a valid FHIR 4.x Bundle which contains a valid FHIR 4.x ValueSet.
Thanks for looking at this.