yunkong2.javascript/lib/patternCompareFunctions.js
2018-07-21 19:30:07 +08:00

371 lines
12 KiB
JavaScript

'use strict';
function isRegExp(obj) {
return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
}
/**
*
* @param {{}} pattern The pattern object to use
* @param {string} propName The name of the property to compare
* @param {(event: any) => any} [eventPropertyExtractor] If given, this function is used to extract the property value from the event object. Otherwise the propName is used
*/
function stringOrRegExpCompare(pattern, propName, eventPropertyExtractor) {
/** @type {RegExp | string | string[]} */
const field = pattern[propName];
const hasExtractor = typeof eventPropertyExtractor === 'function';
if (isRegExp(field)) {
return function (event) {
const eventValue = hasExtractor ? eventPropertyExtractor(event) : event[propName];
return (eventValue != null && /** @type {RegExp} */ (field).test(eventValue));
};
} else if (Array.isArray(field)) {
return function (event) {
const eventValue = hasExtractor ? eventPropertyExtractor(event) : event[propName];
// An array matches when any element is found that satisfies the constraint
return eventValue != null && field.find(f => f === eventValue) != null;
};
} else {
return function (event) {
const eventValue = hasExtractor ? eventPropertyExtractor(event) : event[propName];
return (eventValue != null && field === eventValue);
};
}
}
const patternCompareFunctions = {
logic: function (pattern) {
},
id: (pattern) => stringOrRegExpCompare(pattern, 'id'),
name: (pattern) => stringOrRegExpCompare(pattern, 'name'),
change: function (pattern) {
switch (pattern.change) {
case 'eq': return function (event) { return (event.newState.val === event.oldState.val); };
case 'ne': return function (event) { return (event.newState.val !== event.oldState.val); };
case 'gt': return function (event) { return (event.newState.val > event.oldState.val); };
case 'ge': return function (event) { return (event.newState.val >= event.oldState.val); };
case 'lt': return function (event) { return (event.newState.val < event.oldState.val); };
case 'le': return function (event) { return (event.newState.val <= event.oldState.val); };
default: return function (/* event */) { return true; };
// on any other logic, just signal about message
}
},
ack: function (pattern) {
if (pattern.ack === true || pattern.ack === 'true') {
return function (event) {
return (event.newState.ack === true || event.newState.ack === 'true');
};
} else {
return function (event) {
return (event.newState.ack === false || event.newState.ack === 'false');
};
}
},
oldAck: function (pattern) {
if (pattern.oldAck === true || pattern.oldAck === 'true') {
return function (event) {
return (event.oldState.ack === true || event.oldState.ack === 'true');
};
} else {
return function (event) {
return (event.oldState.ack === false || event.oldState.ack === 'false');
};
}
},
val: function (pattern) {
const pval = pattern.val;
return function (event) {
return pval === event.newState.val;
};
},
valGt: function (pattern) {
const pvalGt = pattern.valGt;
return function (event) {
return event.newState.val > pvalGt;
};
},
valGe: function (pattern) {
const pvalGe = pattern.valGe;
return function (event) {
return event.newState.val >= pvalGe;
};
},
valLt: function (pattern) {
const pvalLt = pattern.valLt;
return function (event) {
return event.newState.val < pvalLt;
};
},
valLe: function (pattern) {
const pvalLe = pattern.valLe;
return function (event) {
return event.newState.val <= pvalLe;
};
},
valNe: function (pattern) {
const pvalNe = pattern.valNe;
return function (event) {
return event.newState.val !== pvalNe;
};
},
oldVal: function (pattern) {
const poldVal = pattern.oldVal;
return function (event) {
return poldVal === event.oldState.val;
};
},
oldValGt: function (pattern) {
const poldValGt = pattern.oldValGt;
return function (event) {
return event.oldState.val > poldValGt;
};
},
oldValGe: function (pattern) {
const poldValGe = pattern.oldValGe;
return function (event) {
return event.oldState.val >= poldValGe;
};
},
oldValLt: function (pattern) {
const poldValLt = pattern.oldValLt;
return function (event) {
return event.oldState.val < poldValLt;
};
},
oldValLe: function (pattern) {
const poldValLe = pattern.oldValLe;
return function (event) {
return event.oldState.val <= poldValLe;
};
},
oldValNe: function (pattern) {
const poldValNe = pattern.oldValNe;
return function (event) {
return event.oldState.val !== poldValNe;
};
},
ts: function (pattern) {
const pts = pattern.ts;
return function (event) {
return pts === event.newState.ts;
};
},
tsGt: function (pattern) {
const ptsGt = pattern.tsGt;
return function (event) {
return event.newState.ts > ptsGt;
};
},
tsGe: function (pattern) {
const ptsGe = pattern.tsGe;
return function (event) {
return event.newState.ts >= ptsGe;
};
},
tsLt: function (pattern) {
const ptsLt = pattern.tsLt;
return function (event) {
return event.newState.ts < ptsLt;
};
},
tsLe: function (pattern) {
const ptsLe = pattern.tsLe;
return function (event) {
return event.newState.ts <= ptsLe;
};
},
oldTs: function (pattern) {
const poldTs = pattern.oldTs;
return function (event) {
return poldTs === event.oldState.ts;
};
},
oldTsGt: function (pattern) {
const poldTsGt = pattern.oldTsGt;
return function (event) {
return event.oldState.ts > poldTsGt;
};
},
oldTsGe: function (pattern) {
const poldTsGe = pattern.oldTsGe;
return function (event) {
return event.oldState.ts >= poldTsGe;
};
},
oldTsLt: function (pattern) {
const poldTsLt = pattern.oldTsLt;
return function (event) {
return event.oldState.ts < poldTsLt;
};
},
oldTsLe: function (pattern) {
const poldTsLe = pattern.oldTsLe;
return function (event) {
return event.oldState.ts <= poldTsLe;
};
},
lc: function (pattern) {
const plc = pattern.lc;
return function (event) {
return plc === event.newState.lc;
};
},
lcGt: function (pattern) {
const plcGt = pattern.lcGt;
return function (event) {
return event.newState.lc > plcGt;
};
},
lcGe: function (pattern) {
const plcGe = pattern.lcGe;
return function (event) {
return event.newState.lc >= plcGe;
};
},
lcLt: function (pattern) {
const plcLt = pattern.lcLt;
return function (event) {
return event.newState.lc < plcLt;
};
},
lcLe: function (pattern) {
const plcLe = pattern.lcLe;
return function (event) {
return event.newState.lc <= plcLe;
};
},
oldLc: function (pattern) {
const poldLc = pattern.oldLc;
return function (event) {
return poldLc === event.oldState.lc;
};
},
oldLcGt: function (pattern) {
const poldLcGt = pattern.oldLcGt;
return function (event) {
return event.oldState.lc > poldLcGt;
};
},
oldLcGe: function (pattern) {
const poldLcGe = pattern.oldLcGe;
return function (event) {
return event.oldState.lc >= poldLcGe;
};
},
oldLcLt: function (pattern) {
const poldLcLt = pattern.oldLcLt;
return function (event) {
return event.oldState.lc < poldLcLt;
};
},
oldLcLe: function (pattern) {
const poldLcLe = pattern.oldLcLe;
return function (event) {
return event.oldState.lc <= poldLcLe;
};
},
from: (pattern) => stringOrRegExpCompare(pattern, 'from',
(event) => event && event.newState && event.newState.from
),
fromNe: (pattern) => !stringOrRegExpCompare(pattern, 'fromNe',
(event) => event && event.newState && event.newState.from
),
oldFrom: (pattern) => stringOrRegExpCompare(pattern, 'oldFrom',
(event) => event && event.oldState && event.oldState.from
),
oldFromNe: (pattern) => !stringOrRegExpCompare(pattern, 'oldFromNe',
(event) => event && event.oldState && event.oldState.from
),
channelId: (pattern) => stringOrRegExpCompare(pattern, 'channelId'),
channelName: (pattern) => stringOrRegExpCompare(pattern, 'channelName'),
deviceId: (pattern) => stringOrRegExpCompare(pattern, 'deviceId'),
deviceName: (pattern) => stringOrRegExpCompare(pattern, 'deviceName'),
enumId: (pattern) => {
/** @type {RegExp | string | string[]} */
const penumId = pattern.enumId;
function ensureEnumIDsIsArray(enumIds) {
if (!Array.isArray(enumIds)) {
console.error(`enumIds is of type ${typeof enumIds} but should be an array: ${JSON.stringify(enumIds)}`);
return false;
}
return true;
}
if (isRegExp(penumId)) {
return function (event) {
const enumIds = event.enumIds;
if (enumIds == null || !ensureEnumIDsIsArray(enumIds)) return false;
// Test if any enum name matches the regex:
return enumIds.find(e => /** @type {RegExp} */ (penumId).test(e)) != null;
};
} else if (Array.isArray(penumId)) {
return function (event) {
const enumIds = event.enumIds;
if (enumIds == null || !ensureEnumIDsIsArray(enumIds)) return false;
// Test if the enum names of the event and the given array intersect
return enumIds.find(e => penumId.indexOf(e) > -1) != null;
};
} else {
return function (event) {
const enumIds = event.enumIds;
if (enumIds == null || !ensureEnumIDsIsArray(enumIds)) return false;
return (enumIds && enumIds.indexOf(penumId) !== -1);
};
}
},
enumName: function (pattern) {
/** @type {RegExp | string | string[]} */
const penumName = pattern.enumName;
function ensureEnumNamesIsArray(enumNames) {
if (!Array.isArray(enumNames)) {
console.error(`enumNames is of type ${typeof enumNames} but should be an array: ${JSON.stringify(enumNames)}`);
return false;
}
return true;
}
if (isRegExp(penumName)) {
return function (event) {
const enumNames = event.enumNames;
if (enumNames == null || !ensureEnumNamesIsArray(enumNames)) return false;
// Test if any enum name matches the regex:
return enumNames.find(e => /** @type {RegExp} */ (penumName).test(e)) != null;
};
} else if (Array.isArray(penumName)) {
return function (event) {
const enumNames = event.enumNames;
if (enumNames == null || !ensureEnumNamesIsArray(enumNames)) return false;
// Test if the enum names of the event and the given array intersect
return enumNames.find(e => penumName.indexOf(e) > -1) != null;
};
} else {
return function (event) {
const enumNames = event.enumNames;
if (enumNames == null || !ensureEnumNamesIsArray(enumNames)) return false;
return (enumNames && enumNames.indexOf(penumName) !== -1);
};
}
}
};
module.exports = patternCompareFunctions;