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