UNPKG

cql-execution

Version:

An execution framework for the Clinical Quality Language (CQL)

727 lines (632 loc) 23.1 kB
// Generated by CoffeeScript 1.12.7 (function() { var Collapse, End, Ends, Expand, Expression, Interval, MIN_FLOAT_PRECISION_VALUE, Meets, MeetsAfter, MeetsBefore, Overlaps, OverlapsAfter, OverlapsBefore, Quantity, Start, Starts, ThreeValuedLogic, UnimplementedExpression, Width, build, cmp, collapseIntervals, compare_units, convert_value, doAddition, doIncludes, doSubtraction, dtivl, intervalListType, predecessor, ref, ref1, ref2, successor, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; ref = require('./expression'), Expression = ref.Expression, UnimplementedExpression = ref.UnimplementedExpression; ThreeValuedLogic = require('../datatypes/logic').ThreeValuedLogic; build = require('./builder').build; ref1 = require('./quantity'), Quantity = ref1.Quantity, doAddition = ref1.doAddition, doSubtraction = ref1.doSubtraction, compare_units = ref1.compare_units, convert_value = ref1.convert_value; ref2 = require('../util/math'), successor = ref2.successor, predecessor = ref2.predecessor, MIN_FLOAT_PRECISION_VALUE = ref2.MIN_FLOAT_PRECISION_VALUE; dtivl = require('../datatypes/interval'); cmp = require('../util/comparison'); module.exports.Interval = Interval = (function(superClass) { extend(Interval, superClass); function Interval(json) { Interval.__super__.constructor.apply(this, arguments); this.lowClosed = json.lowClosed; this.highClosed = json.highClosed; this.low = build(json.low); this.high = build(json.high); } Object.defineProperties(Interval.prototype, { isInterval: { get: function() { return true; } } }); Interval.prototype.exec = function(ctx) { return new dtivl.Interval(this.low.execute(ctx), this.high.execute(ctx), this.lowClosed, this.highClosed); }; return Interval; })(Expression); module.exports.doContains = function(interval, item, precision) { return interval.contains(item, precision); }; module.exports.doIncludes = doIncludes = function(interval, subinterval, precision) { return interval.includes(subinterval, precision); }; module.exports.doProperIncludes = function(interval, subinterval, precision) { return interval.properlyIncludes(subinterval, precision); }; module.exports.doAfter = function(a, b, precision) { return a.after(b, precision); }; module.exports.doBefore = function(a, b, precision) { return a.before(b, precision); }; module.exports.Meets = Meets = (function(superClass) { extend(Meets, superClass); function Meets(json) { var ref3; Meets.__super__.constructor.apply(this, arguments); this.precision = (ref3 = json.precision) != null ? ref3.toLowerCase() : void 0; } Meets.prototype.exec = function(ctx) { var a, b, ref3; ref3 = this.execArgs(ctx), a = ref3[0], b = ref3[1]; if ((a != null) && (b != null)) { return a.meets(b, this.precision); } else { return null; } }; return Meets; })(Expression); module.exports.MeetsAfter = MeetsAfter = (function(superClass) { extend(MeetsAfter, superClass); function MeetsAfter(json) { var ref3; MeetsAfter.__super__.constructor.apply(this, arguments); this.precision = (ref3 = json.precision) != null ? ref3.toLowerCase() : void 0; } MeetsAfter.prototype.exec = function(ctx) { var a, b, ref3; ref3 = this.execArgs(ctx), a = ref3[0], b = ref3[1]; if ((a != null) && (b != null)) { return a.meetsAfter(b, this.precision); } else { return null; } }; return MeetsAfter; })(Expression); module.exports.MeetsBefore = MeetsBefore = (function(superClass) { extend(MeetsBefore, superClass); function MeetsBefore(json) { var ref3; MeetsBefore.__super__.constructor.apply(this, arguments); this.precision = (ref3 = json.precision) != null ? ref3.toLowerCase() : void 0; } MeetsBefore.prototype.exec = function(ctx) { var a, b, ref3; ref3 = this.execArgs(ctx), a = ref3[0], b = ref3[1]; if ((a != null) && (b != null)) { return a.meetsBefore(b, this.precision); } else { return null; } }; return MeetsBefore; })(Expression); module.exports.Overlaps = Overlaps = (function(superClass) { extend(Overlaps, superClass); function Overlaps(json) { var ref3; Overlaps.__super__.constructor.apply(this, arguments); this.precision = (ref3 = json.precision) != null ? ref3.toLowerCase() : void 0; } Overlaps.prototype.exec = function(ctx) { var a, b, ref3; ref3 = this.execArgs(ctx), a = ref3[0], b = ref3[1]; if ((a != null) && (b != null)) { return a.overlaps(b, this.precision); } else { return null; } }; return Overlaps; })(Expression); module.exports.OverlapsAfter = OverlapsAfter = (function(superClass) { extend(OverlapsAfter, superClass); function OverlapsAfter(json) { var ref3; OverlapsAfter.__super__.constructor.apply(this, arguments); this.precision = (ref3 = json.precision) != null ? ref3.toLowerCase() : void 0; } OverlapsAfter.prototype.exec = function(ctx) { var a, b, ref3; ref3 = this.execArgs(ctx), a = ref3[0], b = ref3[1]; if ((a != null) && (b != null)) { return a.overlapsAfter(b, this.precision); } else { return null; } }; return OverlapsAfter; })(Expression); module.exports.OverlapsBefore = OverlapsBefore = (function(superClass) { extend(OverlapsBefore, superClass); function OverlapsBefore(json) { var ref3; OverlapsBefore.__super__.constructor.apply(this, arguments); this.precision = (ref3 = json.precision) != null ? ref3.toLowerCase() : void 0; } OverlapsBefore.prototype.exec = function(ctx) { var a, b, ref3; ref3 = this.execArgs(ctx), a = ref3[0], b = ref3[1]; if ((a != null) && (b != null)) { return a.overlapsBefore(b, this.precision); } else { return null; } }; return OverlapsBefore; })(Expression); module.exports.doUnion = function(a, b) { return a.union(b); }; module.exports.doExcept = function(a, b) { if ((a != null) && (b != null)) { return a.except(b); } else { return null; } }; module.exports.doIntersect = function(a, b) { if ((a != null) && (b != null)) { return a.intersect(b); } else { return null; } }; module.exports.Width = Width = (function(superClass) { extend(Width, superClass); function Width(json) { Width.__super__.constructor.apply(this, arguments); } Width.prototype.exec = function(ctx) { var ref3; return (ref3 = this.arg.execute(ctx)) != null ? ref3.width() : void 0; }; return Width; })(Expression); module.exports.Start = Start = (function(superClass) { extend(Start, superClass); function Start(json) { Start.__super__.constructor.apply(this, arguments); } Start.prototype.exec = function(ctx) { var interval; interval = this.arg.execute(ctx); if (interval == null) { return null; } return interval.start(); }; return Start; })(Expression); module.exports.End = End = (function(superClass) { extend(End, superClass); function End(json) { End.__super__.constructor.apply(this, arguments); } End.prototype.exec = function(ctx) { var interval; interval = this.arg.execute(ctx); if (interval == null) { return null; } return interval.end(); }; return End; })(Expression); module.exports.Starts = Starts = (function(superClass) { extend(Starts, superClass); function Starts(json) { var ref3; Starts.__super__.constructor.apply(this, arguments); this.precision = (ref3 = json.precision) != null ? ref3.toLowerCase() : void 0; } Starts.prototype.exec = function(ctx) { var a, b, ref3; ref3 = this.execArgs(ctx), a = ref3[0], b = ref3[1]; if ((a != null) && (b != null)) { return a.starts(b, this.precision); } else { return null; } }; return Starts; })(Expression); module.exports.Ends = Ends = (function(superClass) { extend(Ends, superClass); function Ends(json) { var ref3; Ends.__super__.constructor.apply(this, arguments); this.precision = (ref3 = json.precision) != null ? ref3.toLowerCase() : void 0; } Ends.prototype.exec = function(ctx) { var a, b, ref3; ref3 = this.execArgs(ctx), a = ref3[0], b = ref3[1]; if ((a != null) && (b != null)) { return a.ends(b, this.precision); } else { return null; } }; return Ends; })(Expression); intervalListType = function(intervals) { var high, itvl, j, len, low, ref3, ref4, type; type = null; for (j = 0, len = intervals.length; j < len; j++) { itvl = intervals[j]; if (itvl == null) { continue; } if ((itvl.low == null) && (itvl.high == null)) { continue; } low = (ref3 = itvl.low) != null ? ref3 : itvl.high; high = (ref4 = itvl.high) != null ? ref4 : itvl.low; if ((typeof low.isTime === "function" ? low.isTime() : void 0) && (typeof high.isTime === "function" ? high.isTime() : void 0)) { if (type == null) { type = 'time'; } else if (type === 'time') { continue; } else { return 'mismatch'; } } else if ((low.isDateTime || high.isDateTime) && (low.isDateTime || low.isDate) && (high.isDateTime || high.isDate)) { if ((type == null) || type === 'date') { type = 'datetime'; } else if (type === 'datetime') { continue; } else { return 'mismatch'; } } else if (low.isDate && high.isDate) { if (type == null) { type = 'date'; } else if (type === 'date' || 'datetime') { continue; } else { return 'mismatch'; } } else if (low.isQuantity && high.isQuantity) { if (type == null) { type = 'quantity'; } else if (type === 'quantity') { continue; } else { return 'mismatch'; } } else if (Number.isInteger(low) && Number.isInteger(high)) { if (type == null) { type = 'integer'; } else if (type === 'integer' || 'decimal') { continue; } else { return 'mismatch'; } } else if (typeof low === 'number' && typeof high === 'number') { if ((type == null) || type === 'integer') { type = 'decimal'; } else if (type === 'decimal') { continue; } else { return 'mismatch'; } } else { return 'mismatch'; } } return type; }; module.exports.Expand = Expand = (function(superClass) { extend(Expand, superClass); function Expand(json) { Expand.__super__.constructor.apply(this, arguments); } Expand.prototype.exec = function(ctx) { var defaultPer, expandFunction, interval, intervals, items, j, len, per, ref3, results, type; ref3 = this.execArgs(ctx), intervals = ref3[0], per = ref3[1]; type = intervalListType(intervals); if (type === 'mismatch') { throw new Error("List of intervals contains mismatched types."); } if (type == null) { return null; } intervals = collapseIntervals(intervals, per); if (intervals.length === 0) { return []; } if (type === "time" || type === "date" || type === "datetime") { expandFunction = this.expandDTishInterval; defaultPer = function(interval) { return new Quantity({ value: 1, unit: interval.low.getPrecision() }); }; } else if (type === "quantity") { expandFunction = this.expandQuantityInterval; defaultPer = function(interval) { return new Quantity({ value: 1, unit: interval.low.unit }); }; } else if (type === "integer" || type === "decimal") { expandFunction = this.expandNumericInterval; defaultPer = function(interval) { return new Quantity({ value: 1, unit: '1' }); }; } else { throw new Error("Interval list type not yet supported."); } results = []; for (j = 0, len = intervals.length; j < len; j++) { interval = intervals[j]; if (interval == null) { continue; } if ((interval.low == null) || (interval.high == null)) { return null; } if (type === 'datetime') { interval.low = interval.low.getDateTime(); interval.high = interval.high.getDateTime(); } per = per != null ? per : defaultPer(interval); items = expandFunction.call(this, interval, per); if (items === null) { return null; } results.push.apply(results, items); } return results; }; Expand.prototype.expandDTishInterval = function(interval, per) { var count, current_high, current_low, high, i, j, k, low, point_intervals, ref3, ref4, ref5, ref6, results; if ((ref3 = per.unit) === 'week' || ref3 === 'weeks') { per.value *= 7; per.unit = 'day'; } if (ref4 = per.unit, indexOf.call(interval.low.constructor.FIELDS, ref4) < 0) { return null; } if (interval.low.isLessPrecise(per.unit)) { return null; } low = interval.lowClosed ? interval.low : interval.low.successor(); high = interval.highClosed ? interval.high : interval.high.predecessor(); if (low.after(high)) { return []; } current_low = low; results = []; point_intervals = current_low.add(per.value, per.unit).predecessor().equals(current_low); if (per.unit === low.getPrecision()) { count = Math.floor((low.durationBetween(high, per.unit).high + 1) / per.value); } else { count = Math.floor((low.durationBetween(high, per.unit).low + 1) / per.value); } if (point_intervals) { for (i = j = 1, ref5 = count + 1; 1 <= ref5 ? j <= ref5 : j >= ref5; i = 1 <= ref5 ? ++j : --j) { results.push(new dtivl.Interval(current_low, current_low.copy(), true, true)); current_low = current_low.add(per.value, per.unit); } } else { for (i = k = 1, ref6 = count; 1 <= ref6 ? k <= ref6 : k >= ref6; i = 1 <= ref6 ? ++k : --k) { current_high = current_low.add(per.value, per.unit).predecessor(); results.push(new dtivl.Interval(current_low, current_high, true, true)); current_low = current_low.add(per.value, per.unit); } } if (results.length > 0 && !results[results.length - 1].high.sameOrBefore(high)) { results.pop(); } return results; }; Expand.prototype.expandQuantityInterval = function(interval, per) { var high_value, itvl, j, len, low_value, per_value, result_units, results; if (compare_units(interval.low.unit, per.unit) > 0) { result_units = per.unit; } else { result_units = interval.low.unit; } low_value = convert_value(interval.low.value, interval.low.unit, result_units); high_value = convert_value(interval.high.value, interval.high.unit, result_units); per_value = convert_value(per.value, per.unit, result_units); if (!((low_value != null) && (high_value != null) && (per_value != null))) { return null; } results = this.makeNumericIntervalList(low_value, high_value, interval.lowClosed, interval.highClosed, per_value); for (j = 0, len = results.length; j < len; j++) { itvl = results[j]; itvl.low = new Quantity({ value: itvl.low, unit: result_units }); itvl.high = new Quantity({ value: itvl.high, unit: result_units }); } return results; }; Expand.prototype.expandNumericInterval = function(interval, per) { if (per.unit !== '1') { return null; } return this.makeNumericIntervalList(interval.low, interval.high, interval.lowClosed, interval.highClosed, per.value); }; Expand.prototype.makeNumericIntervalList = function(low, high, lowClosed, highClosed, per) { var gap, point_intervals, results, width, x; point_intervals = Number.isInteger(low) && Number.isInteger(high) && Number.isInteger(per); gap = point_intervals ? 1 : MIN_FLOAT_PRECISION_VALUE; if (!lowClosed) { low = low + gap; } if (!highClosed) { high = high - gap; } width = per - gap; if (low > high) { return []; } results = (function() { var j, ref3, ref4, ref5, results1; results1 = []; for (x = j = ref3 = low, ref4 = high - width, ref5 = per; ref5 > 0 ? j <= ref4 : j >= ref4; x = j += ref5) { results1.push(new dtivl.Interval(x, x + width, true, true)); } return results1; })(); return results; }; return Expand; })(Expression); module.exports.Collapse = Collapse = (function(superClass) { extend(Collapse, superClass); function Collapse(json) { Collapse.__super__.constructor.apply(this, arguments); } Collapse.prototype.exec = function(ctx) { var intervals, perWidth, ref3; ref3 = this.execArgs(ctx), intervals = ref3[0], perWidth = ref3[1]; return collapseIntervals(intervals, perWidth); }; return Collapse; })(Expression); collapseIntervals = function(intervals, perWidth) { var a, b, collapsedIntervals, interval, intervalsClone, j, len, precisionUnits, ref3, ref4, ref5, ref6; intervalsClone = []; for (j = 0, len = intervals.length; j < len; j++) { interval = intervals[j]; if (interval != null) { intervalsClone.push(interval.copy()); } } if (intervals == null) { return null; } else if ((intervalsClone != null ? intervalsClone.length : void 0) <= 1) { return intervalsClone; } else { if (perWidth == null) { if (intervalsClone[0].low != null) { if (intervalsClone[0].low.isDateTime) { precisionUnits = intervalsClone[0].low.getPrecision(); perWidth = new Quantity({ value: 1, unit: precisionUnits }); } else if (intervalsClone[0].low.isQuantity) { perWidth = doSubtraction(successor(intervalsClone[0].low), intervalsClone[0].low); } else { perWidth = successor(intervalsClone[0].low) - intervalsClone[0].low; } } else if (intervalsClone[0].high != null) { if (intervalsClone[0].high.isDateTime) { precisionUnits = intervalsClone[0].high.getPrecision(); perWidth = new Quantity({ value: 1, unit: precisionUnits }); } else if (intervalsClone[0].high.isQuantity) { perWidth = doSubtraction(successor(intervalsClone[0].high), intervalsClone[0].high); } else { perWidth = successor(intervalsClone[0].high) - intervalsClone[0].high; } } else { throw new Error("Point type of intervals provided to collapse cannot be determined."); } if (typeof perWidth === 'number') { perWidth = new Quantity({ value: perWidth, unit: '1' }); } } intervalsClone.sort(function(a, b) { var ref3, ref4; if (typeof ((ref3 = a.low) != null ? ref3.before : void 0) === 'function') { if ((b.low != null) && a.low.before(b.low)) { return -1; } if ((b.low == null) || a.low.after(b.low)) { return 1; } } else if ((a.low != null) && (b.low != null)) { if (a.low < b.low) { return -1; } if (a.low > b.low) { return 1; } } else if ((a.low != null) && (b.low == null)) { return 1; } else if ((a.low == null) && (b.low != null)) { return -1; } if (typeof ((ref4 = a.high) != null ? ref4.before : void 0) === 'function') { if ((b.high == null) || a.high.before(b.high)) { return -1; } if (a.high.after(b.high)) { return 1; } } else if ((a.high != null) && (b.high != null)) { if (a.high < b.high) { return -1; } if (a.high > b.high) { return 1; } } else if ((a.high != null) && (b.high == null)) { return -1; } else if ((a.high == null) && (b.high != null)) { return 1; } return 0; }); collapsedIntervals = []; a = intervalsClone.shift(); b = intervalsClone.shift(); while (b) { if (typeof ((ref3 = b.low) != null ? ref3.durationBetween : void 0) === 'function') { if ((ref4 = a.high) != null ? ref4.sameOrAfter(b.low) : void 0) { if ((b.high == null) || b.high.after(a.high)) { a.high = b.high; } } else if (((ref5 = a.high) != null ? ref5.durationBetween(b.low, perWidth.unit).high : void 0) <= perWidth.value) { a.high = b.high; } else { collapsedIntervals.push(a); a = b; } } else if (typeof ((ref6 = b.low) != null ? ref6.sameOrBefore : void 0) === 'function') { if ((a.high != null) && b.low.sameOrBefore(doAddition(a.high, perWidth))) { if ((b.high == null) || b.high.after(a.high)) { a.high = b.high; } } else { collapsedIntervals.push(a); a = b; } } else { if ((b.low - a.high) <= perWidth.value) { if (b.high > a.high || (b.high == null)) { a.high = b.high; } } else { collapsedIntervals.push(a); a = b; } } b = intervalsClone.shift(); } collapsedIntervals.push(a); return collapsedIntervals; } }; }).call(this); //# sourceMappingURL=interval.js.map