cql-execution
Version:
An execution framework for the Clinical Quality Language (CQL)
175 lines • 5.81 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValueSet = exports.CQLValueSet = exports.CodeSystem = exports.Vocabulary = exports.Concept = exports.Code = void 0;
const util_1 = require("../util/util");
class Code {
constructor(code, system, version, display) {
this.code = code;
this.system = system;
this.version = version;
this.display = display;
}
get isCode() {
return true;
}
hasMatch(code) {
if (typeof code === 'string') {
// the specific behavior for this is not in the specification. Matching codesystem behavior.
return code === this.code;
}
else {
return codesInList(toCodeList(code), [this]);
}
}
}
exports.Code = Code;
class Concept {
constructor(codes, display) {
this.codes = codes;
this.display = display;
this.codes || (this.codes = []);
}
get isConcept() {
return true;
}
hasMatch(code) {
return codesInList(toCodeList(code), this.codes);
}
}
exports.Concept = Concept;
class Vocabulary {
constructor(id, version, name) {
this.id = id;
this.version = version;
this.name = name;
}
}
exports.Vocabulary = Vocabulary;
class CodeSystem extends Vocabulary {
constructor(id, version, name) {
super(id, version, name);
this.id = id;
this.version = version;
this.name = name;
}
}
exports.CodeSystem = CodeSystem;
class CQLValueSet extends Vocabulary {
constructor(id, version, name, codesystems) {
super(id, version, name);
this.id = id;
this.version = version;
this.name = name;
this.codesystems = codesystems;
}
get isValueSet() {
return true;
}
}
exports.CQLValueSet = CQLValueSet;
class ValueSet {
constructor(oid, version, codes = []) {
this.oid = oid;
this.version = version;
this.codes = codes;
}
/**
* Determines if the provided code matches any code in the current set.
* If the input is a single string, it checks for a direct match with the
* codes in the set, ensuring all code systems are consistent. Throws an
* error if multiple code systems exist and a match is found, indicating
* ambiguity. For other inputs, it checks for any matching codes using
* the `codesInList` function. Used for the `code in valueset` operation.
*
* @param code - The code to be checked for a match, which can be a string
* or an object containing codes.
* @returns {boolean} True if a match is found, otherwise false.
* @throws {Error} If a match is found with multiple code systems present.
*/
hasMatch(code) {
const codesList = toCodeList(code);
// InValueSet String Overload
if (codesList.length === 1 && typeof codesList[0] === 'string') {
let matchFound = false;
let multipleCodeSystemsExist = false;
for (const codeItem of this.codes) {
// Confirm all code systems match
if (codeItem.system !== this.codes[0].system) {
multipleCodeSystemsExist = true;
}
if (codeItem.code === codesList[0]) {
matchFound = true;
}
if (multipleCodeSystemsExist && matchFound) {
throw new Error('In (valueset) is ambiguous -- multiple codes with multiple code systems exist in value set.');
}
}
return matchFound;
}
else {
return codesInList(codesList, this.codes);
}
}
/**
* Expands the current set of codes by returning a list of unique `Code` objects.
* This method filters out duplicate codes from the `codes` array, ensuring each
* code appears only once in the returned list. Use for the ExpandValueset operator
*
* @returns {Code[]} An array of unique `Code` objects.
*/
expand() {
const expanded = [];
this.codes.forEach(code => {
const foundUniqueCode = expanded.find(uniqueCode => {
if (uniqueCode == null || code == null) {
return true;
}
return (uniqueCode.code === code.code &&
uniqueCode.system == code.system &&
uniqueCode.version == code.version &&
uniqueCode.display == code.display);
});
if (!foundUniqueCode) {
expanded.push(code);
}
});
return expanded;
}
}
exports.ValueSet = ValueSet;
function toCodeList(c) {
if (c == null) {
return [];
}
else if ((0, util_1.typeIsArray)(c)) {
let list = [];
for (const c2 of c) {
list = list.concat(toCodeList(c2));
}
return list;
}
else if ((0, util_1.typeIsArray)(c.codes)) {
return c.codes;
}
else {
return [c];
}
}
function codesInList(cl1, cl2) {
// test each code in c1 against each code in c2 looking for a match
return cl1.some((c1) => cl2.some((c2) => {
// only the left argument (cl1) can contain strings. cl2 will only contain codes.
if (typeof c1 === 'string') {
// for "string in codesystem" this should compare the string to
// the code's "code" field according to the specification.
return c1 === c2.code;
}
else {
return codesMatch(c1, c2);
}
}));
}
function codesMatch(code1, code2) {
return code1.code === code2.code && code1.system === code2.system;
}
//# sourceMappingURL=clinical.js.map