@sap/cds-dk
Version:
Command line client and development toolkit for the SAP Cloud Application Programming Model
1,549 lines (1,407 loc) • 57.2 kB
JavaScript
/**
* OData V2 to CSN parser
*/
"use strict";
let messages = require("../message").getMessages();
let common = require("../common");
let versionInfo = require('../../../package.json').version;
const { warn } = require('../../util/term');
const edmxncdsdatatype = {
"Edm.String": "cds.LargeString",
"Edm.Boolean": "cds.Boolean",
"Edm.Int16": "cds.Integer",
"Edm.Int32": "cds.Integer",
"Edm.Int64": "cds.Integer64",
"Edm.Decimal": "cds.Decimal",
"Edm.DateTime": "cds.DateTime",
"Edm.DateTimeOffset": "cds.DateTime",
"Edm.Time": "cds.Time",
"Edm.Binary": "cds.LargeBinary",
"Edm.Guid": "cds.UUID",
"Edm.Double": "cds.Double",
// Special handling of data types
"Edm.String_m": "cds.String", // Max length
"Edm.Decimal_p": "cds.Decimal", // Precision, scale
"Edm.DateTime_f": "cds.Date", // sap:display-format="Date"
"Edm.DateTimeOffset_f": "cds.Date", // sap:display-format="Date"
"Edm.Binary_m": "cds.Binary", // Max Length
"Edm.Byte_m": "cds.Integer", // Max Length
"Edm.Double_p": "cds.Double", // Precision, scale
// Special handling with annotations
"Edm.Byte_a": "cds.Integer",
"Edm.SByte_a": "cds.Integer",
"Edm.Single_a": "cds.Double",
"Edm.Stream_a": "cds.LargeBinary",
"Edm.DateTimeOffset_a": "cds.Timestamp", //precision > 0
"Edm.DateTime_a": "cds.Timestamp" //precision > 0
};
const extendedPrimitiveTypes = [
"Edm.Duration",
"Edm.Geography",
"Edm.GeographyPoint",
"Edm.GeographyLineString",
"Edm.GeographyPolygon",
"Edm.GeographyMultiPoint",
"Edm.GeographyMultiLineString",
"Edm.GeographyMultiPolygon",
"Edm.GeographyCollection",
"Edm.Geometry",
"Edm.GeometryPoint",
"Edm.GeometryLineString",
"Edm.GeometryPolygon",
"Edm.GeometryMultiPoint",
"Edm.GeometryMultiLineString",
"Edm.GeometryMultiPolygon",
"Edm.GeometryCollection"
];
function _initialize(parserContext) {
parserContext.serviceNamespace = "";
parserContext.allEntities = [];
parserContext.allEntitiesMC = [];
parserContext.allEntitySetMap = {};
parserContext.allEntitySetMapMC = {};
parserContext.allEntitySetNamespaces = {};
parserContext.allFunctionImports = [];
parserContext.allFunctionImportsMap = {};
parserContext.allAssociations = {};
parserContext.allAssociationSets = {};
parserContext.allComplexTypes = {};
parserContext.allComplexTypeDocs = {};
parserContext.allComplexTypeNamespaces = {};
parserContext.allInheritedComplexTypes = {};
parserContext.allInheritedEntityTypes = [];
parserContext.allowedNamespaces = [];
parserContext.allowAllNamespaces = false;
parserContext.mockServerUc = true;
}
// Function to extract allowed namespace attributes from given set of attributes
function namespaceAttributeFilter(attributes, parserContext) {
let namespaceAttributes = parserContext.allowAllNamespaces
? Object.keys(attributes).filter((attr) => attr.includes(':'))
: Object.keys(attributes).filter((attr) =>
attr.includes(':') && parserContext.allowedNamespaces.includes(attr.split(':')[0]));
namespaceAttributes = namespaceAttributes.map(attribute => {
const index = attribute.indexOf(':');
let namespace = attribute.slice(0, index);
let name = attribute.slice(index + 1);
name = name.replace(/-/g, '.');
let formattedAttribute = {};
formattedAttribute[`${namespace}.${name}`] = _replaceSpecialCharacters(attributes[attribute]);
return formattedAttribute;
});
return namespaceAttributes;
}
//Function to generate CSN for namespace attributes
function _generateNamespaceAttributes(attributes, isBefore) {
let csn = "";
attributes.forEach((attr) => {
let key = Object.keys(attr)[0];
if (key !== 'm.HasStream') {
if (isBefore) csn = csn + ',\n';
csn = csn + `"@${key}":"${attr[key]}"`;
if (!isBefore) csn = csn + ',\n';
}
});
return csn;
}
function _isValidEDMX(jsonObj) {
let isValid = false;
let edmx;
let dataServices;
let schema;
if (jsonObj) {
edmx = jsonObj["edmx:Edmx"];
if (edmx) {
dataServices = edmx["edmx:DataServices"];
if (dataServices) {
schema = dataServices.Schema;
if (schema) {
isValid = true;
}
}
}
}
return isValid;
}
function _settingMockServerUc(jsonObj, parserContext) {
let EntityContainerObj = jsonObj["edmx:Edmx"]["edmx:DataServices"].Schema.EntityContainer;
// Setting mockerserverUc to false when there is no EntityContainer or when the EntityContainer exists but has no elements inside it
if (!EntityContainerObj || (EntityContainerObj && !EntityContainerObj.EntitySet && !EntityContainerObj.FunctionImport && !EntityContainerObj.AssociationSet)) {
parserContext.mockServerUc = false;
}
// Importer throws an error if AssociationSet is present without corresponding entitySets
else if ((EntityContainerObj && !EntityContainerObj.EntitySet && EntityContainerObj.AssociationSet)) {
throw new Error(messages.MISSING_ENTITY_SETS);
}
}
function _isValidEDMXProvided(jsonObj) {
let isValid = false;
if (_isValidEDMX(jsonObj)) {
isValid = true;
} else {
throw new Error(messages.INVALID_EDMX_METADATA);
}
return isValid;
}
function _getServiceNameSpace(jsonObj) {
let schemaArr = jsonObj["edmx:Edmx"]["edmx:DataServices"].Schema;
let schema = schemaArr;
let schemaAttributes;
if (Array.isArray(schemaArr)) {
// TODO: Consider multiple schema.
schema = schemaArr[0];
// throw (messages.MULTIPLE_SCHEMA_FOUND);
}
Object.keys(schema).forEach((key) => {
if (key === "_attributes") {
schemaAttributes = schema[key];
}
});
if (schemaAttributes) {
return schemaAttributes.Namespace;
}
return null;
}
function _checkAssociation(associationSet, parserContext) {
Object.keys(associationSet).forEach((i) => {
if (!parserContext.allEntitiesMC.includes(associationSet[i]._attributes.EntitySet)) {
throw new Error(messages.UNRESOLVED_TYPE + `'${associationSet[i]._attributes.EntitySet}'`);
}
});
}
function _extractAssociationSet(associationSet, parserContext) {
let associations = {};
Object.keys(associationSet).forEach((key) => {
if (key === "_attributes") {
associations.Name = associationSet[key].Name;
associations.End = associationSet.End;
_checkAssociation(associations.End, parserContext);
parserContext.allAssociationSets[associationSet[key].Association] = associations;
}
});
}
function _extractAllAssociationSets(associationSets, parserContext) {
if (associationSets.length) {
// Has many association sets in metadata
for (let i = 0; i < associationSets.length; i++) {
_extractAssociationSet(associationSets[i], parserContext);
}
} else {
// Has only one association set in metadata
_extractAssociationSet(associationSets, parserContext);
}
}
function _extractAssociation(association, parserContext) {
Object.keys(association).forEach((key) => {
if (key === "_attributes") {
parserContext.allAssociations[association[key].Name] = association;
}
});
}
function _extractAllAssociations(associations, parserContext) {
if (associations.length) {
// Has many associations in metadata
for (let i = 0; i < associations.length; i++) {
_extractAssociation(associations[i], parserContext);
}
} else {
// Has only one association in metadata
_extractAssociation(associations, parserContext);
}
}
function _extractEntityFromNamespace(entityName) {
if (!entityName)
return;
let entityId = "";
let pos = entityName.lastIndexOf(".");
if (pos < 0) {
return entityId;
}
entityId = entityName.substring(pos + 1);
return entityId;
}
function _extractEntityFromEntitySet(entitySet, parserContext) {
let entityName;
Object.keys(entitySet).forEach((key) => {
if (key === "_attributes") {
parserContext.allEntitySetMap[entitySet[key].Name] = entitySet[key].EntityType;
if (parserContext.allEntitySetMapMC[entitySet[key].EntityType] === undefined)
parserContext.allEntitySetMapMC[entitySet[key].EntityType] = [];
parserContext.allEntitySetMapMC[entitySet[key].EntityType].push(entitySet[key].Name);
entityName = _extractEntityFromNamespace(entitySet[key].EntityType);
let namespaces = namespaceAttributeFilter(entitySet[key], parserContext);
if (namespaces.length)
parserContext.allEntitySetNamespaces[entitySet[key].Name] = namespaces;
parserContext.allEntities.push(entityName);
parserContext.allEntitiesMC.push(entitySet[key].Name);
}
});
}
function _extractAllEntityFromEntitySets(entitySets, parserContext) {
if (entitySets.length) {
// Has many entity sets in metadata
for (let i = 0; i < entitySets.length; i++) {
_extractEntityFromEntitySet(entitySets[i], parserContext);
}
} else {
// Has only one entity sets in metadata
_extractEntityFromEntitySet(entitySets, parserContext);
}
}
function _getFunctionAttributes(functionImport, serviceNamespaceParam) {
let funcAttributes = [];
if (functionImport["_attributes"]) {
funcAttributes.push(serviceNamespaceParam + functionImport["_attributes"].Name);
funcAttributes.push(functionImport["_attributes"]["m:HttpMethod"]);
if (functionImport["_attributes"].ReturnType) {
funcAttributes.push(functionImport["_attributes"].ReturnType);
} else {
funcAttributes.push(-1);
}
}
if (functionImport["Parameter"]) {
funcAttributes.push(functionImport["Parameter"]);
} else {
funcAttributes.push(-1);
}
if (functionImport["Documentation"]) {
funcAttributes.push(_parseDocumentationTag(functionImport["Documentation"]));
} else {
funcAttributes.push(-1);
}
return funcAttributes;
}
function _extractFunctionImport(functionImport, parserContext) {
//extracting the bound and unbound function import
let boundFunctionImports = [];
let entityName;
Object.keys(functionImport).forEach((key) => {
if (key === "_attributes") {
if (functionImport[key]["sap:action-for"]) {
//storing bound function imports
entityName = _extractEntityFromNamespace(functionImport[key]["sap:action-for"]);
boundFunctionImports = (parserContext.allFunctionImportsMap[entityName])
? parserContext.allFunctionImportsMap[entityName] : [];
boundFunctionImports.push(_getFunctionAttributes(functionImport, ""));
parserContext.allFunctionImportsMap[entityName] = boundFunctionImports;
}
else {
//storing unbound function imports
parserContext.allFunctionImports.push(
_getFunctionAttributes(functionImport, parserContext.serviceNamespace + ".")
);
}
}
});
}
function _checkFunctionImports(functionImports, parserContext) {
if(functionImports.length) {
functionImports.forEach((functionImport) => {
if (functionImport._attributes.EntitySet && !parserContext.allEntitiesMC.includes(functionImport._attributes.EntitySet)) {
throw new Error(messages.UNRESOLVED_TYPE + `'${functionImport._attributes.EntitySet}'`);
}
});
} else {
if (functionImports._attributes.EntitySet && !parserContext.allEntitiesMC.includes(functionImports._attributes.EntitySet)) {
throw new Error(messages.UNRESOLVED_TYPE + `'${functionImports._attributes.EntitySet}'`);
}
}
}
//extracting the function imports from the metadata
function _extractAllFunctionImports(functionImports, parserContext) {
_checkFunctionImports(functionImports, parserContext)
if (functionImports.length) {
//Has many function imports in metadata
for (let i = 0; i < functionImports.length; i++) {
_extractFunctionImport(functionImports[i], parserContext);
}
} else {
//Has only one function import in metadata
_extractFunctionImport(functionImports, parserContext);
}
}
function _replaceSpecialCharacters(text) {
return text.replace(/\\/g, "\\\\").replace(/(?:\\[rn]|[\r\n]+)+/gm, "\\n").replace(/\s+/g, ' ').replace(/"/g, """).trim();
}
// to parse the documentation tag
function _parseDocumentationTag(documentedContent) {
let documentation = "";
if (documentedContent.Summary && documentedContent.Summary._text) {
documentation = _replaceSpecialCharacters(documentedContent.Summary._text);
}
if (documentedContent.LongDescription && documentedContent.LongDescription._text) {
if (documentedContent.Summary)
documentation += "\\n\\n";
documentation += _replaceSpecialCharacters(documentedContent.LongDescription._text);
}
return documentation;
}
function _extractComplexType(complexType, parserContext) {
let complexTypeKey = "";
let baseType = "";
let namespaceAttributes = {};
Object.keys(complexType).forEach((key) => {
if (key === "_attributes") {
complexTypeKey = parserContext.serviceNamespace + "." + complexType[key].Name;
namespaceAttributes = namespaceAttributeFilter(complexType[key], parserContext);
baseType = complexType[key].BaseType;
if (complexType[key].Abstract || complexType[key].OpenType) {
complexType.open = true;
}
} else if (key === "Property") {
// properties = complexType.Property;
} else if (key === "Documentation") {
parserContext.allComplexTypeDocs[complexTypeKey] = _parseDocumentationTag(complexType.Documentation);
}
});
parserContext.allComplexTypes[complexTypeKey] = complexType;
if (complexTypeKey && baseType) {
parserContext.allInheritedComplexTypes[complexTypeKey] = baseType;
}
if (namespaceAttributes.length) {
parserContext.allComplexTypeNamespaces[complexTypeKey] = namespaceAttributes;
}
}
function _extractAllComplexTypes(complexTypes, parserContext) {
if (complexTypes.length) {
// Has many complex types in metadata
for (let i = 0; i < complexTypes.length; i++) {
_extractComplexType(complexTypes[i], parserContext);
}
} else {
// Has only one association in metadata
_extractComplexType(complexTypes, parserContext);
}
}
function _getServiceEntityProperty(
propertyName,
dataType,
length,
precision,
scale,
displayFormat,
isKey,
documentation,
allowedNamespaceAttributes = -1,
nullable,
defaultValue,
collectionKind,
parserContext
) {
let isCollection = -1;
//preprocessing of datatype in case it is a collection
if (dataType && dataType.substring(0, 10) === 'Collection') {
dataType = dataType.substring(11, dataType.length - 1);
isCollection = 1;
}
//if primary key is of type Collection, an error is thrown
if (isKey && isCollection === 1) {
throw new Error(messages.COLLECTION_IN_KEY);
}
let cdsDataType = null;
let hasInvalidPrecision = false;
let propertyJson = '';
if (length && length > 0) {
if(dataType == "Edm.Binary" && length >= 5000){
console.log(warn("MaxLength for type Edm.Binary should not exceed 5000"));
}
cdsDataType = edmxncdsdatatype[dataType + "_m"];
} else if (precision && precision > 0) {
cdsDataType = edmxncdsdatatype[dataType + "_p"];
// Falling back to actual data type as precision has no meaning for 'Date' related data types
// Using _a data type if precision is there for 'Date' related data types
if (cdsDataType === undefined) {
cdsDataType = edmxncdsdatatype[dataType + "_a"];
hasInvalidPrecision = true;
}
} else if (displayFormat && displayFormat === "Date") {
cdsDataType = edmxncdsdatatype[dataType + "_f"];
} else {
cdsDataType = edmxncdsdatatype[dataType];
}
//checks if it's an annotation case
if (!cdsDataType) {
cdsDataType = edmxncdsdatatype[dataType + "_a"];
}
// Lookup from complex type properties
if (!cdsDataType && parserContext.allComplexTypes[dataType]) {
cdsDataType = dataType;
}
// Lookup from inherited complex type properties
if (!cdsDataType && parserContext.allInheritedComplexTypes[dataType]) {
cdsDataType = dataType;
}
//Possibility of entity type or entity set as the data type
if (!cdsDataType && parserContext.allEntitySetMapMC[dataType]) {
cdsDataType = parserContext.serviceNamespace + "." + parserContext.allEntitySetMapMC[dataType][0];
} else if (!cdsDataType && parserContext.allEntitySetMap[_extractEntityFromNamespace(dataType)]) {
cdsDataType = dataType;
}
else if (!cdsDataType && parserContext.allEntities.includes(_extractEntityFromNamespace(dataType))) {
cdsDataType = dataType;
}
let hasCdsTypeMapping = false;
if (extendedPrimitiveTypes.includes(dataType)) {
cdsDataType = dataType;
hasCdsTypeMapping = true;
}
//if the cdsDataType is undefined/ not supported
if (cdsDataType === undefined) {
if (propertyName)
console.log(warn('"' + dataType + '" is not supported (in element:"' + propertyName + '")'));
return "";
}
if (propertyName)
propertyJson = '"' + propertyName + '": {\n';
if (isKey) {
propertyJson = propertyJson + '"key": true,\n';
}
if (isCollection === 1 || collectionKind === 1) {
//if annotations to be added
if (edmxncdsdatatype[dataType + "_a"] && cdsDataType != "cds.Date") {
if (dataType === 'Edm.Stream')
propertyJson = propertyJson + '"@Core.MediaType": "application/octet-stream",\n';
else
propertyJson = propertyJson + '"@odata.Type": "' + dataType + '",\n';
}
//adding precision in case of DateTime datatypes
if ((dataType === "Edm.DateTimeOffset" || dataType === "Edm.DateTime") && cdsDataType != "cds.Date") {
if (precision && precision > 0) {
propertyJson = propertyJson + '"@odata.Precision": ' + precision + ',\n';
}
}
if (hasCdsTypeMapping) {
propertyJson = propertyJson + '"@odata.Type": "' + dataType + '"';
propertyJson = propertyJson + ',\n"items": { \n'
propertyJson = propertyJson + '"type": "cds.String"';
} else {
propertyJson = propertyJson + '"items": { \n'
propertyJson = propertyJson + '"type":"' + cdsDataType + '"';
}
if (length && length > 0) {
propertyJson = propertyJson + ',\n"length":' + length;
} else if (precision && precision > 0 && hasInvalidPrecision === false) {
propertyJson = propertyJson + ',\n"precision":' + precision;
if (scale && scale > 0) {
propertyJson = propertyJson + ',\n"scale":' + scale;
} else {
propertyJson = propertyJson + ',\n"scale":' + 0;
}
}
if (nullable === "false")
propertyJson = propertyJson + ',\n"notNull": true';
propertyJson = propertyJson + '\n}'
}
else {
if (hasCdsTypeMapping) {
propertyJson = propertyJson + '"type": "cds.String"';
propertyJson = propertyJson + ',\n"@odata.Type": "' + dataType + '"';
} else {
propertyJson = propertyJson + '"type":"' + cdsDataType + '"';
}
// if annotations to be added
if (edmxncdsdatatype[dataType + "_a"] && cdsDataType != "cds.Date") {
if (dataType === 'Edm.Stream')
propertyJson = propertyJson + ',\n"@Core.MediaType": "application/octet-stream"';
else
propertyJson = propertyJson + ',\n"@odata.Type": "' + dataType + '"';
}
if (length && length > 0 && !hasCdsTypeMapping) {
propertyJson = propertyJson + ',\n"length":' + length;
} else if (precision && precision > 0 && hasInvalidPrecision === false) {
propertyJson = propertyJson + ',\n"precision":' + precision;
if (scale && scale > 0) {
propertyJson = propertyJson + ',\n"scale":' + scale;
} else {
propertyJson = propertyJson + ',\n"scale":' + 0;
}
}
//adding precision in case of DateTime datatypes
if ((dataType === "Edm.DateTimeOffset" || dataType === "Edm.DateTime") && cdsDataType !== "cds.Date" && !hasCdsTypeMapping) {
if (precision && precision > 0){
propertyJson = propertyJson + ',\n"@odata.Precision": ' + precision;
}
}
}
if (documentation != -1 && documentation) {
propertyJson = propertyJson + ',\n"doc":"' + documentation + '"';
}
if (allowedNamespaceAttributes !== -1) {
propertyJson += _generateNamespaceAttributes(allowedNamespaceAttributes, true);
}
if (isCollection === -1 && nullable === "false") {
propertyJson = propertyJson + ',\n"notNull": true';
}
if (defaultValue !== -1 && defaultValue) {
propertyJson = propertyJson + ', \n"default": {\n"val": "' + defaultValue + '"\n}';
}
if (propertyName)
propertyJson = propertyJson + "\n}";
return propertyJson;
}
function _getServiceComplexType(complexTypeKey, complexType, parserContext, isOpenType) {
let complexTypeCSN = '"' + complexTypeKey + '": {\n';
let complexTypeProperty;
complexTypeCSN = complexTypeCSN + '"kind": "type",\n';
// checking if the ComplexType is marked open or acts as a BaseType
if (isOpenType || Object.values(parserContext.allInheritedComplexTypes).indexOf(complexTypeKey) > -1) {
complexTypeCSN = complexTypeCSN + '"@open": true,\n';
}
complexTypeCSN = complexTypeCSN + '"@cds.external": true,\n';
if (parserContext.allComplexTypeNamespaces[complexTypeKey]) {
complexTypeCSN += _generateNamespaceAttributes(parserContext.allComplexTypeNamespaces[complexTypeKey], false);
}
if (parserContext.allComplexTypeDocs[complexTypeKey])
complexTypeCSN = complexTypeCSN + '"doc":' + `"${parserContext.allComplexTypeDocs[complexTypeKey]}",` + "\n";
complexTypeCSN = complexTypeCSN + '"elements": {\n';
if (complexType) {
if (complexType.length) {
// More than one complex types
for (let i = 0; i < complexType.length; i++) {
complexTypeProperty = complexType[i]._attributes;
if (complexType[i].Documentation)
complexTypeProperty.doc = _parseDocumentationTag(complexType[i].Documentation);
complexType.CollectionKind = 0;
if (complexType[i]._attributes.CollectionKind === "Bag" || complexType[i]._attributes.CollectionKind === "List") {
complexType.CollectionKind = 1;
}
let namespaceAttributes = namespaceAttributeFilter(complexTypeProperty, parserContext);
const complexTypePropertyNamespace = namespaceAttributes.length ? namespaceAttributes : -1;
let complexProperty =
_getServiceEntityProperty(
complexTypeProperty.Name,
complexTypeProperty.Type,
complexTypeProperty.MaxLength,
complexTypeProperty.Precision,
complexTypeProperty.Scale,
complexTypeProperty["sap:display-format"],
false,
complexTypeProperty.doc,
complexTypePropertyNamespace,
complexTypeProperty.Nullable,
complexTypeProperty.DefaultValue,
complexType.CollectionKind,
parserContext
);
complexTypeCSN = complexTypeCSN + complexProperty;
if (i !== complexType.length - 1 && complexProperty != "") {
complexTypeCSN = complexTypeCSN + ",\n";
} else {
complexTypeCSN = complexTypeCSN + "\n";
}
}
} else {
// Only one complex type
complexTypeProperty = complexType._attributes;
if (complexType.Documentation)
complexTypeProperty.doc = _parseDocumentationTag(complexType.Documentation);
complexType.CollectionKind = 0;
if (complexType._attributes.CollectionKind === "Bag" || complexTypeProperty.CollectionKind === "List") {
complexTypeProperty.CollectionKind = 1;
}
let namespaceAttributes = namespaceAttributeFilter(complexTypeProperty, parserContext);
const complexTypePropertyNamespace = namespaceAttributes.length ? namespaceAttributes : -1;
complexTypeCSN = complexTypeCSN +
_getServiceEntityProperty(
complexTypeProperty.Name,
complexTypeProperty.Type,
complexTypeProperty.MaxLength,
complexTypeProperty.Precision,
complexTypeProperty.Scale,
complexTypeProperty["sap:display-format"],
false,
complexTypeProperty.doc,
complexTypePropertyNamespace,
complexTypeProperty.Nullable,
complexTypeProperty.DefaultValue,
complexTypeProperty.CollectionKind,
parserContext
);
}
if (complexTypeCSN && (complexTypeCSN.endsWith(",\n") || complexTypeCSN.endsWith(",\n\n"))) {
complexTypeCSN = complexTypeCSN.substring(0, complexTypeCSN.lastIndexOf(",\n")) + "\n";
}
}
complexTypeCSN = complexTypeCSN + "}\n";
if (parserContext.allInheritedComplexTypes[complexTypeKey]) {
let baseType = parserContext.allInheritedComplexTypes[complexTypeKey];
if (parserContext.allComplexTypes[baseType]) {
complexTypeCSN = complexTypeCSN + ',\n"includes": ["' + baseType + '"]\n';
}
else {
console.log(warn("BaseType " + baseType + " couldn't be resolved"));
}
}
complexTypeCSN = complexTypeCSN + "}\n";
return complexTypeCSN;
}
function _getServiceComplexTypes(parserContext) {
let complexTypeCSN = "";
let complexTypesKeys = Object.keys(parserContext.allComplexTypes);
let complexTypeKey;
let complexType;
let isOpenType;
for (let i = 0; i < complexTypesKeys.length; i++) {
complexTypeKey = complexTypesKeys[i];
complexType = parserContext.allComplexTypes[complexTypeKey].Property;
isOpenType = parserContext.allComplexTypes[complexTypeKey].open;
complexTypeCSN = complexTypeCSN + _getServiceComplexType(complexTypeKey, complexType, parserContext, isOpenType);
if (i !== complexTypesKeys.length - 1) {
complexTypeCSN = complexTypeCSN + ",\n";
} else {
complexTypeCSN = complexTypeCSN + "\n";
}
}
return complexTypeCSN;
}
function _parseParameter(parameter, parserContext) {
let csn = "";
let doc;
if (parameter.Documentation)
doc = _parseDocumentationTag(parameter.Documentation);
let namespaceAttributes = namespaceAttributeFilter(parameter._attributes, parserContext);
const parameterNamespaceAttributes = namespaceAttributes.length ? namespaceAttributes : -1;
csn = csn +
_getServiceEntityProperty(
parameter["_attributes"].Name,
parameter["_attributes"].Type,
parameter["_attributes"].MaxLength,
parameter["_attributes"].Precision,
parameter["_attributes"].Scale,
parameter["_attributes"]["sap:display-format"],
false,
doc,
parameterNamespaceAttributes,
parameter["_attributes"].Nullable,
-1,
parameter["_attributes"].CollectionKind,
parserContext
);
return csn;
}
function _checkParameterKey(parameter, entityKeysList) {
if (entityKeysList && (Object.values(entityKeysList).indexOf(parameter._attributes.Name) > -1)) {
return true;
}
return false;
}
function _parseParametersFunctionImport(parameters, entityKeysList, parserContext) {
let csn = "";
let parameterCsn = "";
if (parameters.length) {
for (let i = 0; i < parameters.length; i++) {
// check if the parameter is a key of the entity type or not
// If yes then that paramater is ignored in CSN
let isKey = _checkParameterKey(parameters[i], entityKeysList);
if (isKey == false) {
parameterCsn = _parseParameter(parameters[i], parserContext);
csn = csn + parameterCsn;
if (i !== parameters.length - 1 && parameterCsn != "") {
csn = csn + ",\n";
} else {
csn = csn + "\n";
}
}
}
} else {
let isKey = _checkParameterKey(parameters);
if (isKey === false) {
csn = csn + _parseParameter(parameters, parserContext);
}
}
if (csn && (csn.endsWith(",\n") || csn.endsWith(",\n\n"))) {
csn = csn.substring(0, csn.lastIndexOf(",\n")) + "\n";
}
return csn;
}
function _getFunctionImport(functionImport, isBound, entityKeysList, parserContext) {
let noValue;
let csn = "";
csn = csn + '"' + functionImport[0] + '": { \n';
csn = csn + '"kind": "';
if (functionImport[1] === "GET") {
csn = csn + "function";
} else if (functionImport[1] === "POST") {
csn = csn + "action";
} else {
let message = functionImport[0].substring(functionImport[0].lastIndexOf(".") + 1) + " has kind " +
functionImport[1] + " which is not supported.";
console.log(warn(message));
return "";
}
csn = csn + '"';
if (!isBound) csn = csn + ',\n"@cds.external": true';
if (functionImport[3] !== -1) {
if (isBound === 0 || (isBound === 1 && functionImport[3] instanceof Array)) {
let parametersCsn = _parseParametersFunctionImport(functionImport[3], entityKeysList, parserContext);
if (parametersCsn != "") {
csn = csn + ", \n";
csn = csn + '"params": { \n';
csn = csn + parametersCsn;
csn = csn + '\n }';
}
}
}
// if return type exist
if (functionImport[2] !== -1) {
let returnValue = _getServiceEntityProperty(noValue, functionImport[2], noValue, noValue, noValue, noValue,
noValue, noValue, noValue, noValue, -1, noValue, parserContext);
if (returnValue !== "") {
csn = csn + ", \n";
csn = csn + '"returns": { \n';
//return type
csn = csn + returnValue;
csn = csn + '\n }';
} else {
throw new Error(messages.UNRESOLVED_TYPE + `'${functionImport[2]}'`);
}
}
// if return type is missing, add boolean only for functions
if (functionImport[2] === -1 && functionImport[1] === "GET") {
csn = csn + ", \n";
csn = csn + '"returns": { \n';
csn = csn + '"type": "cds.Boolean"';
csn = csn + '\n }';
}
if (functionImport[4] !== -1 && functionImport[4]) {
csn = csn + ',\n "doc": "' + _replaceSpecialCharacters(functionImport[4]) + '"';
}
csn = csn + "\n }";
return csn;
}
function _getAllFunctionImports(functionImports, isBound, entityKeysList, parserContext) {
let functionImportsCSN = "";
let i;
let functionImportCSN = "";
for (i = 0; i < functionImports.length; i++) {
functionImportCSN = _getFunctionImport(functionImports[i], isBound, entityKeysList, parserContext);
functionImportsCSN = functionImportsCSN + functionImportCSN;
if (i !== functionImports.length - 1 && functionImportCSN !== "") {
functionImportsCSN = functionImportsCSN + ",\n";
} else {
functionImportsCSN = functionImportsCSN + "\n";
}
}
//if last function import is omitted, remove the extra characters
if (functionImportsCSN && (functionImportsCSN.endsWith(",\n") || functionImportsCSN.endsWith(",\n\n"))) {
functionImportsCSN = functionImportsCSN.substring(0, functionImportsCSN.lastIndexOf(",\n")) + "\n";
}
return functionImportsCSN;
}
function _getEntityName(entity) {
return entity._attributes.Name;
}
function _parseEntityAttributes(attributes, parserContext) {
let entityAttributes = {};
// Extract only needed entity attributes
entityAttributes.Name = attributes.Name;
entityAttributes.BaseType = attributes.BaseType;
entityAttributes.Abstract = attributes.Abstract;
entityAttributes.OpenType = attributes.OpenType;
entityAttributes.allowedNamespaceAttributes = namespaceAttributeFilter(attributes, parserContext);
return entityAttributes;
}
function _parseEntityKeys(keys) {
// Care for array or non-array (only one property as key)
let retKeys = [];
let i;
let attributes;
if (keys.PropertyRef.length) {
for (i = 0; i < keys.PropertyRef.length; i++) {
attributes = keys.PropertyRef[i]._attributes;
retKeys.push(attributes.Name);
}
} else {
retKeys.push(keys.PropertyRef._attributes.Name);
}
return retKeys;
}
function _getPropertyAttributes(propAttributes, parserContext) {
let propOthers = [];
let namespaceAttributes = namespaceAttributeFilter(propAttributes, parserContext);
propOthers.push(propAttributes.Type);
if (propAttributes.MaxLength) {
propOthers.push(propAttributes.MaxLength);
} else {
propOthers.push(-1);
}
if (propAttributes.Precision) {
propOthers.push(propAttributes.Precision);
} else {
propOthers.push(-1);
}
if (propAttributes.Scale) {
propOthers.push(propAttributes.Scale);
} else {
propOthers.push(-1);
}
if (propAttributes["sap:display-format"]) {
propOthers.push(propAttributes["sap:display-format"]);
} else {
propOthers.push(-1);
}
if (propAttributes.doc) {
propOthers.push(propAttributes.doc.replace(/"/g, '"'));
} else {
propOthers.push(-1);
}
if (namespaceAttributes.length) {
propOthers.push(namespaceAttributes);
} else {
propOthers.push(-1);
}
if (propAttributes.Nullable) {
propOthers.push(propAttributes.Nullable);
} else {
propOthers.push("true");
}
if (propAttributes.DefaultValue) {
propOthers.push(propAttributes.DefaultValue);
} else {
propOthers.push(-1);
}
if (propAttributes.CollectionKind === 'List' || propAttributes.CollectionKind === 'Bag') {
propOthers.push(1);
}
else {
propOthers.push(-1);
}
return propOthers;
}
function _parseEntityProperty(properties, parserContext) {
let propAttributes;
let retProperties = {};
if (properties.length) {
// Has more than one entities
for (let i = 0; i < properties.length; i++) {
propAttributes = properties[i]._attributes;
// if the property contains documentation tag
if (properties[i] && properties[i].Documentation)
propAttributes.doc = _parseDocumentationTag(properties[i].Documentation);
retProperties[propAttributes.Name] = _getPropertyAttributes(propAttributes, parserContext);
}
} else {
// Has only one entity
propAttributes = properties._attributes;
// if the property contains documentatin tag
if (properties && properties.Documentation)
propAttributes.doc = _parseDocumentationTag(properties.Documentation);
retProperties[propAttributes.Name] = _getPropertyAttributes(propAttributes, parserContext);
}
return retProperties;
}
function _parseNavigationProperty(navigationProperties) {
let retNavProperties = {};
let navPropAttributes;
if (navigationProperties.length) {
// Has more than one navigation property
for (let i = 0; i < navigationProperties.length; i++) {
navPropAttributes = navigationProperties[i]._attributes;
// if the property contains documentatin tag
if (navigationProperties[i] && navigationProperties[i].Documentation)
navPropAttributes.doc = _parseDocumentationTag(navigationProperties[i].Documentation);
retNavProperties[navPropAttributes.Name] = navPropAttributes;
}
} else {
// Has only one navigation property
navPropAttributes = navigationProperties._attributes;
// if the property contains documentatin tag
if (navigationProperties && navigationProperties.Documentation)
navPropAttributes.doc = _parseDocumentationTag(navigationProperties.Documentation);
retNavProperties[navPropAttributes.Name] = navPropAttributes;
}
return retNavProperties;
}
function _generateCSNEntityKeys(entityKeysList, entityPropertiesMap, parserContext) {
let csnEntity = "";
let propAttributes;
for (let i = 0; i < entityKeysList.length; i++) {
propAttributes = entityPropertiesMap[entityKeysList[i]];
if (propAttributes[7] === "true") {
console.log(warn("Expected key element to be not nullable"));
}
let keyCsn =
_getServiceEntityProperty(
entityKeysList[i],
propAttributes[0],
propAttributes[1],
propAttributes[2],
propAttributes[3],
propAttributes[4],
true,
propAttributes[5],
propAttributes[6],
"false",
propAttributes[8],
propAttributes[9],
parserContext
);
csnEntity = csnEntity + keyCsn;
if (i !== entityKeysList.length - 1 && keyCsn != "") {
csnEntity = csnEntity + ",\n";
}
}
if (csnEntity && (csnEntity.endsWith(",\n") || csnEntity.endsWith(",\n\n"))) {
csnEntity = csnEntity.substring(0, csnEntity.lastIndexOf(",\n")) + "\n";
}
return csnEntity;
}
function _generateCSNEntityProperties(entityKeysList, entityPropertiesMap, parserContext) {
let csnEntity = "";
let entityProperties = Object.keys(entityPropertiesMap);
let property;
let propAttributes;
if (entityKeysList.length > 0) {
if (entityProperties.length > 0) {
csnEntity = csnEntity + ",\n";
} else {
csnEntity = csnEntity + "\n";
}
}
for (let i = 0; i < entityProperties.length; i++) {
property = entityProperties[i];
// Include Property which are not part of keys
if (entityKeysList.indexOf(property) === -1) {
propAttributes = entityPropertiesMap[property];
let propertyString =
_getServiceEntityProperty(
property,
propAttributes[0], // dataType
propAttributes[1], // length
propAttributes[2], // precision
propAttributes[3], // scale
propAttributes[4], // display
false, // isKey
propAttributes[5], // doc
propAttributes[6], // allowed namespace
propAttributes[7], // nullable
propAttributes[8], // defaultVal
propAttributes[9], // collection
parserContext
);
csnEntity = csnEntity + propertyString;
if (i !== entityProperties.length - 1 && propertyString != "") {
csnEntity = csnEntity + ",\n";
} else {
csnEntity = csnEntity + "\n";
}
}
}
// Last property can be an key; eliminate additional delimiter.
// Last property can have undefined datatype and be ignored too
if (csnEntity && (csnEntity.endsWith(",\n") || csnEntity.endsWith(",\n\n"))) {
csnEntity = csnEntity.substring(0, csnEntity.lastIndexOf(",\n")) + "\n";
}
return csnEntity;
}
function _getAssociatedEntity(associationEnds, toRole, isAssociationSetMissing, parserContext) {
let entityName;
let entitySetName;
let entityTypeName;
Object.keys(associationEnds).forEach((i) => {
if (toRole === associationEnds[i]._attributes.Role) {
if (isAssociationSetMissing && parserContext.mockServerUc) {
entityTypeName = associationEnds[i]._attributes.Type;
entitySetName = parserContext.allEntitySetMapMC[entityTypeName][0];
} else {
entitySetName = associationEnds[i]._attributes.EntitySet;
}
if (parserContext.mockServerUc) {
entityName = parserContext.serviceNamespace + "." + entitySetName;
} else {
entityName = parserContext.allEntitySetMap[entitySetName];
}
}
});
return entityName;
}
function _getCSNMultiplicity(associationEnds, toRole, entityName, parserContext) {
let csn = "";
let multiplicity;
let attributes;
let stop = false;
Object.keys(associationEnds).forEach((i) => {
if (!stop) {
attributes = associationEnds[i]._attributes;
if (parserContext.mockServerUc) {
let entityNameWithOutNS = parserContext.allEntitySetMap[_extractEntityFromNamespace(entityName)];
if (
toRole === attributes.Role &&
entityNameWithOutNS === attributes.Type
) {
multiplicity = attributes.Multiplicity;
stop = true;
}
} else {
if (
toRole === attributes.Role &&
entityName === attributes.Type
) {
multiplicity = attributes.Multiplicity;
stop = true;
}
}
}
});
if (multiplicity === "1" || multiplicity === "0..1") {
// When multiplicity is '1' then in CSN we NO need to generate 'cardinality' section
return csn;
}
if (multiplicity) {
csn = csn + '"cardinality": {\n';
csn = csn + '"max": "' + multiplicity + '"\n';
csn = csn + "}";
}
return csn;
}
function _getCSNAssociatedRefrenentialConstraints(
associations,
toRole,
entityName,
navPropName,
parserContext
) {
let csn = "";
let multiplicity;
csn = csn + '"target": "' + entityName + '"';
if (!associations) {
return csn;
}
multiplicity = _getCSNMultiplicity(
associations.End,
toRole,
entityName,
parserContext
);
if (multiplicity) {
csn = csn + ",\n" + multiplicity;
}
return csn;
}
function _getCSNAssociatedEntitySet(
relationshipName,
toRole,
navPropName,
parserContext
) {
let associationSet = parserContext.allAssociationSets[relationshipName];
let associationName = relationshipName.replace(parserContext.serviceNamespace + '.', '');
let association = parserContext.allAssociations[associationName];
let isAssociationSetMissing = false;
// if association set is missing, use association to extract the informations
if (associationSet === undefined) {
isAssociationSetMissing = true;
}
let associationEnd = associationSet ? associationSet.End : association.End;
let entityName = _getAssociatedEntity(
associationEnd,
toRole,
isAssociationSetMissing,
parserContext
);
let differentAssociationNames;
if (!parserContext.allAssociations[associationName]) {
let array = relationshipName.split(".");
if (
array != "undefined" &&
array != null &&
array.length != null &&
array.length > 0
) {
differentAssociationNames = parserContext.allAssociations[array[array.length - 1]];
}
} else {
differentAssociationNames = association;
}
return _getCSNAssociatedRefrenentialConstraints(
differentAssociationNames,
toRole,
entityName,
navPropName,
parserContext
);
}
function _findAssociationType(relationshipName, fromRole, parserContext) {
const associationName = relationshipName.replace(parserContext.serviceNamespace + '.', '');
const association = parserContext.allAssociations[associationName];
if (association === undefined) throw new Error(`'${associationName}' ` + messages.MISSING_ASSOCIATION);
const associationEnds = association.End;
let associationType;
for (let i = 0; i < associationEnds.length; i++) {
let potentialComposition = false;
Object.keys(associationEnds[i]).forEach((key) => {
if (key === "_attributes" && associationEnds[i][key].Role === fromRole)
potentialComposition = true;
if (key === "OnDelete"
&& associationEnds[i][key]._attributes.Action === "Cascade"
&& potentialComposition
) {
associationType = "composition";
}
});
}
return '"type": "cds.' + (associationType === "composition" ? 'Composition"' : 'Association"') + ',\n';
}
function _getServiceEntityNavigationProperty(navPropAttributes, parserContext) {
let csn = "";
let navPropName;
let relationshipName;
let navPropDoc;
let allowedNamespaceAttributes = namespaceAttributeFilter(navPropAttributes, parserContext);
let fromRole;
let toRole;
if (!navPropAttributes) {
return csn;
}
navPropName = navPropAttributes.Name;
relationshipName = navPropAttributes.Relationship;
fromRole = navPropAttributes.FromRole;
toRole = navPropAttributes.ToRole;
navPropDoc = navPropAttributes.doc;
csn = csn + '"' + navPropName + '": {\n';
if (allowedNamespaceAttributes.length) {
csn += _generateNamespaceAttributes(allowedNamespaceAttributes, false);
}
// if documentation exists for navigation property
if (navPropDoc)
csn = csn + '"doc":' + ` "${navPropDoc}",\n`;
// this function call can throw error if the association is missing in the edmx file
csn = csn + _findAssociationType(relationshipName, fromRole, parserContext);
csn = csn +
_getCSNAssociatedEntitySet(
relationshipName,
toRole,
navPropName,
parserContext
);
// Convert managed associations and compositions in unmanaged with empty key to avoid
// "generation" of keys, that do not exist in the external service.
if (common.checkForEmptyKeys(csn, "V2")) {
csn = csn + ',\n"keys": []\n';
}
csn = csn + "}";
return csn;
}
function _generateCSNEntityNavigationProperties(
entityNavigationPropertiesMap,
hasProperties,
parserContext
) {
let csn = "";
let entityNavProperties;
let navProperty;
let navPropAttributes;
if (!entityNavigationPropertiesMap) {
return csn;
}
entityNavProperties = Object.keys(entityNavigationPropertiesMap);
if (hasProperties && entityNavProperties.length > 0) {
// Has navigation properties
csn = ",\n";
}
for (let i = 0; i < entityNavProperties.length; i++) {
navProperty = entityNavProperties[i];
navPropAttributes = entityNavigationPropertiesMap[navProperty];
csn = csn +
_getServiceEntityNavigationProperty(
navPropAttributes,
parserContext
);
if (i < entityNavProperties.length - 1) {
csn = csn + ",\n";
}
}
return csn;
}
function _getBaseTypeEntityName(entityName, parserContext) {
let baseTypeName;
// if one entity type has mapping to multiple entity sets, use the first entity set
if (parserContext.allEntitySetMapMC[entityName]) {
baseTypeName = parserContext.serviceNamespace + "." + parserContext.allEntitySetMapMC[entityName][0];
return baseTypeName;
}
return entityName;
}
function _constructServiceEntity(
entityName,
entityKeysList,
entityPropertiesMap,
entityNavigationPropertiesMap,
entityAttributes,
ignorePersistenceSkip,
documentation,
parserContext
) {
let filteredNamespaces = {};
let namespaces = [];
let serviceEntityName = parserContext.serviceNamespace + "." + entityName;
let csnEntity = '"' + serviceEntityName + '": {\n';
let csnKeys;
let csnProperties;
let hasProperties;
csnEntity = csnEntity + '"kind": "entity",\n';
csnEntity = csnEntity + '"@cds.external": true,\n';
if (ignorePersistenceSkip === false) {
csnEntity = csnEntity + '"@cds.persistence.skip": true,\n';
}
if ((entityAttributes.Abstract?.toUpperCase() === "TRUE") || (entityAttributes.OpenType?.toUpperCase() === "TRUE")) {
csnEntity = csnEntity + '"@open": true,\n'
}
/* Merging the namespace list from entity set and entity type
And in case of same label, entity set's value will have precedence */
if (parserContext.allEntitySetNamespaces[entityName]) {
parserContext.allEntitySetNamespaces[entityName].forEach((item) => {
filteredNamespaces[Object.keys(item)[0]] = Object.values(item)[0];
});
}
if (entityAttributes.allowedNamespaceAttributes.length) {
entityAttributes.allowedNamespaceAttributes.forEach((item) => {
if (!filteredNamespaces[Object.keys(item)[0]]) {
filteredNamespaces[Object.keys(item)[0]] = Object.values(item)[0];
}
});
}
Object.keys(filteredNamespaces).forEach((item) => {
let obj = {};
obj[item] = filteredNamespaces[item];
namespaces.push(obj);
});
if (namespaces)
csnEntity += _generateNamespaceAttributes(namespaces, false);
// if documentation exists for the entity
if (documentation) {
csnEntity = csnEntity + `"doc": "${documentation}",` + '\n';
}
csnEntity = csnEntity + '"elements": {\n';
// Key Entity attributes
csnKeys = _generateCSNEntityKeys(entityKeysList, entityPropertiesMap, parserContext);
// Non key Entity attributes
csnProperties = _generateCSNEntityProperties(entityKeysList, entityPropertiesMap, parserContext);
csnProperties = csnKeys + csnProperties;
//to remove additional ',\n' in case key datatype is undefined
if (csnProperties && csnProperties.startsWith(",\n")) {
csnProperties = csnProperties.substring(csnProperties.indexOf(",\n") + 2);
}
csnEntity = csnEntity + csnProperties;
// No keys and No properties found
hasProperties = true;
if (csnKeys.trim() === "" && csnProperties.trim() === "") {
hasProperties = false;
}
// Entity navigation properties
csnEntity = csnEntity +
_generateCSNEntityNavigationProperties(
entityNavigationPropertiesMap,
hasProperties,
parserContext
);
csnEntity = csnEntity + "}\n";
if (entityAttributes.BaseType) {
let baseTypeName = _getBaseTypeEntityName(entityAttributes.BaseType, parserContext).replace(parserContext.serviceNamespace + '.', '');
if (parserContext.allEntitiesMC.includes(baseTypeName) || parserContext.allEntities.includes(baseTypeName)) {
csnEntity = csnEntity + ',\n"includes": ["' + parserContext.serviceNamespace + '.' + baseTypeName + '"]\n';
}
else {
throw new Error(messages.UNRESOLVED_TYPE + `'${parserContext.serviceNamespace}.${baseTypeName}'`);
}
}
// if the function import is bound to entitySet
if (parserContext.allFunctionImportsMap[entityName]) {
csnEntity = csnEntity + ', \n "actions": {\n';
csnEntity = csnEntity +
_getAllFunctionImports(parserContext.allFunctionImportsMap[entityName],
1, entityKeysList, parserContext
);
csnEntity = csnEntity + "}";
}
// if the function import is bound to entityType
else if (parserContext.allFunctionImportsMap[_extractEntityFromNamespace(parserContext.allEntitySetMap[entityName])]) {
csnEntity = csnEntity + ', \n "actions": {\n';
csnEntity = csnEntity +
_getAllFunctionImports(
parserContext.allFunctionImportsMap[_extractEntityFromNamespace(parserContext.allEntitySetMap[entityName])],
1, entityKeysList, parserContext
);
csnEntity = csnEntity + "}";
}
return csnEntity;
}
function _addBlobElement(properties) {
const blobElement = ['Edm.Stream', -1, -1, -1, -1, -1, -1];
properties['blob'] = blobElement;
}
function _parseServiceEntity(entityName, entity, ignorePersistenceSkip, parserContext) {
let entityAttributes;
let entityKeysList;
let entityPropertiesMap;
let entityNavigationPropertiesMap;
let documentation;
Object.keys(entity).forEach((key) => {
if (key === "_attributes") {
entityAttributes = _parseEntityAttributes(entity[key], parserContext);
} else if (key.toUpperCase() === "Key".toUpperCase()) {
entityKeysList = _parseEntityKeys(entity[key]);
} else if (key.toUpperCase() === "Property".toUpperCase()) {
entityPropertiesMap = _parseEntityProperty(entity[key], parserContext);
} else if (key.toUpperCase() === "NavigationProperty".toUpperCase()) {
entityNavigationPropertiesMap = _parseNavigationProperty(entity[key]);
} else if (key.toUpperCase() === "Documentation".toUpperCase()) {
documentation = _parseDocumentationTag(entity[key]);
}
});
// No keys in entity
if (entityKeysList === undefined || entityKeysList == null) {
entityKeysList = [];
}
// No properties in entity
if (entityPropertiesMap === undefined || entityPropertiesMap == null) {
entityPropertiesMap = [];
}
// No navigation properties in entity
if (entityNavigationPropertiesMap === undefined || entityNavigationPropertiesMap == null) {
entityNavigationPropertiesMap = [];
}
// If inherited entity found
if (entityAttributes.BaseType) {
let entityName;
if (parserContext.allEntitySetMapMC && parserContext.allEntitySetMapMC[entityAttributes.BaseType]) {
entityName = parserContext.allEntitySetMapMC[entityAttributes.BaseType][0];
}
else entityName = _extractEntityFromNamespace(entityAttributes.BaseType);
if (!parserContext.allInheritedEntityTypes.includes(entityName)) parserContext.allInheritedEntityTypes.push(entityName);
}
// adding blob element if entity has m:HasStream as true
const checkProperty = entityAttributes["allowedNamespaceAttributes"].filter(e => e["m.HasStream"] === 'true');
if (checkProperty.length === 1) _addBlobElement(entityPropertiesMap);
return _constructServiceEntity(
entityName,
entityKeysList,
entityPropertiesMap,
entityNavigationPropertiesMap,
entityAttributes,
ignorePersistenceSkip,
documentation,
parserContext
);
}
function _getEntitesWithNamesFromEntitySets(entityJson, parserContext) {
const getEntityName = parserContext.mockServerUc
? (entity) => parserContext.allEntitySetMapMC[parserContext.serviceNamespace + "." + _getEntityName(entity)]
: (entity) => [_getEntityName(entity)];
const isNameInEntitySet = parserContext.mockServerUc
? (name) => parserContext.allEntitiesMC.indexOf(name) >= 0
: (name) => parserContext.allEntities.indexOf(name) >= 0;
const getEntitySetNames = entityWithName => {
if (!entityWithName.name) return false;
for (let i = 0; i < entityWithName.name.length; i++) {
if (!isNameInEntitySet(entityWithName.name[i]))
return false;
}
return true;
};
return entityJson
.map((entity) => ({
entity,
name: getEntityName(entity)
}))
.filter((entityWithName)