-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmap.js
189 lines (170 loc) · 5.74 KB
/
map.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
module.exports = function(RED) {
var mustache = require("mustache");
function MapConfigNode(n) {
RED.nodes.createNode(this, n);
this.name = n.name;
this.rhsName = n.rhsName;
this.lhsName = n.lhsName;
this.mappings = n.mappings;
var node = this;
/**
* This function returns either the LHS or RHS of a given mapping,
* or LHS|RHS, depending on whether the lhsOrRhsOrBoth parameter is
* set to 'lhs', 'rhs', or 'both'.
*/
var getMappingValue = function(mapping, lhsOrRhsOrBoth) {
switch (lhsOrRhsOrBoth) {
case 'lhs': return mapping.lhs;
case 'rhs': return mapping.rhs;
case 'both': return mapping.lhs+'|'+mapping.rhs;
default: throw "Unsupported lhsOrRhsOrBoth parameter value: "+lhsOrRhsOrBoth;
}
}
/**
* This function converts a mappings array to a map.
*
* Parameters:
* - lhsOrRhsOrBothForKey: May be either 'lhs', 'rhs', or 'both', defining whether to use the mapping
* LHS or RHS as the map key, or to combine both as the map key in the format
* lhs|rhs.
* - keyToLowerCase: true if key needs to be converted to lower case (for case-insensitive look-up),
* false if the key is to be used as-is (for case-sensitive look-up)
*/
var mappingsToMap = function(lhsOrRhsOrBothForKey, keyToLowerCase) {
return !node.mappings ? [] : node.mappings.reduce(function(result, mapping) {
var key = getMappingValue(mapping, lhsOrRhsOrBothForKey);
if ( keyToLowerCase ) {
key = key.toLowerCase();
}
result[key] = mapping;
return result;
}, {});
}
/**
* Define maps with keys as case-sensitive or case-insensitive LHS or RHS values
* and the corresponding mapping as value
*/
this.maps = {
lhs: {
caseSensitive: mappingsToMap('lhs', false),
caseInsensitive: mappingsToMap('lhs', true)
},
rhs: {
caseSensitive: mappingsToMap('rhs', false),
caseInsensitive: mappingsToMap('rhs', true)
},
both: {
caseSensitive: mappingsToMap('both', false),
caseInsensitive: mappingsToMap('both', true)
}
};
/**
* Get the mapping for the given key value. Depending on the value of lhsOrRhsOrBothForKey:
* - 'lhs': Match the given key value against the LHS of the configured mappings
* - 'rhs': Match the given key value against the RHS of the configured mappings
* - 'both': Match the given key value against '[LHS]|[RHS]' of the configured mappings
*/
this.getMapping = function(lhsOrRhsOrBothForKey, keyValue, caseInsensitive) {
if ( !keyValue ) { return null; }
keyValue = String(keyValue);
if ( caseInsensitive ) {
keyValue = keyValue.toLowerCase();
}
return node.maps[lhsOrRhsOrBothForKey][caseInsensitive?'caseInsensitive':'caseSensitive'][keyValue];
}
/**
* Get the mapping for the given key value, matching it against either the
* LHS or RHS value of the mapping, then return wither the LHS or RHS value
* of this mapping
*/
this.getMappingValue = function(lhsOrRhsOrBothForKey, keyValue, lhsOrRhsOrBothForValue, caseInsensitive) {
var mapping = node.getMapping(lhsOrRhsOrBothForKey, keyValue, caseInsensitive);
return !mapping ? null : getMappingValue(mapping, lhsOrRhsOrBothForValue);
}
}
RED.nodes.registerType("map-config", MapConfigNode);
function MapMapNode(n) {
RED.nodes.createNode(this, n);
this.name = n.name;
this.config = RED.nodes.getNode(n.config);
this.in = n.in;
this.inType = n.inType;
this.inLhsOrRhs = n.inLhsOrRhs;
this.out = n.out;
this.outType = n.outType;
this.outLhsOrRhs = n.outLhsOrRhs;
this.caseInsensitive = n.caseInsensitive;
this.forwardIfNoMatch = n.forwardIfNoMatch;
this.defaultIfNoMatch = n.defaultIfNoMatch;
var node = this;
node.on("input", function(msg) {
try {
var inValue = RED.util.getMessageProperty(msg, node.in);
var outValue = node.config.getMappingValue(node.inLhsOrRhs, inValue, node.outLhsOrRhs, node.caseInsensitive);
if ( !outValue && node.forwardIfNoMatch ) {
outValue = mustache.render(node.defaultIfNoMatch, msg);
}
if ( outValue || node.forwardIfNoMatch ) {
RED.util.setMessageProperty(msg, node.out, outValue);
node.send(msg);
}
}
catch(err) {
node.error(err.message, msg);
}
});
}
RED.nodes.registerType("map-map", MapMapNode);
function MapSetNode(n) {
RED.nodes.createNode(this, n);
this.name = n.name;
this.config = RED.nodes.getNode(n.config);
this.from = n.from;
this.out = n.out;
this.outType = n.outType;
this.outLhsOrRhs = n.outLhsOrRhs;
var node = this;
node.on("input", function(msg) {
try {
var outValue = node.config.getMappingValue('both', node.from, node.outLhsOrRhs, false);
RED.util.setMessageProperty(msg, node.out, outValue);
node.send(msg);
}
catch(err) {
node.error(err.message, msg);
}
});
}
RED.nodes.registerType("map-set", MapSetNode);
function MapSwitchNode(n) {
RED.nodes.createNode(this, n);
this.name = n.name;
this.config = RED.nodes.getNode(n.config);
this.outLhsOrRhs = n.outLhsOrRhs;
this.in = n.in;
this.inType = n.inType;
this.inLhsOrRhs = n.inLhsOrRhs;
this.caseInsensitive = n.caseInsensitive;
this.switchValues = n.switchValues;
var node = this;
node.on("input", function(msg) {
try {
var inValue = RED.util.getMessageProperty(msg, node.in);
var outValue = node.config.getMappingValue(node.inLhsOrRhs, inValue, 'both', node.caseInsensitive);
if ( outValue ) {
var msgs = new Array(node.switchValues.length);
node.switchValues.forEach(function(switchValue, i) {
if ( switchValue===outValue ) {
msgs[i]=msg;
}
});
node.send(msgs);
}
}
catch(err) {
node.error(err.message, msg);
}
});
}
RED.nodes.registerType("map-switch", MapSwitchNode);
}