@sap/cds-compiler 4.1.2 → 4.2.2

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.
Files changed (74) hide show
  1. package/CHANGELOG.md +101 -1
  2. package/bin/cdsc.js +6 -3
  3. package/doc/CHANGELOG_BETA.md +5 -0
  4. package/doc/CHANGELOG_DEPRECATED.md +15 -0
  5. package/lib/api/main.js +2 -2
  6. package/lib/api/options.js +2 -2
  7. package/lib/api/validate.js +24 -24
  8. package/lib/base/message-registry.js +41 -6
  9. package/lib/base/messages.js +7 -0
  10. package/lib/base/model.js +37 -8
  11. package/lib/checks/elements.js +11 -10
  12. package/lib/checks/manyNavigations.js +33 -0
  13. package/lib/checks/onConditions.js +5 -2
  14. package/lib/checks/queryNoDbArtifacts.js +2 -3
  15. package/lib/checks/selectItems.js +4 -55
  16. package/lib/checks/utils.js +3 -2
  17. package/lib/checks/validator.js +3 -1
  18. package/lib/compiler/.eslintrc.json +2 -1
  19. package/lib/compiler/assert-consistency.js +27 -24
  20. package/lib/compiler/base.js +6 -2
  21. package/lib/compiler/builtins.js +34 -34
  22. package/lib/compiler/checks.js +179 -208
  23. package/lib/compiler/classes.js +2 -2
  24. package/lib/compiler/cycle-detector.js +6 -6
  25. package/lib/compiler/define.js +66 -45
  26. package/lib/compiler/extend.js +81 -72
  27. package/lib/compiler/finalize-parse-cdl.js +26 -26
  28. package/lib/compiler/generate.js +61 -45
  29. package/lib/compiler/index.js +47 -49
  30. package/lib/compiler/kick-start.js +8 -7
  31. package/lib/compiler/moduleLayers.js +1 -1
  32. package/lib/compiler/populate.js +42 -35
  33. package/lib/compiler/propagator.js +6 -6
  34. package/lib/compiler/resolve.js +170 -126
  35. package/lib/compiler/shared.js +122 -45
  36. package/lib/compiler/tweak-assocs.js +93 -40
  37. package/lib/compiler/utils.js +15 -12
  38. package/lib/edm/.eslintrc.json +40 -1
  39. package/lib/edm/annotations/genericTranslation.js +721 -707
  40. package/lib/edm/annotations/preprocessAnnotations.js +88 -77
  41. package/lib/edm/csn2edm.js +389 -378
  42. package/lib/edm/edm.js +678 -772
  43. package/lib/edm/edmAnnoPreprocessor.js +132 -146
  44. package/lib/edm/edmInboundChecks.js +29 -27
  45. package/lib/edm/edmPreprocessor.js +686 -646
  46. package/lib/edm/edmUtils.js +277 -296
  47. package/lib/gen/language.checksum +1 -1
  48. package/lib/gen/language.interp +1 -1
  49. package/lib/gen/languageParser.js +1253 -1276
  50. package/lib/json/from-csn.js +34 -4
  51. package/lib/json/to-csn.js +4 -4
  52. package/lib/language/language.g4 +2 -5
  53. package/lib/main.d.ts +61 -1
  54. package/lib/model/csnUtils.js +31 -2
  55. package/lib/model/revealInternalProperties.js +1 -1
  56. package/lib/modelCompare/compare.js +37 -2
  57. package/lib/modelCompare/utils/filter.js +1 -1
  58. package/lib/optionProcessor.js +15 -3
  59. package/lib/render/toCdl.js +30 -4
  60. package/lib/render/toSql.js +5 -9
  61. package/lib/render/utils/common.js +8 -6
  62. package/lib/transform/db/applyTransformations.js +1 -1
  63. package/lib/transform/db/cdsPersistence.js +1 -1
  64. package/lib/transform/db/constraints.js +47 -17
  65. package/lib/transform/db/expansion.js +121 -47
  66. package/lib/transform/db/flattening.js +75 -7
  67. package/lib/transform/forOdata.js +4 -1
  68. package/lib/transform/forRelationalDB.js +80 -62
  69. package/lib/transform/localized.js +91 -54
  70. package/lib/transform/transformUtils.js +9 -10
  71. package/lib/utils/file.js +7 -7
  72. package/lib/utils/moduleResolve.js +210 -121
  73. package/lib/utils/objectUtils.js +1 -1
  74. 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
- 'MaxLength': { v2: true, v4: true, remove: true, optional: true },
11
- 'Precision': { v2: true, v4: true, remove: true, optional: true },
12
- 'Scale': { v2: true, v4: true, remove: true, optional: true, extra: 'sap:variable-scale' },
13
- 'SRID': { v4: true, remove: true, optional: true },
14
- //'FixedLength': { v2: true },
15
- //'Collation': { v2: true },
16
- //'Unicode': { v2: true, v4: true },
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': { v2: true, v4: true, MaxLength: true, FixedLength: true, desc: 'Binary data' },
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': { v2: true, v4: true, Precision: true, desc: 'Date and time with a time-zone offset, no leap seconds' },
28
- 'Edm.Decimal': { v2: true, v4: true, Precision: true, Scale: true, desc: 'Numeric values with decimal representation' },
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': { v2: true, v4: true, MaxLength: true, FixedLength: true, Collation: true, Unicode: true, desc: 'Sequence of characters' },
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[]} v Versions in the form of [<v2>, <v4>].
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(v, attributes = Object.create(null), csn=undefined)
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(v))
75
- error(null, 'Please debug me: v is either undefined or not an array: ' + v);
76
- if(v.filter(v => v).length !== 1)
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 = 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() { return this._v[0] }
95
- get v4() { return this._v[1] }
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['$Kind'] = this.kind;
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 : '$' + p] = v;
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 => json[c._edmAttributes.Name] = c.toJSON());
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 kind = this.kind;
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=`Collection(${this._edmAttributes.Type})`;
206
+ this._edmAttributes.Type = `Collection(${this._edmAttributes.Type})`;
197
207
  }
198
208
 
199
209
  head += this.toXMLattributes();
200
210
 
201
- let inner = this.innerXML(indent + ' ', what)
202
- if (inner.length < 1) {
203
- head += '/>'
204
- }
205
- else if (inner.length < 77 && inner.indexOf('<') < 0) {
206
- head += '>' + inner.slice(indent.length + 1, -1) + '</' + kind + '>'
207
- } else {
208
- head += '>\n' + inner + indent + '</' + kind + '>'
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 += ' ' + p + '="' + edmUtils.escapeStringForAttributeValue(v) + '"'
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 += ' ' + p + '="' + edmUtils.escapeStringForAttributeValue(v) + '"'
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) + '\n');
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
- attr && Object.entries(attr).forEach(([p, v]) => {
245
- if (p.match(/^@sap./))
246
- this.setXml( { ['sap:' + p.slice(5).replace(/\./g, '-')] : v } );
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 = {'Property':1, 'EntitySet':1, 'ActionImport':1, 'FunctionImport':1, 'Singleton':1, 'Schema':1};
254
-
255
- class Reference extends Node
256
- {
257
- constructor(v, details)
258
- {
259
- super(v, details);
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() { return 'edmx:Reference' }
274
+ get kind() {
275
+ return 'edmx:Reference';
276
+ }
265
277
 
266
- toJSON()
267
- {
268
- let json = Object.create(null);
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['$Include'] = includes;
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
- get kind() { return 'edmx:Include' }
281
- toJSON()
282
- {
283
- let json = Object.create(null);
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 Schema extends Node
289
- {
290
- constructor(v, ns, alias=undefined, serviceCsn=null, annotations=[], withEntityContainer=true)
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(v, props);
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
- let ecprops = { Name: 'EntityContainer' };
306
- let ec = new EntityContainer(v, ecprops, serviceCsn );
307
- if(this.v2)
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
- this._actions && Object.values(this._actions).forEach(actionArray => {
338
- actionArray.forEach(action => {
339
- xml += action.toXML(indent, what) + '\n'; });
340
- });
341
- }
342
- if(what==='annotations' || what==='all')
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
- this._edmAttributes && Object.entries(this._edmAttributes).forEach(([p, v]) => {
356
- if (p !== 'Name' && p !== 'Namespace')
357
- json[p[0] === '@' ? p : '$' + p] = v;
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
- let json_Annotations = Object.create(null);
372
- this._annotations.filter(a => a._edmAttributes.Target).forEach(a => json_Annotations[a._edmAttributes.Target] = a.toJSON());
373
- if(Object.keys(json_Annotations).length)
374
- json['$Annotations'] = json_Annotations;
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
- this._actions && Object.entries(this._actions).forEach(([actionName, actionArray]) => {
377
- json[actionName] = [];
378
- actionArray.forEach(action => {
379
- json[actionName].push(action.toJSON());
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() { return 'edmx:DataServices'; }
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 => json[s._edmAttributes.Namespace] = s.toJSON());
440
+ this._children.forEach((s) => {
441
+ json[s._edmAttributes.Namespace] = s.toJSON();
442
+ });
413
443
  return json;
414
444
  }
415
445
  }
416
446
 
417
- /* <edmx:Edmx> must contain exactly one <edmx:DataServices> with 1..n <edm:Schema> elements
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
- constructor(v, service)
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'] = undefined;
440
- xmlProps['xmlns:sap'] = undefined;
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'] = 'http://schemas.microsoft.com/ado/2007/08/dataservices/metadata';
446
- xmlProps['xmlns:sap'] = 'http://www.sap.com/Protocols/SAPData';
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() { return 'edmx:Edmx' }
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
- else
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
- let json = Object.create(null);
472
- json['$Version'] = this._edmAttributes.Version;
473
- json['$EntityContainer'] = schema._edmAttributes.Namespace + '.' + schema._ec._edmAttributes.Name;
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
- let reference_json = Object.create(null);
476
- this._defaultRefs.forEach(r => reference_json[r._edmAttributes.Uri] = r.toJSON());
477
- this._children.forEach(r => reference_json[r._edmAttributes.Uri] = r.toJSON());
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(reference_json).length)
480
- json['$Reference'] = reference_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 => xml += r.toXML(indent) + '\n');
499
- this._children.forEach(e => xml += e.toXML(indent) + '\n');
500
- xml += this._service.toXML(indent, what) + '\n';
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 EntityContainer extends Node
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['$Type'] = v;
540
+ if (p === 'EntityType') // it's $Type in json
541
+ json.$Type = v;
535
542
  else
536
- json[p[0] === '@' ? p : '$' + p] = v;
543
+ json[p[0] === '@' ? p : `$${p}`] = v;
537
544
  }
538
545
  });
539
546
  return json;
540
547
  }
541
548
 
542
- toJSONchildren(json)
543
- {
544
- let json_navPropBinding = Object.create(null);
545
- this._children.forEach(npb => json_navPropBinding[npb._edmAttributes.Path] = npb._edmAttributes.Target);
546
- if(Object.keys(json_navPropBinding).length > 0)
547
- json['$NavigationPropertyBinding'] = json_navPropBinding;
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['$Collection']=true;
573
+ json.$Collection = true;
569
574
  return super.toJSONattributes(json);
570
575
  }
571
576
  }
572
577
 
573
- class Key extends Node
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(v, keys)
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
- constructor(v, details)
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) + '\n';
614
- return xml
615
- }
616
-
617
- toJSONchildren(json)
618
- {
619
- let json_parameters = [];
620
- this._children.forEach(p => json_parameters.push(p.toJSON()));
621
- if(json_parameters.length > 0)
622
- json['$Parameter'] = json_parameters;
623
- if(this._returnType)
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
- get kind() { return 'Function'; }
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(v, attributes, csn);
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' ||*/ this._scalarType.type === 'cds.Binary')))
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
- this.setEdmAttribute(facetName, csn['@odata.'+facetName]);
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
- let schemaName = options.whatsMySchemaName(this._edmAttributes[typeName]);
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['$'+this._typeName] = this._type;
748
+ if (this._type !== 'Edm.String' && this._type) // Edm.String is default)
749
+ json[`$${this._typeName}`] = this._type;
750
750
 
751
- this._edmAttributes && Object.entries(this._edmAttributes).forEach(([p, v]) => {
752
- if (p !== 'Name' && p !== this._typeName
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
- && !(p === 'Nullable' && !v))
755
- {
756
- json[p[0] === '@' ? p : '$' + p] = v;
757
- }
758
- });
755
+ !(p === 'Nullable' && !v))
756
+ json[p[0] === '@' ? p : `$${p}`] = v;
757
+ });
758
+ }
759
759
 
760
- if(this._isCollection)
761
- json['$Collection'] = this._isCollection;
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(v, details, csn) {
770
- super(v, details, csn);
771
- if(this.v4 && !!csn['@open']) {
772
- this._edmAttributes['OpenType'] = true;
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
- constructor(v, details, properties, csn)
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)+ '__' +alias.substr(alias.length-13, alias.length);
804
- }
805
- alias = alias+'_'+c.toString().padStart(3, '0');
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)+ '__' +alias.substr(alias.length-15, alias.length);
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(v, csn.$edmKeyPaths);
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) + '\n';
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
- this._jsonOnlyAttributes && Object.entries(this._jsonOnlyAttributes).forEach(([p, v]) => {
839
- json[p[0] === '@' ? p : '$' + p] = v;
840
- });
841
- if(this._keys)
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
- constructor(v, attributes, csn)
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
- constructor(v, attributes, csn)
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['$UnderlyingType'] = this._type;
859
+ json.$UnderlyingType = this._type;
872
860
  return json;
873
861
  }
874
862
  }
875
863
 
876
- class EnumType extends TypeDefinition
877
- {
878
- constructor(v, attributes, csn)
879
- {
880
- super(v, attributes, csn);
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) ||*/ csn.enum;
884
- enumValues && Object.entries(enumValues).forEach(([en, e]) => {
885
- this.append(new Member(v, { Name: en, Value: e.val } ));
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 Member extends Node
903
- {
904
- toJSONattributes(json)
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
- && (typecsn.type !== 'cds.DateTime' && typecsn.type !== 'cds.Timestamp'))
926
- this.setXml( { 'sap:display-format' : 'Date' } );
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
- let nodeCsn = csn || this._csn;
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
- json['$Nullable'] = true;
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
- constructor(v, csn)
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
- constructor(v, attributes, csn)
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'] == true || csn['@cds.etag'] == true)
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( { ['sap:' + p.slice(5).replace(/\./g, '-')] : v });
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
- if(this.v4)
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 PropertyRef extends Node
1052
- {
1053
- constructor(v, Name, Alias) {
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
- let json = Object.create(null);
1082
- json['$Name'] = this._edmAttributes.Name;
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 NavigationProperty extends Property
1090
- {
1091
- constructor(v, attributes, csn)
1092
- {
1093
- super(v, attributes, csn);
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
- let [src, tgt] = edmUtils.determineMultiplicity(csn._constraints._partnerCsn || csn);
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
- let partner =
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(options.pathDelimiter);
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'] == true || csn.containsTarget) {
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(v, { Action: 'Cascade' } ) );
1110
+ this.append(new OnDelete(version, { Action: 'Cascade' } ) );
1144
1111
  }
1145
-
1146
1112
  }
1147
1113
 
1148
1114
  if (this.v2 && this.isNotNullable()) {
1149
- // in V2 not null must be expressed with target cardinality of 1 or more,
1150
- // store Nullable=false and evaluate in determineMultiplicity()
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
- let nodeCsn = csn || this._csn;
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['$Type'] = this._type;
1154
+ json.$Type = this._type;
1190
1155
 
1191
1156
  // attribute Nullable is not allowed in combination with Collection (see Spec)
1192
- if(json['$Collection'])
1193
- delete json['$Nullable'];
1157
+ if (json.$Collection)
1158
+ delete json.$Nullable;
1194
1159
  return json;
1195
1160
  }
1196
1161
 
1197
- toJSONchildren(json)
1198
- {
1199
- let json_constraints = Object.create(null);
1200
- this._children.forEach(c => {
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
- json_constraints[c._edmAttributes.Property] = c._edmAttributes.ReferencedProperty;
1168
+ jsonConstraints[c._edmAttributes.Property] = c._edmAttributes.ReferencedProperty;
1205
1169
  break;
1206
1170
  case 'OnDelete':
1207
- json['$OnDelete'] = c._edmAttributes.Action;
1171
+ json.$OnDelete = c._edmAttributes.Action;
1208
1172
  break;
1209
1173
  default:
1210
- error(null, 'Please debug me: Unhandled NavProp child: ' + c.kind);
1211
-
1174
+ error(null, `Please debug me: Unhandled NavProp child: ${c.kind}`);
1212
1175
  }
1213
1176
  });
1214
1177
  // TODO Annotations
1215
- if(Object.keys(json_constraints).length > 0)
1216
- json['$ReferentialConstraint'] = json_constraints;
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._constraints;
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
- _constraints.constraints && Object.values(_constraints.constraints).forEach(c =>
1231
- this.append(new ReferentialConstraint(this._v,
1232
- { Property: c[i].join(options.pathDelimiter), ReferencedProperty: c[j].join(options.pathDelimiter) } ) )
1233
- );
1234
- }
1235
- }
1236
-
1237
- class ReferentialConstraint extends Node
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
- let v = dict[inline[0]];
1295
- switch(inline[0])
1296
- {
1297
- /* short notation for Edm.Boolean, Edm.String and Edm.Float, see internal project:
1298
- edmx2csn-npm/edm-converters/blob/835d92a1aa6b0be25c56cef85e260c9188187429/lib/edmxV40ToJsonV40/README.md
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
- Object.create(null));
1259
+ return o;
1260
+ },
1261
+ Object.create(null));
1326
1262
  }
1327
1263
  }
1328
1264
 
1329
- class Annotations extends AnnotationBase
1330
- {
1331
- constructor(v, target)
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 : '$' + p] = v;
1274
+ json[p[0] === '@' ? p : `$${p}`] = v;
1342
1275
  });
1343
1276
  return json;
1344
1277
  }
1345
1278
 
1346
- toJSONchildren(json)
1347
- {
1348
- this._children.forEach(a => {
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
- constructor(v, termName)
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 '@' + this._edmAttributes.Term + (this._edmAttributes.Qualifier ? '#' + this._edmAttributes.Qualifier : '');
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
- toJSONattributes(json)
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
- let keys = Object.keys(this._edmAttributes).filter(k => k !== 'Type');
1408
- for(const key of keys)
1409
- json['$'+key] = this._edmAttributes[key];
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
- this._children.forEach(c => {
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, 'Pease debug me: Unhandled Record child: ' + c.kind);
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
- constructor(v, property)
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
- const c = this._children.filter(c => c.kind !== 'Annotation')
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
- else
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
- constructor(v, kind, details)
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() { return this._kind; }
1386
+ get kind() {
1387
+ return this._kind;
1388
+ }
1471
1389
  }
1472
1390
 
1473
- class ValueThing extends Thing
1474
- {
1475
- constructor(v, kind, value)
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 kind = this.kind;
1484
- let xml = indent + '<' + kind + this.toXMLattributes();
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
- else
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
- constructor(v, kind, details) {
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['$'+this.kind] = e[0].toJSON();
1512
- }
1513
- else {
1514
- json['$'+this.kind] = e.map(c => c.toJSON());
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['$'+this.kind] = null;
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['$'+this.kind] = this._children.filter(c=>c.kind !== 'Annotation').map(c => c.toJSON());
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['Collection'])
1542
- return ` Type="Collection(${this._edmAttributes.Type})"`
1543
- else
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 c = this._children.filter(c=>c.kind !== 'Annotation');
1550
- json['$'+this.kind] = c.length ? c[0].toJSON() : {};
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
- this._jsonOnlyAttributes && Object.entries(this._jsonOnlyAttributes).forEach(([p, v]) => {
1557
- json[p[0] === '@' ? p : '$' + p] = v;
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['$'+this.kind] = this._children.filter(c=>c.kind !== 'Annotation').map(c => c.toJSON());
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 c = this._children.filter(c=>c.kind !== 'Annotation');
1576
- json['$'+this.kind] = c.length ? c[0].toJSON() : '';
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 : '$' + p] = v;
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(v, val) {
1592
- super(v, 'LabeledElementReference', val);
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 c = this._children.filter(c=>c.kind !== 'Annotation');
1600
- json['$'+this.kind] = c.length ? c[0].toJSON() : {};
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
- constructor(v, details, navProp, fromRole, toRole, multiplicity)
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(v, { Role: fromRole[0], Type: fromRole[1], Multiplicity: multiplicity[0] } ),
1614
- new End(v, { Role: toRole[0], Type: toRole[1], Multiplicity: multiplicity[1] } )
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(v, { Action: 'Cascade' }));
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(v, { Action: 'Cascade' }));
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 => xml += e.toXML(indent) + '\n');
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
- constructor(v, details, fromRole, toRole, fromEntitySet, toEntitySet)
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
- new End(v, { Role: fromRole, EntitySet: fromEntitySet } ),
1642
- new End(v, { Role: toRole, EntitySet: toEntitySet } )
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
- function(v, from, to, c)
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
- c && Object.values(c).forEach(cv => {
1661
- node._d.append(new PropertyRef(v, cv[0].join(options.pathDelimiter)));
1662
- node._p.append(new PropertyRef(v, cv[1].join(options.pathDelimiter)));
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 = { EdmTypeFacetMap, EdmTypeFacetNames, EdmPrimitiveTypeMap, getEdm };
1629
+ module.exports = {
1630
+ EdmTypeFacetMap, EdmTypeFacetNames, EdmPrimitiveTypeMap, getEdm,
1631
+ };