Skip to content

Commit

Permalink
Not Equal and Not Equivalent clause coverage calculation handling (#291)
Browse files Browse the repository at this point in the history
* Not Equal and Not Equivalent clause coverage calculation handling

* Added unit test for not equivalent

* Check for operand localId

* Remove undefined localId assignment

* Move localId check, check for both localIds

* Added unit test for future translator functionality for Not Equal clauses

* Modified Not Equal unit test cql to not use literal false
  • Loading branch information
elsaperelli authored Dec 15, 2023
1 parent 40b26fb commit a37ab3c
Show file tree
Hide file tree
Showing 6 changed files with 1,314 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/calculation/ClauseResultsHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,19 @@ export function findAllLocalIdsInStatement(
} else if (k === 'type' && v === 'Literal' && statement.localId && statement.value === 'false') {
// If this is a "Literal" expression whose value is false, mark that it `isFalsyLiteral` so we can interpret final results differently
localIds[statement.localId] = { localId: statement.localId, isFalsyLiteral: true };
} else if (k === 'type' && v === 'Not') {
// If this is a "Not" expression, we will want to check if it's operand type is 'Equivalent' or 'Equal'
// If so, we will want to treat this as a 'Not Equivalent' or 'Not Equal' expression which we can do so
// by mapping the 'Equal' or 'Equivalent' clause localId to that of the 'Not' clause
if (statement.operand && statement.localId && statement.operand.localId) {
if (statement.operand.type === 'Equivalent' || statement.operand.type === 'Equal') {
emptyResultClauses.push({
lib: libraryName,
aliasLocalId: statement.operand.localId,
expressionLocalId: statement.localId
});
}
}
} else if (k === 'localId') {
// else if the key is localId, push the value
localIds[v] = { localId: v };
Expand Down
30 changes: 30 additions & 0 deletions test/unit/ClauseResultsHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,36 @@ import { getJSONFixture } from './helpers/testHelpers';

describe('ClauseResultsHelpers', () => {
describe('findAllLocalIdsInStatementByName', () => {
test('finds localIds for an Equivalent comparison operator that is wrapped in a Not expression', () => {
// ELM from test/unit/fixtures/cql/NotEquivalent.cql
const libraryElm: ELM = getJSONFixture('elm/NotEquivalent.json');

const statementName = 'Not Equivalent Clause';
const localIds = ClauseResultsHelpers.findAllLocalIdsInStatementByName(libraryElm, statementName);

// For the fixture loaded for this test it is known that the localId for the Equivalent statement
// is 23 and the localId for the Not expression is 24 but we want the Equivalent clause to take
// the result of the Not expression
expect(localIds[23]).toBeDefined();
expect(localIds[23]).toEqual({ localId: '23', sourceLocalId: '24' });
});

test('finds localIds for an Equal comparison operator that is wrapped in a Not expression', () => {
// ELM from test/unit/fixtures/cql/NotEqual.cql, but modified so that Equal has a localId of "100"
// This will soon be the translator functionality, the Equal clause will get a localId (it currently
// does not get one)
const libraryElm: ELM = getJSONFixture('elm/NotEqual.json');

const statementName = 'Not Equal Clause';
const localIds = ClauseResultsHelpers.findAllLocalIdsInStatementByName(libraryElm, statementName);

// For the fixture loaded for this test it is known that the localId for the Equal statement
// is 100 and the localId for the Not expression is 23 but we want the Equal clause to take
// the result of the Not expression
expect(localIds[100]).toBeDefined();
expect(localIds[100]).toEqual({ localId: '100', sourceLocalId: '23' });
});

test('finds localIds for an ELM Binary Expression with a comparison operator with a literal', () => {
// ELM from test/unit/fixtures/cql/comparisonWithLiteral.cql
const libraryElm: ELM = getJSONFixture('elm/ComparisonWithLiteral.json');
Expand Down
24 changes: 24 additions & 0 deletions test/unit/fixtures/cql/NotEqual.cql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
library Test

using FHIR version '4.0.1'

include FHIRHelpers version '4.0.1'
include MATGlobalCommonFunctions version '5.0.000' called Global

codesystem "EXAMPLE": 'http://example.com'
codesystem "EXAMPLE-2": 'http://example.com/2'
codesystem "ConditionClinicalStatusCodes": 'http://terminology.hl7.org/CodeSystem/condition-clinical'

valueset "test-vs": 'http://example.com/test-vs'

code "Active": 'active' from "ConditionClinicalStatusCodes"
code "Recurrence": 'recurrence' from "ConditionClinicalStatusCodes"
code "Relapse": 'relapse' from "ConditionClinicalStatusCodes"

concept "Condition Active": { "Active", "Recurrence", "Relapse" } display 'Active'

context Patient

define "Not Equal Clause":
[Condition: "test-vs"] C
where C.id != 'notId'
24 changes: 24 additions & 0 deletions test/unit/fixtures/cql/NotEquivalent.cql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
library Test

using FHIR version '4.0.1'

include FHIRHelpers version '4.0.1'
include MATGlobalCommonFunctions version '5.0.000' called Global

codesystem "EXAMPLE": 'http://example.com'
codesystem "EXAMPLE-2": 'http://example.com/2'
codesystem "ConditionClinicalStatusCodes": 'http://terminology.hl7.org/CodeSystem/condition-clinical'

valueset "test-vs": 'http://example.com/test-vs'

code "Active": 'active' from "ConditionClinicalStatusCodes"
code "Recurrence": 'recurrence' from "ConditionClinicalStatusCodes"
code "Relapse": 'relapse' from "ConditionClinicalStatusCodes"

concept "Condition Active": { "Active", "Recurrence", "Relapse" } display 'Active'

context Patient

define "Not Equivalent Clause":
[Condition: "test-vs"] C
where C.clinicalStatus !~ "Condition Active"
Loading

0 comments on commit a37ab3c

Please sign in to comment.