@openui5/sap.ui.core
Version:
OpenUI5 Core Library sap.ui.core
867 lines (832 loc) • 225 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
// Provides the base class for all objects with managed properties and aggregations.
sap.ui.define([
'./BindingParser',
'./DataType',
'./EventProvider',
'./ManagedObjectMetadata',
'./Object',
'../model/BindingMode',
'../model/StaticBinding',
'../model/CompositeBinding',
'../model/Context',
'../model/FormatException',
'../model/ParseException',
'../model/Type',
'../model/ValidateException',
"sap/ui/base/SyncPromise",
"sap/ui/util/ActivityDetection",
"sap/base/util/ObjectPath",
"sap/base/Log",
"sap/base/assert",
"sap/base/util/deepClone",
"sap/base/util/deepEqual",
"sap/base/util/uid",
"sap/base/util/extend",
"sap/base/util/isEmptyObject"
], function(
BindingParser,
DataType,
EventProvider,
ManagedObjectMetadata,
BaseObject,
BindingMode,
StaticBinding,
CompositeBinding,
Context,
FormatException,
ParseException,
Type,
ValidateException,
SyncPromise,
ActivityDetection,
ObjectPath,
Log,
assert,
deepClone,
deepEqual,
uid,
extend,
isEmptyObject
) {
"use strict";
// shortcut for the sap.ui.core.ID type
var IDType;
/**
* Constructs and initializes a managed object with the given <code>sId</code> and settings.
*
* If the optional <code>mSettings</code> are given, they must be a simple object
* that defines values for properties, aggregations, associations or events keyed by their name.
*
* <b>Valid Names and Value Ranges:</b>
*
* The property (key) names supported in the object literal are exactly the (case sensitive)
* names documented in the JSDoc for the properties, aggregations, associations and events
* of the current class and its base classes. Note that for 0..n aggregations and associations this
* name usually is the plural name, whereas it is the singular name in case of 0..1 relations.
*
* The possible values for a setting depend on its kind:
* <ul>
* <li>for simple properties, the value has to match the documented type of the property (no type conversion occurs)</li>
* <li>for 0..1 aggregations, the value has to be an instance of the aggregated type</li>
* <li>for 0..n aggregations, the value has to be an array of instances of the aggregated type or a single instance</li>
* <li>for 0..1 associations, an instance of the associated type or an id (string) is accepted</li>
* <li>for 0..n associations, an array of instances of the associated type or of IDs is accepted</li>
* <li>for events, either a function (event handler) is accepted or an array of length 2
* where the first element is a function and the 2nd element is an object to invoke the method on;
* or an array of length 3, where the first element is an arbitrary payload object, the
* second one is a function and the 3rd one is an object to invoke the method on;
* or an array of arrays where each nested array has the 2 or 3 element structure
* described before (multiple listeners).</li>
* </ul>
*
* Each subclass should document the name and type of its supported settings in its constructor documentation.
*
* Example usage:
* <pre>
* new Dialog({
* title: "Some title text", // property of type "string"
* showHeader: true, // property of type "boolean"
* endButton: new Button(...), // 0..1 aggregation
* content: [ // 0..n aggregation
* new Input(...),
* new Input(...)
* ],
* afterClose: function(oEvent) { ... } // event handler function
* });
* </pre>
*
* Instead of static values and object instances, data binding expressions can be used, either embedded in
* a string or as a binding info object as described in {@link #bindProperty} or {@link #bindAggregation}.
*
* Example usage:
* <pre>
* new Dialog({
* title: "{/title}", // embedded binding expression, points to a string property in the data model
* ...
* content: { // binding info object
* path : "/inputItems", // points to a collection in the data model
* template : new Input(...)
* }
* });
* </pre>
*
* Note that when setting string values, any curly braces in those values need to be escaped, so they are not
* interpreted as binding expressions. Use {@link #escapeSettingsValue} to do so.
*
* Besides the settings documented below, ManagedObject itself supports the following special settings:
* <ul>
* <li><code>id : <i>sap.ui.core.ID</i></code> an ID for the new instance. Some subclasses (Element, Component) require the id
* to be unique in a specific scope (e.g. an Element Id must be unique across all Elements, a Component id must
* be unique across all Components).
* <li><code>models : <i>object</i></code> a map of {@link sap.ui.model.Model} instances keyed by their model name (alias).
* Each entry with key <i>k</i> in this object has the same effect as a call <code>this.setModel(models[k], k);</code>.</li>
* <li><code>bindingContexts : <i>object</i></code> a map of {@link sap.ui.model.Context} instances keyed by their model name.
* Each entry with key <i>k</i> in this object has the same effect as a call <code>this.setBindingContext(bindingContexts[k], k);</code></li>
* <li><code>objectBindings : <i>object</i></code> a map of binding paths keyed by the corresponding model name.
* Each entry with key <i>k</i> in this object has the same effect as a call <code>this.bindObject(objectBindings[k], k);</code></li>
* <li><code>metadataContexts : <i>object</i></code> an array of single binding contexts keyed by the corresponding model or context name.
* The purpose of the <code>metadataContexts</code> special setting is to deduce as much information as possible from the binding context of the control in order
* to be able to predefine certain standard properties like e.g. <i>visible, enabled, tooltip,...</i>
*
* The structure is an array of single contexts, where a single context is a map containing the following keys:
* <ul>
* <li><code>path: <i>string (mandatory)</i></code> The path to the corresponding model property or object, e.g. '/Customers/Name'. A path can also be relative, e.g. 'Name'</li>
* <li><code>model: <i>string (optional)</i></code> The name of the model, in case there is no name then the undefined model is taken</li>
* <li><code>name: <i>string (optional)</i></code> A name for the context to used in templating phase</li>
* <li><code>kind: <i>string (optional)</i></code> The kind of the adapter, either <code>field</code> for single properties or <code>object</code> for structured contexts.
* <li><code>adapter: <i>string (optional)</i></code> The path to an interpretion class that dilivers control relevant data depending on the context, e.g. enabled, visible.
* If not supplied the OData meta data is interpreted.</li>
* </ul>
* The syntax for providing the <code>metadataContexts</code> is as follows:
* <code>{SINGLE_CONTEXT1},...,{SINGLE_CONTEXTn}</code> or for simplicity in case there is only one context <code>{SINGLE_CONTEXT}</code>.
*
* Examples for such metadataContexts are:
* <ul>
* <li><code>{/Customers/Name}</code> a single part with an absolute path to the property <i>Name</i> of the <i>Customers</i> entity set in the default model</li>
* <li><code>{path: 'Customers/Name', model:'json'}</code> a single part with an absolute path to the property <i>Name</i> of the <i>Customers</i> entity set in a named model</li>
* <li><code>{parts: [{path: 'Customers/Name'},{path: 'editable', model: 'viewModel'}]}</code> a combination of single binding contexts, one context from the default model and one from the viewModel</li>
* </ul></li>
* </ul>
*
* @param {string} [sId] ID for the new managed object; generated automatically if no non-empty ID is given
* <b>Note:</b> this can be omitted, no matter whether <code>mSettings</code> will be given or not!
* @param {object} [mSettings] Optional map/JSON-object with initial property values, aggregated objects etc. for the new object
* @param {object} [oScope] Scope object for resolving string based type and formatter references in bindings.
* When a scope object is given, <code>mSettings</code> cannot be omitted, at least <code>null</code> or an empty object literal must be given.
*
*
* @abstract
* @class Base Class that introduces some basic concepts, such as, state management and data binding.
*
* New subclasses of ManagedObject are created with a call to {@link #.extend ManagedObject.extend} and can make use
* of the following managed features:
*
*
* <h3>Properties</h3>
* Managed properties represent the state of a ManagedObject. They can store a single value of a simple data type
* (like 'string' or 'int'). They have a <i>name</i> (e.g. 'size') and methods to get the current value (<code>getSize</code>),
* or to set a new value (<code>setSize</code>). When a property is modified by calling the setter, the ManagedObject is marked as invalidated.
* A managed property can be bound against a property in a {@link sap.ui.model.Model} by using the {@link #bindProperty} method.
* Updates to the model property will be automatically reflected in the managed property and - if TwoWay databinding is active,
* changes to the managed property will be reflected in the model. An existing binding can be removed by calling {@link #unbindProperty}.
*
* If a ManagedObject is cloned, the clone will have the same values for its managed properties as the source of the
* clone - if the property wasn't bound. If it is bound, the property in the clone will be bound to the same
* model property as in the source.
*
* Details about the declaration of a managed property, the metadata that describes it and the set of methods that are automatically
* generated to access it, can be found in the documentation of the {@link sap.ui.base.ManagedObject.extend extend } method.
*
*
* <h3>Aggregations</h3>
* Managed aggregations can store one or more references to other ManagedObjects. They are a mean to control the lifecycle
* of the aggregated objects: one ManagedObject can be aggregated by at most one parent ManagedObject at any time.
* When a ManagedObject is destroyed, all aggregated objects are destroyed as well and the object itself is removed from
* its parent. That is, aggregations won't contain destroyed objects or null/undefined.
*
* Aggregations have a <i>name</i> ('e.g 'header' or 'items'), a <i>cardinality</i> ('0..1' or '0..n') and are of a specific
* <i>type</i> (which must be a subclass of ManagedObject as well or a UI5 interface). A ManagedObject will provide methods to
* set or get the aggregated object for a specific aggregation of cardinality 0..1 (e.g. <code>setHeader</code>, <code>getHeader</code>
* for an aggregation named 'header'). For an aggregation of cardinality 0..n, there are methods to get all aggregated objects
* (<code>getItems</code>), to locate an object in the aggregation (e.g. <code>indexOfItem</code>), to add, insert or remove
* a single aggregated object (<code>addItem</code>, <code>insertItem</code>, <code>removeItem</code>) or to remove or destroy
* all objects from an aggregation (<code>removeAllItems</code>, <code>destroyItems</code>).
*
* Details about the declaration of a managed aggregation, the metadata that describes the aggregation, and the set of methods that are automatically
* generated to access it, can be found in the documentation of the {@link sap.ui.base.ManagedObject.extend extend} method.
*
* Aggregations of cardinality 0..n can be bound to a collection in a model by using {@link #bindAggregation} (and unbound again
* using {@link #unbindAggregation}). For each context in the model collection, a corresponding object will be created in the
* managed aggregation, either by cloning a template object or by calling a factory function.
*
* Aggregations also control the databinding context of bound objects: by default, aggregated objects inherit all models
* and binding contexts from their parent object.
*
* When a ManagedObject is cloned, all aggregated objects will be cloned as well - but only if they haven't been added by
* databinding. In that case, the aggregation in the clone will be bound to the same model collection.
*
*
* <h3>Associations</h3>
* Managed associations also form a relationship between objects, but they don't define a lifecycle for the
* associated objects. They even can 'break' in the sense that an associated object might have been destroyed already
* although it is still referenced in an association. For the same reason, the internal storage for associations
* are not direct object references but only the IDs of the associated target objects.
*
* Associations have a <i>name</i> ('e.g 'initialFocus'), a <i>cardinality</i> ('0..1' or '0..n') and are of a specific <i>type</i>
* (which must be a subclass of ManagedObject as well or a UI5 interface). A ManagedObject will provide methods to set or get
* the associated object for a specific association of cardinality 0..1 (e.g. <code>setInitialFocus</code>, <code>getInitialFocus</code>).
* For an association of cardinality 0..n, there are methods to get all associated objects (<code>getRefItems</code>),
* to add, insert or remove a single associated object (<code>addRefItem</code>,
* <code>insertRefItem</code>, <code>removeRefItem</code>) or to remove all objects from an association
* (<code>removeAllRefItems</code>).
*
* Details about the declaration of a managed association, the metadata that describes it and the set of methods that are automatically
* generated to access it, can be found in the documentation of the {@link sap.ui.base.ManagedObject.extend extend} method.
*
* Associations can't be bound to the model.
*
* When a ManagedObject is cloned, the result for an association depends on the relationship between the associated target
* object and the root of the clone operation. If the associated object is part of the to-be-cloned object tree (reachable
* via aggregations from the root of the clone operation), then the cloned association will reference the clone of the
* associated object. Otherwise the association will reference the same object as in the original tree.
* When a ManagedObject is destroyed, other objects that are only associated, are not affected by the destroy operation.
*
*
* <h3>Events</h3>
* Managed events provide a mean for communicating important state changes to an arbitrary number of 'interested' listeners.
* Events have a <i>name</i> and (optionally) a set of <i>parameters</i>. For each event there will be methods to add or remove an event
* listener as well as a method to fire the event. (e.g. <code>attachChange</code>, <code>detachChange</code>, <code>fireChange</code>
* for an event named 'change').
*
* Details about the declaration of managed events, the metadata that describes the event, and the set of methods that are automatically
* generated to access it, can be found in the documentation of the {@link sap.ui.base.ManagedObject.extend extend} method.
*
* When a ManagedObject is cloned, all listeners registered for any event in the clone source are also registered to the
* clone. Later changes are not reflected in any direction (neither from source to clone, nor vice versa).
*
*
* <a name="lowlevelapi"><h3>Low Level APIs:</h3></a>
* The prototype of ManagedObject provides several generic, low level APIs to manage properties, aggregations, associations,
* and events. These generic methods are solely intended for implementing higher level, non-generic methods that manage
* a single managed property etc. (e.g. a function <code>setSize(value)</code> that sets a new value for property 'size').
* {@link sap.ui.base.ManagedObject.extend} creates default implementations of those higher level APIs for all managed aspects.
* The implementation of a subclass then can override those default implementations with a more specific implementation,
* e.g. to implement a side effect when a specific property is set or retrieved.
* It is therefore important to understand that the generic low-level methods ARE NOT SUITABLE FOR GENERIC ACCESS to the
* state of a managed object, as that would bypass the overriding higher level methods and their side effects.
*
* @extends sap.ui.base.EventProvider
* @author SAP SE
* @version 1.87.1
* @public
* @alias sap.ui.base.ManagedObject
*/
var ManagedObject = EventProvider.extend("sap.ui.base.ManagedObject", {
metadata : {
"abstract" : true,
publicMethods : [ "getId", "getMetadata", "getModel", "setModel", "hasModel", "bindProperty", "unbindProperty", "bindAggregation", "unbindAggregation", "bindObject", "unbindObject", "getObjectBinding"],
library : "sap.ui.core", // UI Library that contains this class
properties : {
},
aggregations : {
},
associations : {},
events : {
/**
* Fired after a new value for a bound property has been propagated to the model.
* Only fired, when the binding uses a data type.
*/
"validationSuccess" : {
enableEventBubbling : true,
parameters : {
/**
* ManagedObject instance whose property initiated the model update.
*/
element : { type : 'sap.ui.base.ManagedObject' },
/**
* Name of the property for which the bound model property has been updated.
*/
property : { type : 'string' },
/**
* Data type used in the binding.
*/
type : { type : 'sap.ui.model.Type' },
/**
* New value (external representation) as propagated to the model.
*
* <b>Note: </b>the model might modify (normalize) the value again and this modification
* will be stored in the ManagedObject. The 'newValue' parameter of this event contains
* the value <b>before</b> such a normalization.
*/
newValue : { type : 'any' },
/**
* Old value (external representation) as previously stored in the ManagedObject.
*/
oldValue : { type : 'any' }
}
},
/**
* Fired when a new value for a bound property should have been propagated to the model,
* but validating the value failed with an exception.
*/
"validationError" : {
enableEventBubbling : true,
parameters : {
/**
* ManagedObject instance whose property initiated the model update.
*/
element : { type : 'sap.ui.base.ManagedObject' },
/**
* Name of the property for which the bound model property should have been been updated.
*/
property : { type : 'string' },
/**
* Data type used in the binding.
*/
type : { type : 'sap.ui.model.Type' },
/**
* New value (external representation) as parsed and validated by the binding.
*/
newValue : { type : 'any' },
/**
* Old value (external representation) as previously stored in the ManagedObject.
*/
oldValue : { type : 'any' },
/**
* Localized message describing the validation issues
*/
message: { type : 'string' }
}
},
/**
* Fired when a new value for a bound property should have been propagated to the model,
* but parsing the value failed with an exception.
*/
"parseError" : {
enableEventBubbling : true,
parameters : {
/**
* ManagedObject instance whose property initiated the model update.
*/
element : { type : 'sap.ui.base.ManagedObject' },
/**
* Name of the property for which the bound model property should have been been updated.
*/
property : { type : 'string' },
/**
* Data type used in the binding.
*/
type : { type : 'sap.ui.model.Type' },
/**
* New value (external representation) as parsed by the binding.
*/
newValue : { type : 'any' },
/**
* Old value (external representation) as previously stored in the ManagedObject.
*/
oldValue : { type : 'any' },
/**
* Localized message describing the parse error
*/
message: { type : 'string' }
}
},
/**
* Fired when a new value for a bound property should have been propagated from the model,
* but formatting the value failed with an exception.
*/
"formatError" : {
enableEventBubbling : true,
parameters : {
/**
* ManagedObject instance whose property should have received the model update.
*/
element : { type : 'sap.ui.base.ManagedObject' },
/**
* Name of the property for which the binding should have been updated.
*/
property : { type : 'string' },
/**
* Data type used in the binding (if any).
*/
type : { type : 'sap.ui.model.Type' },
/**
* New value (model representation) as propagated from the model.
*/
newValue : { type : 'any' },
/**
* Old value (external representation) as previously stored in the ManagedObject.
*/
oldValue : { type : 'any' }
}
},
/**
* Fired when models or contexts are changed on this object (either by calling setModel/setBindingContext or due to propagation)
*/
"modelContextChange" : {}
},
specialSettings : {
/**
* Unique ID of this instance.
* If not given, a so called autoID will be generated by the framework.
* AutoIDs use a unique prefix that must not be used for Ids that the application (or other code) creates.
* It can be configured option 'autoIDPrefix', see {@link sap.ui.core.Configuration}.
*/
id : 'sap.ui.core.ID',
/**
* A map of model instances to which the object should be attached.
* The models are keyed by their model name. For the default model, String(undefined) is expected.
*/
models : 'object',
/**
* A map of model instances to which the object should be attached.
* The models are keyed by their model name. For the default model, String(undefined) is expected.
*/
bindingContexts : 'object',
/**
* A map of model instances to which the object should be attached.
* The models are keyed by their model name. For the default model, String(undefined) is expected.
*/
objectBindings : 'object',
/**
* A map of model instances to which the object should be attached.
* The models are keyed by their model name. For the default model, String(undefined) is expected.
* The special setting is only for internal use.
*/
metadataContexts: 'object',
/**
* Used by ManagedObject.create.
*/
Type : { type: 'string', visibility: 'hidden' }
}
},
constructor : function(sId, mSettings, oScope) {
var that = this;
EventProvider.call(this); // no use to pass our arguments
if ( typeof sId !== 'string' && sId !== undefined ) {
// shift arguments in case sId was missing, but mSettings was given
oScope = mSettings;
mSettings = sId;
sId = mSettings && mSettings.id;
}
if (!sId) {
sId = this.getMetadata().uid();
} else {
var preprocessor = ManagedObject._fnIdPreprocessor;
sId = (preprocessor ? preprocessor.call(this, sId) : sId);
var oType = IDType || (IDType = DataType.getType("sap.ui.core.ID"));
if (!oType.isValid(sId)) {
throw new Error("\"" + sId + "\" is not a valid ID.");
}
}
this.sId = sId;
// managed object interface
// create an empty property bag that uses a map of defaultValues as its prototype
this.mProperties = this.getMetadata().createPropertyBag();
this.mAggregations = {};
this.mAssociations = {};
// private properties
this.oParent = null;
this.aDelegates = [];
this.aBeforeDelegates = [];
this.iSuppressInvalidate = 0;
this.oPropagatedProperties = ManagedObject._oEmptyPropagatedProperties;
this.mSkipPropagation = {};
// data binding
this.oModels = {};
this.aPropagationListeners = [];
this.oBindingContexts = {};
this.mElementBindingContexts = {};
this.mBindingInfos = {};
this.mObjectBindingInfos = {};
// contextual settings
this._oContextualSettings = ManagedObject._defaultContextualSettings;
// apply the owner id if defined
this._sOwnerId = ManagedObject._sOwnerId;
// make sure that the object is registered before initializing
// and to deregister the object in case of errors
(function() {
var bCreated = false;
// registers the object in the Core
// If registration fails (e.g. due to a duplicate ID), the finally block must not be executed.
// Otherwise, the already existing object would be deregistered mistakenly
if (that.register) {
that.register();
}
try {
// TODO: generic concept for init hooks?
if ( that._initCompositeSupport ) {
that._initCompositeSupport(mSettings);
}
// Call init method here instead of specific Controls constructor.
if (that.init) {
that.init();
}
// apply the settings
that.applySettings(mSettings, oScope);
bCreated = true;
// use try finally here since catch leads to the console pointing to the wrong location of the error
// (not the original error's location but to this constructor)
} finally {
// unregisters the object in the Core
// the assumption is that the object was successfully registered
if (!bCreated && that.deregister) {
that.deregister();
}
}
}());
}
}, /* Metadata constructor */ ManagedObjectMetadata);
/**
* Returns the metadata for the ManagedObject class.
*
* @return {sap.ui.base.ManagedObjectMetadata} Metadata for the ManagedObject class.
* @static
* @public
* @name sap.ui.base.ManagedObject.getMetadata
* @function
*/
/**
* Returns the metadata for the class that this object belongs to.
*
* @return {sap.ui.base.ManagedObjectMetadata} Metadata for the class of the object
* @public
* @name sap.ui.base.ManagedObject#getMetadata
* @function
*/
/**
* Defines a new subclass of ManagedObject with name <code>sClassName</code> and enriches it with
* the information contained in <code>oClassInfo</code>.
*
* <code>oClassInfo</code> can contain the same information that {@link sap.ui.base.Object.extend} already accepts,
* plus the following new properties in the 'metadata' object literal:
*
* <ul>
* <li><code>library : <i>string</i></code></li>
* <li><code>properties : <i>object</i></code></li>
* <li><code>defaultProperty : <i>string</i></code></li>
* <li><code>aggregations : <i>object</i></code></li>
* <li><code>defaultAggregation : <i>string</i></code></li>
* <li><code>associations : <i>object</i></code></li>
* <li><code>events : <i>object</i></code></li>
* <li><code>specialSettings : <i>object</i></code>// this one is still experimental and not for public usage!</li>
* </ul>
*
* Each of these properties is explained in more detail lateron.
*
* Example:
* <pre>
* ManagedObect.extend('sap.mylib.MyClass', {
* metadata : {
* library: 'sap.mylib',
* properties : {
* value: 'string',
* width: 'sap.ui.core.CSSSize',
* height: { type: 'sap.ui.core.CSSSize', defaultValue: '100%'}
* description: { type: 'string', defaultValue: '', selector: '#{id}-desc'}
* },
* defaultProperty : 'value',
* aggregations : {
* header : { type: 'sap.mylib.FancyHeader', multiple : false }
* items : 'sap.ui.core.Control',
* buttons: { type: 'sap.mylib.Button', multiple : true, selector: '#{id} > .sapMLButtonsSection'}
* },
* defaultAggregation : 'items',
* associations : {
* initiallyFocused : { type: 'sap.ui.core.Control' }
* },
* events: {
* beforeOpen : {
* parameters : {
* opener : { type: 'sap.ui.core.Control' }
* }
* }
* },
* },
*
* init: function() {
* }
*
* }); // end of 'extend' call
* </pre>
*
* Detailed explanation of properties<br>
*
*
* <b>'library'</b> : <i>string</i><br>
* Name of the library that the new subclass should belong to. If the subclass is a control or element, it will
* automatically register with that library so that authoring tools can discover it.
* By convention, the name of the subclass should have the library name as a prefix, e.g. 'sap.ui.commons.Panel' belongs
* to library 'sap.ui.commons'.
*
*
* <b>'properties'</b> : <i>object</i><br>
* An object literal whose properties each define a new managed property in the ManagedObject subclass.
* The value can either be a simple string which then will be assumed to be the type of the new property or it can be
* an object literal with the following properties
* <ul>
* <li><code>type: <i>string</i></code> type of the new property. Must either be one of the built-in types
* 'string', 'boolean', 'int', 'float', 'object', 'function' or 'any', or a type created and registered with
* {@link sap.ui.base.DataType.createType} or an array type based on one of the previous types (e.g. 'int[]'
* or 'string[]', but not just 'array').</li>
* <li><code>visibility: <i>string</i></code> either 'hidden' or 'public', defaults to 'public'. Properties that
* belong to the API of a class must be 'public' whereas 'hidden' properties can only be used internally.
* Only public properties are accepted by the constructor or by <code>applySettings</code> or in declarative
* representations like an <code>XMLView</code>. Equally, only public properties are cloned.</li>
* <li><code>byValue: <i>boolean</i></code> (either can be omitted or set to the boolean value <code>true</code>)
* If set to <code>true</code>, the property value will be {@link module:sap/base/util/deepClone deep cloned}
* on write and read operations to ensure that the internal value can't be modified by the outside. The property
* <code>byValue</code> is currently limited to a <code>boolean</code> value. Other types are reserved for future
* use. Class definitions must only use boolean values for the flag (or omit it), but readers of ManagedObject
* metadata should handle any truthy value as <code>true</code> to be future safe.
* Note that using <code>byValue:true</code> has a performance impact on property access and therefore should be
* used carefully. It also doesn't make sense to set this option for properties with a primitive type (they have
* value semantic anyhow) or for properties with arrays of primitive types (they have been cloned already in the
* past with a cheaper implementation). Future versions of UI5 might encourage this as a limitation during class
* definition.
* <li><code>group:<i>string</i></code> a semantic grouping of the properties, intended to be used in design time tools.
* Allowed values are (case sensitive): Accessibility, Appearance, Behavior, Data, Designtime, Dimension, Identification, Misc</li>
* <li><code>defaultValue: <i>any</i></code> the default value for the property or null if there is no defaultValue.</li>
* <li><code>bindable: <i>boolean|string</i></code> (either can be omitted or set to the boolean value <code>true</code> or the magic string 'bindable')
* If set to <code>true</code> or 'bindable', additional named methods <code>bind<i>Name</i></code> and <code>unbind<i>Name</i></code> are generated as convenience.
* Despite its name, setting this flag is not mandatory to make the managed property bindable. The generic methods {@link #bindProperty} and
* {@link #unbindProperty} can always be used. </li>
* <li><code>selector: <i>string</i></code> Optional; can be set to a valid CSS selector (as accepted by the
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector Element.prototype.querySelector}
* method). When set, it locates the DOM element that represents this property's value. It should only be set
* for properties that have a visual text representation in the DOM.
*
* The purpose of the selector is to allow other framework parts or design time tooling to identify the DOM parts
* of a control or element that represent a specific property without knowing the control or element implementation
* in detail.
*
* As an extension to the standard CSS selector syntax, the selector string can contain the placeholder <code>{id}</code>
* (multiple times). Before evaluating the selector in the context of an element or control, all occurrences of the
* placeholder have to be replaced by the (potentially escaped) ID of that element or control.
* In fact, any selector should start with <code>#{id}</code> to ensure that the query result is limited to the
* desired element or control.
*
* <b>Note</b>: there is a convenience method {@link sap.ui.core.Element#getDomRefForSetting} that evaluates the
* selector in the context of a concrete element or control instance. It also handles the placeholder <code>{id}</code>.
* Only selected framework features may use that private method, it is not yet a public API and might be changed
* or removed in future versions of UI5. However, instead of maintaining the <code>selector</code> in the metadata,
* element and control classes can overwrite <code>getDomRefForSetting</code> and determine the DOM element
* dynamically.</li>
* </ul>
* Property names should use camelCase notation, start with a lowercase letter and only use characters from the set [a-zA-Z0-9_$].
* If an aggregation in the literal is preceded by a JSDoc comment (doclet) and if the UI5 plugin and template are used for JSDoc3 generation, the doclet will
* be used as generic documentation of the aggregation.
*
* For each public property 'foo', the following methods will be created by the "extend" method and will be added to the
* prototype of the subclass:
* <ul>
* <li>getFoo() - returns the current value of property 'foo'. Internally calls {@link #getProperty}</li>
* <li>setFoo(v) - sets 'v' as the new value of property 'foo'. Internally calls {@link #setProperty}</li>
* <li>bindFoo(c) - (only if property was defined to be 'bindable'): convenience function that wraps {@link #bindProperty}</li>
* <li>unbindFoo() - (only if property was defined to be 'bindable'): convenience function that wraps {@link #unbindProperty}</li>
* </ul>
* For hidden properties, no methods are generated.
*
*
* <b>'defaultProperty'</b> : <i>string</i><br>
* When specified, the default property must match the name of one of the properties defined for the new subclass (either own or inherited).
* The named property can be used to identify the main property to be used for bound data. E.g. the value property of a field control.
*
*
* <b>'aggregations'</b> : <i>object</i><br>
* An object literal whose properties each define a new aggregation in the ManagedObject subclass.
* The value can either be a simple string which then will be assumed to be the type of the new aggregation or it can be
* an object literal with the following properties
* <ul>
* <li><code>type: <i>string</i></code> type of the new aggregation. must be the full global name of a ManagedObject subclass or UI5 interface (in dot notation, e.g. 'sap.m.Button')</li>
* <li><code>[multiple]: <i>boolean</i></code> whether the aggregation is a 0..1 (false) or a 0..n aggregation (true), defaults to true </li>
* <li><code>[singularName]: <i>string</i></code>. Singular name for 0..n aggregations. For 0..n aggregations the name by convention should be the plural name.
* Methods affecting multiple objects in an aggregation will use the plural name (e.g. getItems(), whereas methods that deal with a single object will use
* the singular name (e.g. addItem). The framework knows a set of common rules for building plural form of English nouns and uses these rules to determine
* a singular name on its own. if that name is wrong, a singluarName can be specified with this property. </li>
* <li><code>[visibility]: <i>string</i></code> either 'hidden' or 'public', defaults to 'public'. Aggregations that
* belong to the API of a class must be 'public' whereas 'hidden' aggregations typically are used for the
* implementation of composite classes (e.g. composite controls). Only public aggregations are accepted by
* the constructor or by <code>applySettings</code> or in declarative representations like an <code>XMLView</code>.
* Equally, only public aggregations are cloned.</li>
* <li><code>bindable: <i>boolean|string</i></code> (either can be omitted or set to the boolean value <code>true</code> or the magic string 'bindable')
* If set to <code>true</code> or 'bindable', additional named methods <code>bind<i>Name</i></code> and <code>unbind<i>Name</i></code> are generated as convenience.
* Despite its name, setting this flag is not mandatory to make the managed aggregation bindable. The generic methods {@link #bindAggregation} and
* {@link #unbindAggregation} can always be used. </li>
* <li><code>forwarding: <i>object</i></code>
* If set, this defines a forwarding of objects added to this aggregation into an aggregation of another ManagedObject - typically to an inner control
* within a composite control.
* This means that all adding, removal, or other operations happening on the source aggregation are actually called on the target instance.
* All elements added to the source aggregation will be located at the target aggregation (this means the target instance is their parent).
* Both, source and target element will return the added elements when asked for the content of the respective aggregation.
* If present, the named (non-generic) aggregation methods will be called for the target aggregation.
* Aggregations can only be forwarded to non-hidden aggregations of the same or higher multiplicity (i.e. an aggregation with multiplicity "0..n" cannot be
* forwarded to an aggregation with multiplicity "0..1").
* The target aggregation must also be "compatible" to the source aggregation in the sense that any items given to the source aggregation
* must also be valid in the target aggregation (otherwise the target element will throw a validation error).
* If the forwarded elements use data binding, the target element must be properly aggregated by the source element to make sure all models are available there
* as well.
* The aggregation target must remain the same instance across the entire lifetime of the source control.
* Aggregation forwarding will behave unexpectedly when the content in the target aggregation is modified by other actors (e.g. by the target element or by
* another forwarding from a different source aggregation). Hence, this is not allowed.
* The forwarding configuration object defines the target of the forwarding. The available settings are:
* <ul>
* <li><code>idSuffix: <i>string</i></code>A string which is appended to the ID of <i>this</i> ManagedObject to construct the ID of the target ManagedObject. This is
* one of the two options to specify the target. This option requires the target instance to be created in the init() method of this ManagedObject and to be
* always available.</li>
* <li><code>getter: <i>string</i></code>The name of the function on instances of this ManagedObject which returns the target instance. This second option
* to specify the target can be used for lazy instantiation of the target. Note that either idSuffix or getter must be given. Also note that the target
* instance returned by the getter must remain the same over the entire lifetime of this ManagedObject and the implementation assumes that all instances return
* the same type of object (at least the target aggregation must always be defined in the same class).</li>
* <li><code>aggregation: <i>string</i></code>The name of the aggregation on the target into which the objects shall be forwarded. The multiplicity of the target
* aggregation must be the same as the one of the source aggregation for which forwarding is defined.</li>
* <li><code>[forwardBinding]: <i>boolean</i></code>Whether any binding should happen on the forwarding target or not. Default if omitted is <code>false</code>,
* which means any bindings happen on the outer ManagedObject. When the binding is forwarded, all binding methods like updateAggregation, getBindingInfo,
* refreshAggregation etc. are called on the target element of the forwarding instead of being called on this element. The basic aggregation mutator methods
* (add/remove etc.) are only called on the forwarding target element. Without forwardBinding, they are called on this element, but forwarded to the forwarding
* target, where they actually modify the aggregation.
* </li>
* </ul>
* </li>
* <li><code>selector: <i>string</i></code> Optional; can be set to a valid CSS selector (as accepted by the
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector Element.prototype.querySelector}
* method). When set, it locates the DOM element that surrounds the aggregation's content. It should only be
* set for aggregations that have a visual representation in the DOM. A DOM element surrounding the aggregation's
* rendered content should be available in the DOM, even if the aggregation is empty or not rendered for some reason.
* In cases where this is not possible or not intended, <code>getDomRefForSetting</code> can be overridden, see below.
*
* The purpose of the selector is to allow other framework parts like drag and drop or design time tooling to identify
* those DOM parts of a control or element that represent a specific aggregation without knowing the control or element
* implementation in detail.
*
* As an extension to the standard CSS selector syntax, the selector string can contain the placeholder <code>{id}</code>
* (multiple times). Before evaluating the selector in the context of an element or control, all occurrences of the
* placeholder have to be replaced by the (potentially escaped) ID of that element or control.
* In fact, any selector should start with <code>#{id}</code> to ensure that the query result is limited to the
* desired element or control.
*
* <b>Note</b>: there is a convenience method {@link sap.ui.core.Element#getDomRefForSetting} that evaluates the
* selector in the context of a concrete element or control instance. It also handles the placeholder <code>{id}</code>.
* Only selected framework features may use that private method, it is not yet a public API and might be changed
* or removed in future versions of UI5. However, instead of maintaining the <code>selector</code> in the metadata,
* element and control classes can overwrite <code>getDomRefForSetting</code> to calculate or add the appropriate
* DOM Element dynamically.</li>
* </li>
* </ul>
* Aggregation names should use camelCase notation, start with a lowercase letter and only use characters from the set [a-zA-Z0-9_$].
* The name for a hidden aggregations might start with an underscore.
* If an aggregation in the literal is preceded by a JSDoc comment (doclet) and if the UI5 plugin and template are used for JSDoc3 generation, the doclet will
* be used as generic documentation of the aggregation.
*
* For each public aggregation 'item' of cardinality 0..1, the following methods will be created by the "extend" method and will be added to the
* prototype of the subclass:
* <ul>
* <li>getItem() - returns the current value of aggregation 'item'. Internally calls {@link #getAggregation} with a default value of <code>undefined</code></li>
* <li>setItem(o) - sets 'o' as the new aggregated object in aggregation 'item'. Internally calls {@link #setAggregation}</li>
* <li>destroyItem(o) - destroy a currently aggregated object in aggregation 'item' and clears the aggregation. Internally calls {@link #destroyAggregation}</li>
* <li>bindItem(c) - (only if aggregation was defined to be 'bindable'): convenience function that wraps {@link #bindAggregation}</li>
* <li>unbindItem() - (only if aggregation was defined to be 'bindable'): convenience function that wraps {@link #unbindAggregation}</li>
* </ul>
* For a public aggregation 'items' of cardinality 0..n, the following methods will be created:
* <ul>
* <li>getItems() - returns an array with the objects contained in aggregation 'items'. Internally calls {@link #getAggregation} with a default value of <code>[]</code></li>
* <li>addItem(o) - adds an object as last element in the aggregation 'items'. Internally calls {@link #addAggregation}</li>
* <li>insertItem(o,p) - inserts an object into the aggregation 'items'. Internally calls {@link #insertAggregation}</li>
* <li>indexOfItem(o) - returns the position of the given object within the aggregation 'items'. Internally calls {@link #indexOfAggregation}</li>
* <li>removeItem(v) - removes an object from the aggregation 'items'. Internally calls {@link #removeAggregation}</li>
* <li>removeItems() - removes all objects from the aggregation 'items'. Internally calls {@link #removeAllAggregation}</li>
* <li>destroyItems() - destroy all currently aggregated objects in aggregation 'items' and clears the aggregation. Internally calls {@link #destroyAggregation}</li>
* <li>bindItems(c) - (only if aggregation was defined to be 'bindable'): convenience function that wraps {@link #bindAggregation}</li>
* <li>unbindItems() - (only if aggregation was defined to be 'bindable'): convenience function that wraps {@link #unbindAggregation}</li>
* </ul>
* For hidden aggregations, no methods are generated.
*
*
* <b>'defaultAggregation'</b> : <i>string</i><br>
* When specified, the default aggregation must match the name of one of the aggregations defined for the new subclass (either own or inherited).
* The named aggregation will be used in contexts where no aggregation is specified. E,g. when an object in an XMLView embeds other objects without
* naming an aggregation, as in the following example:
* <pre>
* <!-- assuming the defaultAggregation for Dialog is 'content' -->
* <Dialog>
* <Text/>
* <Button/>
* </Dialog>
* </pre>
*
*
* <b>'associations'</b> : <i>object</i><br>
* An object literal whose properties each define a new association of the ManagedObject subclass.
* The value can either be a simple string which then will be assumed to be the type of the new association or it can be
* an object literal with the following properties
* <ul>
* <li><code>type: <i>string</i></code> type of the new association</li>
* <li><code>multiple: <i>boolean</i></code> whether the association is a 0..1 (false) or a 0..n association (true), defaults to false(1) for associations</li>
* <li><code>[singularName]: <i>string</i></code>. Singular name for 0..n associations. For 0..n associations the name by convention should be the plural name.
* Methods affecting multiple objects in an association will use the plural name (e.g. getItems(), whereas methods that deal with a single object will use
* the singular name (e.g. addItem). The framework knows a set of common rules for building plural form of English nouns and uses these rules to determine
* a singular name on its own. if that name is wrong, a singluarName can be specified with this property.</li>
* <li><code>visibility: <i>string</i></code> either 'hidden' or 'public', defaults to 'public'. Associations that
* belong to the API of a class must be 'public' whereas 'hidden' associations can only be used internally.
* Only public associations are accepted by the constructor or by <code>applySettings</code> or in declarative
* representations like an <code>XMLView</code>. Equally, only public associations are cloned.</li>
* </ul>
* Association names should use camelCase notation, start with a lowercase letter and only use characters from the set [a-zA-Z0-9_$].
* If an association in the literal is preceded by a JSDoc comment (doclet) and if the UI5 plugin and template are used for JSDoc3 generation, the doclet will
* be used as generic documentation of the association.
*
* For each association 'ref' of cardinality 0..1, the following methods will be created by the "extend" method and will be added to the
* prototype of the subclass:
* <ul>
* <li>getRef() - returns the current value of association 'item'. Internally calls {@link #getAssociation} with a default value of <code>undefined</code></li>
* <li>setRef(o) - sets 'o' as the new associated object in association 'item'. Internally calls {@link #setAssociation}</li>
* </ul>
* For a public association 'refs' of cardinality 0..n, the following methods will be created:
* <ul>
* <li>getRefs() - returns an array with the objects contained in association 'items'. Internally calls {@link #getAssociation} with a default value of <code>[]</code></li>
* <li>addRef(o) - adds an object as last element in the association 'item