@openui5/sap.ui.core
Version:
OpenUI5 Core Library sap.ui.core
290 lines (255 loc) • 9.72 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2026 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
// Provides class sap.ui.core.webc.WebComponentMetadata
sap.ui.define([
"../ElementMetadata",
"./WebComponentRenderer",
"sap/base/strings/camelize",
"sap/base/strings/hyphenate"
],
function(ElementMetadata, WebComponentRenderer, camelize, hyphenate) {
"use strict";
var MAPPING_TYPES = ["property", "style", "textContent", "slot", "none"];
/**
* Creates a new metadata object for a WebComponent Wrapper subclass.
*
* @param {string} sClassName fully qualified name of the class that is described by this metadata object
* @param {object} oClassInfo static info to construct the metadata from
*
* @class
* @author SAP SE
* @version 1.147.0
* @since 1.138.0
* @alias sap.ui.core.webc.WebComponentMetadata
* @extends sap.ui.core.ElementMetadata
* @public
*/
var WebComponentMetadata = function(sClassName, oClassInfo) {
// call super constructor
ElementMetadata.apply(this, arguments);
};
//chain the prototypes
WebComponentMetadata.prototype = Object.create(ElementMetadata.prototype);
WebComponentMetadata.prototype.constructor = WebComponentMetadata;
// mapping validation function
var fnValidateType = function (sType) {
return MAPPING_TYPES.includes(sType) ? sType : MAPPING_TYPES[0];
};
// Enrich property factory
var OriginalProperty = ElementMetadata.prototype.metaFactoryProperty;
var WebComponentProperty = function(oClass, name, info) {
OriginalProperty.apply(this, arguments);
if (!info.mapping || typeof info.mapping === "string") {
this._sMapping = fnValidateType(info.mapping);
} else if (typeof info.mapping === "object") {
this._sMapping = fnValidateType(info.mapping.type);
this._sMapTo = info.mapping.to;
this._sSlotName = info.mapping.slotName;
this._fnMappingFormatter = info.mapping.formatter;
this._fnMappingParser = info.mapping.parser;
}
};
WebComponentProperty.prototype = Object.create(OriginalProperty.prototype);
WebComponentProperty.prototype.constructor = WebComponentProperty;
WebComponentMetadata.prototype.metaFactoryProperty = WebComponentProperty;
// Enrich aggregation factory
var OriginalAggregation = ElementMetadata.prototype.metaFactoryAggregation;
var WebComponentAggregation = function(oClass, name, info) {
OriginalAggregation.apply(this, arguments);
this._sSlot = info.slot || "";
};
WebComponentAggregation.prototype = Object.create(OriginalAggregation.prototype);
WebComponentAggregation.prototype.constructor = WebComponentAggregation;
WebComponentMetadata.prototype.metaFactoryAggregation = WebComponentAggregation;
// Enrich association factory
var OriginalAssociation = ElementMetadata.prototype.metaFactoryAssociation;
var WebComponentAssociation = function(oClass, name, info) {
OriginalAssociation.apply(this, arguments);
if (!info.mapping || typeof info.mapping !== "object") {
this._sMapping = ""; // For associations, "mapping" must be an object, because "to" is required
} else {
this._sMapping = "property"; // Associations map only to properties, no matter what is set, it's always "property" mapping
this._sMapTo = info.mapping.to; // The property, to which the association is related
this._fnMappingFormatter = info.mapping.formatter;
this._fnMappingParser = info.mapping.parser;
}
};
WebComponentAssociation.prototype = Object.create(OriginalAssociation.prototype);
WebComponentAssociation.prototype.constructor = WebComponentAssociation;
WebComponentMetadata.prototype.metaFactoryAssociation = WebComponentAssociation;
// Enrich event factory
var OriginalEvent = ElementMetadata.prototype.metaFactoryEvent;
var WebComponentEvent = function(oClass, name, info) {
OriginalEvent.apply(this, arguments);
if (info.mapping) {
this._sMapTo = info.mapping.to;
}
this._sCustomEventName = this._sMapTo ? this._sMapTo : hyphenate(name); // Create the custom event name from the mapping or the event name itself (then hyphenated)
};
WebComponentEvent.prototype = Object.create(OriginalEvent.prototype);
WebComponentEvent.prototype.constructor = WebComponentEvent;
WebComponentMetadata.prototype.metaFactoryEvent = WebComponentEvent;
WebComponentMetadata.prototype.applySettings = function(oClassInfo) {
var oStaticInfo = oClassInfo.metadata;
this._sTag = oStaticInfo.tag;
this._aMethods = oStaticInfo.methods || [];
this._aGetters = oStaticInfo.getters || [];
ElementMetadata.prototype.applySettings.call(this, oClassInfo);
};
WebComponentMetadata.prototype.generateAccessors = function() {
ElementMetadata.prototype.generateAccessors.call(this);
var proto = this.getClass().prototype;
// Generate accessors for proxied public methods - only if not created explicitly already
this._aMethods.forEach(function(name) {
if (!proto[name]) {
proto[name] = function() {
return this.__callPublicMethod(name, arguments);
};
}
});
// Generate accessors for proxied public getters - only if not created explicitly already
this._aGetters.forEach(function(name) {
var functionName = "get" + name.substr(0, 1).toUpperCase() + name.substr(1);
if (!proto[functionName]) {
proto[functionName] = function() {
return this.__callPublicGetter(name);
};
}
});
};
/**
* Returns the tag, used to render the Component Wrapper
* @public
* @returns {string}
*/
WebComponentMetadata.prototype.getTag = function() {
return this._sTag;
};
/**
* Returns the list of public methods, proxied by the Component Wrapper to the component itself
* @public
* @returns {Array}
*/
WebComponentMetadata.prototype.getMethods = function() {
return this._aMethods;
};
/**
* Returns the list of public getters, proxied by the Component Wrapper to the component itself
* @public
* @returns {Array}
*/
WebComponentMetadata.prototype.getGetters = function() {
return this._aGetters;
};
/**
* Returns the slot to be assigned to a particular aggregation's items
* @private
*/
WebComponentMetadata.prototype.getAggregationSlot = function(sAggregationName) {
var oAggregation = this._mAllAggregations[sAggregationName];
return oAggregation ? oAggregation._sSlot : undefined;
};
/**
* Determines whether the attribute corresponds to a managed property
* @param sAttr the attribute's name
* @returns {boolean}
*/
WebComponentMetadata.prototype.isManagedAttribute = function(sAttr) {
var mProperties = this.getAllProperties();
for (var propName in mProperties) {
if (mProperties.hasOwnProperty(propName)) {
var propData = mProperties[propName];
if (propData._sMapping === "property" && (propData._sMapTo === sAttr || camelize(sAttr) === propName)) {
return true;
}
}
}
var mAssociations = this.getAllAssociations();
for (var sAssocName in mAssociations) {
if (mAssociations.hasOwnProperty(sAssocName)) {
var oAssocData = mAssociations[sAssocName];
if (oAssocData._sMapping === "property" && oAssocData._sMapTo === camelize(sAttr)) {
return true;
}
}
}
return false;
};
/**
* Returns a map, containing all properties of a certain mapping type
* @param {string} sMapping mapping type
* @returns {Object} map of all properties of a certain mapping type
*/
WebComponentMetadata.prototype.getPropertiesByMapping = function(sMapping) {
var mFiltered = {};
var mProperties = this.getAllProperties();
var mPrivateProperties = this.getAllPrivateProperties();
for (var propName in mProperties) {
if (mProperties.hasOwnProperty(propName)) {
var propData = mProperties[propName];
if (propData._sMapping === sMapping) {
mFiltered[propName] = propData;
}
}
}
for (var propName in mPrivateProperties) {
if (mPrivateProperties.hasOwnProperty(propName)) {
var propData = mPrivateProperties[propName];
if (propData._sMapping === sMapping) {
mFiltered[propName] = propData;
}
}
}
return mFiltered;
};
/**
* Returns a map of all associations that control properties (have mapping to properties)
* @returns {Object} map of all associations having mappings
*/
WebComponentMetadata.prototype.getAssociationsWithMapping = function() {
var mFiltered = {};
var mAssociations = this.getAllAssociations();
for (var sAssocName in mAssociations) {
if (mAssociations.hasOwnProperty(sAssocName)) {
var oAssocData = mAssociations[sAssocName];
if (oAssocData._sMapping) {
mFiltered[sAssocName] = oAssocData;
}
}
}
return mFiltered;
};
/**
* Returns a map of all events that are custom events (have mapping to a custom event)
* @param {string} [sCustomEventName] if provided, only returns the event with this name
* @returns {Object} map of custom events, where the key is the event name and the value is the event metadata object
*/
WebComponentMetadata.prototype.getCustomEvents = function(sCustomEventName) {
var mFiltered = {};
var mEvents = this.getAllEvents();
for (var sEventName in mEvents) {
var oEventObj = mEvents[sEventName];
if (oEventObj._sCustomEventName) {
if (!sCustomEventName || oEventObj._sCustomEventName === sCustomEventName) {
mFiltered[sEventName] = oEventObj;
}
}
}
return mFiltered;
};
/**
* Retrieves the renderer for the described web component class.
* Note: this is always the default renderer and Web Component wrappers should not define their own renderers.
* @public
*/
WebComponentMetadata.prototype.getRenderer = function() {
if (this._oRenderer) {
return this._oRenderer;
}
return WebComponentRenderer;
};
return WebComponentMetadata;
});