-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathdata-model-filter.parser.js
More file actions
146 lines (141 loc) · 5.91 KB
/
data-model-filter.parser.js
File metadata and controls
146 lines (141 loc) · 5.91 KB
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
const { AsyncSeriesEventEmitter } = require('@themost/events');
const { OpenDataParser, Expression } = require('@themost/query');
const { DataAttributeResolver } = require('./data-attribute-resolver');
const { DataFilterResolver } = require('./data-filter-resolver');
class DataModelFilterParser {
/**
*
* @param {import("./data-model").DataModel} model
*/
constructor(model) {
this.resolvingMember = new AsyncSeriesEventEmitter();
this.resolvingMethod = new AsyncSeriesEventEmitter();
this.model = model;
}
parse(str, callback) {
const self = this;
const thisModel = this.model;
const $expand = [];
const parser = new OpenDataParser();
parser.resolveMember = function(member, cb) {
const attr = thisModel.field(member);
if (attr) {
member = attr.name;
if (attr.multiplicity === 'ZeroOrOne') {
var mapping1 = thisModel.inferMapping(member);
if (mapping1 && mapping1.associationType === 'junction' && mapping1.parentModel === thisModel.name) {
member = attr.name.concat('/', mapping1.childField);
} else if (mapping1 && mapping1.associationType === 'junction' && mapping1.childModel === thisModel.name) {
member = attr.name.concat('/', mapping1.parentField);
}
}
}
const event = {
target: self,
member: member,
result: null
}
void self.resolvingMember.emit(event).then(() => {
if (event.result) {
return cb(null, event.result.$select);
}
if (DataAttributeResolver.prototype.testNestedAttribute.call(thisModel,member)) {
try {
var member1 = member.split('/'),
mapping = thisModel.inferMapping(member1[0]),
expr;
if (mapping && mapping.associationType === 'junction') {
var expr1 = DataAttributeResolver.prototype.resolveJunctionAttributeJoin.call(thisModel, member);
expr = {
$expand: expr1.$expand
};
//replace member expression
member = expr1.$select.$name.replace(/\./g,'/');
}
else {
expr = DataAttributeResolver.prototype.resolveNestedAttributeJoin.call(thisModel, member);
if (expr && expr.$select instanceof Expression) {
// // use it as select expression after converting it to query field
return cb(null, expr.$select);
} else if (expr.$select) {
member = expr.$select.$name.replace(/\./g,'/');
}
}
if (expr && expr.$expand) {
var arrExpr = [];
if (Array.isArray(expr.$expand)) {
arrExpr.push.apply(arrExpr, expr.$expand);
} else {
arrExpr.push(expr.$expand);
}
arrExpr.forEach(function(y) {
var joinExpr = $expand.find(function(x) {
if (x.$entity && x.$entity.$as) {
return (x.$entity.$as === y.$entity.$as);
}
return false;
});
if (joinExpr == null)
$expand.push(y);
});
}
}
catch (err) {
return cb(err);
}
}
if (typeof thisModel.resolveMember === 'function') {
thisModel.resolveMember.call(thisModel, member, cb);
} else {
DataFilterResolver.prototype.resolveMember.call(thisModel, member, cb);
}
}).catch(function(err) {
return callback(err);
});
}
parser.resolveMethod = function(name, args, cb) {
const thisModel = self.model;
const event = {
target: self,
method: name,
args: args,
result: null
}
void self.resolvingMethod.emit(event).then(function() {
if (event.result) {
return cb(null, event.result);
}
if (typeof thisModel.resolveMethod === 'function') {
thisModel.resolveMethod.call(thisModel, name, args, cb);
} else {
DataFilterResolver.prototype.resolveMethod.call(thisModel, name, args, cb);
}
}).catch(function(err) {
return cb(err);
});
}
void parser.parse(str, function(err, result) {
if (err) {
return callback(err);
}
return callback(null, {
$where: result,
$expand: $expand
});
});
}
parseAsync(str) {
const self = this;
return new Promise(function(resolve, reject) {
void self.parse(str, function(err, result) {
if (err) {
return reject(err);
}
return resolve(result);
});
});
}
}
module.exports = {
DataModelFilterParser
}