@phema/cql-execution
Version:
An execution framework for the Clinical Quality Language (CQL)
559 lines (430 loc) • 18.2 kB
JavaScript
"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
};