@sap/odata-v4
Version:
OData V4.0 server library
412 lines (356 loc) • 12.9 kB
JavaScript
'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;