From a4b0c82c66ae29433b3af9ec8a8f63e4116cc933 Mon Sep 17 00:00:00 2001 From: Mark Bjerke Date: Thu, 28 Jan 2016 16:21:14 -0800 Subject: [PATCH] refactored createRule to support collect / query features --- lib/rule.js | 209 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 138 insertions(+), 71 deletions(-) diff --git a/lib/rule.js b/lib/rule.js index 75a73d8..e69fe8f 100644 --- a/lib/rule.js +++ b/lib/rule.js @@ -130,7 +130,17 @@ var getParamType = function getParamType(type, scope) { return _getParamType(type); }; +// +function mergePatterns(patterns, merged, setAliases) { + var flattened = extd(patterns).flatten().value(); + flattened.forEach(function (thePattern) { + setAliases.push(thePattern.alias); + merged.push([thePattern]); + }); + return merged; +} +// var parsePattern = extd .switcher() .containsAt("or", 0, function (condition) { @@ -198,16 +208,16 @@ var parsePattern = extd } condition = normailizeConstraint(condition); if (condition[4] && condition[4].from) { - return [ - new FromPattern( - getParamType(condition[0], condition.scope), - condition[1] || "m", - parseConstraint(condition[2] || "true"), - condition[3] || {}, - parseConstraint(condition[4].from), - {scope: condition.scope, pattern: condition[2]} - ) - ]; + return [ + new FromPattern( + getParamType(condition[0], condition.scope), + condition[1] || "m", + parseConstraint(condition[2] || "true"), + condition[3] || {}, + parseConstraint(condition[4].from), + {scope: condition.scope, pattern: condition[2]} + ) + ]; } else { return [ new ObjectPattern( @@ -218,7 +228,7 @@ var parsePattern = extd {scope: condition.scope, pattern: condition[2]} ) ]; - } + } }).switcher(); var Rule = declare({ @@ -227,6 +237,7 @@ var Rule = declare({ this.name = name; this.pattern = pattern; this.cb = cb; + this.noLoop = options.noLoop; if (options.agendaGroup) { this.agendaGroup = options.agendaGroup; this.autoFocus = extd.isBoolean(options.autoFocus) ? options.autoFocus : false; @@ -236,7 +247,7 @@ var Rule = declare({ fire: function (flow, match) { var ret = new Promise(), cb = this.cb; - try { + try { if (cb.length === 3) { cb.call(flow, match.factHash, flow, ret.resolve); } else { @@ -249,67 +260,123 @@ var Rule = declare({ } } }); +exports.Rule = Rule; +// +function _mergePatterns (patterns) { + // + return function (patt, i) { + // [pattern], [pattern], ... in arrays of length 1 + // we wish to build a single array in order of lhs progression + if( isArray(patt) ) { + if( patt.length === 1 ) { + patt = patt[0]; + i = 0; + } + else { + throw new Error('invalid pattern structure'); + } + } + if (!patterns[i]) { + patterns[i] = i === 0 ? [] : patterns[i - 1].slice(); + //remove dup + if (i !== 0) { + patterns[i].pop(); + } + patterns[i].push(patt); + } else { + extd(patterns).forEach(function (p) { + p.push(patt); + }); + } + }; +} +// +// function createRule(name, options, conditions, cb) { - if (isArray(options)) { - cb = conditions; - conditions = options; - } else { - options = options || {}; - } - var isRules = extd.every(conditions, function (cond) { - return isArray(cond); - }); - if (isRules && conditions.length === 1) { - conditions = conditions[0]; - isRules = false; - } - var rules = []; - var scope = options.scope || {}; - conditions.scope = scope; - if (isRules) { - var _mergePatterns = function (patt, i) { - if (!patterns[i]) { - patterns[i] = i === 0 ? [] : patterns[i - 1].slice(); - //remove dup - if (i !== 0) { - patterns[i].pop(); - } - patterns[i].push(patt); - } else { - extd(patterns).forEach(function (p) { - p.push(patt); - }); - } - - }; - var l = conditions.length, patterns = [], condition; - for (var i = 0; i < l; i++) { - condition = conditions[i]; - condition.scope = scope; - extd.forEach(parsePattern(condition), _mergePatterns); - - } - rules = extd.map(patterns, function (patterns) { - var compPat = null; - for (var i = 0; i < patterns.length; i++) { - if (compPat === null) { - compPat = new CompositePattern(patterns[i++], patterns[i]); - } else { - compPat = new CompositePattern(compPat, patterns[i]); - } - } - return new Rule(name, options, compPat, cb); - }); - } else { - rules = extd.map(parsePattern(conditions), function (cond) { - return new Rule(name, options, cond, cb); - }); - } - return rules; + var rules = [], scope, patterns, isComposite; + function processConditions(conditions, scope) { + var l = conditions.length, + merged = [], + fnMerge = _mergePatterns(merged), + isRules = extd.every(conditions, function (cond) {return isArray(cond);}), + condition, rules, patterns; + // + if( isRules && conditions.length === 1 ) { + isRules = false; + conditions = conditions[0]; + } + // + function isSinglePattern(patterns) { + var ret = true; + if( patterns.length > 1 ) { + if( isArray(patterns[0]) ) { + ret = false; + } + // else it's OR [ p, p,...] which we treat as a single rule which results in multiple rules + } + return ret; + } + // + function patternFromCondition(condition, scope) { + var patterns; + condition.scope = scope; + patterns = parsePattern(condition); + return patterns; + } + // + function compositePattern(patterns) { + + return extd.map(merged, function (patterns) { + var compPat = null; + for (var i = 0; i < patterns.length; i++) { + if (compPat === null) { + compPat = new CompositePattern(patterns[i++], patterns[i]); + } else { + compPat = new CompositePattern(compPat, patterns[i]); + } + } + return new Rule(name, options, compPat, cb); + }); + } + // + function singlePattern(pattern) { + return extd.map(patterns, function (cond) { + return new Rule(name, options, cond, cb); + }); + } + // + if( isRules ) { + for (var i = 0; i < l; i++) { + condition = conditions[i]; + condition.scope = scope; + patterns = patternFromCondition(condition, scope); + extd.forEach( patterns, fnMerge ); + } + rules = compositePattern(merged); + } + else { + patterns = patternFromCondition(conditions, scope); + if( isSinglePattern(patterns) ) { + rules = singlePattern(patterns); + } + else { + extd.forEach( patterns, fnMerge ); + rules = compositePattern(merged); + } + } + return rules; + } + // + if (isArray(options)) { + cb = conditions; + conditions = options; + options = {}; + } else { + options = options || {}; + } + scope = options.scope || {}; + return processConditions(conditions, scope); } - exports.createRule = createRule; - -