@sap/cds-compiler 4.1.2 → 4.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +107 -1
- package/bin/cdsc.js +6 -3
- package/doc/CHANGELOG_BETA.md +5 -0
- package/doc/CHANGELOG_DEPRECATED.md +15 -0
- package/lib/api/main.js +2 -2
- package/lib/api/options.js +2 -2
- package/lib/api/validate.js +24 -24
- package/lib/base/message-registry.js +41 -6
- package/lib/base/messages.js +7 -0
- package/lib/base/model.js +38 -8
- package/lib/checks/elements.js +11 -10
- package/lib/checks/manyNavigations.js +33 -0
- package/lib/checks/onConditions.js +5 -2
- package/lib/checks/queryNoDbArtifacts.js +2 -3
- package/lib/checks/selectItems.js +4 -55
- package/lib/checks/utils.js +3 -2
- package/lib/checks/validator.js +3 -1
- package/lib/compiler/.eslintrc.json +2 -1
- package/lib/compiler/assert-consistency.js +27 -24
- package/lib/compiler/base.js +6 -2
- package/lib/compiler/builtins.js +34 -34
- package/lib/compiler/checks.js +179 -208
- package/lib/compiler/classes.js +2 -2
- package/lib/compiler/cycle-detector.js +6 -6
- package/lib/compiler/define.js +66 -45
- package/lib/compiler/extend.js +81 -72
- package/lib/compiler/finalize-parse-cdl.js +26 -26
- package/lib/compiler/generate.js +61 -45
- package/lib/compiler/index.js +47 -49
- package/lib/compiler/kick-start.js +8 -7
- package/lib/compiler/moduleLayers.js +1 -1
- package/lib/compiler/populate.js +42 -35
- package/lib/compiler/propagator.js +6 -6
- package/lib/compiler/resolve.js +170 -126
- package/lib/compiler/shared.js +122 -45
- package/lib/compiler/tweak-assocs.js +93 -40
- package/lib/compiler/utils.js +15 -12
- package/lib/edm/.eslintrc.json +40 -1
- package/lib/edm/annotations/genericTranslation.js +721 -707
- package/lib/edm/annotations/preprocessAnnotations.js +88 -77
- package/lib/edm/csn2edm.js +389 -378
- package/lib/edm/edm.js +678 -772
- package/lib/edm/edmAnnoPreprocessor.js +132 -146
- package/lib/edm/edmInboundChecks.js +29 -27
- package/lib/edm/edmPreprocessor.js +686 -646
- package/lib/edm/edmUtils.js +277 -296
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +1253 -1276
- package/lib/json/from-csn.js +34 -4
- package/lib/json/to-csn.js +4 -4
- package/lib/language/language.g4 +2 -5
- package/lib/main.d.ts +61 -1
- package/lib/model/csnUtils.js +31 -2
- package/lib/model/revealInternalProperties.js +1 -1
- package/lib/modelCompare/compare.js +37 -2
- package/lib/modelCompare/utils/filter.js +1 -1
- package/lib/optionProcessor.js +15 -3
- package/lib/render/toCdl.js +30 -4
- package/lib/render/toSql.js +5 -9
- package/lib/render/utils/common.js +8 -6
- package/lib/transform/db/applyTransformations.js +1 -1
- package/lib/transform/db/cdsPersistence.js +1 -1
- package/lib/transform/db/constraints.js +47 -17
- package/lib/transform/db/expansion.js +133 -50
- package/lib/transform/db/flattening.js +75 -7
- package/lib/transform/forOdata.js +4 -1
- package/lib/transform/forRelationalDB.js +80 -62
- package/lib/transform/localized.js +91 -54
- package/lib/transform/transformUtils.js +9 -10
- package/lib/utils/file.js +7 -7
- package/lib/utils/moduleResolve.js +210 -121
- package/lib/utils/objectUtils.js +1 -1
- package/package.json +5 -5
package/lib/edm/edm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict'
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
const edmUtils = require('./edmUtils.js');
|
|
4
4
|
const { isBuiltinType } = require('../model/csnUtils.js');
|
|
@@ -7,25 +7,37 @@ const { forEach } = require('../utils/objectUtils');
|
|
|
7
7
|
// facet definitions, optional could either be true or array of edm types
|
|
8
8
|
// remove indicates wether or not the canonic facet shall be removed when applying @odata.Type
|
|
9
9
|
const EdmTypeFacetMap = {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
MaxLength: {
|
|
11
|
+
v2: true, v4: true, remove: true, optional: true,
|
|
12
|
+
},
|
|
13
|
+
Precision: {
|
|
14
|
+
v2: true, v4: true, remove: true, optional: true,
|
|
15
|
+
},
|
|
16
|
+
Scale: {
|
|
17
|
+
v2: true, v4: true, remove: true, optional: true, extra: 'sap:variable-scale',
|
|
18
|
+
},
|
|
19
|
+
SRID: { v4: true, remove: true, optional: true },
|
|
20
|
+
// 'FixedLength': { v2: true },
|
|
21
|
+
// 'Collation': { v2: true },
|
|
22
|
+
// 'Unicode': { v2: true, v4: true },
|
|
17
23
|
};
|
|
18
24
|
const EdmTypeFacetNames = Object.keys(EdmTypeFacetMap);
|
|
19
25
|
|
|
20
26
|
// Merged primitive type map with descriptions taken from V4 spec and filled up with V2 spec
|
|
21
27
|
const EdmPrimitiveTypeMap = {
|
|
22
|
-
'Edm.Binary': {
|
|
28
|
+
'Edm.Binary': {
|
|
29
|
+
v2: true, v4: true, MaxLength: true, FixedLength: true, desc: 'Binary data',
|
|
30
|
+
},
|
|
23
31
|
'Edm.Boolean': { v2: true, v4: true, desc: 'Binary-valued logic' },
|
|
24
32
|
'Edm.Byte': { v2: true, v4: true, desc: 'Unsigned 8-bit integer' },
|
|
25
33
|
'Edm.Date': { v4: true, desc: 'Date without a time-zone offset' },
|
|
26
34
|
'Edm.DateTime': { v2: true, Precision: true, desc: 'Date and time with values ranging from 12:00:00 midnight, January 1, 1753 A.D. through 11:59:59 P.M, December 31, 9999 A.D.' },
|
|
27
|
-
'Edm.DateTimeOffset': {
|
|
28
|
-
|
|
35
|
+
'Edm.DateTimeOffset': {
|
|
36
|
+
v2: true, v4: true, Precision: true, desc: 'Date and time with a time-zone offset, no leap seconds',
|
|
37
|
+
},
|
|
38
|
+
'Edm.Decimal': {
|
|
39
|
+
v2: true, v4: true, Precision: true, Scale: true, desc: 'Numeric values with decimal representation',
|
|
40
|
+
},
|
|
29
41
|
'Edm.Double': { v2: true, v4: true, desc: 'IEEE 754 binary64 floating-point number (15-17 decimal digits)' },
|
|
30
42
|
'Edm.Duration': { v4: true, Precision: true, desc: 'Signed duration in days, hours, minutes, and (sub)seconds' },
|
|
31
43
|
'Edm.Guid': { v2: true, v4: true, desc: '16-byte (128-bit) unique identifier' },
|
|
@@ -35,7 +47,9 @@ const EdmPrimitiveTypeMap = {
|
|
|
35
47
|
'Edm.SByte': { v2: true, v4: true, desc: 'Signed 8-bit integer' },
|
|
36
48
|
'Edm.Single': { v2: true, v4: true, desc: 'IEEE 754 binary32 floating-point number (6-9 decimal digits)' },
|
|
37
49
|
'Edm.Stream': { v4: true, MaxLength: true, desc: 'Binary data stream' },
|
|
38
|
-
'Edm.String': {
|
|
50
|
+
'Edm.String': {
|
|
51
|
+
v2: true, v4: true, MaxLength: true, FixedLength: true, Collation: true, Unicode: true, desc: 'Sequence of characters',
|
|
52
|
+
},
|
|
39
53
|
'Edm.Time': { v2: true, Precision: true, desc: 'time of day with values ranging from 0:00:00.x to 23:59:59.y, where x and y depend upon the precision' },
|
|
40
54
|
'Edm.TimeOfDay': { v4: true, Precision: true, desc: 'Clock time 00:00-23:59:59.999999999999' },
|
|
41
55
|
'Edm.Geography': { v4: true, SRID: true, desc: 'Abstract base type for all Geography types' },
|
|
@@ -55,25 +69,23 @@ const EdmPrimitiveTypeMap = {
|
|
|
55
69
|
'Edm.GeometryMultiPolygon': { v4: true, SRID: true, desc: 'Collection of polygons in a flat-earth coordinate system' },
|
|
56
70
|
'Edm.GeometryCollection': { v4: true, SRID: true, desc: 'Collection of arbitrary Geometry values' },
|
|
57
71
|
'Edm.PrimitiveType': { v4: true, desc: 'Abstract meta type' },
|
|
58
|
-
//'Edm.Untyped': { v4: true, desc: 'Abstract void type' },
|
|
72
|
+
// 'Edm.Untyped': { v4: true, desc: 'Abstract void type' },
|
|
59
73
|
};
|
|
60
74
|
|
|
61
|
-
function getEdm(options, messageFunctions) {
|
|
62
|
-
const { error } = messageFunctions || { error: ()=>true, warning: ()=>true };
|
|
63
|
-
class Node
|
|
64
|
-
{
|
|
75
|
+
function getEdm( options, messageFunctions ) {
|
|
76
|
+
const { error } = messageFunctions || { error: () => true, warning: () => true };
|
|
77
|
+
class Node {
|
|
65
78
|
/**
|
|
66
|
-
* @param {boolean[]}
|
|
79
|
+
* @param {boolean[]} version Versions in the form of [<v2>, <v4>].
|
|
67
80
|
* @param {object} attributes
|
|
68
81
|
* @param {CSN.Model} csn
|
|
69
82
|
*/
|
|
70
|
-
constructor(
|
|
71
|
-
|
|
72
|
-
if(!attributes || typeof attributes !== 'object')
|
|
83
|
+
constructor(version, attributes = Object.create(null), csn = undefined) {
|
|
84
|
+
if (!attributes || typeof attributes !== 'object')
|
|
73
85
|
error(null, 'Please debug me: attributes must be a dictionary');
|
|
74
|
-
if(!Array.isArray(
|
|
75
|
-
error(null,
|
|
76
|
-
if(
|
|
86
|
+
if (!Array.isArray(version))
|
|
87
|
+
error(null, `Please debug me: v is either undefined or not an array: ${version}`);
|
|
88
|
+
if (version.filter(v => v).length !== 1)
|
|
77
89
|
error(null, 'Please debug me: exactly one version must be set');
|
|
78
90
|
|
|
79
91
|
// Common attributes of JSON and XML.
|
|
@@ -85,17 +97,21 @@ function getEdm(options, messageFunctions) {
|
|
|
85
97
|
|
|
86
98
|
this._children = [];
|
|
87
99
|
this._ignoreChildren = false;
|
|
88
|
-
this._v =
|
|
100
|
+
this._v = version;
|
|
89
101
|
|
|
90
|
-
if(this.v2)
|
|
102
|
+
if (this.v2)
|
|
91
103
|
this.setSapVocabularyAsAttributes(csn);
|
|
92
104
|
}
|
|
93
105
|
|
|
94
|
-
get v2() {
|
|
95
|
-
|
|
106
|
+
get v2() {
|
|
107
|
+
return this._v[0];
|
|
108
|
+
}
|
|
109
|
+
get v4() {
|
|
110
|
+
return this._v[1];
|
|
111
|
+
}
|
|
96
112
|
|
|
97
113
|
get kind() {
|
|
98
|
-
return this.constructor.name
|
|
114
|
+
return this.constructor.name;
|
|
99
115
|
}
|
|
100
116
|
|
|
101
117
|
/**
|
|
@@ -104,7 +120,7 @@ function getEdm(options, messageFunctions) {
|
|
|
104
120
|
* @param {any} value
|
|
105
121
|
*/
|
|
106
122
|
setEdmAttribute(key, value) {
|
|
107
|
-
if(key !== undefined && key !== null && value !== undefined && value !== null)
|
|
123
|
+
if (key !== undefined && key !== null && value !== undefined && value !== null)
|
|
108
124
|
this._edmAttributes[key] = value;
|
|
109
125
|
}
|
|
110
126
|
|
|
@@ -124,8 +140,7 @@ function getEdm(options, messageFunctions) {
|
|
|
124
140
|
* @param {object} attributes
|
|
125
141
|
* @return {any}
|
|
126
142
|
*/
|
|
127
|
-
setXml(attributes)
|
|
128
|
-
{
|
|
143
|
+
setXml(attributes) {
|
|
129
144
|
return Object.assign(this._xmlOnlyAttributes, attributes);
|
|
130
145
|
}
|
|
131
146
|
|
|
@@ -136,176 +151,188 @@ function getEdm(options, messageFunctions) {
|
|
|
136
151
|
* @param {object} attributes
|
|
137
152
|
* @return {any}
|
|
138
153
|
*/
|
|
139
|
-
setJSON(attributes)
|
|
140
|
-
{
|
|
154
|
+
setJSON(attributes) {
|
|
141
155
|
return Object.assign(this._jsonOnlyAttributes, attributes);
|
|
142
156
|
}
|
|
143
157
|
|
|
144
|
-
prepend(...children)
|
|
145
|
-
{
|
|
158
|
+
prepend(...children) {
|
|
146
159
|
this._children.splice(0, 0, ...children.filter(c => c));
|
|
147
160
|
return this;
|
|
148
161
|
}
|
|
149
162
|
|
|
150
|
-
append(...children)
|
|
151
|
-
{
|
|
163
|
+
append(...children) {
|
|
152
164
|
// remove undefined entries
|
|
153
165
|
this._children.push(...children.filter(c => c));
|
|
154
|
-
return this
|
|
166
|
+
return this;
|
|
155
167
|
}
|
|
156
168
|
|
|
157
169
|
// virtual
|
|
158
|
-
toJSON()
|
|
159
|
-
{
|
|
170
|
+
toJSON() {
|
|
160
171
|
const json = Object.create(null);
|
|
161
172
|
// $kind Property MAY be omitted in JSON for performance reasons
|
|
162
|
-
if(!(this.kind in Node.noJsonKinds))
|
|
163
|
-
json
|
|
173
|
+
if (!(this.kind in Node.noJsonKinds))
|
|
174
|
+
json.$Kind = this.kind;
|
|
164
175
|
|
|
165
176
|
this.toJSONattributes(json);
|
|
166
177
|
this.toJSONchildren(json);
|
|
167
|
-
return json
|
|
178
|
+
return json;
|
|
168
179
|
}
|
|
169
180
|
|
|
170
181
|
// virtual
|
|
171
|
-
toJSONattributes(json)
|
|
172
|
-
{
|
|
182
|
+
toJSONattributes(json) {
|
|
173
183
|
forEach(this._edmAttributes, (p, v) => {
|
|
174
184
|
if (p !== 'Name')
|
|
175
|
-
json[p[0] === '@' ? p :
|
|
185
|
+
json[p[0] === '@' ? p : `$${p}`] = v;
|
|
176
186
|
});
|
|
177
187
|
return json;
|
|
178
188
|
}
|
|
179
189
|
|
|
180
190
|
// virtual
|
|
181
|
-
toJSONchildren(json)
|
|
182
|
-
{
|
|
191
|
+
toJSONchildren(json) {
|
|
183
192
|
// any child with a Name should be added by its name into the JSON object
|
|
184
193
|
// all others must overload toJSONchildren()
|
|
185
|
-
this._children.filter(c => c._edmAttributes.Name).forEach(c =>
|
|
194
|
+
this._children.filter(c => c._edmAttributes.Name).forEach((c) => {
|
|
195
|
+
json[c._edmAttributes.Name] = c.toJSON();
|
|
196
|
+
});
|
|
186
197
|
}
|
|
187
198
|
|
|
188
199
|
// virtual
|
|
189
|
-
toXML(indent = '', what='all')
|
|
190
|
-
|
|
191
|
-
let
|
|
192
|
-
let head = indent + '<' + kind;
|
|
200
|
+
toXML(indent = '', what = 'all') {
|
|
201
|
+
const { kind } = this;
|
|
202
|
+
let head = `${indent}<${kind}`;
|
|
193
203
|
|
|
194
|
-
if(kind==='Parameter' && this._edmAttributes.Collection) {
|
|
204
|
+
if (kind === 'Parameter' && this._edmAttributes.Collection) {
|
|
195
205
|
delete this._edmAttributes.Collection;
|
|
196
|
-
this._edmAttributes.Type
|
|
206
|
+
this._edmAttributes.Type = `Collection(${this._edmAttributes.Type})`;
|
|
197
207
|
}
|
|
198
208
|
|
|
199
209
|
head += this.toXMLattributes();
|
|
200
210
|
|
|
201
|
-
|
|
202
|
-
if (inner.length < 1)
|
|
203
|
-
head += '/>'
|
|
204
|
-
|
|
205
|
-
else if (inner.length < 77 && inner.indexOf('<') < 0)
|
|
206
|
-
head +=
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
211
|
+
const inner = this.innerXML(`${indent} `, what);
|
|
212
|
+
if (inner.length < 1)
|
|
213
|
+
head += '/>';
|
|
214
|
+
|
|
215
|
+
else if (inner.length < 77 && inner.indexOf('<') < 0)
|
|
216
|
+
head += `>${inner.slice(indent.length + 1, -1)}</${kind}>`;
|
|
217
|
+
|
|
218
|
+
else
|
|
219
|
+
head += `>\n${inner}${indent}</${kind}>`;
|
|
220
|
+
|
|
210
221
|
return head;
|
|
211
222
|
}
|
|
212
223
|
|
|
213
224
|
// virtual
|
|
214
|
-
toXMLattributes()
|
|
215
|
-
{
|
|
225
|
+
toXMLattributes() {
|
|
216
226
|
let tmpStr = '';
|
|
217
227
|
forEach(this._edmAttributes, (p, v) => {
|
|
218
228
|
if (v !== undefined && typeof v !== 'object')
|
|
219
|
-
tmpStr +=
|
|
229
|
+
tmpStr += ` ${p}="${edmUtils.escapeStringForAttributeValue(v)}"`;
|
|
220
230
|
});
|
|
221
231
|
forEach(this._xmlOnlyAttributes, (p, v) => {
|
|
222
232
|
if (v !== undefined && typeof v !== 'object')
|
|
223
|
-
tmpStr +=
|
|
233
|
+
tmpStr += ` ${p}="${edmUtils.escapeStringForAttributeValue(v)}"`;
|
|
224
234
|
});
|
|
225
235
|
return tmpStr;
|
|
226
236
|
}
|
|
227
237
|
|
|
228
238
|
// virtual
|
|
229
|
-
innerXML(indent, what='all')
|
|
230
|
-
{
|
|
239
|
+
innerXML(indent, what = 'all') {
|
|
231
240
|
let xml = '';
|
|
232
241
|
|
|
233
|
-
this._children.forEach(e =>
|
|
234
|
-
xml += e.toXML(indent, what)
|
|
242
|
+
this._children.forEach((e) => {
|
|
243
|
+
xml += `${e.toXML(indent, what)}\n`;
|
|
244
|
+
});
|
|
235
245
|
return xml;
|
|
236
246
|
}
|
|
237
247
|
|
|
238
248
|
// virtual
|
|
239
|
-
setSapVocabularyAsAttributes(csn, useSetAttributes=false)
|
|
240
|
-
|
|
241
|
-
if(csn)
|
|
242
|
-
{
|
|
249
|
+
setSapVocabularyAsAttributes(csn, useSetAttributes = false) {
|
|
250
|
+
if (csn) {
|
|
243
251
|
const attr = (useSetAttributes ? csn._SetAttributes : csn);
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
252
|
+
if (attr) {
|
|
253
|
+
Object.entries(attr).forEach(([ p, v ]) => {
|
|
254
|
+
if (p.match(/^@sap./))
|
|
255
|
+
this.setXml( { [`sap:${p.slice(5).replace(/\./g, '-')}`]: v } );
|
|
256
|
+
});
|
|
257
|
+
}
|
|
248
258
|
}
|
|
249
259
|
}
|
|
250
260
|
}
|
|
251
261
|
|
|
252
262
|
// $kind Property MAY be omitted in JSON for performance reasons
|
|
253
|
-
Node.noJsonKinds = {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
{
|
|
259
|
-
super(
|
|
260
|
-
if(this.v2)
|
|
263
|
+
Node.noJsonKinds = {
|
|
264
|
+
Property: 1, EntitySet: 1, ActionImport: 1, FunctionImport: 1, Singleton: 1, Schema: 1,
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
class Reference extends Node {
|
|
268
|
+
constructor(version, details) {
|
|
269
|
+
super(version, details);
|
|
270
|
+
if (this.v2)
|
|
261
271
|
this._edmAttributes['xmlns:edmx'] = 'http://docs.oasis-open.org/odata/ns/edmx';
|
|
262
272
|
}
|
|
263
273
|
|
|
264
|
-
get kind() {
|
|
274
|
+
get kind() {
|
|
275
|
+
return 'edmx:Reference';
|
|
276
|
+
}
|
|
265
277
|
|
|
266
|
-
toJSON()
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
let includes = [];
|
|
278
|
+
toJSON() {
|
|
279
|
+
const json = Object.create(null);
|
|
280
|
+
const includes = [];
|
|
270
281
|
|
|
271
282
|
this._children.forEach(c => includes.push(c.toJSON()));
|
|
272
|
-
if(includes.length > 0)
|
|
273
|
-
json
|
|
283
|
+
if (includes.length > 0)
|
|
284
|
+
json.$Include = includes;
|
|
274
285
|
return json;
|
|
275
286
|
}
|
|
276
287
|
}
|
|
277
288
|
|
|
278
|
-
class Include extends Node
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
{
|
|
283
|
-
|
|
289
|
+
class Include extends Node {
|
|
290
|
+
get kind() {
|
|
291
|
+
return 'edmx:Include';
|
|
292
|
+
}
|
|
293
|
+
toJSON() {
|
|
294
|
+
const json = Object.create(null);
|
|
284
295
|
return this.toJSONattributes(json);
|
|
285
296
|
}
|
|
286
297
|
}
|
|
287
298
|
|
|
288
|
-
class
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
299
|
+
class EntityContainer extends Node {
|
|
300
|
+
constructor(version, attributes, csn) {
|
|
301
|
+
super(version, attributes, csn);
|
|
302
|
+
this._registry = Object.create(null);
|
|
303
|
+
}
|
|
304
|
+
// use the _SetAttributes
|
|
305
|
+
setSapVocabularyAsAttributes(csn) {
|
|
306
|
+
super.setSapVocabularyAsAttributes(csn, true);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
register(entry) {
|
|
310
|
+
if (!this._registry[entry._edmAttributes.Name])
|
|
311
|
+
this._registry[entry._edmAttributes.Name] = [ entry ];
|
|
312
|
+
else
|
|
313
|
+
this._registry[entry._edmAttributes.Name].push(entry);
|
|
314
|
+
this.append(entry);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
class Schema extends Node {
|
|
319
|
+
constructor(version, ns, alias = undefined, serviceCsn = null, annotations = [], withEntityContainer = true) {
|
|
292
320
|
const props = { Namespace: ns };
|
|
293
|
-
if(alias !== undefined)
|
|
321
|
+
if (alias !== undefined)
|
|
294
322
|
props.Alias = alias;
|
|
295
|
-
super(
|
|
323
|
+
super(version, props);
|
|
296
324
|
this._annotations = annotations;
|
|
297
325
|
this._actions = Object.create(null);
|
|
298
326
|
this.setXml( { xmlns: (this.v2) ? 'http://schemas.microsoft.com/ado/2008/09/edm' : 'http://docs.oasis-open.org/odata/ns/edm' } );
|
|
299
327
|
|
|
300
|
-
if(this.v2 && serviceCsn)
|
|
328
|
+
if (this.v2 && serviceCsn)
|
|
301
329
|
this.setSapVocabularyAsAttributes(serviceCsn);
|
|
302
330
|
|
|
303
|
-
if(withEntityContainer)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
ec.setXml( { 'm:IsDefaultEntityContainer': true } );
|
|
331
|
+
if (withEntityContainer) {
|
|
332
|
+
const ecprops = { Name: 'EntityContainer' };
|
|
333
|
+
const ec = new EntityContainer(version, ecprops, serviceCsn );
|
|
334
|
+
if (this.v2)
|
|
335
|
+
ec.setXml( { 'm:IsDefaultEntityContainer': true } );
|
|
309
336
|
// append for rendering, ok ec has Name
|
|
310
337
|
this.append(ec);
|
|
311
338
|
// set as attribute for later access...
|
|
@@ -314,107 +341,110 @@ function getEdm(options, messageFunctions) {
|
|
|
314
341
|
}
|
|
315
342
|
|
|
316
343
|
// hold actions and functions in V4
|
|
317
|
-
addAction(action)
|
|
318
|
-
|
|
319
|
-
if(this._actions[action._edmAttributes.Name])
|
|
344
|
+
addAction(action) {
|
|
345
|
+
if (this._actions[action._edmAttributes.Name])
|
|
320
346
|
this._actions[action._edmAttributes.Name].push(action);
|
|
321
347
|
else
|
|
322
|
-
this._actions[action._edmAttributes.Name] = [action];
|
|
348
|
+
this._actions[action._edmAttributes.Name] = [ action ];
|
|
323
349
|
}
|
|
324
350
|
|
|
325
|
-
setAnnotations(annotations)
|
|
326
|
-
|
|
327
|
-
if(Array.isArray(annotations) && annotations.length > 0)
|
|
351
|
+
setAnnotations(annotations) {
|
|
352
|
+
if (Array.isArray(annotations) && annotations.length > 0)
|
|
328
353
|
this._annotations.push(...annotations);
|
|
329
354
|
}
|
|
330
355
|
|
|
331
|
-
innerXML(indent, what)
|
|
332
|
-
{
|
|
356
|
+
innerXML(indent, what) {
|
|
333
357
|
let xml = '';
|
|
334
|
-
if(what==='metadata' || what==='all')
|
|
335
|
-
{
|
|
358
|
+
if (what === 'metadata' || what === 'all') {
|
|
336
359
|
xml += super.innerXML(indent);
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
{
|
|
344
|
-
if(this._annotations.length > 0) {
|
|
345
|
-
this._annotations.filter(a => a._edmAttributes.Term).forEach(a => xml += a.toXML(indent) + '\n');
|
|
346
|
-
this._annotations.filter(a => a._edmAttributes.Target).forEach(a => xml += a.toXML(indent) + '\n');
|
|
360
|
+
if (this._actions) {
|
|
361
|
+
Object.values(this._actions).forEach((actionArray) => {
|
|
362
|
+
actionArray.forEach((action) => {
|
|
363
|
+
xml += `${action.toXML(indent, what)}\n`;
|
|
364
|
+
});
|
|
365
|
+
});
|
|
347
366
|
}
|
|
348
367
|
}
|
|
368
|
+
if ((what === 'annotations' || what === 'all') && this._annotations.length > 0) {
|
|
369
|
+
this._annotations.filter(a => a._edmAttributes.Term).forEach((a) => {
|
|
370
|
+
xml += `${a.toXML(indent)}\n`;
|
|
371
|
+
});
|
|
372
|
+
this._annotations.filter(a => a._edmAttributes.Target).forEach((a) => {
|
|
373
|
+
xml += `${a.toXML(indent)}\n`;
|
|
374
|
+
});
|
|
375
|
+
}
|
|
349
376
|
return xml;
|
|
350
377
|
}
|
|
351
378
|
|
|
352
379
|
// no $Namespace
|
|
353
|
-
toJSONattributes(json)
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
380
|
+
toJSONattributes(json) {
|
|
381
|
+
if (this._edmAttributes) {
|
|
382
|
+
Object.entries(this._edmAttributes).forEach(([ p, v ]) => {
|
|
383
|
+
if (p !== 'Name' && p !== 'Namespace')
|
|
384
|
+
json[p[0] === '@' ? p : `$${p}`] = v;
|
|
385
|
+
});
|
|
386
|
+
}
|
|
359
387
|
}
|
|
360
388
|
|
|
361
|
-
toJSONchildren(json)
|
|
362
|
-
{
|
|
389
|
+
toJSONchildren(json) {
|
|
363
390
|
// 'edmx:DataServices' should not appear in JSON
|
|
364
391
|
super.toJSONchildren(json);
|
|
365
|
-
if(this._annotations.length > 0) {
|
|
366
|
-
this._annotations.filter(a => a._edmAttributes.Term).forEach(a => {
|
|
367
|
-
Object.entries(a.toJSON()).forEach(([n, v]) => {
|
|
392
|
+
if (this._annotations.length > 0) {
|
|
393
|
+
this._annotations.filter(a => a._edmAttributes.Term).forEach((a) => {
|
|
394
|
+
Object.entries(a.toJSON()).forEach(([ n, v ]) => {
|
|
368
395
|
json[n] = v;
|
|
369
396
|
});
|
|
370
397
|
});
|
|
371
|
-
|
|
372
|
-
this._annotations.filter(a => a._edmAttributes.Target).forEach(a =>
|
|
373
|
-
|
|
374
|
-
|
|
398
|
+
const jsonAnnotations = Object.create(null);
|
|
399
|
+
this._annotations.filter(a => a._edmAttributes.Target).forEach((a) => {
|
|
400
|
+
jsonAnnotations[a._edmAttributes.Target] = a.toJSON();
|
|
401
|
+
});
|
|
402
|
+
if (Object.keys(jsonAnnotations).length)
|
|
403
|
+
json.$Annotations = jsonAnnotations;
|
|
375
404
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
405
|
+
if (this._actions) {
|
|
406
|
+
Object.entries(this._actions).forEach(([ actionName, actionArray ]) => {
|
|
407
|
+
json[actionName] = [];
|
|
408
|
+
actionArray.forEach((action) => {
|
|
409
|
+
json[actionName].push(action.toJSON());
|
|
410
|
+
});
|
|
380
411
|
});
|
|
381
|
-
}
|
|
412
|
+
}
|
|
382
413
|
|
|
383
414
|
return json;
|
|
384
415
|
}
|
|
385
|
-
|
|
386
416
|
}
|
|
387
417
|
|
|
388
|
-
class DataServices extends Node
|
|
389
|
-
|
|
390
|
-
constructor(v)
|
|
391
|
-
{
|
|
418
|
+
class DataServices extends Node {
|
|
419
|
+
constructor(v) {
|
|
392
420
|
super(v);
|
|
393
421
|
this._schemas = Object.create(null);
|
|
394
422
|
|
|
395
|
-
if(this.v2)
|
|
396
|
-
this.setXml( { 'm:DataServiceVersion': '2.0' } )
|
|
423
|
+
if (this.v2)
|
|
424
|
+
this.setXml( { 'm:DataServiceVersion': '2.0' } );
|
|
397
425
|
}
|
|
398
426
|
|
|
399
|
-
get kind() {
|
|
427
|
+
get kind() {
|
|
428
|
+
return 'edmx:DataServices';
|
|
429
|
+
}
|
|
400
430
|
|
|
401
|
-
registerSchema(fqName, schema)
|
|
402
|
-
|
|
403
|
-
if(!this._schemas[fqName]) {
|
|
431
|
+
registerSchema(fqName, schema) {
|
|
432
|
+
if (!this._schemas[fqName]) {
|
|
404
433
|
this._schemas[fqName] = schema;
|
|
405
434
|
super.append(schema);
|
|
406
435
|
}
|
|
407
436
|
}
|
|
408
437
|
|
|
409
|
-
toJSONchildren(json)
|
|
410
|
-
{
|
|
438
|
+
toJSONchildren(json) {
|
|
411
439
|
// 'edmx:DataServices' should not appear in JSON
|
|
412
|
-
this._children.forEach(s =>
|
|
440
|
+
this._children.forEach((s) => {
|
|
441
|
+
json[s._edmAttributes.Namespace] = s.toJSON();
|
|
442
|
+
});
|
|
413
443
|
return json;
|
|
414
444
|
}
|
|
415
445
|
}
|
|
416
446
|
|
|
417
|
-
|
|
447
|
+
/* <edmx:Edmx> must contain exactly one <edmx:DataServices> with 1..n <edm:Schema> elements
|
|
418
448
|
may contain 0..n <edmx:Reference> elements
|
|
419
449
|
|
|
420
450
|
For Odata 1.0..3.0 EDMX is an independent container with its own version 1.0.
|
|
@@ -424,60 +454,58 @@ function getEdm(options, messageFunctions) {
|
|
|
424
454
|
OData version
|
|
425
455
|
*/
|
|
426
456
|
|
|
427
|
-
class Edm extends Node
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
{
|
|
431
|
-
super(v, { Version : (v[1]) ? '4.0' : '1.0' });
|
|
457
|
+
class Edm extends Node {
|
|
458
|
+
constructor(version, service) {
|
|
459
|
+
super(version, { Version: (version[1]) ? '4.0' : '1.0' });
|
|
432
460
|
this._service = service;
|
|
433
461
|
this._defaultRefs = [];
|
|
434
462
|
|
|
435
463
|
const xmlProps = Object.create(null);
|
|
436
|
-
if(this.v4)
|
|
437
|
-
{
|
|
464
|
+
if (this.v4) {
|
|
438
465
|
xmlProps['xmlns:edmx'] = 'http://docs.oasis-open.org/odata/ns/edmx';
|
|
439
|
-
xmlProps['xmlns:m']
|
|
440
|
-
xmlProps['xmlns:sap']
|
|
466
|
+
xmlProps['xmlns:m'] = undefined;
|
|
467
|
+
xmlProps['xmlns:sap'] = undefined;
|
|
441
468
|
}
|
|
442
|
-
else
|
|
443
|
-
{
|
|
469
|
+
else {
|
|
444
470
|
xmlProps['xmlns:edmx'] = 'http://schemas.microsoft.com/ado/2007/06/edmx';
|
|
445
|
-
xmlProps['xmlns:m']
|
|
446
|
-
xmlProps['xmlns:sap']
|
|
471
|
+
xmlProps['xmlns:m'] = 'http://schemas.microsoft.com/ado/2007/08/dataservices/metadata';
|
|
472
|
+
xmlProps['xmlns:sap'] = 'http://www.sap.com/Protocols/SAPData';
|
|
447
473
|
}
|
|
448
474
|
this.setXml(xmlProps);
|
|
449
475
|
}
|
|
450
476
|
|
|
451
|
-
get kind() {
|
|
477
|
+
get kind() {
|
|
478
|
+
return 'edmx:Edmx';
|
|
479
|
+
}
|
|
452
480
|
|
|
453
|
-
getAnnotations(schemaIndex=0)
|
|
454
|
-
|
|
455
|
-
if(this._service && this._service._children[schemaIndex])
|
|
481
|
+
getAnnotations(schemaIndex = 0) {
|
|
482
|
+
if (this._service && this._service._children[schemaIndex])
|
|
456
483
|
return this._service._children[schemaIndex]._annotations;
|
|
457
|
-
|
|
458
|
-
return undefined;
|
|
484
|
+
return undefined;
|
|
459
485
|
}
|
|
460
486
|
|
|
461
|
-
setAnnotations(annotations, schemaIndex=0)
|
|
462
|
-
|
|
463
|
-
if(this._service && this._service._children[schemaIndex])
|
|
487
|
+
setAnnotations(annotations, schemaIndex = 0) {
|
|
488
|
+
if (this._service && this._service._children[schemaIndex])
|
|
464
489
|
this._service._children[schemaIndex]._annotations = annotations;
|
|
465
490
|
}
|
|
466
491
|
|
|
467
|
-
toJSON()
|
|
468
|
-
|
|
469
|
-
let schema = this._service._children[0];
|
|
492
|
+
toJSON() {
|
|
493
|
+
const schema = this._service._children[0];
|
|
470
494
|
|
|
471
|
-
|
|
472
|
-
json
|
|
473
|
-
json
|
|
495
|
+
const json = Object.create(null);
|
|
496
|
+
json.$Version = this._edmAttributes.Version;
|
|
497
|
+
json.$EntityContainer = `${schema._edmAttributes.Namespace}.${schema._ec._edmAttributes.Name}`;
|
|
474
498
|
|
|
475
|
-
|
|
476
|
-
this._defaultRefs.forEach(r =>
|
|
477
|
-
|
|
499
|
+
const referenceJson = Object.create(null);
|
|
500
|
+
this._defaultRefs.forEach((r) => {
|
|
501
|
+
referenceJson[r._edmAttributes.Uri] = r.toJSON();
|
|
502
|
+
});
|
|
503
|
+
this._children.forEach((r) => {
|
|
504
|
+
referenceJson[r._edmAttributes.Uri] = r.toJSON();
|
|
505
|
+
});
|
|
478
506
|
|
|
479
|
-
if(Object.keys(
|
|
480
|
-
json
|
|
507
|
+
if (Object.keys(referenceJson).length)
|
|
508
|
+
json.$Reference = referenceJson;
|
|
481
509
|
|
|
482
510
|
this._service.toJSONattributes(json);
|
|
483
511
|
this._service.toJSONchildren(json);
|
|
@@ -485,106 +513,88 @@ function getEdm(options, messageFunctions) {
|
|
|
485
513
|
}
|
|
486
514
|
|
|
487
515
|
// all(default), metadata, annotations
|
|
488
|
-
toXML(what='all')
|
|
489
|
-
|
|
490
|
-
return '<?xml version="1.0" encoding="utf-8"?>\n' + super.toXML('', what);
|
|
516
|
+
toXML(what = 'all') {
|
|
517
|
+
return `<?xml version="1.0" encoding="utf-8"?>\n${super.toXML('', what)}`;
|
|
491
518
|
}
|
|
492
519
|
|
|
493
|
-
innerXML(indent, what)
|
|
494
|
-
{
|
|
520
|
+
innerXML(indent, what) {
|
|
495
521
|
let xml = '';
|
|
496
522
|
|
|
497
|
-
if(this.v4 || (this.v2 && (what === 'all' || what === 'annotations')))
|
|
498
|
-
this._defaultRefs.forEach(r =>
|
|
499
|
-
|
|
500
|
-
|
|
523
|
+
if (this.v4 || (this.v2 && (what === 'all' || what === 'annotations'))) {
|
|
524
|
+
this._defaultRefs.forEach((r) => {
|
|
525
|
+
xml += `${r.toXML(indent)}\n`;
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
this._children.forEach((e) => {
|
|
529
|
+
xml += `${e.toXML(indent)}\n`;
|
|
530
|
+
});
|
|
531
|
+
xml += `${this._service.toXML(indent, what)}\n`;
|
|
501
532
|
return xml;
|
|
502
533
|
}
|
|
503
534
|
}
|
|
504
535
|
|
|
505
|
-
class
|
|
506
|
-
|
|
507
|
-
constructor(v, attributes, csn) {
|
|
508
|
-
super(v, attributes, csn);
|
|
509
|
-
this._registry = Object.create(null);
|
|
510
|
-
}
|
|
511
|
-
// use the _SetAttributes
|
|
512
|
-
setSapVocabularyAsAttributes(csn)
|
|
513
|
-
{
|
|
514
|
-
super.setSapVocabularyAsAttributes(csn, true);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
register(entry) {
|
|
518
|
-
if(!this._registry[entry._edmAttributes.Name])
|
|
519
|
-
this._registry[entry._edmAttributes.Name] = [entry];
|
|
520
|
-
else
|
|
521
|
-
this._registry[entry._edmAttributes.Name].push(entry);
|
|
522
|
-
this.append(entry);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
class Singleton extends Node
|
|
528
|
-
{
|
|
529
|
-
toJSONattributes(json)
|
|
530
|
-
{
|
|
536
|
+
class Singleton extends Node {
|
|
537
|
+
toJSONattributes(json) {
|
|
531
538
|
forEach(this._edmAttributes, (p, v) => {
|
|
532
539
|
if (p !== 'Name') {
|
|
533
|
-
if(p === 'EntityType') // it's $Type in json
|
|
534
|
-
json
|
|
540
|
+
if (p === 'EntityType') // it's $Type in json
|
|
541
|
+
json.$Type = v;
|
|
535
542
|
else
|
|
536
|
-
json[p[0] === '@' ? p :
|
|
543
|
+
json[p[0] === '@' ? p : `$${p}`] = v;
|
|
537
544
|
}
|
|
538
545
|
});
|
|
539
546
|
return json;
|
|
540
547
|
}
|
|
541
548
|
|
|
542
|
-
toJSONchildren(json)
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
549
|
+
toJSONchildren(json) {
|
|
550
|
+
const jsonNavPropBinding = Object.create(null);
|
|
551
|
+
this._children.forEach((npb) => {
|
|
552
|
+
jsonNavPropBinding[npb._edmAttributes.Path] = npb._edmAttributes.Target;
|
|
553
|
+
});
|
|
554
|
+
if (Object.keys(jsonNavPropBinding).length > 0)
|
|
555
|
+
json.$NavigationPropertyBinding = jsonNavPropBinding;
|
|
548
556
|
|
|
549
557
|
return json;
|
|
550
558
|
}
|
|
551
559
|
|
|
552
560
|
getDuplicateMessage() {
|
|
553
|
-
return `EntityType "${this._edmAttributes.EntityType}"
|
|
561
|
+
return `EntityType "${this._edmAttributes.EntityType}"`;
|
|
554
562
|
}
|
|
555
563
|
}
|
|
556
564
|
|
|
557
|
-
class EntitySet extends Singleton
|
|
558
|
-
{
|
|
565
|
+
class EntitySet extends Singleton {
|
|
559
566
|
// use the _SetAttributes
|
|
560
|
-
setSapVocabularyAsAttributes(csn)
|
|
561
|
-
{
|
|
567
|
+
setSapVocabularyAsAttributes(csn) {
|
|
562
568
|
super.setSapVocabularyAsAttributes(csn, true);
|
|
563
569
|
}
|
|
564
570
|
|
|
565
|
-
toJSONattributes(json)
|
|
566
|
-
{
|
|
571
|
+
toJSONattributes(json) {
|
|
567
572
|
// OASIS ODATA-1231 $Collection=true
|
|
568
|
-
json
|
|
573
|
+
json.$Collection = true;
|
|
569
574
|
return super.toJSONattributes(json);
|
|
570
575
|
}
|
|
571
576
|
}
|
|
572
577
|
|
|
573
|
-
class
|
|
574
|
-
|
|
578
|
+
class PropertyRef extends Node {
|
|
579
|
+
constructor(version, Name, Alias) {
|
|
580
|
+
super(version, (Alias) ? { Name, Alias } : { Name });
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
toJSON() {
|
|
584
|
+
return this._edmAttributes.Alias ? { [this._edmAttributes.Alias]: this._edmAttributes.Name } : this._edmAttributes.Name;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
class Key extends Node {
|
|
575
589
|
// keys is an array of [name] or [name, alias]
|
|
576
|
-
constructor(
|
|
577
|
-
|
|
578
|
-
super(v);
|
|
590
|
+
constructor(version, keys) {
|
|
591
|
+
super(version);
|
|
579
592
|
if (keys && keys.length > 0)
|
|
580
|
-
|
|
581
|
-
keys.forEach(k => this.append(new PropertyRef(v, ...k)));
|
|
582
|
-
}
|
|
593
|
+
keys.forEach(k => this.append(new PropertyRef(version, ...k)));
|
|
583
594
|
}
|
|
584
595
|
|
|
585
|
-
toJSON()
|
|
586
|
-
|
|
587
|
-
let json = [];
|
|
596
|
+
toJSON() {
|
|
597
|
+
const json = [];
|
|
588
598
|
this._children.forEach(c => json.push(c.toJSON()));
|
|
589
599
|
return json;
|
|
590
600
|
}
|
|
@@ -598,40 +608,36 @@ function getEdm(options, messageFunctions) {
|
|
|
598
608
|
to the FunctionImport. See comment in class FunctionImport.
|
|
599
609
|
*/
|
|
600
610
|
|
|
601
|
-
class ActionFunctionBase extends Node
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
{
|
|
605
|
-
super(v, details);
|
|
611
|
+
class ActionFunctionBase extends Node {
|
|
612
|
+
constructor(version, details) {
|
|
613
|
+
super(version, details);
|
|
606
614
|
this._returnType = undefined;
|
|
607
615
|
}
|
|
608
616
|
|
|
609
|
-
innerXML(indent)
|
|
610
|
-
{
|
|
617
|
+
innerXML(indent) {
|
|
611
618
|
let xml = super.innerXML(indent);
|
|
612
|
-
if(this._returnType !== undefined)
|
|
613
|
-
xml += this._returnType.toXML(indent)
|
|
614
|
-
return xml
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
toJSONchildren(json)
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
json['$ReturnType'] = this._returnType.toJSON();
|
|
626
|
-
}
|
|
619
|
+
if (this._returnType !== undefined)
|
|
620
|
+
xml += `${this._returnType.toXML(indent)}\n`;
|
|
621
|
+
return xml;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
toJSONchildren(json) {
|
|
625
|
+
const jsonParameters = [];
|
|
626
|
+
this._children.forEach(p => jsonParameters.push(p.toJSON()));
|
|
627
|
+
if (jsonParameters.length > 0)
|
|
628
|
+
json.$Parameter = jsonParameters;
|
|
629
|
+
if (this._returnType)
|
|
630
|
+
json.$ReturnType = this._returnType.toJSON();
|
|
631
|
+
|
|
627
632
|
return json;
|
|
628
633
|
}
|
|
629
634
|
}
|
|
630
635
|
// FunctionDefinition should be named 'Function', but this would
|
|
631
636
|
// collide with a method 'Function' of the Istanbul/NYC tool
|
|
632
|
-
class FunctionDefinition extends ActionFunctionBase
|
|
633
|
-
|
|
634
|
-
|
|
637
|
+
class FunctionDefinition extends ActionFunctionBase {
|
|
638
|
+
get kind() {
|
|
639
|
+
return 'Function';
|
|
640
|
+
}
|
|
635
641
|
}
|
|
636
642
|
class Action extends ActionFunctionBase {}
|
|
637
643
|
|
|
@@ -642,46 +648,43 @@ function getEdm(options, messageFunctions) {
|
|
|
642
648
|
*/
|
|
643
649
|
class FunctionImport extends Node {
|
|
644
650
|
getDuplicateMessage() {
|
|
645
|
-
return `Function "${this._edmAttributes.Name}"
|
|
651
|
+
return `Function "${this._edmAttributes.Name}"`;
|
|
646
652
|
}
|
|
647
|
-
} //ActionFunctionBase {}
|
|
653
|
+
} // ActionFunctionBase {}
|
|
648
654
|
class ActionImport extends Node {
|
|
649
655
|
getDuplicateMessage() {
|
|
650
|
-
return `Action "${this._edmAttributes.Name}"
|
|
656
|
+
return `Action "${this._edmAttributes.Name}"`;
|
|
651
657
|
}
|
|
652
658
|
}
|
|
653
659
|
|
|
654
|
-
class TypeBase extends Node
|
|
655
|
-
|
|
656
|
-
constructor(v, attributes, csn, typeName='Type')
|
|
657
|
-
{
|
|
660
|
+
class TypeBase extends Node {
|
|
661
|
+
constructor(version, attributes, csn, typeName = 'Type') {
|
|
658
662
|
// ??? Is CSN still required? NavProp?
|
|
659
|
-
super(
|
|
663
|
+
super(version, attributes, csn);
|
|
660
664
|
this._typeName = typeName;
|
|
661
665
|
this._scalarType = undefined;
|
|
662
|
-
if(this._edmAttributes[typeName] === undefined)
|
|
663
|
-
|
|
664
|
-
let typecsn = csn.type ? csn : (csn.items && csn.items.type ? csn.items : csn);
|
|
666
|
+
if (this._edmAttributes[typeName] === undefined) {
|
|
667
|
+
const typecsn = csn.type ? csn : (csn.items && csn.items.type ? csn.items : csn);
|
|
665
668
|
// Complex/EntityType are derived from TypeBase
|
|
666
669
|
// but have no type attribute in their CSN
|
|
667
|
-
if(typecsn.type) { // this thing has a type
|
|
670
|
+
if (typecsn.type) { // this thing has a type
|
|
668
671
|
// check whether this is a scalar type (or array of scalar type) or a named type
|
|
669
|
-
if(typecsn.items && typecsn.items.type &&
|
|
670
|
-
isBuiltinType(typecsn.items.type))
|
|
672
|
+
if (typecsn.items && typecsn.items.type &&
|
|
673
|
+
isBuiltinType(typecsn.items.type))
|
|
671
674
|
this._scalarType = typecsn.items;
|
|
672
|
-
|
|
673
|
-
else if(isBuiltinType(typecsn.type))
|
|
675
|
+
|
|
676
|
+
else if (isBuiltinType(typecsn.type))
|
|
674
677
|
this._scalarType = typecsn;
|
|
675
|
-
|
|
676
|
-
if(this._scalarType) {
|
|
678
|
+
|
|
679
|
+
if (this._scalarType) {
|
|
677
680
|
this._edmAttributes[typeName] = csn._edmType;
|
|
678
681
|
// CDXCORE-CDXCORE-173 ignore type facets for Edm.Stream
|
|
679
682
|
// cds-compiler/issues/7835: Only set length for Binary as long as it is
|
|
680
683
|
// unclear how many bytes a string character represents.
|
|
681
684
|
// We can't calculate an unambiguous byte stream length for DB dependent
|
|
682
685
|
// multi-byte characters.
|
|
683
|
-
if(!(this._edmAttributes[typeName] === 'Edm.Stream' &&
|
|
684
|
-
!( /*scalarType.type === 'cds.String'
|
|
686
|
+
if (!(this._edmAttributes[typeName] === 'Edm.Stream' &&
|
|
687
|
+
!( /* scalarType.type === 'cds.String' || */ this._scalarType.type === 'cds.Binary')))
|
|
685
688
|
edmUtils.addTypeFacets(this, this._scalarType);
|
|
686
689
|
}
|
|
687
690
|
else {
|
|
@@ -693,30 +696,29 @@ function getEdm(options, messageFunctions) {
|
|
|
693
696
|
// optionally add @odata { MaxLength, Precision, Scale, SRID }
|
|
694
697
|
// but only in combination with @odata.Type
|
|
695
698
|
// Allow to override type only on scalar and undefined types
|
|
696
|
-
if((this._scalarType || typecsn.type == null) && !csn.elements) {
|
|
699
|
+
if ((this._scalarType || typecsn.type == null) && !csn.elements) {
|
|
697
700
|
const odataType = csn['@odata.Type'];
|
|
698
|
-
if(odataType) {
|
|
701
|
+
if (odataType) {
|
|
699
702
|
const td = EdmPrimitiveTypeMap[odataType];
|
|
700
703
|
// If type is known, it must be available in the current version
|
|
701
704
|
// Reason: EDMX Importer may set `@odata.Type: 'Edm.DateTime'` on imported V2 services
|
|
702
705
|
// Not filtering out this incompatible type here in case of a V4 rendering would
|
|
703
706
|
// produce an unrecoverable error.
|
|
704
|
-
if(td && (td.v2 === this.v2 || td.v4 === this.v4)) {
|
|
707
|
+
if (td && (td.v2 === this.v2 || td.v4 === this.v4)) {
|
|
705
708
|
this.setEdmAttribute(typeName, odataType);
|
|
706
|
-
EdmTypeFacetNames.forEach(facetName => {
|
|
709
|
+
EdmTypeFacetNames.forEach((facetName) => {
|
|
707
710
|
const facet = EdmTypeFacetMap[facetName];
|
|
708
|
-
if(facet.remove) {
|
|
711
|
+
if (facet.remove) {
|
|
709
712
|
this.removeEdmAttribute(facetName);
|
|
710
713
|
this.removeEdmAttribute(facet.extra);
|
|
711
714
|
}
|
|
712
|
-
if(td[facetName] !== undefined &&
|
|
715
|
+
if (td[facetName] !== undefined &&
|
|
713
716
|
(facet.v2 === this.v2 ||
|
|
714
|
-
facet.v4 === this.v4))
|
|
715
|
-
{
|
|
716
|
-
if(this.v2 && facetName === 'Scale' && csn['@odata.'+facetName] === 'variable')
|
|
717
|
+
facet.v4 === this.v4)) {
|
|
718
|
+
if (this.v2 && facetName === 'Scale' && csn[`@odata.${facetName}`] === 'variable')
|
|
717
719
|
this.setXml({ [facet.extra]: true });
|
|
718
720
|
else
|
|
719
|
-
|
|
721
|
+
this.setEdmAttribute(facetName, csn[`@odata.${facetName}`]);
|
|
720
722
|
}
|
|
721
723
|
});
|
|
722
724
|
}
|
|
@@ -727,278 +729,245 @@ function getEdm(options, messageFunctions) {
|
|
|
727
729
|
// Set the collection property if this is either an element, parameter or a term def
|
|
728
730
|
this._isCollection = (csn.kind === undefined || csn.kind === 'annotation') ? csn._isCollection : false;
|
|
729
731
|
|
|
730
|
-
if(options.whatsMySchemaName && this._edmAttributes[typeName]) {
|
|
731
|
-
|
|
732
|
-
if(schemaName && schemaName !== options.serviceName)
|
|
733
|
-
this._edmAttributes[typeName] = this._edmAttributes[typeName].replace(options.serviceName
|
|
734
|
-
}
|
|
732
|
+
if (options.whatsMySchemaName && this._edmAttributes[typeName]) {
|
|
733
|
+
const schemaName = options.whatsMySchemaName(this._edmAttributes[typeName]);
|
|
734
|
+
if (schemaName && schemaName !== options.serviceName)
|
|
735
|
+
this._edmAttributes[typeName] = this._edmAttributes[typeName].replace(`${options.serviceName}.`, '');
|
|
735
736
|
}
|
|
736
737
|
|
|
737
738
|
// store undecorated type for JSON
|
|
738
739
|
this._type = this._edmAttributes[typeName];
|
|
739
740
|
// decorate for XML (not for Complex/EntityType)
|
|
740
|
-
if(this._isCollection && this._edmAttributes[typeName])
|
|
741
|
-
this._edmAttributes[typeName] = `Collection(${this._edmAttributes[typeName]})
|
|
741
|
+
if (this._isCollection && this._edmAttributes[typeName])
|
|
742
|
+
this._edmAttributes[typeName] = `Collection(${this._edmAttributes[typeName]})`;
|
|
742
743
|
}
|
|
743
744
|
|
|
744
|
-
toJSONattributes(json)
|
|
745
|
-
{
|
|
745
|
+
toJSONattributes(json) {
|
|
746
746
|
// $Type Edm.String, $Nullable=false MAY be omitted
|
|
747
747
|
// @ property and parameter for performance reasons
|
|
748
|
-
if(this._type !== 'Edm.String' && this._type) // Edm.String is default)
|
|
749
|
-
json[
|
|
748
|
+
if (this._type !== 'Edm.String' && this._type) // Edm.String is default)
|
|
749
|
+
json[`$${this._typeName}`] = this._type;
|
|
750
750
|
|
|
751
|
-
|
|
752
|
-
|
|
751
|
+
if (this._edmAttributes) {
|
|
752
|
+
Object.entries(this._edmAttributes).forEach(([ p, v ]) => {
|
|
753
|
+
if (p !== 'Name' && p !== this._typeName &&
|
|
753
754
|
// remove this line if Nullable=true becomes default
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
});
|
|
755
|
+
!(p === 'Nullable' && !v))
|
|
756
|
+
json[p[0] === '@' ? p : `$${p}`] = v;
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
759
|
|
|
760
|
-
if(this._isCollection)
|
|
761
|
-
json
|
|
760
|
+
if (this._isCollection)
|
|
761
|
+
json.$Collection = this._isCollection;
|
|
762
762
|
|
|
763
763
|
return json;
|
|
764
|
-
|
|
765
764
|
}
|
|
766
765
|
}
|
|
767
766
|
|
|
768
767
|
class ComplexType extends TypeBase {
|
|
769
|
-
constructor(
|
|
770
|
-
super(
|
|
771
|
-
if(this.v4 && !!csn['@open'])
|
|
772
|
-
this._edmAttributes
|
|
773
|
-
}
|
|
768
|
+
constructor(version, details, csn) {
|
|
769
|
+
super(version, details, csn);
|
|
770
|
+
if (this.v4 && !!csn['@open'])
|
|
771
|
+
this._edmAttributes.OpenType = true;
|
|
774
772
|
}
|
|
775
773
|
}
|
|
776
|
-
class EntityType extends ComplexType
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
{
|
|
780
|
-
super(v, details, csn);
|
|
774
|
+
class EntityType extends ComplexType {
|
|
775
|
+
constructor(version, details, properties, csn) {
|
|
776
|
+
super(version, details, csn);
|
|
781
777
|
this.append(...properties);
|
|
782
778
|
const aliasXref = Object.create(null);
|
|
783
779
|
|
|
784
|
-
csn.$edmKeyPaths.forEach(p => {
|
|
785
|
-
const [alias, ...tail] = p[0].split('/').reverse();
|
|
780
|
+
csn.$edmKeyPaths.forEach((p) => {
|
|
781
|
+
const [ alias, ...tail ] = p[0].split('/').reverse();
|
|
786
782
|
|
|
787
|
-
if(aliasXref[alias] === undefined)
|
|
783
|
+
if (aliasXref[alias] === undefined)
|
|
788
784
|
aliasXref[alias] = 0;
|
|
789
785
|
else
|
|
790
786
|
aliasXref[alias]++;
|
|
791
787
|
// if it's a path, push the alias
|
|
792
|
-
if(tail.length > 0)
|
|
788
|
+
if (tail.length > 0)
|
|
793
789
|
p.push(alias);
|
|
794
790
|
});
|
|
795
|
-
csn.$edmKeyPaths.slice().reverse().forEach(p => {
|
|
791
|
+
csn.$edmKeyPaths.slice().reverse().forEach((p) => {
|
|
796
792
|
let alias = p[1];
|
|
797
|
-
if(alias)
|
|
798
|
-
{
|
|
793
|
+
if (alias) {
|
|
799
794
|
const c = aliasXref[alias]--;
|
|
800
795
|
// Limit Key length to 32 characters
|
|
801
|
-
if(c > 0) {
|
|
802
|
-
if(alias.length > 28)
|
|
803
|
-
alias = alias.substr(0, 13)
|
|
804
|
-
|
|
805
|
-
alias = alias
|
|
796
|
+
if (c > 0) {
|
|
797
|
+
if (alias.length > 28)
|
|
798
|
+
alias = `${alias.substr(0, 13)}__${alias.substr(alias.length - 13, alias.length)}`;
|
|
799
|
+
|
|
800
|
+
alias = `${alias}_${c.toString().padStart(3, '0')}`;
|
|
806
801
|
}
|
|
807
|
-
else if(alias.length > 32) {
|
|
808
|
-
alias = alias.substr(0, 15)
|
|
802
|
+
else if (alias.length > 32) {
|
|
803
|
+
alias = `${alias.substr(0, 15)}__${alias.substr(alias.length - 15, alias.length)}`;
|
|
809
804
|
}
|
|
810
805
|
p[1] = alias;
|
|
811
806
|
}
|
|
812
807
|
});
|
|
813
808
|
|
|
814
|
-
if(csn.$edmKeyPaths && csn.$edmKeyPaths.length)
|
|
815
|
-
this._keys = new Key(
|
|
809
|
+
if (csn.$edmKeyPaths && csn.$edmKeyPaths.length)
|
|
810
|
+
this._keys = new Key(version, csn.$edmKeyPaths);
|
|
816
811
|
else
|
|
817
812
|
this._keys = undefined;
|
|
818
813
|
|
|
819
|
-
if(options.odataOpenapiHints) {
|
|
820
|
-
if(csn['@cds.autoexpose'])
|
|
814
|
+
if (options.odataOpenapiHints) {
|
|
815
|
+
if (csn['@cds.autoexpose'])
|
|
821
816
|
this.setJSON({ '@cds.autoexpose': true });
|
|
822
|
-
if(csn['@cds.autoexposed'])
|
|
817
|
+
if (csn['@cds.autoexposed'])
|
|
823
818
|
this.setJSON({ '@cds.autoexposed': true });
|
|
824
819
|
}
|
|
825
820
|
}
|
|
826
821
|
|
|
827
|
-
innerXML(indent)
|
|
828
|
-
{
|
|
822
|
+
innerXML(indent) {
|
|
829
823
|
let xml = '';
|
|
830
|
-
if(this._keys)
|
|
831
|
-
xml += this._keys.toXML(indent)
|
|
824
|
+
if (this._keys)
|
|
825
|
+
xml += `${this._keys.toXML(indent)}\n`;
|
|
832
826
|
return xml + super.innerXML(indent);
|
|
833
827
|
}
|
|
834
828
|
|
|
835
|
-
toJSONattributes(json)
|
|
836
|
-
{
|
|
829
|
+
toJSONattributes(json) {
|
|
837
830
|
super.toJSONattributes(json);
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
{
|
|
843
|
-
json['$Key'] = this._keys.toJSON();
|
|
831
|
+
if (this._jsonOnlyAttributes) {
|
|
832
|
+
Object.entries(this._jsonOnlyAttributes).forEach(([ p, v ]) => {
|
|
833
|
+
json[p[0] === '@' ? p : `$${p}`] = v;
|
|
834
|
+
});
|
|
844
835
|
}
|
|
836
|
+
if (this._keys)
|
|
837
|
+
json.$Key = this._keys.toJSON();
|
|
838
|
+
|
|
845
839
|
return json;
|
|
846
840
|
}
|
|
847
841
|
}
|
|
848
842
|
|
|
849
|
-
class Term extends TypeBase
|
|
850
|
-
{
|
|
851
|
-
|
|
852
|
-
{
|
|
853
|
-
super(v, attributes, csn);
|
|
843
|
+
class Term extends TypeBase {
|
|
844
|
+
constructor(version, attributes, csn) {
|
|
845
|
+
super(version, attributes, csn);
|
|
854
846
|
const appliesTo = csn['@odata.term.AppliesTo'];
|
|
855
|
-
if(appliesTo)
|
|
856
|
-
this.setEdmAttribute('AppliesTo', Array.isArray(appliesTo) ? appliesTo.map(v=>v['=']||v).join(' ') : appliesTo['='] || appliesTo);
|
|
857
|
-
}
|
|
858
|
-
}
|
|
847
|
+
if (appliesTo)
|
|
848
|
+
this.setEdmAttribute('AppliesTo', Array.isArray(appliesTo) ? appliesTo.map(v => v['='] || v).join(' ') : appliesTo['='] || appliesTo);
|
|
859
849
|
}
|
|
850
|
+
}
|
|
860
851
|
|
|
861
|
-
class TypeDefinition extends TypeBase
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
{
|
|
865
|
-
super(v, attributes, csn, 'UnderlyingType');
|
|
852
|
+
class TypeDefinition extends TypeBase {
|
|
853
|
+
constructor(version, attributes, csn) {
|
|
854
|
+
super(version, attributes, csn, 'UnderlyingType');
|
|
866
855
|
}
|
|
867
856
|
|
|
868
|
-
toJSONattributes(json)
|
|
869
|
-
{
|
|
857
|
+
toJSONattributes(json) {
|
|
870
858
|
super.toJSONattributes(json);
|
|
871
|
-
json
|
|
859
|
+
json.$UnderlyingType = this._type;
|
|
872
860
|
return json;
|
|
873
861
|
}
|
|
874
862
|
}
|
|
875
863
|
|
|
876
|
-
class
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
864
|
+
class Member extends Node {
|
|
865
|
+
toJSONattributes(json) {
|
|
866
|
+
json[this._edmAttributes.Name] = this._edmAttributes.Value;
|
|
867
|
+
return json;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
class EnumType extends TypeDefinition {
|
|
872
|
+
constructor(version, attributes, csn) {
|
|
873
|
+
super(version, attributes, csn);
|
|
881
874
|
|
|
882
875
|
// array of enum not yet allowed
|
|
883
|
-
const enumValues = /*(csn.items && csn.items.enum)
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
876
|
+
const enumValues = /* (csn.items && csn.items.enum) || */ csn.enum;
|
|
877
|
+
if (enumValues) {
|
|
878
|
+
Object.entries(enumValues).forEach(([ en, e ]) => {
|
|
879
|
+
this.append(new Member(version, { Name: en, Value: e.val } ));
|
|
880
|
+
});
|
|
881
|
+
}
|
|
887
882
|
}
|
|
888
883
|
|
|
889
|
-
toJSONattributes(json)
|
|
890
|
-
{
|
|
884
|
+
toJSONattributes(json) {
|
|
891
885
|
super.toJSONattributes(json);
|
|
892
886
|
return json;
|
|
893
887
|
}
|
|
894
888
|
|
|
895
|
-
toJSONchildren(json)
|
|
896
|
-
{
|
|
889
|
+
toJSONchildren(json) {
|
|
897
890
|
this._children.forEach(c => c.toJSONattributes(json));
|
|
898
891
|
return json;
|
|
899
892
|
}
|
|
900
893
|
}
|
|
901
894
|
|
|
902
|
-
class
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
{
|
|
906
|
-
json[this._edmAttributes.Name] = this._edmAttributes.Value;
|
|
907
|
-
return json;
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
class PropertyBase extends TypeBase
|
|
912
|
-
{
|
|
913
|
-
constructor(v, attributes, csn)
|
|
914
|
-
{
|
|
915
|
-
super(v, attributes, csn);
|
|
895
|
+
class PropertyBase extends TypeBase {
|
|
896
|
+
constructor(version, attributes, csn) {
|
|
897
|
+
super(version, attributes, csn);
|
|
916
898
|
this._csn = csn;
|
|
917
|
-
if(this.v2)
|
|
918
|
-
|
|
919
|
-
let typecsn = csn.items || csn;
|
|
899
|
+
if (this.v2) {
|
|
900
|
+
const typecsn = csn.items || csn;
|
|
920
901
|
|
|
921
902
|
// see edmUtils.mapsCdsToEdmType => add sap:display-format annotation
|
|
922
903
|
// only if Edm.DateTime is the result of a cast from Edm.Date
|
|
923
904
|
// but not if Edm.DateTime is the result of a regular cds type mapping
|
|
924
|
-
if(this._edmAttributes.Type === 'Edm.DateTime'
|
|
925
|
-
|
|
926
|
-
this.setXml( { 'sap:display-format'
|
|
927
|
-
|
|
905
|
+
if (this._edmAttributes.Type === 'Edm.DateTime' &&
|
|
906
|
+
(typecsn.type !== 'cds.DateTime' && typecsn.type !== 'cds.Timestamp'))
|
|
907
|
+
this.setXml( { 'sap:display-format': 'Date' } );
|
|
928
908
|
}
|
|
929
909
|
this.setNullable();
|
|
930
910
|
}
|
|
931
911
|
|
|
932
|
-
setNullable()
|
|
933
|
-
{
|
|
912
|
+
setNullable() {
|
|
934
913
|
// From the Spec: In OData 4.01 responses a collection-valued property MUST specify a value for the Nullable attribute.
|
|
935
|
-
if(this._isCollection)
|
|
914
|
+
if (this._isCollection)
|
|
936
915
|
this._edmAttributes.Nullable = !this.isNotNullable();
|
|
937
|
-
|
|
916
|
+
|
|
938
917
|
// Nullable=true is default, mention Nullable=false only in XML
|
|
939
918
|
// Nullable=false is default for EDM JSON representation 4.01
|
|
940
919
|
// When a key explicitly (!) has 'notNull = false', it stays nullable
|
|
941
|
-
else if(this.isNotNullable())
|
|
942
|
-
{
|
|
920
|
+
else if (this.isNotNullable())
|
|
943
921
|
this._edmAttributes.Nullable = false;
|
|
944
|
-
}
|
|
945
922
|
}
|
|
946
923
|
|
|
947
|
-
isNotNullable(csn=undefined) {
|
|
948
|
-
|
|
924
|
+
isNotNullable(csn = undefined) {
|
|
925
|
+
const nodeCsn = csn || this._csn;
|
|
949
926
|
// Nullable=true is default, mention Nullable=false only in XML
|
|
950
927
|
// Nullable=false is default for EDM JSON representation 4.01
|
|
951
928
|
// When a key explicitly (!) has 'notNull = false', it stays nullable
|
|
952
|
-
return (nodeCsn._NotNullCollection !== undefined ? nodeCsn._NotNullCollection
|
|
953
|
-
(nodeCsn.key && nodeCsn.notNull !== false) || nodeCsn.notNull === true);
|
|
929
|
+
return (nodeCsn._NotNullCollection !== undefined ? nodeCsn._NotNullCollection
|
|
930
|
+
: (nodeCsn.key && nodeCsn.notNull !== false) || nodeCsn.notNull === true);
|
|
954
931
|
}
|
|
955
932
|
|
|
956
|
-
toJSONattributes(json)
|
|
957
|
-
{
|
|
933
|
+
toJSONattributes(json) {
|
|
958
934
|
super.toJSONattributes(json);
|
|
959
935
|
// mention all nullable elements explicitly, remove if Nullable=true becomes default
|
|
960
|
-
if(this._edmAttributes.Nullable === undefined || this._edmAttributes.Nullable === true)
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
}
|
|
936
|
+
if (this._edmAttributes.Nullable === undefined || this._edmAttributes.Nullable === true)
|
|
937
|
+
json.$Nullable = true;
|
|
938
|
+
|
|
964
939
|
return json;
|
|
965
940
|
}
|
|
966
941
|
}
|
|
967
942
|
|
|
968
943
|
/* ReturnType is only used in v4, mapCdsToEdmType can be safely
|
|
969
944
|
called with V2=false */
|
|
970
|
-
class ReturnType extends PropertyBase
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
{
|
|
974
|
-
super(v, {}, csn);
|
|
945
|
+
class ReturnType extends PropertyBase {
|
|
946
|
+
constructor(version, csn) {
|
|
947
|
+
super(version, {}, csn);
|
|
975
948
|
}
|
|
976
949
|
|
|
977
950
|
// we need Name but NO $kind, can't use standard to JSON()
|
|
978
|
-
toJSON()
|
|
979
|
-
|
|
980
|
-
let json = Object.create(null);
|
|
951
|
+
toJSON() {
|
|
952
|
+
const json = Object.create(null);
|
|
981
953
|
this.toJSONattributes(json);
|
|
982
954
|
return json;
|
|
983
955
|
}
|
|
984
956
|
}
|
|
985
957
|
|
|
986
|
-
class Property extends PropertyBase
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
{
|
|
990
|
-
super(v, attributes, csn);
|
|
958
|
+
class Property extends PropertyBase {
|
|
959
|
+
constructor(version, attributes, csn) {
|
|
960
|
+
super(version, attributes, csn);
|
|
991
961
|
// TIPHANACDS-4180
|
|
992
|
-
if(this.v2)
|
|
993
|
-
{
|
|
962
|
+
if (this.v2) {
|
|
994
963
|
// eslint-disable-next-line sonarjs/no-redundant-boolean
|
|
995
|
-
if(csn['@odata.etag']
|
|
996
|
-
this._edmAttributes.ConcurrencyMode='Fixed'
|
|
964
|
+
if (csn['@odata.etag'] || csn['@cds.etag'])
|
|
965
|
+
this._edmAttributes.ConcurrencyMode = 'Fixed';
|
|
997
966
|
|
|
998
967
|
// translate the following @sap annos as xml attributes to the Property
|
|
999
968
|
forEach(csn, (p, v) => {
|
|
1000
969
|
if (p in Property.SAP_Annotation_Attributes)
|
|
1001
|
-
this.setXml( { [
|
|
970
|
+
this.setXml( { [`sap:${p.slice(5).replace(/\./g, '-')}`]: v });
|
|
1002
971
|
});
|
|
1003
972
|
}
|
|
1004
973
|
|
|
@@ -1006,15 +975,14 @@ function getEdm(options, messageFunctions) {
|
|
|
1006
975
|
// This is a poor man's expr renderer, assuming that edmPreprocessor has
|
|
1007
976
|
// added a @Core.ComputedDefaultValue for complex defaults
|
|
1008
977
|
if (csn.default && !csn['@Core.ComputedDefaultValue']) {
|
|
1009
|
-
|
|
1010
978
|
const def = csn.default;
|
|
1011
979
|
// if def has a value, it's a simple value
|
|
1012
980
|
let defVal = def.val;
|
|
1013
981
|
// if it's a simple value with signs, produce a string representation
|
|
1014
|
-
if(csn.default.xpr) {
|
|
1015
|
-
defVal = csn.default.xpr.map(i => {
|
|
1016
|
-
if(i.val !== undefined) {
|
|
1017
|
-
if(csn.type === 'cds.Boolean')
|
|
982
|
+
if (csn.default.xpr) {
|
|
983
|
+
defVal = csn.default.xpr.map((i) => {
|
|
984
|
+
if (i.val !== undefined) {
|
|
985
|
+
if (csn.type === 'cds.Boolean')
|
|
1018
986
|
return i.val ? 'true' : 'false';
|
|
1019
987
|
return i.val;
|
|
1020
988
|
}
|
|
@@ -1022,13 +990,12 @@ function getEdm(options, messageFunctions) {
|
|
|
1022
990
|
}).join('');
|
|
1023
991
|
}
|
|
1024
992
|
// complex values should be marked with @Core.ComputedDefaultValue already in the edmPreprocessor
|
|
1025
|
-
if(defVal !== undefined) {
|
|
993
|
+
if (this.v4 && defVal !== undefined) {
|
|
1026
994
|
/* No Default Value rendering in V2 (or only with future flag).
|
|
1027
995
|
Reason: Fiori UI5 expects 'Default' under extension namespace 'sap:'
|
|
1028
996
|
Additionally: The attribute is named 'Default' in V2 and 'DefaultValue' in V4
|
|
1029
997
|
*/
|
|
1030
|
-
|
|
1031
|
-
this._edmAttributes[`Default${this.v4 ? 'Value' : ''}`] = defVal;
|
|
998
|
+
this._edmAttributes[`Default${this.v4 ? 'Value' : ''}`] = defVal;
|
|
1032
999
|
}
|
|
1033
1000
|
}
|
|
1034
1001
|
}
|
|
@@ -1040,72 +1007,72 @@ function getEdm(options, messageFunctions) {
|
|
|
1040
1007
|
// the annotations in this array shall become exposed as Property attributes in
|
|
1041
1008
|
// the V2 metadata.xml
|
|
1042
1009
|
Property.SAP_Annotation_Attributes = {
|
|
1043
|
-
'@sap.hierarchy.node.for':1, // -> sap:hierarchy-node-for
|
|
1044
|
-
'@sap.hierarchy.parent.node.for':1, // -> sap:hierarchy-parent-node-for
|
|
1045
|
-
'@sap.hierarchy.level.for':1, // -> sap:hierarchy-level-for
|
|
1046
|
-
'@sap.hierarchy.drill.state.for':1, // -> sap:hierarchy-drill-state-for
|
|
1047
|
-
'@sap.hierarchy.node.descendant.count.for':1, // -> sap:hierarchy-node-descendant-count-for
|
|
1048
|
-
'@sap.parameter':1
|
|
1010
|
+
'@sap.hierarchy.node.for': 1, // -> sap:hierarchy-node-for
|
|
1011
|
+
'@sap.hierarchy.parent.node.for': 1, // -> sap:hierarchy-parent-node-for
|
|
1012
|
+
'@sap.hierarchy.level.for': 1, // -> sap:hierarchy-level-for
|
|
1013
|
+
'@sap.hierarchy.drill.state.for': 1, // -> sap:hierarchy-drill-state-for
|
|
1014
|
+
'@sap.hierarchy.node.descendant.count.for': 1, // -> sap:hierarchy-node-descendant-count-for
|
|
1015
|
+
'@sap.parameter': 1,
|
|
1049
1016
|
};
|
|
1050
1017
|
|
|
1051
|
-
class
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
super(v, (Alias) ? { Name, Alias } : { Name });
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
toJSON() {
|
|
1058
|
-
return this._edmAttributes.Alias ? { [this._edmAttributes.Alias]:this._edmAttributes.Name } : this._edmAttributes.Name;
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
class Parameter extends PropertyBase
|
|
1063
|
-
{
|
|
1064
|
-
constructor(v, attributes, csn={}, mode=null)
|
|
1065
|
-
{
|
|
1066
|
-
super(v, attributes, csn);
|
|
1018
|
+
class Parameter extends PropertyBase {
|
|
1019
|
+
constructor(version, attributes, csn = {}, mode = null) {
|
|
1020
|
+
super(version, attributes, csn);
|
|
1067
1021
|
|
|
1068
|
-
if(mode != null)
|
|
1022
|
+
if (mode != null)
|
|
1069
1023
|
this._edmAttributes.Mode = mode;
|
|
1070
1024
|
|
|
1071
1025
|
// V2 XML: Parameters that are not explicitly marked as Nullable or NotNullable in the CSN must become Nullable=true
|
|
1072
1026
|
// V2 XML Spec does only mention default Nullable=true for Properties not for Parameters so omitting Nullable=true let
|
|
1073
1027
|
// the client assume that Nullable is false.... Correct Nullable Handling is done inside Parameter constructor
|
|
1074
|
-
if(this.v2 && this._edmAttributes.Nullable === undefined)
|
|
1075
|
-
this.setXml({Nullable: true});
|
|
1028
|
+
if (this.v2 && this._edmAttributes.Nullable === undefined)
|
|
1029
|
+
this.setXml({ Nullable: true });
|
|
1076
1030
|
}
|
|
1077
1031
|
|
|
1078
|
-
toJSON()
|
|
1079
|
-
{
|
|
1032
|
+
toJSON() {
|
|
1080
1033
|
// we need Name but NO $kind, can't use standard to JSON()
|
|
1081
|
-
|
|
1082
|
-
json
|
|
1034
|
+
const json = Object.create(null);
|
|
1035
|
+
json.$Name = this._edmAttributes.Name;
|
|
1083
1036
|
return this.toJSONattributes(json);
|
|
1084
1037
|
}
|
|
1085
1038
|
}
|
|
1086
1039
|
|
|
1087
1040
|
class NavigationPropertyBinding extends Node {}
|
|
1088
1041
|
|
|
1089
|
-
class
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
{
|
|
1093
|
-
super(
|
|
1042
|
+
class OnDelete extends Node {}
|
|
1043
|
+
|
|
1044
|
+
class ReferentialConstraint extends Node {
|
|
1045
|
+
constructor(version, attributes, csn) {
|
|
1046
|
+
super(version, attributes, csn);
|
|
1047
|
+
this._d = null;
|
|
1048
|
+
this._p = null;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
innerXML(indent) {
|
|
1052
|
+
if (this._d && this._p)
|
|
1053
|
+
return `${this._p.toXML(indent)}\n${this._d.toXML(indent)}\n`;
|
|
1054
|
+
|
|
1055
|
+
return super.innerXML(indent);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
class NavigationProperty extends Property {
|
|
1060
|
+
constructor(version, attributes, csn) {
|
|
1061
|
+
super(version, attributes, csn);
|
|
1094
1062
|
|
|
1095
|
-
|
|
1096
|
-
csn._constraints._multiplicity = csn._constraints._partnerCsn ? [tgt, src] : [src, tgt];
|
|
1063
|
+
const [ src, tgt ] = edmUtils.determineMultiplicity(csn._constraints._partnerCsn || csn);
|
|
1064
|
+
csn._constraints._multiplicity = csn._constraints._partnerCsn ? [ tgt, src ] : [ src, tgt ];
|
|
1097
1065
|
this._type = attributes.Type;
|
|
1098
1066
|
this._isCollection = this.isToMany();
|
|
1099
1067
|
this._targetCsn = csn._target;
|
|
1100
1068
|
|
|
1101
|
-
if (this.v4)
|
|
1102
|
-
|
|
1103
|
-
if(options.isStructFormat && this._csn.key)
|
|
1069
|
+
if (this.v4) {
|
|
1070
|
+
if (options.isStructFormat && this._csn.key)
|
|
1104
1071
|
this._edmAttributes.Nullable = false;
|
|
1105
1072
|
|
|
1106
1073
|
// either csn has multiplicity or we have to use the multiplicity of the backlink
|
|
1107
|
-
if(this._isCollection) {
|
|
1108
|
-
this._edmAttributes.Type = `Collection(${attributes.Type})
|
|
1074
|
+
if (this._isCollection) {
|
|
1075
|
+
this._edmAttributes.Type = `Collection(${attributes.Type})`;
|
|
1109
1076
|
// attribute Nullable is not allowed in combination with Collection (see Spec)
|
|
1110
1077
|
// Even if min cardinality is > 0, remove Nullable, because the implicit OData contract
|
|
1111
1078
|
// is that a navigation property must either return an empty collection or all collection
|
|
@@ -1113,15 +1080,15 @@ function getEdm(options, messageFunctions) {
|
|
|
1113
1080
|
delete this._edmAttributes.Nullable;
|
|
1114
1081
|
}
|
|
1115
1082
|
// we have exactly one selfReference or the default partner
|
|
1116
|
-
|
|
1117
|
-
!csn.$noPartner
|
|
1118
|
-
csn._selfReferences.length === 1
|
|
1083
|
+
const partner
|
|
1084
|
+
= !csn.$noPartner
|
|
1085
|
+
? csn._selfReferences.length === 1
|
|
1119
1086
|
? csn._selfReferences[0]
|
|
1120
1087
|
: csn._constraints._partnerCsn
|
|
1121
1088
|
: undefined;
|
|
1122
|
-
if(partner && partner['@odata.navigable'] !== false && this._csn._edmParentCsn.kind !== 'type') {
|
|
1089
|
+
if (partner && partner['@odata.navigable'] !== false && this._csn._edmParentCsn.kind !== 'type') {
|
|
1123
1090
|
// $abspath[0] is main entity
|
|
1124
|
-
this._edmAttributes.Partner = partner.$abspath.slice(1).join(
|
|
1091
|
+
this._edmAttributes.Partner = partner.$abspath.slice(1).join('/');
|
|
1125
1092
|
}
|
|
1126
1093
|
|
|
1127
1094
|
/*
|
|
@@ -1134,20 +1101,19 @@ function getEdm(options, messageFunctions) {
|
|
|
1134
1101
|
2) ContainsTarget stems from the @odata.contained annotation
|
|
1135
1102
|
*/
|
|
1136
1103
|
// eslint-disable-next-line sonarjs/no-redundant-boolean
|
|
1137
|
-
if(csn['@odata.contained']
|
|
1104
|
+
if (csn['@odata.contained'] || csn.containsTarget)
|
|
1138
1105
|
this._edmAttributes.ContainsTarget = true;
|
|
1139
|
-
|
|
1140
|
-
if(this._edmAttributes.ContainsTarget === undefined && csn.type === 'cds.Composition') {
|
|
1106
|
+
|
|
1107
|
+
if (this._edmAttributes.ContainsTarget === undefined && csn.type === 'cds.Composition') {
|
|
1141
1108
|
// Delete is redundant in containment
|
|
1142
1109
|
// TODO: to be specified via @sap.on.delete
|
|
1143
|
-
this.append(new OnDelete(
|
|
1110
|
+
this.append(new OnDelete(version, { Action: 'Cascade' } ) );
|
|
1144
1111
|
}
|
|
1145
|
-
|
|
1146
1112
|
}
|
|
1147
1113
|
|
|
1148
1114
|
if (this.v2 && this.isNotNullable()) {
|
|
1149
|
-
|
|
1150
|
-
|
|
1115
|
+
// in V2 not null must be expressed with target cardinality of 1 or more,
|
|
1116
|
+
// store Nullable=false and evaluate in determineMultiplicity()
|
|
1151
1117
|
delete this._edmAttributes.Nullable;
|
|
1152
1118
|
}
|
|
1153
1119
|
// A nav prop has no default value
|
|
@@ -1163,8 +1129,8 @@ function getEdm(options, messageFunctions) {
|
|
|
1163
1129
|
return this._csn._isToContainer || this._csn['@odata.contained'];
|
|
1164
1130
|
}
|
|
1165
1131
|
|
|
1166
|
-
isNotNullable(csn=undefined) {
|
|
1167
|
-
|
|
1132
|
+
isNotNullable(csn = undefined) {
|
|
1133
|
+
const nodeCsn = csn || this._csn;
|
|
1168
1134
|
// Set Nullable=false only if 'NOT NULL' was specified in the model
|
|
1169
1135
|
// Do not derive Nullable=false from key attribute.
|
|
1170
1136
|
// OR if an association has cardinality.min > 0
|
|
@@ -1182,101 +1148,79 @@ function getEdm(options, messageFunctions) {
|
|
|
1182
1148
|
return (this._isCollection || this._csn._constraints._multiplicity[1] === '*');
|
|
1183
1149
|
}
|
|
1184
1150
|
|
|
1185
|
-
toJSONattributes(json)
|
|
1186
|
-
{
|
|
1151
|
+
toJSONattributes(json) {
|
|
1187
1152
|
// use the original type, not the decorated one
|
|
1188
1153
|
super.toJSONattributes(json);
|
|
1189
|
-
json
|
|
1154
|
+
json.$Type = this._type;
|
|
1190
1155
|
|
|
1191
1156
|
// attribute Nullable is not allowed in combination with Collection (see Spec)
|
|
1192
|
-
if(json
|
|
1193
|
-
delete json
|
|
1157
|
+
if (json.$Collection)
|
|
1158
|
+
delete json.$Nullable;
|
|
1194
1159
|
return json;
|
|
1195
1160
|
}
|
|
1196
1161
|
|
|
1197
|
-
toJSONchildren(json)
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
switch(c.kind) {
|
|
1162
|
+
toJSONchildren(json) {
|
|
1163
|
+
const jsonConstraints = Object.create(null);
|
|
1164
|
+
this._children.forEach((c) => {
|
|
1165
|
+
switch (c.kind) {
|
|
1202
1166
|
case 'ReferentialConstraint':
|
|
1203
1167
|
// collect ref constraints in dictionary
|
|
1204
|
-
|
|
1168
|
+
jsonConstraints[c._edmAttributes.Property] = c._edmAttributes.ReferencedProperty;
|
|
1205
1169
|
break;
|
|
1206
1170
|
case 'OnDelete':
|
|
1207
|
-
json
|
|
1171
|
+
json.$OnDelete = c._edmAttributes.Action;
|
|
1208
1172
|
break;
|
|
1209
1173
|
default:
|
|
1210
|
-
error(null,
|
|
1211
|
-
|
|
1174
|
+
error(null, `Please debug me: Unhandled NavProp child: ${c.kind}`);
|
|
1212
1175
|
}
|
|
1213
1176
|
});
|
|
1214
1177
|
// TODO Annotations
|
|
1215
|
-
if(Object.keys(
|
|
1216
|
-
json
|
|
1178
|
+
if (Object.keys(jsonConstraints).length > 0)
|
|
1179
|
+
json.$ReferentialConstraint = jsonConstraints;
|
|
1217
1180
|
return json;
|
|
1218
1181
|
}
|
|
1219
1182
|
|
|
1220
1183
|
// V4 referential constraints!
|
|
1221
|
-
addReferentialConstraintNodes()
|
|
1222
|
-
{
|
|
1184
|
+
addReferentialConstraintNodes() {
|
|
1223
1185
|
// flip the constrains if this is a $self partner
|
|
1224
|
-
let _constraints = this._csn
|
|
1225
|
-
let [i,j] = [0,1];
|
|
1226
|
-
if(this._csn._constraints._partnerCsn) {
|
|
1186
|
+
let { _constraints } = this._csn;
|
|
1187
|
+
let [ i, j ] = [ 0, 1 ];
|
|
1188
|
+
if (this._csn._constraints._partnerCsn) {
|
|
1227
1189
|
_constraints = this._csn._constraints._partnerCsn._constraints;
|
|
1228
|
-
[i,j] = [1,0];
|
|
1190
|
+
[ i, j ] = [ 1, 0 ];
|
|
1229
1191
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
constructor(v, attributes, csn) {
|
|
1240
|
-
super(v, attributes, csn);
|
|
1241
|
-
this._d = null;
|
|
1242
|
-
this._p = null;
|
|
1243
|
-
}
|
|
1244
|
-
|
|
1245
|
-
innerXML(indent)
|
|
1246
|
-
{
|
|
1247
|
-
if(this._d && this._p)
|
|
1248
|
-
{
|
|
1249
|
-
return this._p.toXML(indent) + '\n' + this._d.toXML(indent) + '\n';
|
|
1192
|
+
if (_constraints.constraints) {
|
|
1193
|
+
Object.values(_constraints.constraints)
|
|
1194
|
+
.forEach(c => this.append(
|
|
1195
|
+
new ReferentialConstraint(this._v,
|
|
1196
|
+
{
|
|
1197
|
+
Property: c[i].join(options.pathDelimiter),
|
|
1198
|
+
ReferencedProperty: c[j].join(options.pathDelimiter),
|
|
1199
|
+
} )
|
|
1200
|
+
));
|
|
1250
1201
|
}
|
|
1251
|
-
else
|
|
1252
|
-
return super.innerXML(indent);
|
|
1253
1202
|
}
|
|
1254
1203
|
}
|
|
1255
1204
|
|
|
1256
|
-
class OnDelete extends Node {}
|
|
1257
|
-
|
|
1258
1205
|
// Annotations below
|
|
1259
|
-
class AnnotationBase extends Node
|
|
1260
|
-
{
|
|
1206
|
+
class AnnotationBase extends Node {
|
|
1261
1207
|
// No Kind: AnnotationBase is base class for Thing and ValueThing with dynamic kinds,
|
|
1262
1208
|
// this requires an explicit constructor as the kinds cannot be blacklisted in
|
|
1263
1209
|
// Node.toJSON()
|
|
1264
|
-
toJSON()
|
|
1265
|
-
|
|
1266
|
-
let json = Object.create(null);
|
|
1210
|
+
toJSON() {
|
|
1211
|
+
const json = Object.create(null);
|
|
1267
1212
|
this.toJSONattributes(json);
|
|
1268
1213
|
this.toJSONchildren(json);
|
|
1269
|
-
return json
|
|
1214
|
+
return json;
|
|
1270
1215
|
}
|
|
1271
1216
|
|
|
1272
|
-
getConstantExpressionValue()
|
|
1273
|
-
{
|
|
1217
|
+
getConstantExpressionValue() {
|
|
1274
1218
|
// short form: key: value
|
|
1275
|
-
const inlineConstExpr
|
|
1276
|
-
[ 'Edm.Binary', 'Edm.Boolean', 'Edm.Byte', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Decimal', 'Edm.Double', 'Edm.Duration', 'Edm.Guid',
|
|
1277
|
-
'Edm.Int16', 'Edm.Int32', 'Edm.Int64', 'Edm.SByte','Edm.Single', 'Edm.Stream', 'Edm.String', 'Edm.TimeOfDay',
|
|
1219
|
+
const inlineConstExpr
|
|
1220
|
+
= [ 'Edm.Binary', 'Edm.Boolean', 'Edm.Byte', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Decimal', 'Edm.Double', 'Edm.Duration', 'Edm.Guid',
|
|
1221
|
+
'Edm.Int16', 'Edm.Int32', 'Edm.Int64', 'Edm.SByte', 'Edm.Single', 'Edm.Stream', 'Edm.String', 'Edm.TimeOfDay',
|
|
1278
1222
|
// Edm.Geo* according to https://issues.oasis-open.org/browse/ODATA-1323
|
|
1279
|
-
/* 'Edm.Geography', 'Edm.GeographyPoint', 'Edm.GeographyLineString', 'Edm.GeographyPolygon', 'Edm.GeographyMultiPoint',
|
|
1223
|
+
/* 'Edm.Geography', 'Edm.GeographyPoint', 'Edm.GeographyLineString', 'Edm.GeographyPolygon', 'Edm.GeographyMultiPoint',
|
|
1280
1224
|
'Edm.GeographyMultiLineString', 'Edm.GeographyMultiPolygon', 'Edm.GeographyCollection', 'Edm.Geometry', 'Edm.GeometryPoint',
|
|
1281
1225
|
'Edm.GeometryLineString', 'Edm.GeometryPolygon', 'Edm.GeometryMultiPoint', 'Edm.GeometryMultiLineString', 'Edm.GeometryMultiPolygon',
|
|
1282
1226
|
'Edm.GeometryCollection',
|
|
@@ -1284,72 +1228,60 @@ function getEdm(options, messageFunctions) {
|
|
|
1284
1228
|
/* UI.xml: defines Annotations with generic type 'Edm.PrimitiveType' */
|
|
1285
1229
|
'Edm.PrimitiveType', 'Edm.Untyped', 'Bool',
|
|
1286
1230
|
// Official JSON V4.01 Spec defines these paths as constant inline expression:
|
|
1287
|
-
'AnnotationPath', 'ModelElementPath', 'NavigationPropertyPath', 'PropertyPath'
|
|
1288
|
-
];
|
|
1231
|
+
'AnnotationPath', 'ModelElementPath', 'NavigationPropertyPath', 'PropertyPath' ];
|
|
1289
1232
|
|
|
1290
1233
|
const dict = this._jsonOnlyAttributes;
|
|
1291
1234
|
const inline = edmUtils.intersect(Object.keys(dict), inlineConstExpr);
|
|
1292
|
-
if(inline.length === 1)
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
case 'Edm.Boolean':
|
|
1301
|
-
v = (v=='true'?true:(v=='false'?false:v));
|
|
1302
|
-
// eslint-no-fallthrough
|
|
1303
|
-
default:
|
|
1304
|
-
return v;
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
else
|
|
1308
|
-
{
|
|
1309
|
-
// if this is not a constant expression shortcut, render key/value pair verbatim
|
|
1310
|
-
// without filtering non-spec-compliant constExpr
|
|
1311
|
-
let json = Object.create(null);
|
|
1312
|
-
Object.entries(dict).forEach(([k,v]) => {
|
|
1313
|
-
json['$'+k] = v;
|
|
1314
|
-
});
|
|
1315
|
-
return json;
|
|
1235
|
+
if (inline.length === 1) {
|
|
1236
|
+
const v = dict[inline[0]];
|
|
1237
|
+
/* short notation for Edm.Boolean, Edm.String and Edm.Float, see internal project:
|
|
1238
|
+
edmx2csn-npm/edm-converters/blob/835d92a1aa6b0be25c56cef85e260c9188187429/lib/edmxV40ToJsonV40/README.md
|
|
1239
|
+
*/
|
|
1240
|
+
if (inline[0] === 'Edm.Boolean')
|
|
1241
|
+
return (v === 'true' ? true : (v === 'false' ? false : v));
|
|
1242
|
+
return v;
|
|
1316
1243
|
}
|
|
1244
|
+
|
|
1245
|
+
// if this is not a constant expression shortcut, render key/value pair verbatim
|
|
1246
|
+
// without filtering non-spec-compliant constExpr
|
|
1247
|
+
const json = Object.create(null);
|
|
1248
|
+
Object.entries(dict).forEach(([ k, v ]) => {
|
|
1249
|
+
json[`$${k}`] = v;
|
|
1250
|
+
});
|
|
1251
|
+
return json;
|
|
1317
1252
|
}
|
|
1318
1253
|
|
|
1319
|
-
mergeJSONAnnotations(prefix='') {
|
|
1254
|
+
mergeJSONAnnotations(prefix = '') {
|
|
1320
1255
|
return this._children.filter(c => c.kind === 'Annotation').reduce((o, a) => {
|
|
1321
|
-
Object.entries(a.toJSON()).forEach(([n, v]) => {
|
|
1322
|
-
o[prefix+n] = v;
|
|
1256
|
+
Object.entries(a.toJSON()).forEach(([ n, v ]) => {
|
|
1257
|
+
o[prefix + n] = v;
|
|
1323
1258
|
});
|
|
1324
|
-
return o;
|
|
1325
|
-
|
|
1259
|
+
return o;
|
|
1260
|
+
},
|
|
1261
|
+
Object.create(null));
|
|
1326
1262
|
}
|
|
1327
1263
|
}
|
|
1328
1264
|
|
|
1329
|
-
class Annotations extends AnnotationBase
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
super(v, { Target: target });
|
|
1334
|
-
this.setXml( { xmlns : this.v2 ? 'http://docs.oasis-open.org/odata/ns/edm' : undefined } );
|
|
1265
|
+
class Annotations extends AnnotationBase {
|
|
1266
|
+
constructor(version, target) {
|
|
1267
|
+
super(version, { Target: target });
|
|
1268
|
+
this.setXml( { xmlns: this.v2 ? 'http://docs.oasis-open.org/odata/ns/edm' : undefined } );
|
|
1335
1269
|
}
|
|
1336
1270
|
|
|
1337
|
-
toJSONattributes(json)
|
|
1338
|
-
{
|
|
1271
|
+
toJSONattributes(json) {
|
|
1339
1272
|
forEach(this._edmAttributes, (p, v) => {
|
|
1340
1273
|
if (p !== 'Target')
|
|
1341
|
-
json[p[0] === '@' ? p :
|
|
1274
|
+
json[p[0] === '@' ? p : `$${p}`] = v;
|
|
1342
1275
|
});
|
|
1343
1276
|
return json;
|
|
1344
1277
|
}
|
|
1345
1278
|
|
|
1346
|
-
toJSONchildren(json)
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
Object.entries(a.toJSON()).forEach(([n, v]) => {
|
|
1279
|
+
toJSONchildren(json) {
|
|
1280
|
+
this._children.forEach((a) => {
|
|
1281
|
+
Object.entries(a.toJSON()).forEach(([ n, v ]) => {
|
|
1350
1282
|
json[n] = v;
|
|
1351
1283
|
});
|
|
1352
|
-
})
|
|
1284
|
+
});
|
|
1353
1285
|
}
|
|
1354
1286
|
}
|
|
1355
1287
|
|
|
@@ -1365,18 +1297,15 @@ function getEdm(options, messageFunctions) {
|
|
|
1365
1297
|
// the constant expression value is the same for both XML and JSON. But
|
|
1366
1298
|
// since it was discovered, that in JSON the EnumMember type must be
|
|
1367
1299
|
// transported this is no longer the case....
|
|
1368
|
-
class Annotation extends AnnotationBase
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
{
|
|
1372
|
-
super(v, { Term: termName } );
|
|
1300
|
+
class Annotation extends AnnotationBase {
|
|
1301
|
+
constructor(version, termName) {
|
|
1302
|
+
super(version, { Term: termName } );
|
|
1373
1303
|
}
|
|
1374
1304
|
|
|
1375
|
-
toJSON()
|
|
1376
|
-
{
|
|
1305
|
+
toJSON() {
|
|
1377
1306
|
const json = super.mergeJSONAnnotations(this.getJsonFQTermName());
|
|
1378
1307
|
const e = this._children.filter(c => c.kind !== 'Annotation');
|
|
1379
|
-
if(e.length === 0 || this._ignoreChildren) // must be a constant expression
|
|
1308
|
+
if (e.length === 0 || this._ignoreChildren) // must be a constant expression
|
|
1380
1309
|
json[this.getJsonFQTermName()] = this.getConstantExpressionValue();
|
|
1381
1310
|
else
|
|
1382
1311
|
// annotation must have exactly one child (=record or collection)
|
|
@@ -1385,44 +1314,38 @@ function getEdm(options, messageFunctions) {
|
|
|
1385
1314
|
}
|
|
1386
1315
|
|
|
1387
1316
|
getJsonFQTermName() {
|
|
1388
|
-
return
|
|
1317
|
+
return `@${this._edmAttributes.Term}${this._edmAttributes.Qualifier ? `#${this._edmAttributes.Qualifier}` : ''}`;
|
|
1389
1318
|
}
|
|
1390
1319
|
}
|
|
1391
1320
|
|
|
1392
|
-
class Collection extends AnnotationBase
|
|
1393
|
-
|
|
1394
|
-
toJSON()
|
|
1395
|
-
{
|
|
1321
|
+
class Collection extends AnnotationBase {
|
|
1322
|
+
toJSON() {
|
|
1396
1323
|
// EDM JSON doesn't mention annotations on collections
|
|
1397
1324
|
return this._children.map(a => a.toJSON());
|
|
1398
1325
|
}
|
|
1399
1326
|
}
|
|
1400
1327
|
|
|
1401
|
-
class Record extends AnnotationBase
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
{
|
|
1405
|
-
if(this._jsonOnlyAttributes.Type)
|
|
1328
|
+
class Record extends AnnotationBase {
|
|
1329
|
+
toJSONattributes(json) {
|
|
1330
|
+
if (this._jsonOnlyAttributes.Type)
|
|
1406
1331
|
json['@type'] = this._jsonOnlyAttributes.Type;
|
|
1407
|
-
|
|
1408
|
-
for(const key of keys)
|
|
1409
|
-
json[
|
|
1332
|
+
const keys = Object.keys(this._edmAttributes).filter(k => k !== 'Type');
|
|
1333
|
+
for (const key of keys)
|
|
1334
|
+
json[`$${key}`] = this._edmAttributes[key];
|
|
1410
1335
|
}
|
|
1411
1336
|
|
|
1412
|
-
toJSONchildren(json)
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
switch(c.kind)
|
|
1416
|
-
{
|
|
1337
|
+
toJSONchildren(json) {
|
|
1338
|
+
this._children.forEach((c) => {
|
|
1339
|
+
switch (c.kind) {
|
|
1417
1340
|
case 'Annotation': {
|
|
1418
|
-
Object.entries(c.toJSON()).forEach(([n, v]) => {
|
|
1341
|
+
Object.entries(c.toJSON()).forEach(([ n, v ]) => {
|
|
1419
1342
|
json[n] = v;
|
|
1420
1343
|
});
|
|
1421
1344
|
break;
|
|
1422
1345
|
}
|
|
1423
1346
|
case 'PropertyValue': {
|
|
1424
1347
|
// plus property annotations as [a.Property]@anno: val
|
|
1425
|
-
Object.entries(c.mergeJSONannotations()).forEach(([n, a]) => {
|
|
1348
|
+
Object.entries(c.mergeJSONannotations()).forEach(([ n, a ]) => {
|
|
1426
1349
|
json[n] = a;
|
|
1427
1350
|
});
|
|
1428
1351
|
// render property as const expr (or subnode)
|
|
@@ -1430,89 +1353,73 @@ function getEdm(options, messageFunctions) {
|
|
|
1430
1353
|
break;
|
|
1431
1354
|
}
|
|
1432
1355
|
default:
|
|
1433
|
-
error(null,
|
|
1356
|
+
error(null, `Pease debug me: Unhandled Record child: ${c.kind}`);
|
|
1434
1357
|
}
|
|
1435
1358
|
});
|
|
1436
1359
|
}
|
|
1437
1360
|
}
|
|
1438
1361
|
|
|
1439
|
-
class PropertyValue extends AnnotationBase
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
{
|
|
1443
|
-
super(v);
|
|
1362
|
+
class PropertyValue extends AnnotationBase {
|
|
1363
|
+
constructor(version, property) {
|
|
1364
|
+
super(version);
|
|
1444
1365
|
this._edmAttributes.Property = property;
|
|
1445
1366
|
}
|
|
1446
1367
|
|
|
1447
|
-
toJSON()
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
if(c.length === 0 || this._ignoreChildren)
|
|
1368
|
+
toJSON() {
|
|
1369
|
+
const children = this._children.filter(child => child.kind !== 'Annotation');
|
|
1370
|
+
if (children.length === 0 || this._ignoreChildren)
|
|
1451
1371
|
return this.getConstantExpressionValue();
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
return c[0].toJSON();
|
|
1455
|
-
}
|
|
1372
|
+
|
|
1373
|
+
return children[0].toJSON();
|
|
1456
1374
|
}
|
|
1457
1375
|
mergeJSONannotations() {
|
|
1458
1376
|
return super.mergeJSONAnnotations(this._edmAttributes.Property);
|
|
1459
1377
|
}
|
|
1460
1378
|
}
|
|
1461
1379
|
|
|
1462
|
-
class Thing extends AnnotationBase
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
{
|
|
1466
|
-
super(v, details);
|
|
1380
|
+
class Thing extends AnnotationBase {
|
|
1381
|
+
constructor(version, kind, details) {
|
|
1382
|
+
super(version, details);
|
|
1467
1383
|
this._kind = kind;
|
|
1468
1384
|
}
|
|
1469
1385
|
|
|
1470
|
-
get kind() {
|
|
1386
|
+
get kind() {
|
|
1387
|
+
return this._kind;
|
|
1388
|
+
}
|
|
1471
1389
|
}
|
|
1472
1390
|
|
|
1473
|
-
class ValueThing extends Thing
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
{
|
|
1477
|
-
super(v, kind, undefined);
|
|
1391
|
+
class ValueThing extends Thing {
|
|
1392
|
+
constructor(version, kind, value) {
|
|
1393
|
+
super(version, kind, undefined);
|
|
1478
1394
|
this._value = value;
|
|
1479
1395
|
}
|
|
1480
1396
|
|
|
1481
|
-
toXML(indent='')
|
|
1482
|
-
|
|
1483
|
-
let
|
|
1484
|
-
|
|
1485
|
-
xml += (this._value !== undefined ? '>' + edmUtils.escapeStringForText(this._value) + '</' + kind + '>' : '/>');
|
|
1397
|
+
toXML(indent = '') {
|
|
1398
|
+
const { kind } = this;
|
|
1399
|
+
let xml = `${indent}<${kind}${this.toXMLattributes()}`;
|
|
1400
|
+
xml += (this._value !== undefined ? `>${edmUtils.escapeStringForText(this._value)}</${kind}>` : '/>');
|
|
1486
1401
|
return xml;
|
|
1487
1402
|
}
|
|
1488
1403
|
|
|
1489
|
-
toJSON()
|
|
1490
|
-
|
|
1491
|
-
if(this._children.length === 0 || this._ignoreChildren) // must be a constant expression
|
|
1404
|
+
toJSON() {
|
|
1405
|
+
if (this._children.length === 0 || this._ignoreChildren) // must be a constant expression
|
|
1492
1406
|
return this.getConstantExpressionValue();
|
|
1493
|
-
|
|
1494
|
-
// annotation must have exactly one child (=record or collection)
|
|
1495
|
-
return this._children[0].toJSON();
|
|
1407
|
+
return this._children[0].toJSON();
|
|
1496
1408
|
}
|
|
1497
1409
|
}
|
|
1498
1410
|
|
|
1499
1411
|
// Binary/Unary dynamic expression
|
|
1500
1412
|
class Expr extends Thing {
|
|
1501
|
-
|
|
1502
|
-
super(v, kind, details);
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
toJSON()
|
|
1506
|
-
{
|
|
1413
|
+
toJSON() {
|
|
1507
1414
|
// toJSON: depending on number of children unary or n-ary expr
|
|
1508
1415
|
const json = this.mergeJSONAnnotations();
|
|
1509
|
-
const e = this._children.filter(c=>c.kind !== 'Annotation');
|
|
1510
|
-
if(e.length === 1)
|
|
1511
|
-
json[
|
|
1512
|
-
|
|
1513
|
-
else
|
|
1514
|
-
json[
|
|
1515
|
-
|
|
1416
|
+
const e = this._children.filter(c => c.kind !== 'Annotation');
|
|
1417
|
+
if (e.length === 1)
|
|
1418
|
+
json[`$${this.kind}`] = e[0].toJSON();
|
|
1419
|
+
|
|
1420
|
+
else
|
|
1421
|
+
json[`$${this.kind}`] = e.map(c => c.toJSON());
|
|
1422
|
+
|
|
1516
1423
|
return json;
|
|
1517
1424
|
}
|
|
1518
1425
|
}
|
|
@@ -1523,14 +1430,14 @@ function getEdm(options, messageFunctions) {
|
|
|
1523
1430
|
}
|
|
1524
1431
|
toJSON() {
|
|
1525
1432
|
const json = this.mergeJSONAnnotations();
|
|
1526
|
-
json[
|
|
1433
|
+
json[`$${this.kind}`] = null;
|
|
1527
1434
|
return json;
|
|
1528
1435
|
}
|
|
1529
1436
|
}
|
|
1530
1437
|
class Apply extends AnnotationBase {
|
|
1531
1438
|
toJSON() {
|
|
1532
1439
|
const json = this.mergeJSONAnnotations();
|
|
1533
|
-
json[
|
|
1440
|
+
json[`$${this.kind}`] = this._children.filter(c => c.kind !== 'Annotation').map(c => c.toJSON());
|
|
1534
1441
|
this.toJSONattributes(json);
|
|
1535
1442
|
return json;
|
|
1536
1443
|
}
|
|
@@ -1538,24 +1445,25 @@ function getEdm(options, messageFunctions) {
|
|
|
1538
1445
|
class Cast extends AnnotationBase {
|
|
1539
1446
|
toXMLattributes() {
|
|
1540
1447
|
// TODO: Why json?
|
|
1541
|
-
if(this._jsonOnlyAttributes
|
|
1542
|
-
return ` Type="Collection(${this._edmAttributes.Type})"
|
|
1543
|
-
|
|
1544
|
-
return ` Type="${this._edmAttributes.Type}"`
|
|
1448
|
+
if (this._jsonOnlyAttributes.Collection)
|
|
1449
|
+
return ` Type="Collection(${this._edmAttributes.Type})"`;
|
|
1450
|
+
return ` Type="${this._edmAttributes.Type}"`;
|
|
1545
1451
|
}
|
|
1546
1452
|
toJSON() {
|
|
1547
1453
|
const json = this.mergeJSONAnnotations();
|
|
1548
1454
|
// first expression only, if any
|
|
1549
|
-
const
|
|
1550
|
-
json[
|
|
1455
|
+
const children = this._children.filter(child => child.kind !== 'Annotation');
|
|
1456
|
+
json[`$${this.kind}`] = children.length ? children[0].toJSON() : {};
|
|
1551
1457
|
this.toJSONattributes(json);
|
|
1552
1458
|
return json;
|
|
1553
1459
|
}
|
|
1554
1460
|
toJSONattributes(json) {
|
|
1555
1461
|
super.toJSONattributes(json);
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1462
|
+
if (this._jsonOnlyAttributes) {
|
|
1463
|
+
Object.entries(this._jsonOnlyAttributes).forEach(([ p, v ]) => {
|
|
1464
|
+
json[p[0] === '@' ? p : `$${p}`] = v;
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1559
1467
|
return json;
|
|
1560
1468
|
}
|
|
1561
1469
|
}
|
|
@@ -1564,7 +1472,7 @@ function getEdm(options, messageFunctions) {
|
|
|
1564
1472
|
class If extends AnnotationBase {
|
|
1565
1473
|
toJSON() {
|
|
1566
1474
|
const json = this.mergeJSONAnnotations();
|
|
1567
|
-
json[
|
|
1475
|
+
json[`$${this.kind}`] = this._children.filter(c => c.kind !== 'Annotation').map(c => c.toJSON());
|
|
1568
1476
|
return json;
|
|
1569
1477
|
}
|
|
1570
1478
|
}
|
|
@@ -1572,97 +1480,94 @@ function getEdm(options, messageFunctions) {
|
|
|
1572
1480
|
toJSON() {
|
|
1573
1481
|
const json = this.mergeJSONAnnotations();
|
|
1574
1482
|
// first expression only, if any
|
|
1575
|
-
const
|
|
1576
|
-
json[
|
|
1483
|
+
const children = this._children.filter(child => child.kind !== 'Annotation');
|
|
1484
|
+
json[`$${this.kind}`] = children.length ? children[0].toJSON() : '';
|
|
1577
1485
|
this.toJSONattributes(json);
|
|
1578
1486
|
return json;
|
|
1579
1487
|
}
|
|
1580
1488
|
|
|
1581
|
-
toJSONattributes(json) // including Name
|
|
1582
|
-
{
|
|
1489
|
+
toJSONattributes(json) { // including Name
|
|
1583
1490
|
forEach(this._edmAttributes, (p, v) => {
|
|
1584
|
-
json[p[0] === '@' ? p :
|
|
1491
|
+
json[p[0] === '@' ? p : `$${p}`] = v;
|
|
1585
1492
|
});
|
|
1586
1493
|
return json;
|
|
1587
1494
|
}
|
|
1588
1495
|
}
|
|
1589
1496
|
// LabeledElementReference is a
|
|
1590
1497
|
class LabeledElementReference extends ValueThing {
|
|
1591
|
-
constructor(
|
|
1592
|
-
super(
|
|
1498
|
+
constructor(version, val) {
|
|
1499
|
+
super(version, 'LabeledElementReference', val);
|
|
1593
1500
|
}
|
|
1594
1501
|
}
|
|
1595
1502
|
class UrlRef extends AnnotationBase {
|
|
1596
1503
|
toJSON() {
|
|
1597
1504
|
const json = this.mergeJSONAnnotations();
|
|
1598
1505
|
// first expression only, if any
|
|
1599
|
-
const
|
|
1600
|
-
json[
|
|
1506
|
+
const children = this._children.filter(child => child.kind !== 'Annotation');
|
|
1507
|
+
json[`$${this.kind}`] = children.length ? children[0].toJSON() : {};
|
|
1601
1508
|
return json;
|
|
1602
1509
|
}
|
|
1603
1510
|
}
|
|
1604
1511
|
|
|
1605
1512
|
// V2 specials
|
|
1606
1513
|
class End extends Node {}
|
|
1607
|
-
class Association extends Node
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
{
|
|
1611
|
-
super(v, details);
|
|
1514
|
+
class Association extends Node {
|
|
1515
|
+
constructor(version, details, navProp, fromRole, toRole, multiplicity) {
|
|
1516
|
+
super(version, details);
|
|
1612
1517
|
this._end = [
|
|
1613
|
-
new End(
|
|
1614
|
-
new End(
|
|
1518
|
+
new End(version, { Role: fromRole[0], Type: fromRole[1], Multiplicity: multiplicity[0] } ),
|
|
1519
|
+
new End(version, { Role: toRole[0], Type: toRole[1], Multiplicity: multiplicity[1] } ),
|
|
1615
1520
|
];
|
|
1616
1521
|
|
|
1617
1522
|
// set Delete:Cascade on composition end
|
|
1618
|
-
if(navProp._csn.type === 'cds.Composition')
|
|
1619
|
-
this._end[0].append(new OnDelete(
|
|
1523
|
+
if (navProp._csn.type === 'cds.Composition')
|
|
1524
|
+
this._end[0].append(new OnDelete(version, { Action: 'Cascade' }));
|
|
1620
1525
|
|
|
1621
|
-
if(navProp._csn._selfReferences && navProp._csn._selfReferences.length &&
|
|
1526
|
+
if (navProp._csn._selfReferences && navProp._csn._selfReferences.length &&
|
|
1622
1527
|
navProp._csn._selfReferences[0].type === 'cds.Composition')
|
|
1623
|
-
this._end[1].append(new OnDelete(
|
|
1528
|
+
this._end[1].append(new OnDelete(version, { Action: 'Cascade' }));
|
|
1624
1529
|
}
|
|
1625
1530
|
|
|
1626
|
-
innerXML(indent)
|
|
1627
|
-
{
|
|
1531
|
+
innerXML(indent) {
|
|
1628
1532
|
let xml = '';
|
|
1629
|
-
this._end.forEach(e =>
|
|
1533
|
+
this._end.forEach((e) => {
|
|
1534
|
+
xml += `${e.toXML(indent)}\n`;
|
|
1535
|
+
});
|
|
1630
1536
|
xml += super.innerXML(indent);
|
|
1631
1537
|
return xml;
|
|
1632
1538
|
}
|
|
1633
1539
|
}
|
|
1634
1540
|
|
|
1635
|
-
class AssociationSet extends Node
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
{
|
|
1639
|
-
super(v, details);
|
|
1541
|
+
class AssociationSet extends Node {
|
|
1542
|
+
constructor(version, details, fromRole, toRole, fromEntitySet, toEntitySet) {
|
|
1543
|
+
super(version, details);
|
|
1640
1544
|
this.append(
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1545
|
+
new End(version, { Role: fromRole, EntitySet: fromEntitySet } ),
|
|
1546
|
+
new End(version, { Role: toRole, EntitySet: toEntitySet } )
|
|
1547
|
+
);
|
|
1644
1548
|
}
|
|
1645
1549
|
getDuplicateMessage() {
|
|
1646
|
-
return `Association "${this._edmAttributes.Association}"
|
|
1550
|
+
return `Association "${this._edmAttributes.Association}"`;
|
|
1647
1551
|
}
|
|
1648
|
-
}
|
|
1552
|
+
}
|
|
1649
1553
|
|
|
1650
1554
|
class Dependent extends Node {}
|
|
1651
1555
|
class Principal extends Node {}
|
|
1652
1556
|
|
|
1653
|
-
ReferentialConstraint.createV2
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
let node = new ReferentialConstraint(v, {});
|
|
1557
|
+
ReferentialConstraint.createV2
|
|
1558
|
+
= (v, from, to, c) => {
|
|
1559
|
+
const node = new ReferentialConstraint(v, {});
|
|
1657
1560
|
node._d = new Dependent(v, { Role: from } );
|
|
1658
1561
|
node._p = new Principal(v, { Role: to } );
|
|
1659
1562
|
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1563
|
+
if (c) {
|
|
1564
|
+
Object.values(c).forEach((cv) => {
|
|
1565
|
+
node._d.append(new PropertyRef(v, cv[0].join(options.pathDelimiter)));
|
|
1566
|
+
node._p.append(new PropertyRef(v, cv[1].join(options.pathDelimiter)));
|
|
1567
|
+
});
|
|
1568
|
+
}
|
|
1664
1569
|
return node;
|
|
1665
|
-
}
|
|
1570
|
+
};
|
|
1666
1571
|
|
|
1667
1572
|
return {
|
|
1668
1573
|
Edm,
|
|
@@ -1680,7 +1585,7 @@ function getEdm(options, messageFunctions) {
|
|
|
1680
1585
|
ComplexType,
|
|
1681
1586
|
EntityType,
|
|
1682
1587
|
Key,
|
|
1683
|
-
//ActionFunctionBase,
|
|
1588
|
+
// ActionFunctionBase,
|
|
1684
1589
|
FunctionDefinition,
|
|
1685
1590
|
Action,
|
|
1686
1591
|
FunctionImport,
|
|
@@ -1717,9 +1622,10 @@ function getEdm(options, messageFunctions) {
|
|
|
1717
1622
|
Association,
|
|
1718
1623
|
AssociationSet,
|
|
1719
1624
|
Dependent,
|
|
1720
|
-
Principal
|
|
1721
|
-
}
|
|
1722
|
-
|
|
1625
|
+
Principal,
|
|
1626
|
+
};
|
|
1723
1627
|
} // instance function
|
|
1724
1628
|
|
|
1725
|
-
module.exports = {
|
|
1629
|
+
module.exports = {
|
|
1630
|
+
EdmTypeFacetMap, EdmTypeFacetNames, EdmPrimitiveTypeMap, getEdm,
|
|
1631
|
+
};
|