8
8
9
9
using CLI . Helpers ;
10
10
using Dumpify ;
11
+ using Hl7 . Cql . Abstractions ;
11
12
using Hl7 . Cql . CodeGeneration . NET ;
12
13
using Hl7 . Cql . Fhir ;
13
14
using Hl7 . Cql . Fhir . Serialization . Extensions ;
14
15
using Hl7 . Cql . Invocation . Toolkit ;
15
16
using Hl7 . Cql . Invocation . Toolkit . Extensions ;
17
+ using Hl7 . Cql . Primitives ;
16
18
using Hl7 . Cql . Runtime ;
17
19
using Hl7 . Cql . ValueSets ;
18
20
using Hl7 . Fhir . Model ;
@@ -50,25 +52,66 @@ public void RunWithResources()
50
52
{
51
53
//run using Library Resource files - production scenario, no debugging inline with measures project
52
54
Console . WriteLine ( $ "Loading resources for Library: { _opts . Library } ") ;
53
- var librarySetName = CqlVersionedLibraryIdentifier . ParseFromIdentifierAndVersion ( _opts . LibraryName , _opts . LibraryVersion ) ;
55
+ var libraryIdentifier = _opts . LibraryIdentifier ;
56
+
57
+ // TODO: Not efficient to load all resources in the directory,
58
+ // still have to add an extension to InvocationToolkit to load only the library resource
59
+ // and its dependencies
54
60
using var librarySetInvoker = new InvocationToolkit ( )
55
61
. AddAssemblyBinariesInFhirLibrariesFromDirectory ( new ( _opts . ResourcesDirectory ) )
56
- . CreateLibrarySetInvoker ( librarySetName ) ;
62
+ . CreateLibrarySetInvoker ( libraryIdentifier ) ;
57
63
RunShared ( _opts , librarySetInvoker ) ;
58
64
}
59
65
60
66
private void RunShared ( CommandLineOptions opt , LibrarySetInvoker librarySetInvoker )
61
67
{
62
68
Console . WriteLine ( "Loading value sets" ) ;
63
- IValueSetDictionary valueSets = ResourceHelper . LoadValueSets ( new DirectoryInfo ( opt . ValueSetsDirectory ) ) ;
69
+ var valueSetIds = GetValueSetIds ( librarySetInvoker , opt . Library ) ;
70
+ IValueSetDictionary valueSets = ResourceHelper . LoadValueSets (
71
+ new DirectoryInfo ( opt . ValueSetsDirectory ) ,
72
+ valueSetIds ) ;
64
73
65
74
Console . WriteLine ( "Loading test case files" ) ;
66
- var testDataDir = Path . Join ( opt . DataDirectory , opt . LibraryName ) ;
75
+ var testDataDir = Path . Join ( opt . DataDirectory , ( string ) opt . LibraryIdentifier . Identifier ) ;
67
76
var patientList = ProcessTestPatients ( testDataDir , librarySetInvoker , valueSets ) ;
68
77
//optionally use patientList Dictionary
69
78
}
70
79
71
-
80
+ /// <summary>
81
+ /// Retrieves a set of unique ValueSet IDs from the specified library and its dependencies.
82
+ /// </summary>
83
+ /// <param name="librarySetInvoker">
84
+ /// An instance of <see cref="LibrarySetInvoker"/> used to access library invokers and their dependencies.
85
+ /// </param>
86
+ /// <param name="libraryName">
87
+ /// The name of the library from which to retrieve ValueSet IDs. This should be a valid CQL library identifier.
88
+ /// </param>
89
+ /// <returns>
90
+ /// A <see cref="HashSet{T}"/> containing the unique ValueSet IDs defined in the specified library and its dependencies.
91
+ /// </returns>
92
+ /// <exception cref="KeyNotFoundException">
93
+ /// Thrown if the specified library name does not exist in the <paramref name="librarySetInvoker"/>.
94
+ /// </exception>
95
+ /// <exception cref="ArgumentException">
96
+ /// Thrown if the <paramref name="libraryName"/> is not a valid CQL library identifier.
97
+ /// </exception>
98
+ private static List < string > GetValueSetIds ( LibrarySetInvoker librarySetInvoker , string libraryName )
99
+ {
100
+ var libraryIdentifier = CqlVersionedLibraryIdentifier . Parse ( libraryName ) ;
101
+ var libraryInvoker = librarySetInvoker . LibraryInvokers [ libraryIdentifier ] ;
102
+ var libraryInvokerAndDependencies = libraryInvoker
103
+ . SelectDependencyLibraries ( includeSelf : true , recursive : true )
104
+ . ToArray ( ) ;
105
+ var valueSetIds = libraryInvokerAndDependencies
106
+ . SelectMany ( li => li . Definitions . Values )
107
+ . SelectWhere ( d =>
108
+ d . CqlDefinitionAttribute is CqlValueSetDefinitionAttribute vsda
109
+ ? ( true , vsda )
110
+ : default )
111
+ . Select ( vsda => vsda . ValueSetId )
112
+ . ToList ( ) ;
113
+ return valueSetIds ;
114
+ }
72
115
73
116
#region Processing Patients
74
117
private Dictionary < string , Dictionary < string , object > > ProcessTestPatients (
@@ -160,7 +203,7 @@ public Dictionary<string, object> ProcessBundle(LibrarySetInvoker librarySetInvo
160
203
161
204
// Invoke all expressions and collect results
162
205
var results = expressions . SelectResults ( setup , new SelectResultsOptions (
163
- InvocationExceptionCallback : ( definition , exception , _ ) =>
206
+ InvocationExceptionCallback : ( definition , exception , _ ) =>
164
207
{
165
208
var errorKey = $ "{ definition . LibraryInvoker . LibraryIdentifier . Identifier } -{ definition . DefinitionSignature . Name } ";
166
209
errors . TryAdd ( errorKey , exception ) ;
@@ -173,7 +216,7 @@ public Dictionary<string, object> ProcessBundle(LibrarySetInvoker librarySetInvo
173
216
// Use library identifier and definition name to create unique key
174
217
var declName = $ "{ definitionInvoker . LibraryInvoker . LibraryIdentifier . Identifier } -{ definitionInvoker . DefinitionSignature . Name } ";
175
218
Console . WriteLine ( $ "Running definition: { definitionInvoker . DefinitionSignature . Name } ") ;
176
-
219
+
177
220
// Use TryAdd to avoid duplicate key exceptions
178
221
if ( ! values . TryAdd ( declName , invocationResult ! ) )
179
222
{
@@ -243,3 +286,22 @@ private void WritePatientResults(Dictionary<string, object> patientResults)
243
286
#endregion Writing Output
244
287
}
245
288
}
289
+
290
+ file static class EnumerableExtensions
291
+ {
292
+ /// <summary>
293
+ /// Projects each element of a collection into a new form based on a selector function, and filters out elements based on a condition.
294
+ /// </summary>
295
+ /// <typeparam name="T">The type of elements in the source collection.</typeparam>
296
+ /// <typeparam name="TR">The type of elements in the resulting collection.</typeparam>
297
+ /// <param name="source">The source collection.</param>
298
+ /// <param name="selector">A function to test each element for a condition and project the element into a new form.</param>
299
+ /// <returns>An enumerable collection that contains the transformed elements that satisfy the condition.</returns>
300
+ public static IEnumerable < TR > SelectWhere < T , TR > ( this IEnumerable < T > source , Func < T , ( bool include , TR resultOrDefault ) > selector )
301
+ {
302
+ foreach ( var item in source )
303
+ if ( selector ( item ) is ( include : true , { } resultOrDefault) )
304
+ yield return resultOrDefault ;
305
+ }
306
+
307
+ }
0 commit comments