@sap/xsodata 8.3.0 → 8.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/index.js +2 -2
- package/lib/configuration.js +1 -1
- package/lib/db/connect.js +1 -1
- package/lib/db/dbSegment.js +68 -123
- package/lib/db/dbVersionChecks.js +2 -8
- package/lib/handlerConfiguration.js +2 -2
- package/lib/http/conditionalHttpHandler.js +27 -34
- package/lib/http/simpleHttpRequest.js +14 -18
- package/lib/http/simpleHttpResponse.js +4 -4
- package/lib/http/uriParser.js +9 -9
- package/lib/http/validator/httpRequestValidator.js +9 -9
- package/lib/model/annotationFactory.js +11 -11
- package/lib/model/association.js +3 -3
- package/lib/model/entityType.js +33 -67
- package/lib/model/metadataReader.js +31 -52
- package/lib/model/model.js +0 -1
- package/lib/model/validator/xsoDataConcurrencyTokenValidator.js +6 -6
- package/lib/model/xsodataReader.js +36 -28
- package/lib/processor/authorizationProcessor.js +22 -33
- package/lib/processor/batchProcessor.js +22 -33
- package/lib/processor/errorProcessor.js +4 -4
- package/lib/processor/exitProcessor.js +19 -19
- package/lib/processor/processor.js +9 -9
- package/lib/processor/resourceProcessor.js +31 -61
- package/lib/processor/resourceProcessorDelete.js +16 -16
- package/lib/processor/resourceProcessorDeleteLinks.js +25 -25
- package/lib/processor/resourceProcessorGet.js +5 -5
- package/lib/processor/resourceProcessorPost.js +43 -45
- package/lib/processor/resourceProcessorPut.js +35 -39
- package/lib/processor/resourceProcessorPutPostLinks.js +38 -39
- package/lib/security/securityContext.js +5 -5
- package/lib/serializer/atomSerializer.js +54 -55
- package/lib/serializer/atomXmlToJsonSerializer.js +32 -44
- package/lib/serializer/content.js +5 -5
- package/lib/serializer/json.js +31 -33
- package/lib/serializer/jsonSerializer.js +4 -4
- package/lib/serializer/metadataSerializer.js +32 -35
- package/lib/serializer/serializer.js +29 -43
- package/lib/serializer/serviceSerializer.js +19 -24
- package/lib/serializer/value.js +1 -2
- package/lib/serializer/xmlToJsonSerializer.js +18 -18
- package/lib/sql/createDeleteLinksStatements.js +10 -10
- package/lib/sql/createDeleteStatements.js +12 -12
- package/lib/sql/createGetStatements.js +49 -107
- package/lib/sql/createLinksSQLStatements_1_n.js +27 -27
- package/lib/sql/createPutPostLinksStatements.js +9 -9
- package/lib/sql/createPutStatements.js +0 -1
- package/lib/sql/dataCollectorDelete.js +9 -9
- package/lib/sql/dataCollectorDeleteLinks.js +3 -3
- package/lib/sql/dataCollectorGet.js +9 -17
- package/lib/sql/dataCollectorLinks.js +23 -27
- package/lib/sql/dataCollectorPost.js +20 -20
- package/lib/sql/dataCollectorPut.js +36 -36
- package/lib/sql/dataCollectorPutPostLinks.js +3 -3
- package/lib/sql/sqlStatement.js +81 -128
- package/lib/sql/sqlTools.js +3 -7
- package/lib/sql/statementProcessor.js +7 -14
- package/lib/uri/applyChecks.js +3 -3
- package/lib/uri/checks/checkAllowedMethod.js +3 -3
- package/lib/uri/checks/checkAllowedMethodForBatch.js +2 -2
- package/lib/uri/checks/checkAllowedMethodsForResourcePath.js +3 -3
- package/lib/uri/checks/checkFilterOnAggregatedColumn.js +5 -5
- package/lib/uri/checks/checkFilterOrderByOnGenKeyColumn.js +6 -6
- package/lib/uri/checks/checkGenKeyRestrictions.js +2 -2
- package/lib/uri/checks/checkModificationForbidden.js +3 -3
- package/lib/uri/checks/checkPostPutDeleteChecks.js +5 -5
- package/lib/uri/checks/checkSystemQueryOptions.js +10 -10
- package/lib/uri/checks.js +15 -15
- package/lib/uri/expandSelectTreeBuilder.js +12 -16
- package/lib/uri/oDataUriParser.js +20 -20
- package/lib/uri/queryParameterParser.js +25 -33
- package/lib/uri/resourcePathParser.js +47 -62
- package/lib/uri/uriType.js +4 -4
- package/lib/utils/associations.js +4 -4
- package/lib/utils/batch/batchExecutor.js +49 -51
- package/lib/utils/batch/batchObjects.js +10 -10
- package/lib/utils/batch/batchParser.js +27 -28
- package/lib/utils/batch/batchWriter.js +1 -1
- package/lib/utils/checkContentType.js +34 -39
- package/lib/utils/debugView.js +35 -36
- package/lib/utils/errors/applicationError.js +2 -2
- package/lib/utils/errors/debugInfo.js +2 -2
- package/lib/utils/errors/http/badRequest.js +2 -2
- package/lib/utils/errors/http/forbidden.js +2 -2
- package/lib/utils/errors/http/methodNotAllowed.js +2 -2
- package/lib/utils/errors/http/notAcceptable.js +2 -2
- package/lib/utils/errors/http/notFound.js +2 -2
- package/lib/utils/errors/http/notImplemented.js +2 -2
- package/lib/utils/errors/http/notModified.js +2 -2
- package/lib/utils/errors/http/notSupported.js +2 -2
- package/lib/utils/errors/http/preconditionFailed.js +2 -2
- package/lib/utils/errors/http/preconditionRequired.js +2 -2
- package/lib/utils/errors/http/unauthorized.js +2 -2
- package/lib/utils/errors/http/unsupportedMediaType.js +2 -2
- package/lib/utils/errors/httpError.js +2 -2
- package/lib/utils/errors/internalError.js +2 -2
- package/lib/utils/errors/modelFileError.js +2 -2
- package/lib/utils/errors/sqlError.js +2 -2
- package/lib/utils/errors/testError.js +2 -2
- package/lib/utils/errors/typeError.js +5 -5
- package/lib/utils/errors/xsODataError.js +1 -1
- package/lib/utils/logger.js +21 -32
- package/lib/utils/measurement.js +14 -13
- package/lib/utils/requestContext.js +2 -2
- package/lib/utils/stateMaschine.js +6 -6
- package/lib/utils/tableCleanup.js +3 -3
- package/lib/utils/typeConverter.js +21 -21
- package/lib/utils/typeConverters/converterTools.js +25 -331
- package/lib/utils/typeConverters/dbToJson.js +3 -3
- package/lib/utils/typeConverters/dbToUri.js +7 -7
- package/lib/utils/typeConverters/dbToXml.js +9 -9
- package/lib/utils/typeConverters/jsonToDb.js +20 -27
- package/lib/utils/typeConverters/uriToDb.js +45 -92
- package/lib/utils/typeConverters/xmlValueToJson.js +9 -13
- package/lib/utils/typedObjects.js +11 -79
- package/lib/utils/utils.js +20 -23
- package/lib/xsodata.js +37 -47
- package/package.json +3 -5
- package/.npmignore +0 -40
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Usage:
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* const xmlStringData = getXmlStringSomeHow().toString('urf-8');
|
|
12
12
|
*
|
|
13
|
-
*
|
|
13
|
+
* const atomSerializer = new AtomXmlToJsonSerializer(xmlStringData, null, {
|
|
14
14
|
* logger:logger
|
|
15
15
|
* });
|
|
16
16
|
*
|
|
@@ -21,13 +21,13 @@
|
|
|
21
21
|
*
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
const lodash = require('lodash');
|
|
25
|
+
const utils = require('./../utils/utils');
|
|
26
|
+
const XmlSerializer = require('./xmlToJsonSerializer');
|
|
27
|
+
const inherits = require('util').inherits;
|
|
28
|
+
const typeConverter = require('./../utils/typeConverter');
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
const NAMESPACES = {
|
|
31
31
|
m: "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata",
|
|
32
32
|
d: "http://schemas.microsoft.com/ado/2007/08/dataservices"
|
|
33
33
|
};
|
|
@@ -124,7 +124,7 @@ AtomXmlToJsonSerializer.prototype.toJson = AtomXmlToJsonSerializer.prototype.toO
|
|
|
124
124
|
*/
|
|
125
125
|
function normalize(context, asyncDone) {
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
const result = {
|
|
128
128
|
document: context.result.document,
|
|
129
129
|
namespaces: context.result.namespaces
|
|
130
130
|
};
|
|
@@ -144,15 +144,15 @@ function toOdataJson(typeModelContext) {
|
|
|
144
144
|
|
|
145
145
|
return function (context, asyncDone) {
|
|
146
146
|
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
const doc = context.document;
|
|
148
|
+
const ns = context.namespaces;
|
|
149
149
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
const nsMetadataPrefix = getNamespacePrefix(NAMESPACES.m, ns);
|
|
151
|
+
const nsDataservicePrefix = getNamespacePrefix(NAMESPACES.d, ns);
|
|
152
|
+
const propertiesKey = nsMetadataPrefix + ":properties";
|
|
153
153
|
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
const entries = findEntries(doc);
|
|
155
|
+
const entryProperties = findEntryProperties(entries, propertiesKey);
|
|
156
156
|
|
|
157
157
|
context.result = entryProperties
|
|
158
158
|
.map(function (item) {
|
|
@@ -182,7 +182,7 @@ function mapDataValueTypeToEdmType(key, value, typeModelContext) {
|
|
|
182
182
|
return value;
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
const modelTypeInfo = typeModelContext[key];
|
|
186
186
|
return typeConverter.serializeXmlValueToODataJsonValue(value, modelTypeInfo);
|
|
187
187
|
}
|
|
188
188
|
|
|
@@ -202,9 +202,9 @@ function mapDataValueTypeToEdmType(key, value, typeModelContext) {
|
|
|
202
202
|
*/
|
|
203
203
|
function buildOdataJson(entry, nsDataservicePrefix, nsMetadataPrefix, typeModelContext) {
|
|
204
204
|
|
|
205
|
-
|
|
205
|
+
const target = {};
|
|
206
206
|
|
|
207
|
-
|
|
207
|
+
const propertiesRegEx = new RegExp(nsMetadataPrefix + ":properties\.", "g"),
|
|
208
208
|
dataServiceRegEx = new RegExp(nsDataservicePrefix + ":", "g"),
|
|
209
209
|
childrenRegEx = new RegExp("\\$children\\.", "g"),
|
|
210
210
|
valueRegEx = new RegExp("\\.\\$value$", "g");
|
|
@@ -214,10 +214,10 @@ function buildOdataJson(entry, nsDataservicePrefix, nsMetadataPrefix, typeModelC
|
|
|
214
214
|
// keypath is an array containing the current recursive properties path
|
|
215
215
|
// i.e. key looks like --> m:properties.$children.d:EmployeeId.$value
|
|
216
216
|
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
const k = keyPath.join('.');
|
|
218
|
+
let value = obj.$value;
|
|
219
219
|
|
|
220
|
-
|
|
220
|
+
const targetKey = k
|
|
221
221
|
.replace(propertiesRegEx, "")
|
|
222
222
|
.replace(dataServiceRegEx, "")
|
|
223
223
|
.replace(childrenRegEx, "")
|
|
@@ -260,7 +260,7 @@ function buildOdataJson(entry, nsDataservicePrefix, nsMetadataPrefix, typeModelC
|
|
|
260
260
|
*/
|
|
261
261
|
function findEntryProperties(entries, propertiesKey) {
|
|
262
262
|
|
|
263
|
-
|
|
263
|
+
const properties = [];
|
|
264
264
|
|
|
265
265
|
utils.iterateObject(entries, function validation(key, obj) {
|
|
266
266
|
properties.push(obj);
|
|
@@ -359,7 +359,7 @@ function findEntries(result) {
|
|
|
359
359
|
*/
|
|
360
360
|
function getNamespacePrefix(namespaceDef, namespaces) {
|
|
361
361
|
|
|
362
|
-
|
|
362
|
+
let search = null;
|
|
363
363
|
|
|
364
364
|
lodash.forOwn(namespaces, function (value, key) {
|
|
365
365
|
if (namespaceDef === value) {
|
|
@@ -384,14 +384,14 @@ function getNamespacePrefix(namespaceDef, namespaces) {
|
|
|
384
384
|
*/
|
|
385
385
|
function validateNamespace(context, asyncDone) {
|
|
386
386
|
|
|
387
|
-
|
|
388
|
-
|
|
387
|
+
const target = context.document;
|
|
388
|
+
const namespaces = context.namespaces;
|
|
389
389
|
|
|
390
390
|
// Iterate over all object properties and corresponding
|
|
391
391
|
// object child property values properties recursive
|
|
392
392
|
utils.iterateObject(target, function validation(key /* , obj */) {
|
|
393
393
|
|
|
394
|
-
|
|
394
|
+
const isValid = isNamespacedValue(key, namespaces);
|
|
395
395
|
|
|
396
396
|
if (isValid !== true) {
|
|
397
397
|
throw new Error("No valid namespace for key \"" + key + "\" available");
|
|
@@ -434,7 +434,7 @@ function validateNamespace(context, asyncDone) {
|
|
|
434
434
|
*/
|
|
435
435
|
function isNamespacedValue(value, namespaces, nextFn) {
|
|
436
436
|
|
|
437
|
-
|
|
437
|
+
const split = value.split(":");
|
|
438
438
|
|
|
439
439
|
if (split.length !== 2) {
|
|
440
440
|
|
|
@@ -442,9 +442,9 @@ function isNamespacedValue(value, namespaces, nextFn) {
|
|
|
442
442
|
|
|
443
443
|
} else {
|
|
444
444
|
|
|
445
|
-
|
|
445
|
+
const prefix = split[0];
|
|
446
446
|
|
|
447
|
-
|
|
447
|
+
const namespace = namespaces[prefix];
|
|
448
448
|
|
|
449
449
|
if (nextFn && lodash.isFunction(nextFn)) {
|
|
450
450
|
return nextFn(prefix, namespace, namespaces);
|
|
@@ -471,19 +471,7 @@ function isNamespacedValue(value, namespaces, nextFn) {
|
|
|
471
471
|
* @returns {boolean} - true if special string was found, else false
|
|
472
472
|
*/
|
|
473
473
|
function isExceptionalNamespaceProperty(value) {
|
|
474
|
-
|
|
475
474
|
/*jshint eqnull:true */
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
if (value.indexOf("xml:base") !== -1) {
|
|
481
|
-
return true;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
if (value.indexOf("xmlns") !== -1) {
|
|
485
|
-
return true;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
return false;
|
|
475
|
+
return (value == null || !lodash.isString(value)) ||
|
|
476
|
+
value.indexOf("xml:base") !== -1 || value.indexOf("xmlns") !== -1;
|
|
489
477
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
//SAPINFO atom response format not supported yet
|
|
3
|
-
|
|
3
|
+
const utils = require('./../utils/utils');
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const XMLWriter = require('xml-writer');
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const XMLSerializer = function XMLSerializer(context, bufferSize) {
|
|
8
|
+
const self = this;
|
|
9
9
|
|
|
10
10
|
this.context = context;
|
|
11
11
|
|
|
12
12
|
self.response = context.response;
|
|
13
13
|
self.bufferSize = bufferSize;
|
|
14
14
|
self.buffer = '';
|
|
15
|
-
|
|
15
|
+
const writer = function writer(string) {
|
|
16
16
|
self.buffer += string;
|
|
17
17
|
if (self.buffer.length > bufferSize) {
|
|
18
18
|
self.response.write(self.buffer);
|
package/lib/serializer/json.js
CHANGED
|
@@ -22,12 +22,12 @@ JsonBuilder.prototype.createConverterArray = function (dbSeg) {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
JsonBuilder.prototype.serializeEntity = function (dbSegment) {
|
|
25
|
-
|
|
25
|
+
const entity = this._serializeEntity(dbSegment);
|
|
26
26
|
return toODataJson(this._context, entity);
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
JsonBuilder.prototype._serializeEntity = function (dbSeg) {
|
|
30
|
-
|
|
30
|
+
const rows = dbSeg.getRowsWithGenKey();
|
|
31
31
|
if (rows.length === 0) {
|
|
32
32
|
if (dbSeg.entityType._entityType.parameters && dbSeg.entityType._entityType.parameters.viaKey === true) {
|
|
33
33
|
throw new NotFound('Entity with provided input parameter and key not found.');
|
|
@@ -37,7 +37,7 @@ JsonBuilder.prototype._serializeEntity = function (dbSeg) {
|
|
|
37
37
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
const converter = this.createConverterArray(dbSeg);
|
|
41
41
|
return this.serializeRow(this._context, dbSeg, rows[0], converter);
|
|
42
42
|
};
|
|
43
43
|
|
|
@@ -45,10 +45,10 @@ JsonBuilder.prototype.serializeProperty = function (dbSeg) {
|
|
|
45
45
|
if (dbSeg.getRowsWithGenKey().length > 1) {
|
|
46
46
|
throw new InternalError('Too many rows for serializing a property.');
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
const property = dbSeg.singleProperty;
|
|
49
|
+
let converter;
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
const result = {};
|
|
52
52
|
converter = dbSeg.entityType.converterMapToJsonPayload[property];
|
|
53
53
|
result[property] = converter(dbSeg.getRowsWithGenKey()[0][property]);
|
|
54
54
|
|
|
@@ -56,8 +56,8 @@ JsonBuilder.prototype.serializeProperty = function (dbSeg) {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
JsonBuilder.prototype.serializeFeed = function (dbSegment, inlineCount) {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
const results = this._serializeFeed(dbSegment, inlineCount);
|
|
60
|
+
const feed = {
|
|
61
61
|
"__count": inlineCount,
|
|
62
62
|
"results": results
|
|
63
63
|
};
|
|
@@ -65,25 +65,25 @@ JsonBuilder.prototype.serializeFeed = function (dbSegment, inlineCount) {
|
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
JsonBuilder.prototype._serializeFeed = function (dbSeg) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
for (
|
|
72
|
-
|
|
68
|
+
const rows = dbSeg.getRowsWithGenKey();
|
|
69
|
+
const results = [];
|
|
70
|
+
const converter = this.createConverterArray(dbSeg);
|
|
71
|
+
for (const row of rows) {
|
|
72
|
+
const line = this.serializeRow(this._context, dbSeg, row, converter);
|
|
73
73
|
results.push(line);
|
|
74
74
|
}
|
|
75
75
|
return results;
|
|
76
76
|
};
|
|
77
77
|
|
|
78
78
|
JsonBuilder.prototype.serializeNavMany = function (context, dbSeg, parent1row) {
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
const rows = dbSeg.getRowsWithGenKey();
|
|
80
|
+
const results = [];
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
let row = rows[dbSeg.sql.readPosition];
|
|
84
|
+
const converter = this.createConverterArray(dbSeg);
|
|
85
85
|
while (row && (row['0row'] === parent1row)) {
|
|
86
|
-
|
|
86
|
+
const line = this.serializeRow(context, dbSeg, row, converter);
|
|
87
87
|
results.push(line);
|
|
88
88
|
//next
|
|
89
89
|
dbSeg.sql.readPosition++;
|
|
@@ -94,13 +94,13 @@ JsonBuilder.prototype.serializeNavMany = function (context, dbSeg, parent1row) {
|
|
|
94
94
|
};
|
|
95
95
|
|
|
96
96
|
JsonBuilder.prototype.serializeNavOne = function (context, dbSeg, parent1row) {
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
const rows = dbSeg.getRowsWithGenKey();
|
|
98
|
+
const results = [];
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
let row = rows[dbSeg.sql.readPosition];
|
|
101
|
+
const converter = this.createConverterArray(dbSeg);
|
|
102
102
|
while (row && (row['0row'] === parent1row)) {
|
|
103
|
-
|
|
103
|
+
const line = this.serializeRow(context, dbSeg, row, converter);
|
|
104
104
|
results.push(line);
|
|
105
105
|
//next
|
|
106
106
|
dbSeg.sql.readPosition++;
|
|
@@ -116,8 +116,8 @@ JsonBuilder.prototype.serializeNavOne = function (context, dbSeg, parent1row) {
|
|
|
116
116
|
};
|
|
117
117
|
|
|
118
118
|
JsonBuilder.prototype.createAbsUrl = function (dbSeg, row) {
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
let ret = this._baseUrl + dbSeg.entityType.name;
|
|
120
|
+
const keysProperties = dbSeg.getKeysProperties();
|
|
121
121
|
|
|
122
122
|
ret += '(';
|
|
123
123
|
|
|
@@ -155,7 +155,6 @@ JsonBuilder.prototype.createAbsUrl = function (dbSeg, row) {
|
|
|
155
155
|
} else {
|
|
156
156
|
value = typeConverter.serializeDbValueToUriLiteral(row[keyProperty.COLUMN_NAME], keyProperty);
|
|
157
157
|
}
|
|
158
|
-
|
|
159
158
|
if (array.length === 1) {
|
|
160
159
|
return value;
|
|
161
160
|
}
|
|
@@ -165,8 +164,8 @@ JsonBuilder.prototype.createAbsUrl = function (dbSeg, row) {
|
|
|
165
164
|
};
|
|
166
165
|
|
|
167
166
|
JsonBuilder.prototype.serializeRow = function (context, dbSeg, row, converter) {
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
const ret = {};
|
|
168
|
+
const url = this.createAbsUrl(dbSeg, row);
|
|
170
169
|
|
|
171
170
|
if (context.oData.dbSegment.isLinks) {
|
|
172
171
|
ret.uri = url;
|
|
@@ -202,9 +201,8 @@ JsonBuilder.prototype.serializeRow = function (context, dbSeg, row, converter) {
|
|
|
202
201
|
}
|
|
203
202
|
}
|
|
204
203
|
|
|
205
|
-
for (
|
|
206
|
-
|
|
207
|
-
var navDbSeg = dbSeg.getRelevantNavigationSegments()[sn];
|
|
204
|
+
for (const sn of dbSeg._SelectedNavigations) {
|
|
205
|
+
const navDbSeg = dbSeg.getRelevantNavigationSegments()[sn];
|
|
208
206
|
if (navDbSeg && navDbSeg.isExpand) {
|
|
209
207
|
ret[sn] = this.serializeDbSeg(context, navDbSeg, row['1row']);
|
|
210
208
|
} else {
|
|
@@ -216,7 +214,7 @@ JsonBuilder.prototype.serializeRow = function (context, dbSeg, row, converter) {
|
|
|
216
214
|
};
|
|
217
215
|
|
|
218
216
|
JsonBuilder.prototype.serializeDbSeg = function (context, dbSeg, parent1row) {
|
|
219
|
-
|
|
217
|
+
let d;
|
|
220
218
|
if (dbSeg.kind === dbs.DBS_Entity) {
|
|
221
219
|
if (dbSeg.isCollection) {
|
|
222
220
|
d = { results: this._serializeFeed(context, dbSeg) };
|
|
@@ -235,7 +233,7 @@ JsonBuilder.prototype.serializeDbSeg = function (context, dbSeg, parent1row) {
|
|
|
235
233
|
};
|
|
236
234
|
|
|
237
235
|
function toODataJson(context, object) {
|
|
238
|
-
|
|
236
|
+
const response = { d: object };
|
|
239
237
|
if (context.mode === configuration.modes.development) {
|
|
240
238
|
return JSON.stringify(response, null, 4);
|
|
241
239
|
} else {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const configuration = require('./../configuration');
|
|
4
4
|
|
|
5
5
|
exports.JsonSerializer = JsonSerializer;
|
|
6
6
|
|
|
7
7
|
function JsonSerializer(context, bufferSize, code) {
|
|
8
|
-
|
|
8
|
+
const self = this;
|
|
9
9
|
|
|
10
10
|
self.context = context;
|
|
11
11
|
self.request = context.request;
|
|
@@ -14,12 +14,12 @@ function JsonSerializer(context, bufferSize, code) {
|
|
|
14
14
|
self.buffer = '';
|
|
15
15
|
code = code || 200;
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
const header = {
|
|
18
18
|
'Content-Type': context.payloadType + ';charset=utf-8'
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
if (context.gModel) {
|
|
22
|
-
|
|
22
|
+
const cacheControl = context.gModel.getSetting('content', 'cache-control');
|
|
23
23
|
if (cacheControl) {
|
|
24
24
|
header['cache-control'] = cacheControl;
|
|
25
25
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
const dbutils = require('./../utils/typeConverter');
|
|
4
|
+
const typConv = require('./../utils/typeConverter');
|
|
5
|
+
const XMLWriter = require('xml-writer');
|
|
6
|
+
const contentTypeTools = require('./../utils/checkContentType');
|
|
7
|
+
const associationsUtil = require('./../utils/associations');
|
|
8
|
+
const Measurement = require('./../utils/measurement');
|
|
9
9
|
|
|
10
10
|
function writeNavProperty(xw, navigation, associations, entityType, areAnnotationsEnabled) {
|
|
11
11
|
|
|
12
12
|
xw.startElement('NavigationProperty');
|
|
13
13
|
xw.writeAttribute('Name', navigation.name);
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
const assocName = navigation.association;
|
|
15
|
+
const association = associations[assocName];
|
|
16
16
|
//
|
|
17
17
|
xw.writeAttribute('Relationship', xw._ns + '.' + association.name + 'Type');
|
|
18
18
|
|
|
@@ -34,7 +34,7 @@ function writeProperty(xw, propertyName, col, entityType, areAnnotationsEnabled)
|
|
|
34
34
|
xw.writeAttribute('ConcurrencyMode', 'Fixed');
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
const oOataType = dbutils.dbTypeNameToODataTypeID(col.DATA_TYPE_NAME);
|
|
38
38
|
xw.writeAttribute('Type', typConv.oDataTypeIDs[oOataType]);
|
|
39
39
|
if (col.IS_NULLABLE !== 'TRUE') {
|
|
40
40
|
xw.writeAttribute('Nullable', 'false');
|
|
@@ -55,10 +55,10 @@ function writeProperty(xw, propertyName, col, entityType, areAnnotationsEnabled)
|
|
|
55
55
|
}
|
|
56
56
|
function writeAssociationTypes(xw, associations) {
|
|
57
57
|
// Associations
|
|
58
|
-
for (
|
|
58
|
+
for (const assocName in associations) {
|
|
59
59
|
|
|
60
60
|
if (associations.hasOwnProperty(assocName)) {
|
|
61
|
-
|
|
61
|
+
const assoc = associations[assocName];
|
|
62
62
|
xw.startElement('Association');
|
|
63
63
|
xw.writeAttribute('Name', assocName + 'Type');
|
|
64
64
|
|
|
@@ -101,12 +101,12 @@ function writeAssociationTypes(xw, associations) {
|
|
|
101
101
|
|
|
102
102
|
|
|
103
103
|
function writeEntityTypes(xw, entityTypes, associations, areAnnotationsEnabled) {
|
|
104
|
-
|
|
104
|
+
let i, ii, j;
|
|
105
105
|
|
|
106
106
|
/**
|
|
107
107
|
* @type {EntityType}
|
|
108
108
|
* */
|
|
109
|
-
|
|
109
|
+
let entityType = null;
|
|
110
110
|
|
|
111
111
|
for (i = 0; i < entityTypes.length; i++) {
|
|
112
112
|
entityType = entityTypes[i];
|
|
@@ -125,14 +125,14 @@ function writeEntityTypes(xw, entityTypes, associations, areAnnotationsEnabled)
|
|
|
125
125
|
entityType.getKeysOrGenKey().forEach(writeKey);
|
|
126
126
|
xw.endElement();
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
const props = entityType.getPropertiesWithGenKey();
|
|
129
129
|
for (j = 0; j < props.length; j++) {
|
|
130
130
|
writeProp(props[j], entityType);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
//nav properties
|
|
134
134
|
for (ii = 0; ii < entityType.navProperties.length; ii++) {
|
|
135
|
-
|
|
135
|
+
const navigation = entityType.navProperties[ii];
|
|
136
136
|
writeNavProperty(xw, navigation, associations, entityType, areAnnotationsEnabled);
|
|
137
137
|
}
|
|
138
138
|
xw.endElement();
|
|
@@ -150,8 +150,7 @@ function writeEntityTypes(xw, entityTypes, associations, areAnnotationsEnabled)
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
function writeEntitySets(xw, entityTypes, areAnnotationsEnabled) {
|
|
153
|
-
for (
|
|
154
|
-
var entityType = entityTypes[i];
|
|
153
|
+
for (const entityType of entityTypes) {
|
|
155
154
|
xw.startElement('EntitySet');
|
|
156
155
|
xw.writeAttribute('Name', entityType.name);
|
|
157
156
|
xw.writeAttribute('EntityType', xw._ns + '.' + entityType.name + 'Type');
|
|
@@ -165,25 +164,23 @@ function writeEntitySets(xw, entityTypes, areAnnotationsEnabled) {
|
|
|
165
164
|
}
|
|
166
165
|
|
|
167
166
|
function writeAssociations(xw, associations, areAnnotationsEnabled) {
|
|
168
|
-
for (
|
|
169
|
-
|
|
170
|
-
var assocication = associations[i];
|
|
167
|
+
for (const association of associations) {
|
|
171
168
|
xw.startElement('AssociationSet');
|
|
172
|
-
xw.writeAttribute('Name',
|
|
173
|
-
xw.writeAttribute('Association', xw._ns + '.' +
|
|
169
|
+
xw.writeAttribute('Name', association.name);
|
|
170
|
+
xw.writeAttribute('Association', xw._ns + '.' + association.name + 'Type');
|
|
174
171
|
|
|
175
172
|
if (areAnnotationsEnabled) {
|
|
176
|
-
writeAnnotationAttributes(
|
|
173
|
+
writeAnnotationAttributes(association.getAssociationSetAnnotations(), xw);
|
|
177
174
|
}
|
|
178
175
|
|
|
179
176
|
xw.startElement('End');
|
|
180
|
-
xw.writeAttribute('Role',
|
|
181
|
-
xw.writeAttribute('EntitySet',
|
|
177
|
+
xw.writeAttribute('Role', association.principal.type + 'Principal');
|
|
178
|
+
xw.writeAttribute('EntitySet', association.principal.type);
|
|
182
179
|
xw.endElement();
|
|
183
180
|
|
|
184
181
|
xw.startElement('End');
|
|
185
|
-
xw.writeAttribute('Role',
|
|
186
|
-
xw.writeAttribute('EntitySet',
|
|
182
|
+
xw.writeAttribute('Role', association.dependent.type + 'Dependent');
|
|
183
|
+
xw.writeAttribute('EntitySet', association.dependent.type);
|
|
187
184
|
xw.endElement();
|
|
188
185
|
|
|
189
186
|
xw.endElement();//AssociationSet
|
|
@@ -192,29 +189,29 @@ function writeAssociations(xw, associations, areAnnotationsEnabled) {
|
|
|
192
189
|
}
|
|
193
190
|
|
|
194
191
|
exports.process = function (context, asyncDone) {
|
|
195
|
-
|
|
192
|
+
const response = context.response,
|
|
196
193
|
format = context.oData.systemQueryParameters.format,
|
|
197
194
|
areAnnotationsEnabled = context.gModel.areAnnotationsEnabled();
|
|
198
195
|
|
|
199
196
|
context.logger.silly('metadataprocessor', 'process');
|
|
200
197
|
context.payloadType = Measurement.measureSync(contentTypeTools.checkServiceMetadata, context.request, format, 'contentTypeTools.checkServiceMetadata');
|
|
201
198
|
|
|
202
|
-
|
|
199
|
+
const header = {
|
|
203
200
|
'Content-Type': context.payloadType + ';charset=utf-8'
|
|
204
201
|
};
|
|
205
202
|
|
|
206
|
-
|
|
203
|
+
const cacheControl = context.gModel.getSetting('metadata','cache-control');
|
|
207
204
|
if (cacheControl) {
|
|
208
205
|
header['cache-control'] = cacheControl;
|
|
209
206
|
}
|
|
210
207
|
|
|
211
208
|
response.writeHead(200, header);
|
|
212
209
|
|
|
213
|
-
|
|
210
|
+
const writer = function writer(string) {
|
|
214
211
|
response.write(string);
|
|
215
212
|
};
|
|
216
213
|
|
|
217
|
-
|
|
214
|
+
const xw = new XMLWriter(true, writer);//change to false for unformatted output
|
|
218
215
|
|
|
219
216
|
//xsodata.scenario
|
|
220
217
|
xw._ns = context.gModel.getNamespace();
|
|
@@ -238,8 +235,8 @@ exports.process = function (context, asyncDone) {
|
|
|
238
235
|
xw.writeAttribute('xmlns:m', 'http://schemas.microsoft.com/ado/2007/08/dataservices/metadata');
|
|
239
236
|
xw.writeAttribute('xmlns', 'http://schemas.microsoft.com/ado/2008/09/edm');
|
|
240
237
|
|
|
241
|
-
|
|
242
|
-
|
|
238
|
+
const entityTypes = context.gModel.getEntityTypes();
|
|
239
|
+
const associations = context.gModel.getAssociationsMap();
|
|
243
240
|
Measurement.measureSync(writeEntityTypes, xw, entityTypes, associations, areAnnotationsEnabled, 'writeEntityTypes');
|
|
244
241
|
Measurement.measureSync(writeAssociationTypes, xw, associations, 'writeAssociationTypes');
|
|
245
242
|
|
|
@@ -267,7 +264,7 @@ exports._writeAnnotationAttributes = writeAnnotationAttributes;
|
|
|
267
264
|
* @param {Object} xmlWriter - XMLWriter instance, which is used for the metadata serialization
|
|
268
265
|
*/
|
|
269
266
|
function writeAnnotationAttributes(annotations, xmlWriter) {
|
|
270
|
-
|
|
267
|
+
let annotation;
|
|
271
268
|
|
|
272
269
|
if (!annotations) {
|
|
273
270
|
return;
|