@sap/cds-compiler 4.0.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 (101) hide show
  1. package/CHANGELOG.md +200 -5
  2. package/bin/cdsc.js +18 -15
  3. package/doc/CHANGELOG_BETA.md +16 -0
  4. package/doc/CHANGELOG_DEPRECATED.md +15 -0
  5. package/lib/api/main.js +33 -13
  6. package/lib/api/options.js +2 -2
  7. package/lib/api/validate.js +25 -25
  8. package/lib/base/location.js +6 -7
  9. package/lib/base/message-registry.js +123 -42
  10. package/lib/base/messages.js +18 -10
  11. package/lib/base/model.js +43 -10
  12. package/lib/checks/defaultValues.js +6 -6
  13. package/lib/checks/elements.js +11 -10
  14. package/lib/checks/foreignKeys.js +0 -5
  15. package/lib/checks/manyNavigations.js +33 -0
  16. package/lib/checks/onConditions.js +22 -14
  17. package/lib/checks/queryNoDbArtifacts.js +132 -73
  18. package/lib/checks/selectItems.js +4 -55
  19. package/lib/checks/sql-snippets.js +15 -4
  20. package/lib/checks/types.js +3 -3
  21. package/lib/checks/utils.js +4 -3
  22. package/lib/checks/validator.js +3 -1
  23. package/lib/compiler/.eslintrc.json +2 -1
  24. package/lib/compiler/assert-consistency.js +71 -40
  25. package/lib/compiler/base.js +7 -2
  26. package/lib/compiler/builtins.js +40 -41
  27. package/lib/compiler/checks.js +415 -367
  28. package/lib/compiler/classes.js +62 -0
  29. package/lib/compiler/cycle-detector.js +9 -9
  30. package/lib/compiler/define.js +124 -90
  31. package/lib/compiler/extend.js +115 -88
  32. package/lib/compiler/finalize-parse-cdl.js +26 -25
  33. package/lib/compiler/generate.js +57 -49
  34. package/lib/compiler/index.js +56 -56
  35. package/lib/compiler/kick-start.js +10 -7
  36. package/lib/compiler/moduleLayers.js +1 -1
  37. package/lib/compiler/populate.js +180 -144
  38. package/lib/compiler/propagator.js +10 -9
  39. package/lib/compiler/resolve.js +321 -246
  40. package/lib/compiler/shared.js +812 -433
  41. package/lib/compiler/tweak-assocs.js +114 -50
  42. package/lib/compiler/utils.js +241 -46
  43. package/lib/edm/.eslintrc.json +40 -1
  44. package/lib/edm/annotations/genericTranslation.js +721 -707
  45. package/lib/edm/annotations/preprocessAnnotations.js +88 -77
  46. package/lib/edm/csn2edm.js +389 -378
  47. package/lib/edm/edm.js +679 -770
  48. package/lib/edm/edmAnnoPreprocessor.js +132 -146
  49. package/lib/edm/edmInboundChecks.js +29 -27
  50. package/lib/edm/edmPreprocessor.js +689 -648
  51. package/lib/edm/edmUtils.js +279 -300
  52. package/lib/gen/Dictionary.json +34 -10
  53. package/lib/gen/language.checksum +1 -1
  54. package/lib/gen/language.interp +1 -1
  55. package/lib/gen/languageParser.js +2857 -2856
  56. package/lib/json/from-csn.js +77 -51
  57. package/lib/json/to-csn.js +15 -15
  58. package/lib/language/antlrParser.js +2 -1
  59. package/lib/language/genericAntlrParser.js +52 -43
  60. package/lib/language/language.g4 +61 -64
  61. package/lib/language/multiLineStringParser.js +2 -0
  62. package/lib/main.d.ts +65 -0
  63. package/lib/model/csnRefs.js +37 -19
  64. package/lib/model/csnUtils.js +51 -18
  65. package/lib/model/revealInternalProperties.js +30 -22
  66. package/lib/modelCompare/compare.js +149 -41
  67. package/lib/modelCompare/utils/filter.js +55 -25
  68. package/lib/optionProcessor.js +21 -9
  69. package/lib/render/manageConstraints.js +20 -17
  70. package/lib/render/toCdl.js +63 -23
  71. package/lib/render/toHdbcds.js +2 -2
  72. package/lib/render/toRename.js +4 -9
  73. package/lib/render/toSql.js +82 -35
  74. package/lib/render/utils/common.js +11 -9
  75. package/lib/render/utils/unique.js +52 -0
  76. package/lib/transform/db/applyTransformations.js +62 -21
  77. package/lib/transform/db/assertUnique.js +7 -8
  78. package/lib/transform/db/associations.js +2 -2
  79. package/lib/transform/db/cdsPersistence.js +9 -9
  80. package/lib/transform/db/constraints.js +47 -17
  81. package/lib/transform/db/expansion.js +138 -68
  82. package/lib/transform/db/flattening.js +98 -30
  83. package/lib/transform/db/rewriteCalculatedElements.js +20 -14
  84. package/lib/transform/db/temporal.js +1 -1
  85. package/lib/transform/db/transformExists.js +8 -7
  86. package/lib/transform/db/views.js +73 -33
  87. package/lib/transform/draft/db.js +11 -9
  88. package/lib/transform/draft/odata.js +1 -1
  89. package/lib/transform/{forOdataNew.js → forOdata.js} +10 -7
  90. package/lib/transform/forRelationalDB.js +148 -136
  91. package/lib/transform/localized.js +92 -54
  92. package/lib/transform/odata/toFinalBaseType.js +3 -3
  93. package/lib/transform/{transformUtilsNew.js → transformUtils.js} +13 -111
  94. package/lib/transform/translateAssocsToJoins.js +14 -28
  95. package/lib/utils/file.js +7 -7
  96. package/lib/utils/moduleResolve.js +210 -121
  97. package/lib/utils/objectUtils.js +1 -1
  98. package/package.json +5 -5
  99. package/share/messages/check-proper-type-of.md +1 -1
  100. package/share/messages/{check-proper-type.md → def-missing-type.md} +3 -5
  101. package/share/messages/message-explanations.json +1 -1
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,98 +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
- {
1223
- let _constraints = this._csn._constraints;
1224
- if(this._csn._constraints._partnerCsn) {
1184
+ addReferentialConstraintNodes() {
1185
+ // flip the constrains if this is a $self partner
1186
+ let { _constraints } = this._csn;
1187
+ let [ i, j ] = [ 0, 1 ];
1188
+ if (this._csn._constraints._partnerCsn) {
1225
1189
  _constraints = this._csn._constraints._partnerCsn._constraints;
1190
+ [ i, j ] = [ 1, 0 ];
1226
1191
  }
1227
- _constraints.constraints && Object.values(_constraints.constraints).forEach(c =>
1228
- this.append(new ReferentialConstraint(this._v,
1229
- { Property: c[0].join(options.pathDelimiter), ReferencedProperty: c[1].join(options.pathDelimiter) } ) )
1230
- );
1231
- }
1232
- }
1233
-
1234
- class ReferentialConstraint extends Node
1235
- {
1236
- constructor(v, attributes, csn) {
1237
- super(v, attributes, csn);
1238
- this._d = null;
1239
- this._p = null;
1240
- }
1241
-
1242
- innerXML(indent)
1243
- {
1244
- if(this._d && this._p)
1245
- {
1246
- 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
+ ));
1247
1201
  }
1248
- else
1249
- return super.innerXML(indent);
1250
1202
  }
1251
1203
  }
1252
1204
 
1253
- class OnDelete extends Node {}
1254
-
1255
1205
  // Annotations below
1256
- class AnnotationBase extends Node
1257
- {
1206
+ class AnnotationBase extends Node {
1258
1207
  // No Kind: AnnotationBase is base class for Thing and ValueThing with dynamic kinds,
1259
1208
  // this requires an explicit constructor as the kinds cannot be blacklisted in
1260
1209
  // Node.toJSON()
1261
- toJSON()
1262
- {
1263
- let json = Object.create(null);
1210
+ toJSON() {
1211
+ const json = Object.create(null);
1264
1212
  this.toJSONattributes(json);
1265
1213
  this.toJSONchildren(json);
1266
- return json
1214
+ return json;
1267
1215
  }
1268
1216
 
1269
- getConstantExpressionValue()
1270
- {
1217
+ getConstantExpressionValue() {
1271
1218
  // short form: key: value
1272
- const inlineConstExpr =
1273
- [ 'Edm.Binary', 'Edm.Boolean', 'Edm.Byte', 'Edm.Date', 'Edm.DateTimeOffset', 'Edm.Decimal', 'Edm.Double', 'Edm.Duration', 'Edm.Guid',
1274
- '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',
1275
1222
  // Edm.Geo* according to https://issues.oasis-open.org/browse/ODATA-1323
1276
- /* 'Edm.Geography', 'Edm.GeographyPoint', 'Edm.GeographyLineString', 'Edm.GeographyPolygon', 'Edm.GeographyMultiPoint',
1223
+ /* 'Edm.Geography', 'Edm.GeographyPoint', 'Edm.GeographyLineString', 'Edm.GeographyPolygon', 'Edm.GeographyMultiPoint',
1277
1224
  'Edm.GeographyMultiLineString', 'Edm.GeographyMultiPolygon', 'Edm.GeographyCollection', 'Edm.Geometry', 'Edm.GeometryPoint',
1278
1225
  'Edm.GeometryLineString', 'Edm.GeometryPolygon', 'Edm.GeometryMultiPoint', 'Edm.GeometryMultiLineString', 'Edm.GeometryMultiPolygon',
1279
1226
  'Edm.GeometryCollection',
@@ -1281,72 +1228,60 @@ function getEdm(options, messageFunctions) {
1281
1228
  /* UI.xml: defines Annotations with generic type 'Edm.PrimitiveType' */
1282
1229
  'Edm.PrimitiveType', 'Edm.Untyped', 'Bool',
1283
1230
  // Official JSON V4.01 Spec defines these paths as constant inline expression:
1284
- 'AnnotationPath', 'ModelElementPath', 'NavigationPropertyPath', 'PropertyPath',
1285
- ];
1231
+ 'AnnotationPath', 'ModelElementPath', 'NavigationPropertyPath', 'PropertyPath' ];
1286
1232
 
1287
1233
  const dict = this._jsonOnlyAttributes;
1288
1234
  const inline = edmUtils.intersect(Object.keys(dict), inlineConstExpr);
1289
- if(inline.length === 1)
1290
- {
1291
- let v = dict[inline[0]];
1292
- switch(inline[0])
1293
- {
1294
- /* short notation for Edm.Boolean, Edm.String and Edm.Float, see internal project:
1295
- edmx2csn-npm/edm-converters/blob/835d92a1aa6b0be25c56cef85e260c9188187429/lib/edmxV40ToJsonV40/README.md
1296
- */
1297
- case 'Edm.Boolean':
1298
- v = (v=='true'?true:(v=='false'?false:v));
1299
- // eslint-no-fallthrough
1300
- default:
1301
- return v;
1302
- }
1303
- }
1304
- else
1305
- {
1306
- // if this is not a constant expression shortcut, render key/value pair verbatim
1307
- // without filtering non-spec-compliant constExpr
1308
- let json = Object.create(null);
1309
- Object.entries(dict).forEach(([k,v]) => {
1310
- json['$'+k] = v;
1311
- });
1312
- 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;
1313
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;
1314
1252
  }
1315
1253
 
1316
- mergeJSONAnnotations(prefix='') {
1254
+ mergeJSONAnnotations(prefix = '') {
1317
1255
  return this._children.filter(c => c.kind === 'Annotation').reduce((o, a) => {
1318
- Object.entries(a.toJSON()).forEach(([n, v]) => {
1319
- o[prefix+n] = v;
1256
+ Object.entries(a.toJSON()).forEach(([ n, v ]) => {
1257
+ o[prefix + n] = v;
1320
1258
  });
1321
- return o; },
1322
- Object.create(null));
1259
+ return o;
1260
+ },
1261
+ Object.create(null));
1323
1262
  }
1324
1263
  }
1325
1264
 
1326
- class Annotations extends AnnotationBase
1327
- {
1328
- constructor(v, target)
1329
- {
1330
- super(v, { Target: target });
1331
- 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 } );
1332
1269
  }
1333
1270
 
1334
- toJSONattributes(json)
1335
- {
1271
+ toJSONattributes(json) {
1336
1272
  forEach(this._edmAttributes, (p, v) => {
1337
1273
  if (p !== 'Target')
1338
- json[p[0] === '@' ? p : '$' + p] = v;
1274
+ json[p[0] === '@' ? p : `$${p}`] = v;
1339
1275
  });
1340
1276
  return json;
1341
1277
  }
1342
1278
 
1343
- toJSONchildren(json)
1344
- {
1345
- this._children.forEach(a => {
1346
- Object.entries(a.toJSON()).forEach(([n, v]) => {
1279
+ toJSONchildren(json) {
1280
+ this._children.forEach((a) => {
1281
+ Object.entries(a.toJSON()).forEach(([ n, v ]) => {
1347
1282
  json[n] = v;
1348
1283
  });
1349
- })
1284
+ });
1350
1285
  }
1351
1286
  }
1352
1287
 
@@ -1362,18 +1297,15 @@ function getEdm(options, messageFunctions) {
1362
1297
  // the constant expression value is the same for both XML and JSON. But
1363
1298
  // since it was discovered, that in JSON the EnumMember type must be
1364
1299
  // transported this is no longer the case....
1365
- class Annotation extends AnnotationBase
1366
- {
1367
- constructor(v, termName)
1368
- {
1369
- super(v, { Term: termName } );
1300
+ class Annotation extends AnnotationBase {
1301
+ constructor(version, termName) {
1302
+ super(version, { Term: termName } );
1370
1303
  }
1371
1304
 
1372
- toJSON()
1373
- {
1305
+ toJSON() {
1374
1306
  const json = super.mergeJSONAnnotations(this.getJsonFQTermName());
1375
1307
  const e = this._children.filter(c => c.kind !== 'Annotation');
1376
- if(e.length === 0 || this._ignoreChildren) // must be a constant expression
1308
+ if (e.length === 0 || this._ignoreChildren) // must be a constant expression
1377
1309
  json[this.getJsonFQTermName()] = this.getConstantExpressionValue();
1378
1310
  else
1379
1311
  // annotation must have exactly one child (=record or collection)
@@ -1382,44 +1314,38 @@ function getEdm(options, messageFunctions) {
1382
1314
  }
1383
1315
 
1384
1316
  getJsonFQTermName() {
1385
- return '@' + this._edmAttributes.Term + (this._edmAttributes.Qualifier ? '#' + this._edmAttributes.Qualifier : '');
1317
+ return `@${this._edmAttributes.Term}${this._edmAttributes.Qualifier ? `#${this._edmAttributes.Qualifier}` : ''}`;
1386
1318
  }
1387
1319
  }
1388
1320
 
1389
- class Collection extends AnnotationBase
1390
- {
1391
- toJSON()
1392
- {
1321
+ class Collection extends AnnotationBase {
1322
+ toJSON() {
1393
1323
  // EDM JSON doesn't mention annotations on collections
1394
1324
  return this._children.map(a => a.toJSON());
1395
1325
  }
1396
1326
  }
1397
1327
 
1398
- class Record extends AnnotationBase
1399
- {
1400
- toJSONattributes(json)
1401
- {
1402
- if(this._jsonOnlyAttributes.Type)
1328
+ class Record extends AnnotationBase {
1329
+ toJSONattributes(json) {
1330
+ if (this._jsonOnlyAttributes.Type)
1403
1331
  json['@type'] = this._jsonOnlyAttributes.Type;
1404
- let keys = Object.keys(this._edmAttributes).filter(k => k !== 'Type');
1405
- for(const key of keys)
1406
- 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];
1407
1335
  }
1408
1336
 
1409
- toJSONchildren(json)
1410
- {
1411
- this._children.forEach(c => {
1412
- switch(c.kind)
1413
- {
1337
+ toJSONchildren(json) {
1338
+ this._children.forEach((c) => {
1339
+ switch (c.kind) {
1414
1340
  case 'Annotation': {
1415
- Object.entries(c.toJSON()).forEach(([n, v]) => {
1341
+ Object.entries(c.toJSON()).forEach(([ n, v ]) => {
1416
1342
  json[n] = v;
1417
1343
  });
1418
1344
  break;
1419
1345
  }
1420
1346
  case 'PropertyValue': {
1421
1347
  // plus property annotations as [a.Property]@anno: val
1422
- Object.entries(c.mergeJSONannotations()).forEach(([n, a]) => {
1348
+ Object.entries(c.mergeJSONannotations()).forEach(([ n, a ]) => {
1423
1349
  json[n] = a;
1424
1350
  });
1425
1351
  // render property as const expr (or subnode)
@@ -1427,89 +1353,73 @@ function getEdm(options, messageFunctions) {
1427
1353
  break;
1428
1354
  }
1429
1355
  default:
1430
- error(null, 'Pease debug me: Unhandled Record child: ' + c.kind);
1356
+ error(null, `Pease debug me: Unhandled Record child: ${c.kind}`);
1431
1357
  }
1432
1358
  });
1433
1359
  }
1434
1360
  }
1435
1361
 
1436
- class PropertyValue extends AnnotationBase
1437
- {
1438
- constructor(v, property)
1439
- {
1440
- super(v);
1362
+ class PropertyValue extends AnnotationBase {
1363
+ constructor(version, property) {
1364
+ super(version);
1441
1365
  this._edmAttributes.Property = property;
1442
1366
  }
1443
1367
 
1444
- toJSON()
1445
- {
1446
- const c = this._children.filter(c => c.kind !== 'Annotation')
1447
- 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)
1448
1371
  return this.getConstantExpressionValue();
1449
- else
1450
- {
1451
- return c[0].toJSON();
1452
- }
1372
+
1373
+ return children[0].toJSON();
1453
1374
  }
1454
1375
  mergeJSONannotations() {
1455
1376
  return super.mergeJSONAnnotations(this._edmAttributes.Property);
1456
1377
  }
1457
1378
  }
1458
1379
 
1459
- class Thing extends AnnotationBase
1460
- {
1461
- constructor(v, kind, details)
1462
- {
1463
- super(v, details);
1380
+ class Thing extends AnnotationBase {
1381
+ constructor(version, kind, details) {
1382
+ super(version, details);
1464
1383
  this._kind = kind;
1465
1384
  }
1466
1385
 
1467
- get kind() { return this._kind; }
1386
+ get kind() {
1387
+ return this._kind;
1388
+ }
1468
1389
  }
1469
1390
 
1470
- class ValueThing extends Thing
1471
- {
1472
- constructor(v, kind, value)
1473
- {
1474
- super(v, kind, undefined);
1391
+ class ValueThing extends Thing {
1392
+ constructor(version, kind, value) {
1393
+ super(version, kind, undefined);
1475
1394
  this._value = value;
1476
1395
  }
1477
1396
 
1478
- toXML(indent='')
1479
- {
1480
- let kind = this.kind;
1481
- let xml = indent + '<' + kind + this.toXMLattributes();
1482
- 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}>` : '/>');
1483
1401
  return xml;
1484
1402
  }
1485
1403
 
1486
- toJSON()
1487
- {
1488
- 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
1489
1406
  return this.getConstantExpressionValue();
1490
- else
1491
- // annotation must have exactly one child (=record or collection)
1492
- return this._children[0].toJSON();
1407
+ return this._children[0].toJSON();
1493
1408
  }
1494
1409
  }
1495
1410
 
1496
1411
  // Binary/Unary dynamic expression
1497
1412
  class Expr extends Thing {
1498
- constructor(v, kind, details) {
1499
- super(v, kind, details);
1500
- }
1501
-
1502
- toJSON()
1503
- {
1413
+ toJSON() {
1504
1414
  // toJSON: depending on number of children unary or n-ary expr
1505
1415
  const json = this.mergeJSONAnnotations();
1506
- const e = this._children.filter(c=>c.kind !== 'Annotation');
1507
- if(e.length === 1) {
1508
- json['$'+this.kind] = e[0].toJSON();
1509
- }
1510
- else {
1511
- json['$'+this.kind] = e.map(c => c.toJSON());
1512
- }
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
+
1513
1423
  return json;
1514
1424
  }
1515
1425
  }
@@ -1520,14 +1430,14 @@ function getEdm(options, messageFunctions) {
1520
1430
  }
1521
1431
  toJSON() {
1522
1432
  const json = this.mergeJSONAnnotations();
1523
- json['$'+this.kind] = null;
1433
+ json[`$${this.kind}`] = null;
1524
1434
  return json;
1525
1435
  }
1526
1436
  }
1527
1437
  class Apply extends AnnotationBase {
1528
1438
  toJSON() {
1529
1439
  const json = this.mergeJSONAnnotations();
1530
- 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());
1531
1441
  this.toJSONattributes(json);
1532
1442
  return json;
1533
1443
  }
@@ -1535,24 +1445,25 @@ function getEdm(options, messageFunctions) {
1535
1445
  class Cast extends AnnotationBase {
1536
1446
  toXMLattributes() {
1537
1447
  // TODO: Why json?
1538
- if(this._jsonOnlyAttributes['Collection'])
1539
- return ` Type="Collection(${this._edmAttributes.Type})"`
1540
- else
1541
- return ` Type="${this._edmAttributes.Type}"`
1448
+ if (this._jsonOnlyAttributes.Collection)
1449
+ return ` Type="Collection(${this._edmAttributes.Type})"`;
1450
+ return ` Type="${this._edmAttributes.Type}"`;
1542
1451
  }
1543
1452
  toJSON() {
1544
1453
  const json = this.mergeJSONAnnotations();
1545
1454
  // first expression only, if any
1546
- const c = this._children.filter(c=>c.kind !== 'Annotation');
1547
- 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() : {};
1548
1457
  this.toJSONattributes(json);
1549
1458
  return json;
1550
1459
  }
1551
1460
  toJSONattributes(json) {
1552
1461
  super.toJSONattributes(json);
1553
- this._jsonOnlyAttributes && Object.entries(this._jsonOnlyAttributes).forEach(([p, v]) => {
1554
- json[p[0] === '@' ? p : '$' + p] = v;
1555
- });
1462
+ if (this._jsonOnlyAttributes) {
1463
+ Object.entries(this._jsonOnlyAttributes).forEach(([ p, v ]) => {
1464
+ json[p[0] === '@' ? p : `$${p}`] = v;
1465
+ });
1466
+ }
1556
1467
  return json;
1557
1468
  }
1558
1469
  }
@@ -1561,7 +1472,7 @@ function getEdm(options, messageFunctions) {
1561
1472
  class If extends AnnotationBase {
1562
1473
  toJSON() {
1563
1474
  const json = this.mergeJSONAnnotations();
1564
- 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());
1565
1476
  return json;
1566
1477
  }
1567
1478
  }
@@ -1569,97 +1480,94 @@ function getEdm(options, messageFunctions) {
1569
1480
  toJSON() {
1570
1481
  const json = this.mergeJSONAnnotations();
1571
1482
  // first expression only, if any
1572
- const c = this._children.filter(c=>c.kind !== 'Annotation');
1573
- 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() : '';
1574
1485
  this.toJSONattributes(json);
1575
1486
  return json;
1576
1487
  }
1577
1488
 
1578
- toJSONattributes(json) // including Name
1579
- {
1489
+ toJSONattributes(json) { // including Name
1580
1490
  forEach(this._edmAttributes, (p, v) => {
1581
- json[p[0] === '@' ? p : '$' + p] = v;
1491
+ json[p[0] === '@' ? p : `$${p}`] = v;
1582
1492
  });
1583
1493
  return json;
1584
1494
  }
1585
1495
  }
1586
1496
  // LabeledElementReference is a
1587
1497
  class LabeledElementReference extends ValueThing {
1588
- constructor(v, val) {
1589
- super(v, 'LabeledElementReference', val);
1498
+ constructor(version, val) {
1499
+ super(version, 'LabeledElementReference', val);
1590
1500
  }
1591
1501
  }
1592
1502
  class UrlRef extends AnnotationBase {
1593
1503
  toJSON() {
1594
1504
  const json = this.mergeJSONAnnotations();
1595
1505
  // first expression only, if any
1596
- const c = this._children.filter(c=>c.kind !== 'Annotation');
1597
- 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() : {};
1598
1508
  return json;
1599
1509
  }
1600
1510
  }
1601
1511
 
1602
1512
  // V2 specials
1603
1513
  class End extends Node {}
1604
- class Association extends Node
1605
- {
1606
- constructor(v, details, navProp, fromRole, toRole, multiplicity)
1607
- {
1608
- super(v, details);
1514
+ class Association extends Node {
1515
+ constructor(version, details, navProp, fromRole, toRole, multiplicity) {
1516
+ super(version, details);
1609
1517
  this._end = [
1610
- new End(v, { Role: fromRole[0], Type: fromRole[1], Multiplicity: multiplicity[0] } ),
1611
- 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] } ),
1612
1520
  ];
1613
1521
 
1614
1522
  // set Delete:Cascade on composition end
1615
- if(navProp._csn.type === 'cds.Composition')
1616
- 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' }));
1617
1525
 
1618
- if(navProp._csn._selfReferences && navProp._csn._selfReferences.length &&
1526
+ if (navProp._csn._selfReferences && navProp._csn._selfReferences.length &&
1619
1527
  navProp._csn._selfReferences[0].type === 'cds.Composition')
1620
- this._end[1].append(new OnDelete(v, { Action: 'Cascade' }));
1528
+ this._end[1].append(new OnDelete(version, { Action: 'Cascade' }));
1621
1529
  }
1622
1530
 
1623
- innerXML(indent)
1624
- {
1531
+ innerXML(indent) {
1625
1532
  let xml = '';
1626
- this._end.forEach(e => xml += e.toXML(indent) + '\n');
1533
+ this._end.forEach((e) => {
1534
+ xml += `${e.toXML(indent)}\n`;
1535
+ });
1627
1536
  xml += super.innerXML(indent);
1628
1537
  return xml;
1629
1538
  }
1630
1539
  }
1631
1540
 
1632
- class AssociationSet extends Node
1633
- {
1634
- constructor(v, details, fromRole, toRole, fromEntitySet, toEntitySet)
1635
- {
1636
- super(v, details);
1541
+ class AssociationSet extends Node {
1542
+ constructor(version, details, fromRole, toRole, fromEntitySet, toEntitySet) {
1543
+ super(version, details);
1637
1544
  this.append(
1638
- new End(v, { Role: fromRole, EntitySet: fromEntitySet } ),
1639
- new End(v, { Role: toRole, EntitySet: toEntitySet } )
1640
- );
1545
+ new End(version, { Role: fromRole, EntitySet: fromEntitySet } ),
1546
+ new End(version, { Role: toRole, EntitySet: toEntitySet } )
1547
+ );
1641
1548
  }
1642
1549
  getDuplicateMessage() {
1643
- return `Association "${this._edmAttributes.Association}"`
1550
+ return `Association "${this._edmAttributes.Association}"`;
1644
1551
  }
1645
- }
1552
+ }
1646
1553
 
1647
1554
  class Dependent extends Node {}
1648
1555
  class Principal extends Node {}
1649
1556
 
1650
- ReferentialConstraint.createV2 =
1651
- function(v, from, to, c)
1652
- {
1653
- let node = new ReferentialConstraint(v, {});
1557
+ ReferentialConstraint.createV2
1558
+ = (v, from, to, c) => {
1559
+ const node = new ReferentialConstraint(v, {});
1654
1560
  node._d = new Dependent(v, { Role: from } );
1655
1561
  node._p = new Principal(v, { Role: to } );
1656
1562
 
1657
- c && Object.values(c).forEach(cv => {
1658
- node._d.append(new PropertyRef(v, cv[0].join(options.pathDelimiter)));
1659
- node._p.append(new PropertyRef(v, cv[1].join(options.pathDelimiter)));
1660
- });
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
+ }
1661
1569
  return node;
1662
- }
1570
+ };
1663
1571
 
1664
1572
  return {
1665
1573
  Edm,
@@ -1677,7 +1585,7 @@ function getEdm(options, messageFunctions) {
1677
1585
  ComplexType,
1678
1586
  EntityType,
1679
1587
  Key,
1680
- //ActionFunctionBase,
1588
+ // ActionFunctionBase,
1681
1589
  FunctionDefinition,
1682
1590
  Action,
1683
1591
  FunctionImport,
@@ -1714,9 +1622,10 @@ function getEdm(options, messageFunctions) {
1714
1622
  Association,
1715
1623
  AssociationSet,
1716
1624
  Dependent,
1717
- Principal
1718
- }
1719
-
1625
+ Principal,
1626
+ };
1720
1627
  } // instance function
1721
1628
 
1722
- module.exports = { EdmTypeFacetMap, EdmTypeFacetNames, EdmPrimitiveTypeMap, getEdm };
1629
+ module.exports = {
1630
+ EdmTypeFacetMap, EdmTypeFacetNames, EdmPrimitiveTypeMap, getEdm,
1631
+ };