371 lines
12 KiB
JavaScript
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;
|