UNPKG

@phema/cql-execution

Version:

An execution framework for the Clinical Quality Language (CQL)

559 lines (430 loc) 18.2 kB
"use strict"; function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var _require = require('./expression'), Expression = _require.Expression, UnimplementedExpression = _require.UnimplementedExpression; var _require2 = require('../runtime/context'), Context = _require2.Context; var _require3 = require('./builder'), build = _require3.build; var _require4 = require('../util/util'), typeIsArray = _require4.typeIsArray, allTrue = _require4.allTrue; var _require5 = require('../util/comparison'), equals = _require5.equals; var AliasedQuerySource = function AliasedQuerySource(json) { _classCallCheck(this, AliasedQuerySource); this.alias = json.alias; this.expression = build(json.expression); }; var LetClause = function LetClause(json) { _classCallCheck(this, LetClause); this.identifier = json.identifier; this.expression = build(json.expression); }; var With = /*#__PURE__*/function (_Expression) { _inherits(With, _Expression); var _super = _createSuper(With); function With(json) { var _this; _classCallCheck(this, With); _this = _super.call(this, json); _this.alias = json.alias; _this.expression = build(json.expression); _this.suchThat = build(json.suchThat); return _this; } _createClass(With, [{ key: "exec", value: function exec(ctx) { var _this2 = this; var records = this.expression.execute(ctx); if (!typeIsArray(records)) { records = [records]; } var returns = records.map(function (rec) { var childCtx = ctx.childContext(); childCtx.set(_this2.alias, rec); return _this2.suchThat.execute(childCtx); }); return returns.some(function (x) { return x; }); } }]); return With; }(Expression); var Without = /*#__PURE__*/function (_With) { _inherits(Without, _With); var _super2 = _createSuper(Without); function Without(json) { _classCallCheck(this, Without); return _super2.call(this, json); } _createClass(Without, [{ key: "exec", value: function exec(ctx) { return !_get(_getPrototypeOf(Without.prototype), "exec", this).call(this, ctx); } }]); return Without; }(With); // ELM-only, not a product of CQL var Sort = /*#__PURE__*/function (_UnimplementedExpress) { _inherits(Sort, _UnimplementedExpress); var _super3 = _createSuper(Sort); function Sort() { _classCallCheck(this, Sort); return _super3.apply(this, arguments); } return Sort; }(UnimplementedExpression); var ByDirection = /*#__PURE__*/function (_Expression2) { _inherits(ByDirection, _Expression2); var _super4 = _createSuper(ByDirection); function ByDirection(json) { var _this3; _classCallCheck(this, ByDirection); _this3 = _super4.call(this, json); _this3.direction = json.direction; _this3.low_order = _this3.direction === 'asc' ? -1 : 1; _this3.high_order = _this3.low_order * -1; return _this3; } _createClass(ByDirection, [{ key: "exec", value: function exec(ctx, a, b) { if (a === b) { return 0; } else if (a.isQuantity && b.isQuantity) { if (a.before(b)) { return this.low_order; } else { return this.high_order; } } else if (a < b) { return this.low_order; } else { return this.high_order; } } }]); return ByDirection; }(Expression); var ByExpression = /*#__PURE__*/function (_Expression3) { _inherits(ByExpression, _Expression3); var _super5 = _createSuper(ByExpression); function ByExpression(json) { var _this4; _classCallCheck(this, ByExpression); _this4 = _super5.call(this, json); _this4.expression = build(json.expression); _this4.direction = json.direction; _this4.low_order = _this4.direction === 'asc' ? -1 : 1; _this4.high_order = _this4.low_order * -1; return _this4; } _createClass(ByExpression, [{ key: "exec", value: function exec(ctx, a, b) { var sctx = ctx.childContext(a); var a_val = this.expression.execute(sctx); sctx = ctx.childContext(b); var b_val = this.expression.execute(sctx); if (a_val === b_val) { return 0; } else if (a_val.isQuantity && b_val.isQuantity) { if (a_val.before(b_val)) { return this.low_order; } else { return this.high_order; } } else if (a_val < b_val) { return this.low_order; } else { return this.high_order; } } }]); return ByExpression; }(Expression); var ByColumn = /*#__PURE__*/function (_ByExpression) { _inherits(ByColumn, _ByExpression); var _super6 = _createSuper(ByColumn); function ByColumn(json) { var _this5; _classCallCheck(this, ByColumn); _this5 = _super6.call(this, json); _this5.expression = build({ name: json.path, type: 'IdentifierRef' }); return _this5; } return ByColumn; }(ByExpression); var ReturnClause = function ReturnClause(json) { _classCallCheck(this, ReturnClause); this.expression = build(json.expression); this.distinct = json.distinct != null ? json.distinct : true; }; var SortClause = /*#__PURE__*/function () { function SortClause(json) { _classCallCheck(this, SortClause); this.by = build(json != null ? json.by : undefined); } _createClass(SortClause, [{ key: "sort", value: function sort(ctx, values) { var _this6 = this; if (this.by) { return values.sort(function (a, b) { var order = 0; var _iterator = _createForOfIteratorHelper(_this6.by), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var item = _step.value; // Do not use execute here because the value of the sort order is not important. order = item.exec(ctx, a, b); if (order !== 0) { break; } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return order; }); } } }]); return SortClause; }(); var toDistinctList = function toDistinctList(xList) { var yList = []; xList.forEach(function (x) { if (!yList.some(function (y) { return equals(x, y); })) { yList.push(x); } }); return yList; }; var AggregateClause = /*#__PURE__*/function (_Expression4) { _inherits(AggregateClause, _Expression4); var _super7 = _createSuper(AggregateClause); function AggregateClause(json) { var _this7; _classCallCheck(this, AggregateClause); _this7 = _super7.call(this, json); _this7.identifier = json.identifier; _this7.expression = build(json.expression); _this7.starting = json.starting ? build(json.starting) : null; _this7.distinct = json.distinct != null ? json.distinct : true; return _this7; } _createClass(AggregateClause, [{ key: "aggregate", value: function aggregate(returnedValues, ctx) { var _this8 = this; var aggregateValue = this.starting != null ? this.starting.exec(ctx) : null; returnedValues.forEach(function (contextValues) { var childContext = ctx.childContext(contextValues); childContext.set(_this8.identifier, aggregateValue); aggregateValue = _this8.expression.exec(childContext); }); return aggregateValue; } }]); return AggregateClause; }(Expression); var Query = /*#__PURE__*/function (_Expression5) { _inherits(Query, _Expression5); var _super8 = _createSuper(Query); function Query(json) { var _this9; _classCallCheck(this, Query); _this9 = _super8.call(this, json); _this9.sources = new MultiSource(json.source.map(function (s) { return new AliasedQuerySource(s); })); _this9.letClauses = json.let != null ? json.let.map(function (d) { return new LetClause(d); }) : []; _this9.relationship = json.relationship != null ? build(json.relationship) : []; _this9.where = build(json.where); _this9.returnClause = json.return != null ? new ReturnClause(json.return) : null; _this9.aggregateClause = json.aggregate != null ? new AggregateClause(json.aggregate) : null; _this9.aliases = _this9.sources.aliases(); _this9.sortClause = json.sort != null ? new SortClause(json.sort) : null; return _this9; } _createClass(Query, [{ key: "isDistinct", value: function isDistinct() { if (this.aggregateClause != null && this.aggregateClause.distinct != null) { return this.aggregateClause.distinct; } else if (this.returnClause != null && this.returnClause.distinct != null) { return this.returnClause.distinct; } return true; } }, { key: "exec", value: function exec(ctx) { var _this10 = this; var returnedValues = []; this.sources.forEach(ctx, function (rctx) { var _iterator2 = _createForOfIteratorHelper(_this10.letClauses), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var def = _step2.value; rctx.set(def.identifier, def.expression.execute(rctx)); } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } var relations = _this10.relationship.map(function (rel) { var child_ctx = rctx.childContext(); return rel.execute(child_ctx); }); var passed = allTrue(relations) && (_this10.where ? _this10.where.execute(rctx) : true); if (passed) { if (_this10.returnClause != null) { var val = _this10.returnClause.expression.execute(rctx); returnedValues.push(val); } else { if (_this10.aliases.length === 1 && _this10.aggregateClause == null) { returnedValues.push(rctx.get(_this10.aliases[0])); } else { returnedValues.push(rctx.context_values); } } } }); if (this.isDistinct()) { returnedValues = toDistinctList(returnedValues); } if (this.aggregateClause != null) { returnedValues = this.aggregateClause.aggregate(returnedValues, ctx); } if (this.sortClause != null) { this.sortClause.sort(ctx, returnedValues); } if (this.sources.returnsList() || this.aggregateClause != null) { return returnedValues; } else { return returnedValues[0]; } } }]); return Query; }(Expression); var AliasRef = /*#__PURE__*/function (_Expression6) { _inherits(AliasRef, _Expression6); var _super9 = _createSuper(AliasRef); function AliasRef(json) { var _this11; _classCallCheck(this, AliasRef); _this11 = _super9.call(this, json); _this11.name = json.name; return _this11; } _createClass(AliasRef, [{ key: "exec", value: function exec(ctx) { return ctx != null ? ctx.get(this.name) : undefined; } }]); return AliasRef; }(Expression); var QueryLetRef = /*#__PURE__*/function (_AliasRef) { _inherits(QueryLetRef, _AliasRef); var _super10 = _createSuper(QueryLetRef); function QueryLetRef(json) { _classCallCheck(this, QueryLetRef); return _super10.call(this, json); } return QueryLetRef; }(AliasRef); // The following is not defined by ELM but is helpful for execution var MultiSource = /*#__PURE__*/function () { function MultiSource(sources) { _classCallCheck(this, MultiSource); this.sources = sources; this.alias = this.sources[0].alias; this.expression = this.sources[0].expression; this.isList = true; if (this.sources.length > 1) { this.rest = new MultiSource(this.sources.slice(1)); } } _createClass(MultiSource, [{ key: "aliases", value: function aliases() { var a = [this.alias]; if (this.rest) { a = a.concat(this.rest.aliases()); } return a; } }, { key: "returnsList", value: function returnsList() { return this.isList || this.rest && this.rest.returnsList(); } }, { key: "forEach", value: function forEach(ctx, func) { var _this12 = this; var records = this.expression.execute(ctx); this.isList = typeIsArray(records); records = this.isList ? records : [records]; return records.map(function (rec) { var rctx = new Context(ctx); rctx.set(_this12.alias, rec); if (_this12.rest) { return _this12.rest.forEach(rctx, func); } else { return func(rctx); } }); } }]); return MultiSource; }(); module.exports = { AliasedQuerySource: AliasedQuerySource, AliasRef: AliasRef, ByColumn: ByColumn, ByDirection: ByDirection, ByExpression: ByExpression, LetClause: LetClause, Query: Query, QueryLetRef: QueryLetRef, ReturnClause: ReturnClause, Sort: Sort, SortClause: SortClause, With: With, Without: Without };