UNPKG

@sap/odata-v4

Version:

OData V4.0 server library

279 lines (246 loc) 9.8 kB
'use strict'; const EdmAnnotation = require('./EdmAnnotation'); const EdmType = require('./EdmType'); const EdmProperty = require('./EdmProperty'); const EdmNavigationProperty = require('./EdmNavigationProperty'); const EdmTypeFactory = require('./EdmTypeFactory'); const FullQualifiedName = require('../FullQualifiedName'); const validateThat = require('../validator/ParameterValidator').validateThat; const NotImplementedError = require('../errors/NotImplementedError'); const FeatureSupport = require('../FeatureSupport'); /** * {@link EdmComplexType} and {@link EdmEntityType} share much information, this * information contained in this class. * * @extends EdmType * @abstract * @hideconstructor * @ignore */ class AbstractEdmStructuredType extends EdmType { /** * Creates an instance of AbstractEdmStructuredType. * * @param {Edm} edm The edm itself * @param {FullQualifiedName} fqn The full qualified name of this structured type * @param {EdmType.TypeKind|number} kind The kind of this structured type * @param {CsdlEntityType|CsdlComplexType} csdlStructuredType The structured object * @param {Object} configuration Configuration object with additional configuration properties * @param {string[]} configuration.customAggregates the custom aggregates defined for this type */ constructor(edm, fqn, kind, csdlStructuredType, configuration = {}) { validateThat('edm', edm).truthy(); super(fqn, kind); validateThat('csdlStructuredType', csdlStructuredType).truthy(); if (csdlStructuredType.isOpenType) { FeatureSupport.failUnsupported(FeatureSupport.features.AttributeOpenType); } if (csdlStructuredType.isAbstract) { FeatureSupport.failUnsupported(FeatureSupport.features.AttributeAbstract); } this._edm = edm; /** * * @type {CsdlEntityType|CsdlComplexType} * @private */ this.csdlStructuredType = csdlStructuredType; /** * @type {Map.<string, EdmProperty>} * @private */ this._properties = null; /** * @type {Map.<string, EdmProperty>} * @private */ this._ownProperties = null; /** * @type {Map.<string, EdmNavigationProperty>} * @private */ this._navigationProperties = null; /** * @type {Map.<string, EdmNavigationProperty>} * @private */ this._ownNavigationProperties = null; /** * @type {EdmAnnotation[]} * @private */ this._annotations = null; this._configuration = configuration; } /** * Returns a base type of this instance. The base type is the object from which * this instance inherits properties, navigation properties, etc... * * @returns {?(EdmEntityType|EdmComplexType)} The base type if defined or null * @abstract */ getBaseType() { // Throw an error if the child type does not overwrite this method throw new NotImplementedError(); } /** * Returns a Map of structural properties. These properties are defined in the type of the * current instance and are not inherited from any baseType. * * @returns {Map.<string, EdmProperty>} A Map of structural properties */ getOwnProperties() { if (!this._ownProperties) { this._ownProperties = new Map(); this.csdlStructuredType.properties.forEach( property => this._ownProperties.set(property.name, new EdmProperty(this._edm, property))); } return this._ownProperties; } /** * Returns the requested property found by its name. This can either be a navigation property * of type EdmNavigationProperty or a structural property of type EdmProperty. * * @param {string} name Name of the requested property. * @returns {EdmProperty|EdmNavigationProperty} */ getProperty(name) { return this.getStructuralProperty(name) || this.getNavigationProperty(name); } /** * Returns a single structural property instance found by its name. * * @param {string} name Name of the requested structural property * @returns {EdmProperty} The requested property if found, else null */ getStructuralProperty(name) { return this.getProperties().get(name); } /** * Returns a single navigation property instance found by its name. * * @param {string} name Name of the requested navigation property * @returns {EdmNavigationProperty} The requested property if found, else null */ getNavigationProperty(name) { return this.getNavigationProperties().get(name); } /** * Returns a Map of navigation properties. These properties are defined in the type of the * current instance and are not inherited from any baseType. * * @returns {Map.<string, EdmNavigationProperty>} A Map of navigation properties */ getOwnNavigationProperties() { if (!this._ownNavigationProperties) { this._ownNavigationProperties = new Map(); this.csdlStructuredType.navigationProperties.forEach( property => this._ownNavigationProperties.set(property.name, new EdmNavigationProperty(this._edm, property))); } return this._ownNavigationProperties; } /** * Returns true if the provided type is compatible to this instance type. A type is compatible * to this type if it is a base type of this type, i.e., in the inheritance hierarchy * a derived type is compatible to its parent type but not the opposite way. * In other words: derived.compatibleTo(parent) --> true. * @param {AbstractEdmStructuredType} type * @returns {boolean} True if this type is compatible to provided type, else false */ compatibleTo(type) { return this === type || (this.getBaseType() ? this.getBaseType() === type || this.getBaseType().compatibleTo(type) : false); } /** * Returns a Map of structural properties. * * @returns {Map.<string, EdmProperty>} A Map of structural properties */ getProperties() { if (!this._properties) { this._properties = new Map(this.getBaseType() ? this.getBaseType().getProperties() : []); this.getOwnProperties().forEach(property => this._properties.set(property.getName(), property)); } return this._properties; } /** * Returns a map of navigation properties including those from base type. * * @returns {Map.<string, EdmNavigationProperty>} A Map of navigation properties */ getNavigationProperties() { if (!this._navigationProperties) { this._navigationProperties = new Map( this.getBaseType() ? this.getBaseType().getNavigationProperties() : []); this.getOwnNavigationProperties().forEach( property => this._navigationProperties.set(property.getName(), property)); } return this._navigationProperties; } /** * Returns true if this type is an open type. * * @returns {boolean} Return true if this type is open type, else false */ isOpenType() { return this.csdlStructuredType.isOpenType; } /** * Returns true if this type is an abstract type. * * @returns {boolean} Return true if this type is abstract type, else false */ isAbstract() { return this.csdlStructuredType.isAbstract; } /** * Returns the annotations for this object * * @returns {EdmAnnotation[]} */ getAnnotations() { if (!this._annotations) { this._annotations = this.csdlStructuredType.annotations.map(item => new EdmAnnotation(this._edm, item)); } return this._annotations; } /** * Returns the custom aggregates for this structured type. * @returns {Map.<string, EdmPrimitiveType|EdmTypeDefinition>} a Map of custom aggregates */ getCustomAggregates() { if (!this._customAggregates) { this._customAggregates = new Map(); if (this._configuration && this._configuration.customAggregates) { for (const name of Object.keys(this._configuration.customAggregates)) { this._customAggregates.set(name, EdmTypeFactory.createTypeFromFQN(this._edm, FullQualifiedName.createFromNameSpaceAndName(this._configuration.customAggregates[name]))); } } } return this._customAggregates; } /** * Returns the custom aggregation methods for this structured type. * @returns {Map.<string, EdmPrimitiveType|EdmTypeDefinition>} a Map of custom aggregation methods */ getCustomAggregationMethods() { if (!this._customAggregationMethods) { this._customAggregationMethods = new Map(); if (this._configuration && this._configuration.customAggregationMethods) { for (const name of Object.keys(this._configuration.customAggregationMethods)) { this._customAggregationMethods.set(name, EdmTypeFactory.createTypeFromFQN(this._edm, FullQualifiedName.createFromNameSpaceAndName( this._configuration.customAggregationMethods[name]))); } } } return this._customAggregationMethods; } } module.exports = AbstractEdmStructuredType;