UNPKG

@sap/odata-v4

Version:

OData V4.0 server library

412 lines (356 loc) 12.9 kB
'use strict'; const Edm = require('../edm/Edm'); const FullQualifiedName = require('../FullQualifiedName'); const EdmAction = require('../edm/EdmAction'); const EdmFunction = require('../edm/EdmFunction'); const EdmComplexType = require('../edm/EdmComplexType'); const EdmEntityContainer = require('../edm/EdmEntityContainer'); const EdmEntityType = require('../edm/EdmEntityType'); const EdmTerm = require('../edm/EdmTerm'); const EdmSchema = require('../edm/EdmSchema'); const EdmReference = require('../edm/EdmReference'); const EdmEnumType = require('../edm/EdmEnumType'); const EdmTypeDefinition = require('../edm/EdmTypeDefinition'); /** * Uses a given CsdlProvider which contains classes from the application * @extends Edm */ class EdmProvider extends Edm { /** * @param {CsdlProvider} provider * @param {Object} configuration */ constructor(provider, configuration) { super(); this._configuration = configuration; /** * @type {CsdlProvider} * @private */ this._provider = provider; /** * @type {CsdlSchema} * @private */ this.localSchemas = null; /** * @type {Map.<FullQualifiedName, CsdlAction[]>} * @private */ this.actionsMap = new Map(); /** * @type {Map.<FullQualifiedName, CsdlFunction[]>} * @private */ this.functionsMap = new Map(); } /** * Creates the references list * * @override * @returns {Map.<string, EdmReference>} */ createReferences() { const references = this._provider.getReferences(); let ret = new Map(); for (const reference of references) { ret.set(reference.uri, new EdmReference(this, reference)); } return ret; } /** * Creates the schemas map * * @override * @returns {Map.<string, EdmSchema>} */ createSchemas() { const localSchemas = this._provider.getSchemas(); let providerSchemas = new Map(); for (let schema of localSchemas) { providerSchemas.set(schema.namespace, new EdmSchema(this, this._provider, schema, this._configuration)); } return providerSchemas; } /** * Creates a map to resolve aliases to namespaces * * @override * @returns {Map.<string, string>} */ createAliasToNamespaceInfo() { let aliasToNamespaceInfos = new Map(); /** * @type {CsdlAliasInfo[]} */ const aliasInfos = this._provider.getAliasInfos(); if (aliasInfos) { for (let info of aliasInfos) { aliasToNamespaceInfos.set(info.alias, info.namespace); } } return aliasToNamespaceInfos; } /** * Creates an entity container * * @Override * @param {FullQualifiedName} containerName Container name * @returns {EdmEntityContainer} */ createEntityContainer(containerName) { let entityContainerInfo = this._provider.getEntityContainerInfo(containerName); // CsdlEntityContainerInfo if (entityContainerInfo != null) { return EdmEntityContainer.createWithContainerInfo( this, this._provider, entityContainerInfo, this._configuration); } return null; } /** * Creates an enumeration type. * * @override * @param {FullQualifiedName} enumTypeName Name of the enumeration type */ createEnumType(enumTypeName) { const enumType = this._provider.getEnumType(enumTypeName); return enumType ? new EdmEnumType(this, enumTypeName, enumType) : null; } /** * Creates a type definition. * * @override * @param {FullQualifiedName} typeDefinitionName Name of the type definition */ createTypeDefinition(typeDefinitionName) { const typeDefinition = this._provider.getTypeDefinition(typeDefinitionName); return typeDefinition ? new EdmTypeDefinition(this, typeDefinitionName, typeDefinition) : null; } /** * Creates an entity type. * * @override * @param {FullQualifiedName} entityTypeName Type name */ createEntityType(entityTypeName) { const entityType = this._provider.getEntityType(entityTypeName); // CsdlEntityType if (entityType != null) { const config = this._configuration && this._configuration[entityTypeName.namespace] ? this._configuration[entityTypeName.namespace][entityTypeName.name] : null; return new EdmEntityType(this, entityTypeName, entityType, config); } return null; } /** * Creates a complex type. * * @override * @param {FullQualifiedName} complexTypeName Type name */ createComplexType(complexTypeName) { const complexType = this._provider.getComplexType(complexTypeName); // CsdlEntityType if (complexType != null) { const config = this._configuration && this._configuration[complexTypeName.namespace] ? this._configuration[complexTypeName.namespace][complexTypeName.name] : null; return new EdmComplexType(this, complexTypeName, complexType, config); } return null; } /** * Creates an unbound action. * * @override * @param {FullQualifiedName} actionName Action name * @returns {EdmAction} */ createUnboundAction(actionName) { /** * @type {CsdlAction[]} */ let actions = this.actionsMap.get(actionName.toString()); if (!actions) { actions = this._provider.getActions(actionName); if (!actions) { return null; } this.actionsMap.set(actionName.toString(), actions); } // Search for first unbound action for (let action of actions) { if (!action.isBound) { return new EdmAction(this, actionName, action); } } return null; } /** * Creates all overloadings of a bound function. * * @override * @param {FullQualifiedName} functionName Function name * @returns {EdmFunction[]} */ createBoundFunctions(functionName) { let result = []; let functions = this.functionsMap.get(functionName.toString()); if (!functions) { functions = this._provider.getFunctions(functionName); if (functions) { this.functionsMap.set(functionName.toString(), functions); } } if (functions) { for (let ffunction of functions) { if (ffunction.isBound) { result.push(new EdmFunction(this, functionName, ffunction)); } } } return result; } /** * Creates all overloadings of an unbound function. * * @override * @param {FullQualifiedName} functionName Function name * @returns {EdmFunction[]} */ createUnboundFunctions(functionName) { let result = []; let functions = this.functionsMap.get(functionName.toString()); if (!functions) { functions = this._provider.getFunctions(functionName); if (functions) { this.functionsMap.set(functionName.toString(), functions); } } if (functions) { for (let ffunction of functions) { if (!ffunction.isBound) { result.push(new EdmFunction(this, functionName, ffunction)); } } } return result; } /** * Creates a specific unbound function. * * @override * @param {FullQualifiedName} functionName Function name * @param {string[]} parameterNames Parameter names to identify the overloading * @returns {EdmFunction} */ createUnboundFunction(functionName, parameterNames) { let functions = this.functionsMap.get(functionName.toString()); if (!functions) { functions = this._provider.getFunctions(functionName); if (!functions) { return null; } this.functionsMap.set(functionName.toString(), functions); } let parameterNamesCopy = parameterNames === null ? [] : parameterNames; for (let ffunction of functions) { if (!ffunction.isBound) { const providerParameters = ffunction.parameters || []; if (parameterNamesCopy.length === providerParameters.length) { const functionParameterNames = providerParameters.map(parameter => parameter.name); if (functionParameterNames.every(name => parameterNamesCopy.indexOf(name) > -1)) { return new EdmFunction(this, functionName, ffunction); } } } } return null; } /** * Creates a bound action. * * @override * @param {FullQualifiedName} actionName Action name * @param {FullQualifiedName} bindingParameterTypeName Name of the binding parameter type * @param {boolean} isBindingParameterCollection True if the binding parameter is a collection, otherwise false * @returns {EdmAction} */ createBoundAction(actionName, bindingParameterTypeName, isBindingParameterCollection) { /** * @type {CsdlAction[]} */ let actions = this.actionsMap.get(actionName.toString()); if (!actions) { actions = this._provider.getActions(actionName); if (!actions) { return null; } this.actionsMap.set(actionName.toString(), actions); } // Search for bound action where binding parameter matches for (let action of actions) { if (action.isBound) { const parameters = action.parameters; const parameter = parameters[0]; if (FullQualifiedName.equals(bindingParameterTypeName, parameter.type) && isBindingParameterCollection === parameter.isCollection) { return new EdmAction(this, actionName, action); } } } return null; } /** * Creates a specific overloading of a bound function. * * @override * @param {FullQualifiedName} functionName Function name * @param {FullQualifiedName} bindingParameterTypeName Name of the binding parameter type * @param {boolean} isBindingParameterCollection True if the binding parameter is a collection, otherwise false * @param {string[]} parameterNames Parameter names to identify the overloading * @returns {EdmFunction} */ createBoundFunction(functionName, bindingParameterTypeName, isBindingParameterCollection, parameterNames) { let functions = this.functionsMap.get(functionName.toString()); if (!functions) { functions = this._provider.getFunctions(functionName); if (!functions) { return null; } this.functionsMap.set(functionName.toString(), functions); } let parameterNamesCopy = parameterNames === null ? [] : parameterNames; for (let ffunction of functions) { // CsdlFunction if (ffunction.isBound) { let providerParameters = ffunction.parameters; let bindingParameter = providerParameters[0]; if (FullQualifiedName.equals(bindingParameterTypeName, bindingParameter.type) && isBindingParameterCollection === bindingParameter.isCollection) { if (parameterNamesCopy.length === providerParameters.length - 1) { let providerParameterNames = []; for (let i = 1; i < providerParameters.length; i++) { providerParameterNames.push(providerParameters[i].name); } if (providerParameterNames.every(name => parameterNamesCopy.indexOf(name) > -1)) { return new EdmFunction(this, functionName, ffunction); } } } } } return null; } /** * Creates a term. * * @param {FullQualifiedName} termName Term name * @returns {EdmTerm} */ createTerm(termName) { let providerTerm = this._provider.getTerm(termName); if (providerTerm != null) { return new EdmTerm(this, providerTerm); } return null; } } module.exports = EdmProvider;