@@ -7,10 +7,8 @@ import { SearchParameters } from '../compartment-definition/SearchParameters';
77import {
88 AnyELMExpression ,
99 ELM ,
10- ELMAliasedQuerySource ,
1110 ELMFunctionRef ,
1211 ELMIdentifier ,
13- ELMLast ,
1412 ELMProperty ,
1513 ELMQuery ,
1614 ELMStatement
@@ -31,7 +29,7 @@ import { DateTime, Interval } from 'cql-execution';
3129import { parseTimeStringAsUTC } from '../execution/ValueSetHelper' ;
3230import * as MeasureBundleHelpers from './MeasureBundleHelpers' ;
3331import { findLibraryReference } from './elm/ELMDependencyHelpers' ;
34- import { findClauseInExpression , findClauseInLibrary , findNamedClausesInExpression } from './elm/ELMHelpers' ;
32+ import { findClauseInLibrary , findNamedClausesInExpression } from './elm/ELMHelpers' ;
3533const FHIR_QUERY_PATTERN_URL = 'http://hl7.org/fhir/us/cqfmeasures/StructureDefinition/cqfm-fhirQueryPattern' ;
3634
3735/**
@@ -467,6 +465,7 @@ function didEncounterDetailedValueFilterErrors(tbd: fhir4.Extension | GracefulEr
467465function addMustSupport ( allRetrieves : DataTypeQuery [ ] , statement : ELMStatement , rootLib : ELM , allELM : ELM [ ] ) {
468466 const propertyExpressions = findPropertyExpressions ( statement , [ ] , rootLib , allELM ) ;
469467
468+ // TODO: double check that the property is applicable for the retrieve type before adding is as a mustSupport
470469 propertyExpressions . forEach ( prop => {
471470 // find all matches for this property in allRetrieves
472471 const retrieveMatches = findRetrieveMatches ( prop , allRetrieves , allELM ) ;
@@ -630,20 +629,20 @@ export function findRetrieveMatches(prop: PropertyTracker, retrieves: DataTypeQu
630629 const matchIdx = prop . stack . findIndex (
631630 s => s . localId === stackMatch . localId && s . libraryName === stackMatch . libraryName
632631 ) ;
632+ const retMatchIdx = retrieve . expressionStack ?. findIndex (
633+ s => s . localId === stackMatch . localId && s . libraryName === stackMatch . libraryName
634+ ) ;
633635 if ( prop . property . scope ) {
634636 // travel the stack looking for nearest queries (limited by stackMatch)
635637 const scopedQuery = findStackScopedQuery ( prop . stack . slice ( matchIdx ) , prop . property . scope , allELM ) ;
636638
637639 if ( ! scopedQuery ) return false ;
638640 const { query, position, source } = scopedQuery ;
639641 // if the query is our stackMatch, stop here, otherwise continue with query source
640- if ( position === 0 ) {
641- // confirm alias matches scope (i.e. the retrieve is somewhere within the source expression tree) // TODO: this is not sufficient, multiple retrieves could be defined within the tree of this source, not just the right one
642- return (
643- source &&
644- source . expression . localId &&
645- ! ! retrieve . expressionStack ?. find ( st => st . localId === source . expression . localId )
646- ) ;
642+ if ( position === 0 && 'alias' in source && source . alias && retrieve . expressionStack ) {
643+ //TODO: combine this and the if below??? or just get rid of position 0?
644+ // confirm alias matches scope (i.e. follow the alias down the retrieve stack)
645+ return checkRetrieveStackForAlias ( retrieve . expressionStack . slice ( retMatchIdx ) , source . alias , allELM ) ;
647646 }
648647 if ( 'name' in source . expression && source . expression . name ) {
649648 // TODO: do we need any further checks here with the highest reference name?
@@ -661,18 +660,6 @@ export function findRetrieveMatches(prop: PropertyTracker, retrieves: DataTypeQu
661660 const stackSlice = prop . stack . slice ( matchIdx ) ;
662661 const checkName = checkStackFunctionDefs ( stackSlice , prop . property . source . name , allELM ) ;
663662 if ( checkName ) {
664- // get highest FunctionRef in the stack
665- // check that the operand has an AliasRef type expression with a name equal to...
666- // top alias in the retrieve stack (up to stackMatch) -> BipolarDiagnosis vs QualifyingEncounter
667- // const funcRefStackEntry = stackSlice.find(se => se.type === 'FunctionRef');
668- // if (!funcRefStackEntry) return true;
669- // const aliasExp = (expressionFromStackEntry(funcRefStackEntry, allELM) as ELMFunctionRef).operand.find(
670- // o => o.type === 'AliasRef'
671- // );
672-
673- const retMatchIdx = retrieve . expressionStack ?. findIndex (
674- s => s . localId === stackMatch . localId && s . libraryName === stackMatch . libraryName
675- ) ;
676663 const retSlice = retrieve . expressionStack ?. slice ( retMatchIdx ) ;
677664 const topAlias = retSlice
678665 ?. map ( se => {
@@ -694,6 +681,27 @@ export function findRetrieveMatches(prop: PropertyTracker, retrieves: DataTypeQu
694681 } ) ;
695682}
696683
684+ // traverse down a retrieve stack, checking query sources and traversing expression references all the way to the retrieve
685+ // currently checks first query and whether a with/without invalidates a contained retrieve, TODO: may need further checks down the stack
686+ export function checkRetrieveStackForAlias ( stack : ExpressionStackEntry [ ] , alias : string , allELM : ELM [ ] ) {
687+ for ( let i = 0 ; i < stack . length - 1 ; i ++ ) {
688+ if ( stack [ i ] . type === 'Query' ) {
689+ const query = expressionFromStackEntry ( stack [ i ] , allELM ) as ELMQuery ;
690+ // search source or relationship next stack expression
691+ const sourceMatch = query . source . find ( s => s . expression . localId === stack [ i + 1 ] . localId ) ;
692+ const relationshipMatch = query . relationship ?. find ( r => r . localId === stack [ i + 1 ] . localId ) ;
693+ const expRefChange =
694+ stack [ i + 1 ] . type === 'ExpressionRef' && stack . find ( se => se . type === 'With' || se . type === 'Without' ) ;
695+ if ( sourceMatch ) {
696+ return sourceMatch . alias === alias && ! expRefChange ;
697+ } else if ( relationshipMatch ) {
698+ return relationshipMatch . alias === alias && ! expRefChange ;
699+ }
700+ }
701+ }
702+ return true ;
703+ }
704+
697705// traverse from end of the stack to find the nearest query that has alias labeled with the passed scope
698706export function findStackScopedQuery ( stack : ExpressionStackEntry [ ] , scope : string , allELM : ELM [ ] ) {
699707 for ( let i = stack . length - 1 ; i >= 0 ; i -- ) {
0 commit comments