text: /*!
   * UI development toolkit for HTML5 (OpenUI5)
   * (c) Copyright 2009-2016 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([
  		'jquery.sap.global',
  		'./BindingParser', './DataType', './EventProvider', './ManagedObjectMetadata',
  		'../model/BindingMode', '../model/CompositeBinding', '../model/Context', '../model/FormatException', '../model/ListBinding',
  		'../model/Model', '../model/ParseException', '../model/TreeBinding', '../model/Type', '../model/ValidateException',
  		'jquery.sap.act', 'jquery.sap.script', 'jquery.sap.strings'
  	], function(
  		jQuery,
  		BindingParser, DataType, EventProvider, ManagedObjectMetadata,
  		BindingMode, CompositeBinding, Context, FormatException, ListBinding,
  		Model, ParseException, TreeBinding, Type, ValidateException
  		/* , jQuerySap2, jQuerySap, jQuerySap1 */) {
  
  	"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.
  	 *
  	 * If a key name is ambiguous for a specific managed object class (e.g. a property has the same
  	 * name as an event), then this method prefers property, aggregation, association and
  	 * event in that order. To resolve such ambiguities, the keys can be prefixed with
  	 * <code>aggregation:</code>, <code>association:</code> or <code>event:</code>
  	 * (such keys containing a colon (':') must be quoted to be valid Javascript).
  	 *
  	 * 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>for 0..1 aggregations, the value has to be an instance of the aggregated type
  	 * <li>for 0..n aggregations, the value has to be an array of instances of the aggregated type or a single instance
  	 * <li>for 0..1 associations, an instance of the associated type or an id (string) is accepted
  	 * <li>for 0..n associations, an array of instances of the associated type or of Ids is accepted
  	 * <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.
  	 * </ul>
  	 *
  	 * Each subclass should document the name and type of its supported settings in its constructor documentation.
  	 *
  	 * 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>
  	 * </ul>
  	 *
  	 * @param {string} [sId] id for the new managed object; generated automatically if no non-empty id is given
  	 *      Note: 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.
  	 *
  	 *
  	 * @class Base Class that introduces some basic concepts like state management or databinding.
  	 *
  	 * New subclasses of ManagedObject are created with a call to {@link .extend ManagedObject.extend} and can make use
  	 * of the following managed features:
  	 *
  	 * <b>Properties</b><br>
  	 * 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, 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.
  	 *
  	 *
  	 * <b>Aggregations</b><br>
  	 * 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 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.
  	 *
  	 * 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.
  	 *
  	 *
  	 * <b>Associations</b><br>
  	 * 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 it 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.
  	 *
  	 *
  	 * <b>Events</b><br>
  	 * 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 a managed events, 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.
  	 *
  	 * 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 reflect in any direction (neither from source to clone nor vice versa).
  	 *
  	 *
  	 * <a name="lowlevelapi"><b>Low Level APIs:</b></a><br>
  	 * 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.36.6
  	 * @public
  	 * @alias sap.ui.base.ManagedObject
  	 * @experimental Since 1.11.2. ManagedObject as such is public and usable. Only the support for the optional parameter
  	 * oScope in the constructor is still experimental and might change in future versions. Applications should not rely on it.
  	 */
  	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' }
  					}
  				}
  			},
  			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 : true,
  				//id : {type : "string", group : "Identification", defaultValue : '', readOnly : true}
  
  				/**
  				 * 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 : true,
  
  				/**
  				 * 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 : true,
  
  				/**
  				 * 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 : true,
  
  				/**
  				 * Used by ManagedObject.create.
  				 */
  				Type : true
  			}
  		},
  
  		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 = {oModels:{}, oBindingContexts:{}};
  			this.mSkipPropagation = {};
  
  			// data binding
  			this.oModels = {};
  			this.oBindingContexts = {};
  			this.mElementBindingContexts = {};
  			this.mBindingInfos = {};
  			this.sBindingPath = null;
  			this.mBindingParameters = null;
  			this.mBoundObjects = {};
  
  			// 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() {
  
  				try {
  					// registers the object in the Core
  					if (that.register) {
  						that.register();
  					}
  
  					// 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);
  
  				} catch (ex) {
  
  					// unregisters the object in the Core
  					if (that.deregister) {
  						that.deregister();
  					}
  
  					// forward the exception
  					throw ex;
  
  				}
  
  			}());
  
  		}
  
  	}, /* 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>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 : {
  	 *       width: 'sap.ui.core.CSSSize',
  	 *       height: { type: 'sap.ui.core.CSSSize', defaultValue: '100%' }
  	 *     },
  	 *     aggregations : {
  	 *       header : { type: 'sap.mylib.FancyHeader', multiple : false }
  	 *       items : 'sap.ui.core.Control'
  	 *     },
  	 *     defaultAggregation : 'items',
  	 *     associations : {
  	 *       initiallyFocused : { type: 'sap.ui.core.Control' }
  	 *     },
  	 *     events: {
  	 *       beforeOpen : {
  	 *         parameters : {
  	 *           opener : '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' 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.</li>
  	 * <li><code>group: ...</code></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>
  	 * </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>setFoo(v) - sets 'v' as the new value of property 'foo'. Internally calls {@link #setProperty}
  	 * <li>bindFoo(c) - (only if property was defined to be 'bindable'): convenience function that wraps {@link #bindProperty}
  	 * <li>unbindFoo() - (only if property was defined to be 'bindable'): convenience function that wraps {@link #unbindProperty}
  	 * </ul>
  	 *
  	 *
  	 * <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 (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>[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) </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>
  	 * </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>removeItem(v) - removes an object from the aggregation 'items'. Internally calls {@link #removeAggregation}</li>
  	 * <li>removeItems() - removes all object 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 private or 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>
  	 *  &lt;!-- assuming the defaultAggregation for Dialog is 'content' -->
  	 *  &lt;Dialog>
  	 *    &lt;Text/>
  	 *    &lt;Button/>
  	 *  &lt;/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>
  	 * </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 'items'. Internally calls {@link #addAssociation}</li>
  	 * <li>removeRef(v) - removes an object from the association 'items'. Internally calls {@link #removeAssociation}</li>
  	 * <li>removeAllRefs() - removes all objects from the association 'items'. Internally calls {@link #removeAllAssociation}</li>
  	 * </ul>
  	 *
  	 *
  	 * <b>'events'</b> : <i>object</i><br>
  	 * An object literal whose properties each define a new event 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>allowPreventDefault: <i>boolean</i></code> whether the event allows to prevented the default behavior of the event source</li>
  	 * <li><code>parameters: <i>object</i></code> an object literal that describes the parameters of this event. </li>
  	 * </ul>
  	 * Event names should use camelCase notation, start with a lowercase letter and only use characters from the set [a-zA-Z0-9_$].
  	 * If an event 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 event.
  	 *
  	 * For each event 'Some' the following methods will be created by the "extend" method and will be added to the
  	 * prototype of the subclass:
  	 * <ul>
  	 * <li>attachSome(fn,o) - registers a listener for the event. Internally calls {@link #attachEvent}</li>
  	 * <li>detachSome(fn,o) - deregisters a listener for the event. Internally calls {@link #detachEvent}</li>
  	 * <li>fireSome() - fire the event. Internally calls {@link #fireEvent}</li>
  	 * </ul>
  	 *
  	 *
  	 * <b>'specialSettings'</b> : <i>object</i><br>
  	 * Special settings are an experimental feature and MUST NOT BE USED by controls or applications outside of the sap.ui.core project.
  	 *
  	 * @param {string} sClassName name of the class to be created
  	 * @param {object} [oClassInfo] object literal with informations about the class
  	 * @param {function} [FNMetaImpl] constructor function for the metadata object. If not given, it defaults to sap.ui.core.ManagedObjectMetadata.
  	 * @return {function} the created class / constructor function
  	 *
  	 * @public
  	 * @static
  	 * @experimental Since 1.27.0 Support for 'specialSettings' is experimental and might be modified or removed in future versions.
  	 *   They must not be used in any way outside of the sap.ui.core library. Code outside sap.ui.core must not declare special settings
  	 *   nor must it try to retrieve / evaluate metadata for such settings.
  	 * @name sap.ui.base.ManagedObject.extend
  	 * @function
  	 */
  
  	/**
  	 * Creates a new ManagedObject from the given data.
  	 *
  	 * If vData is a managed object already, that object is returned.
  	 * If vData is an object (literal), then a new object is created with vData as settings.
  	 * The type of the object is either determined by a "Type" entry in the vData or
  	 * by a type information in the oKeyInfo object
  	 * @param {sap.ui.base.ManagedObject|object} vData the data to create the object from
  	 * @param {object} oKeyInfo
  	 * @param {object} [oScope] Scope object to resolve types and formatters in bindings
  	 * @public
  	 * @static
  	 */
  	ManagedObject.create = function(vData, oKeyInfo, oScope) {
  		if ( !vData || vData instanceof ManagedObject || typeof vData !== "object" || vData instanceof String) {
  			return vData;
  		}
  
  		function getClass(vType) {
  			if ( typeof vType === "function" ) {
  				return vType;
  			}
  			if (typeof vType === "string" ) {
  				return jQuery.sap.getObject(vType);
  			}
  		}
  
  		var fnClass = getClass(vData.Type) || getClass(oKeyInfo && oKeyInfo.type);
  		if ( typeof fnClass === "function" ) {
  			return new fnClass(vData, oScope);
  		}
  
  		// we don't know how to create the ManagedObject from vData, so fail
  		// extension points could be integrated here
  		var message = "Don't know how to create a ManagedObject from " + vData + " (" + (typeof vData) + ")";
  		jQuery.sap.log.fatal(message);
  		throw new Error(message);
  	};
  
  	/**
  	 * Optional StashedControlSupport dependecy
  	 * @private
  	 */
  	var StashedControlSupport;
  
  	/**
  	 * Returns an array of stashed child elements or an empty array if there are none.
  	 *
  	 * @param {string} sId id of the object which should have stashed children
  	 * @return {sap.ui.core._StashedControl[]} array of stashed children
  	 * @private
  	 */
  	function getStashedControls(sId) {
  		if (!StashedControlSupport) {
  			StashedControlSupport = sap.ui.require("sap/ui/core/StashedControlSupport");
  		}
  		if (StashedControlSupport) {
  			return StashedControlSupport.getStashedControls(sId);
  		}
  		return [];
  	}
  
  	/**
  	 * A global preprocessor for the ID of a ManagedObject (used internally).
  	 * If set, this function will be called before the ID is applied to any ManagedObject.
  	 * If the original ID was empty, the hook will not be called (to be discussed).
  	 *
  	 * The expected signature is <code>function(sId)</code>, and <code>this</code> will
  	 * be the current ManagedObject.
  	 *
  	 * @return new ID of the ManagedObject
  	 * @type function
  	 * @private
  	 */
  	ManagedObject._fnIdPreprocessor = null;
  
  	/**
  	 * A global preprocessor for the settings of a ManagedObject (used internally).
  	 * If set, this function will be called before the settings are applied to any ManagedObject.
  	 * If the original settings are empty, the hook will not be called (to be discussed).
  	 *
  	 * The expected signature is <code>function(mSettings)</code>, and <code>this</code> will
  	 * be the current ManagedObject.
  	 *
  	 * @type function
  	 * @private
  	 */
  	ManagedObject._fnSettingsPreprocessor = null;
  
  	ManagedObject.runWithPreprocessors = function(fn, oPreprocessors) {
  		jQuery.sap.assert(typeof fn === "function", "fn must be a function");
  		jQuery.sap.assert(!oPreprocessors || typeof oPreprocessors === "object", "oPreprocessors must be an object");
  
  		var oOldPreprocessors = { id : this._fnIdPreprocessor, settings : this._fnSettingsPreprocessor };
  		oPreprocessors = oPreprocessors || {};
  
  		this._fnIdPreprocessor = oPreprocessors.id;
  		this._fnSettingsPreprocessor = oPreprocessors.settings;
  
  		try {
  			var result = fn.call();
  			this._fnIdPreprocessor = oOldPreprocessors.id;
  			this._fnSettingsPreprocessor = oOldPreprocessors.settings;
  			return result;
  		} catch (e) {
  			this._fnIdPreprocessor = oOldPreprocessors.id;
  			this._fnSettingsPreprocessor = oOldPreprocessors.settings;
  			throw e;
  		}
  
  	};
  
  	/**
  	 * Sets all the properties, aggregations, associations and event handlers as given in
  	 * the object literal <code>mSettings</code>. If a property, aggregation, etc.
  	 * is not listed in <code>mSettings</code>, then its value is not changed by this method.
  	 *
  	 * For properties and 0..1 aggregations/associations, any given setting overwrites
  	 * the current value. For 0..n aggregations, the given values are appended; event
  	 * listeners are registered in addition to existing ones.
  	 *
  	 * For the possible keys and values in <code>mSettings</code> see the general
  	 * documentation in {@link sap.ui.base.ManagedObject} or the specific documentation
  	 * of the constructor of the concrete managed object class.
  	 *
  	 * @param {object} mSettings the settings to apply to this managed object
  	 * @param {object} [oScope] Scope object to resolve types and formatters
  	 * @return {sap.ui.base.ManagedObject} Returns <code>this</code> to allow method chaining
  	 * @public
  	 * @experimental Since 1.11.2 support for the scope object for resolving string based type
  	 * and formatter references in bindings is still experimental
  	 */
  	ManagedObject.prototype.applySettings = function(mSettings, oScope) {
  
  		// PERFOPT: don't retrieve (expensive) JSONKeys if no settings are given
  		if ( !mSettings || jQuery.isEmptyObject(mSettings) ) {
  			return this;
  		}
  
  		var that = this,
  			oMetadata = this.getMetadata(),
  			mValidKeys = oMetadata.getJSONKeys(), // UID names required, they're part of the documented contract of applySettings
  			makeObject = ManagedObject.create,
  			preprocessor = ManagedObject._fnSettingsPreprocessor,
  			sKey, oValue, oKeyInfo;
  
  		// add all given objects to the given aggregation. nested arrays are flattened
  		// (might occur e.g. in case of content from an extension point)
  		function addAllToAggregation(aObjects) {
  			for (var i = 0, len = aObjects.length; i < len; i++) {
  				var vObject = aObjects[i];
  				if ( Array.isArray(vObject) ) {
  					addAllToAggregation(vObject);
  				} else {
  					that[oKeyInfo._sMutator](makeObject(vObject, oKeyInfo, oScope));
  				}
  			}
  		}
  
  		// call the preprocessor if it has been defined
  		preprocessor && preprocessor.call(this, mSettings); // TODO: decide whether to call for empty settings as well?
  
  		// process models
  		if ( mSettings.models ) {
  			if ( typeof mSettings.models !== "object" ) {
  				throw new Error("models must be a simple object");
  			}
  			if ( mSettings.models instanceof Model) {
  				this.setModel(mSettings.models);
  			} else {
  				for (sKey in mSettings.models ) {
  					this.setModel(mSettings.models[sKey], sKey === "undefined" ? undefined : sKey);
  				}
  			}
  		}
  		//process BindingContext
  		if ( mSettings.bindingContexts ) {
  			if ( typeof mSettings.bindingContexts !== "object" ) {
  				throw new Error("bindingContexts must be a simple object");
  			}
  			if ( mSettings.bindingContexts instanceof Context) {
  				this.setBindingContext(mSettings.bindingContexts);
  			} else {
  				for (sKey in mSettings.bindingContexts ) {
  					this.setBindingContext(mSettings.bindingContexts[sKey], sKey === "undefined" ? undefined : sKey);
  				}
  			}
  		}
  		//process object bindings
  		if ( mSettings.objectBindings ) {
  			if ( typeof mSettings.objectBindings !== "string" && typeof mSettings.objectBindings !== "object" ) {
  				throw new Error("binding must be a string or simple object");
  			}
  			if ( typeof mSettings.objectBindings === "string" || mSettings.objectBindings.path ) { // excludes "path" as model name
  				this.bindObject(mSettings.objectBindings);
  			} else {
  				for (var sKey in mSettings.objectBindings ) {
  					mSettings.objectBindings.model = sKey;
  					this.bindObject(mSettings.objectBindings[sKey]);
  				}
  			}
  		}
  
  		// process all settings
  		// process settings
  		for (sKey in mSettings) {
  			oValue = mSettings[sKey];
  			// get info object for the key
  			if ( (oKeyInfo = mValidKeys[sKey]) !== undefined ) {
  				var oBindingInfo;
  				switch (oKeyInfo._iKind) {
  				case 0: // PROPERTY
  					oBindingInfo = this.extractBindingInfo(oValue, oScope);
  					if (oBindingInfo && typeof oBindingInfo === "object") {
  						this.bindProperty(sKey, oBindingInfo);
  					} else {
  						this[oKeyInfo._sMutator](oBindingInfo || oValue);
  					}
  					break;
  				case 1: // SINGLE_AGGREGATION
  					oBindingInfo = oKeyInfo.altTypes && this.extractBindingInfo(oValue, oScope);
  					if ( oBindingInfo && typeof oBindingInfo === "object" ) {
  						this.bindProperty(sKey, oBindingInfo);
  					} else {
  						if (Array.isArray(oValue)){
  							// assumption: we have an extensionPoint here which is always an array, even if it contains a single control
  							if (oValue.length > 1){
  								jQuery.sap.log.error("Tried to add an array of controls to a single aggregation");
  							}
  							oValue = oValue[0];
  						}
  						this[oKeyInfo._sMutator](makeObject(oBindingInfo || oValue, oKeyInfo, oScope));
  					}
  					break;
  				case 2: // MULTIPLE_AGGREGATION
  					oBindingInfo = this.extractBindingInfo(oValue, oScope);
  					if (oBindingInfo && typeof oBindingInfo === "object" ) {
  						this.bindAggregation(sKey, oBindingInfo);
  					} else {
  						oValue = oBindingInfo || oValue; // could be an unescaped string if altTypes contains 'string'
  						if ( oValue ) {
  							if ( Array.isArray(oValue) ) {
  								addAllToAggregation(oValue); // wrap a single object as array
  							} else {
  								that[oKeyInfo._sMutator](makeObject(oValue, oKeyInfo, oScope));
  							}
  						}
  					}
  					break;
  				case 3: // SINGLE_ASSOCIATION
  					this[oKeyInfo._sMutator](oValue);
  					break;
  				case 4: // MULTIPLE_ASSOCIATION
  					if ( oValue ) {
  						if ( Array.isArray(oValue) ) {
  							for (var i = 0,l = oValue.length; i < l; i++) {
  								this[oKeyInfo._sMutator](oValue[i]);
  							}
  						} else {
  							this[oKeyInfo._sMutator](oValue);
  						}
  					}
  					break;
  				case 5: // EVENT
  					if ( typeof oValue == "function" ) {
  						this[oKeyInfo._sMutator](oValue);
  					} else {
  						this[oKeyInfo._sMutator](oValue[0], oValue[1], oValue[2]);
  					}
  					break;
  				case -1: // SPECIAL_SETTING
  					// No assert
  				default:
  					break;
  				}
  			} else {
  				// there must be no unknown settings
  				jQuery.sap.assert(false, "ManagedObject.apply: encountered unknown setting '" + sKey + "' for class '" + oMetadata.getName() + "' (value:'" + oValue + "')");
  			}
  		}
  
  		return this;
  	};
  
  	/**
  	 * Returns a simple string representation of this managed object.
  	 *
  	 * Mainly useful for tracing purposes.
  	 * @public
  	 * @return {string} a string description of this managed object
  	 */
  	ManagedObject.prototype.toString = function() {
  		return "ManagedObject " + this.getMetadata().getName() + "#" + this.getId();
  	};
  
  	/**
  	 * Returns the object's Id.
  	 *
  	 * @return {string} the objects's Id.
  	 * @public
  	 */
  	ManagedObject.prototype.getId = function() {
  		return this.sId;
  	};
  
  	// ######################################################################################################
  	// Properties
  	// ######################################################################################################
  
  	/**
  	 * Sets the given value for the given property after validating and normalizing it,
  	 * marks this object as changed.
  	 *
  	 * If the value is not valid with regard to the declared data type of the property,
  	 * an Error is thrown (see {@link #validateProperty}. If the validated and normalized
  	 * <code>oValue</code> equals the current value of the property, the internal state of
  	 * this object is not changed. If the value changes, it is stored internally and
  	 * the {@link #invalidate} method is called on this object. In the case of TwoWay
  	 * databinding, the bound model is informed about the property change.
  	 *
  	 * Note that ManagedObject only implements a single level of change tracking: if a first
  	 * call to setProperty recognizes a change, 'invalidate' is called. If another call to
  	 * setProperty reverts that change, invalidate() will be called again, the new status
  	 * is not recognized as being 'clean' again.
  	 *
  	 * <b>Note:</b> This method is a low level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically set a property.
  	 * Use the concrete method set<i>XYZ</i> for property 'XYZ' or the generic {@link #applySettings} instead.
  	 *
  	 * @param {string}  sPropertyName name of the property to set
  	 * @param {any}     oValue value to set the property to
  	 * @param {boolean} [bSuppressInvalidate] if true, the managed object is not marked as changed
  	 * @returns {sap.ui.base.ManagedObject} Returns <code>this</code> to allow method chaining
  	 * @protected
  	 */
  	ManagedObject.prototype.setProperty = function(sPropertyName, oValue, bSuppressInvalidate) {
  
  		// check for a value change
  		var oOldValue = this.mProperties[sPropertyName];
  
  		// value validation
  		oValue = this.validateProperty(sPropertyName, oValue);
  
  		if (jQuery.sap.equal(oOldValue, oValue)) {
  			return this;
  		} // no change
  
  		// set suppress invalidate flag
  		if (bSuppressInvalidate) {
  			//Refresh only for property changes with suppressed invalidation (others lead to rerendering and refresh is handled there)
  			jQuery.sap.act.refresh();
  			this.iSuppressInvalidate++;
  		}
  
  		// change the property (and invalidate if the rendering should be updated)
  		this.mProperties[sPropertyName] = oValue;
  		if (!this.isInvalidateSuppressed()) {
  			this.invalidate();
  		}
  
  		// check whether property is bound and update model in case of two way binding
  		this.updateModelProperty(sPropertyName, oValue, oOldValue);
  
  		// fire property change event (experimental, only for internal use)
  		if ( this.mEventRegistry["_change"] ) {
  			EventProvider.prototype.fireEvent.call(this, "_change", {
  				"id": this.getId(),
  				"name": sPropertyName,
  				"oldValue": oOldValue,
  				"newValue": oValue
  			});
  		}
  
  		// reset suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate--;
  		}
  
  		return this;
  	};
  
  	/**
  	 * Returns the value for the property with the given <code>sPropertyName</code>.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically retrieve the value of a property.
  	 * Use the concrete method get<i>XYZ</i> for property 'XYZ' instead.
  	 *
  	 * @param {string} sPropertyName the name of the property
  	 * @returns {any} the value of the property
  	 * @protected
  	 */
  	ManagedObject.prototype.getProperty = function(sPropertyName) {
  		var oValue = this.mProperties[sPropertyName],
  			oProperty = this.getMetadata().getProperty(sPropertyName),
  			oType;
  
  		if (!oProperty) {
  			throw new Error("Property \"" + sPropertyName + "\" does not exist in " + this);
  		}
  
  		oType = DataType.getType(oProperty.type);
  
  		// If property has an array type, clone the array to avoid modification of original data
  		if (oType instanceof DataType && oType.isArrayType() && jQuery.isArray(oValue)) {
  			oValue = oValue.slice(0);
  		}
  
  		// If property is of type String instead of string, convert with valueOf()
  		if (oValue instanceof String) {
  			oValue = oValue.valueOf();
  		}
  
  		return oValue;
  	};
  
  	/**
  	 * Checks whether the given value is of the proper type for the given property name.
  	 *
  	 * In case <code>null</code> or <code>undefined</code> is passed, the default value for
  	 * this property is used as value. If no default value is defined for the property, the
  	 * default value of the type of the property is used.
  	 *
  	 * If the property has a data type that is an instance of sap.ui.base.DataType and if
  	 * a <code>normalize</code> function is defined for that type, that function will be
  	 * called with the resulting value as only argument. The result of the function call is
  	 * then used instead of the raw value.
  	 *
  	 * This method is called by {@link #setProperty}. In many cases, subclasses of
  	 * ManagedObject don't need to call it themselves.
  	 *
  	 * @param {string} sPropertyName the name of the property
  	 * @param {any} oValue the value
  	 * @return {any} the normalized value for the passed value or for the default value if null or undefined was passed
  	 * @throws Error if no property with the given name is found or the given value does not fit to the property type
  	 * @protected
  	 */
  	ManagedObject.prototype.validateProperty = function(sPropertyName, oValue) {
  		var oProperty = this.getMetadata().getProperty(sPropertyName),
  			oType;
  
  		if (!oProperty) {
  			throw new Error("Property \"" + sPropertyName + "\" does not exist in " + this);
  		}
  
  		oType = DataType.getType(oProperty.type);
  
  		// If property has an array type, clone the array to avoid modification of original data
  		if (oType instanceof DataType && oType.isArrayType() && jQuery.isArray(oValue)) {
  			oValue = oValue.slice(0);
  		}
  
  		// In case null is passed as the value return the default value, either from the property or from the type
  		if (oValue === null || oValue === undefined) {
  			if (oProperty.defaultValue !== null) {
  				oValue = oProperty.defaultValue;
  			} else {
  				oValue = oType.getDefaultValue();
  			}
  		} else if (oType instanceof DataType) {
  			// Implicit casting for string only, other types are causing errors
  
  			if (oType.getName() == "string") {
  				if (!(typeof oValue == "string" || oValue instanceof String)) {
  					oValue = "" + oValue;
  				}
  			} else if (oType.getName() == "string[]") {
  				// For compatibility convert string values to array with single entry
  				if (typeof oValue == "string") {
  					oValue = [oValue];
  				}
  				if (!jQuery.isArray(oValue)) {
  					throw new Error("\"" + oValue + "\" is of type " + typeof oValue + ", expected string[]" +
  							" for property \"" + sPropertyName + "\" of " + this);
  				}
  				for (var i = 0; i < oValue.length; i++) {
  					if (!typeof oValue[i] == "string") {
  						oValue[i] = "" + oValue[i];
  					}
  				}
  			} else if (!oType.isValid(oValue)) {
  				throw new Error("\"" + oValue + "\" is of type " + typeof oValue + ", expected " +
  						oType.getName() + " for property \"" + sPropertyName + "\" of " + this);
  			}
  		}
  
  		// Normalize the value (if a normalizer was set using the setNormalizer method on the type)
  		if (oType && oType.normalize && typeof oType.normalize === "function") {
  			oValue = oType.normalize(oValue);
  		}
  
  		return oValue;
  	};
  
  	/**
  	 * Returns the origin info for the value of the given property.
  	 *
  	 * The origin info might contain additional information for translatable
  	 * texts. The bookkeeping of this information is not active by default and must be
  	 * activated by configuration. Even then, it might not be present for all properties
  	 * and their values depending on where the value came form.
  	 *
  	 * @param {string} sPropertyName the name of the property
  	 * @return {object} a map of properties describing the origin of this property value or null
  	 * @public
  	 */
  	ManagedObject.prototype.getOriginInfo = function(sPropertyName) {
  		var oValue = this.mProperties[sPropertyName];
  		if (!(oValue instanceof String && oValue.originInfo)) {
  			return null;
  		}
  		return oValue.originInfo;
  	};
  
  
  	// ######################################################################################################
  	// Associations
  	// ######################################################################################################
  
  	/**
  	 * Sets the associatied object for the given managed association of cardinality '0..1' and
  	 * marks this ManagedObject as changed.
  	 *
  	 * The associated object can either be given by itself or by its id. If <code>null</code> or
  	 * <code>undefined</code> is given, the association is cleared.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically set an object in an association.
  	 * Use the concrete method set<i>XYZ</i> for association 'XYZ' or the generic {@link #applySettings} instead.
  	 *
  	 * @param {string}
  	 *            sAssociationName name of the association
  	 * @param {string | sap.ui.base.ManagedObject}
  	 *            sId the ID of the managed object that is set as an association, or the managed object itself or null
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, the managed objects invalidate method is not called
  	 * @return {sap.ui.base.ManagedObject} Returns <code>this</code> to allow method chaining
  	 * @protected
  	 */
  	ManagedObject.prototype.setAssociation = function(sAssociationName, sId, bSuppressInvalidate) {
  		if (sId instanceof ManagedObject) {
  			sId = sId.getId();
  		} else if (sId != null && typeof sId !== "string") {
  			jQuery.sap.assert(false, "setAssociation(): sId must be a string, an instance of sap.ui.base.ManagedObject or null");
  			return this;
  		}
  
  		if (this.mAssociations[sAssociationName] === sId) {
  			return this;
  		} // no change
  
  		// set suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate++;
  		}
  
  		this.mAssociations[sAssociationName] = sId;
  
  		if (!this.isInvalidateSuppressed()) {
  			this.invalidate();
  		}
  
  		// reset suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate--;
  		}
  
  		return this;
  	};
  
  	/**
  	 * Returns the content of the association wit hthe given name.
  	 *
  	 * For associations of cardinality 0..1, a single string with the ID of an associated
  	 * object is returned (if any). For cardinality 0..n, an array with the IDs of the
  	 * associated objects is returned.
  	 *
  	 * If the association does not contain any objects(s), the given <code>oDefaultForCreation</code>
  	 * is set as new value of the association and returned to the caller. The only supported values for
  	 * <code>oDefaultForCreation</code> are <code>null</code> and <code>undefined</code> in the case of
  	 * cardinality 0..1 and <code>null</code>, <code>undefined</code> or an empty array (<code>[]</code>)
  	 * in case of cardinality 0..n. If the argument is omitted, <code>null</code> is used independently
  	 * from the cardinality.
  	 *
  	 * <b>Note:</b> the need to specify a default value and the fact that it is stored as
  	 * new value of a so far empty association is recognized as a shortcoming of this API
  	 * but can no longer be changed for compatibility reasons.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically retrieve the content of an association.
  	 * Use the concrete method get<i>XYZ</i> for association 'XYZ' instead.
  	 *
  	 * @param {string} sAssociationName the name of the association
  	 * @param {object}
  	 *			  oDefaultForCreation the object that is used in case the current aggregation is empty (only null or empty array allowed)
  	 * @return {string | string[]} the ID of the associated managed object or an array of such IDs; may be null if the association has not been populated
  	 * @protected
  	 */
  	ManagedObject.prototype.getAssociation = function(sAssociationName, oDefaultForCreation) {
  		var result = this.mAssociations[sAssociationName];
  
  		if (!result) {
  			result = this.mAssociations[sAssociationName] = oDefaultForCreation || null;
  		} else {
  			if (typeof result.length === 'number' && !(result.propertyIsEnumerable('length')) ) {
  				// Return a copy of the array instead of the array itself as reference!!
  				return result.slice();
  			}
  			// simple type or ManagedObject
  			return result;
  		}
  
  		return result;
  	};
  
  	/**
  	 * Adds some object with the ID <code>sId</code> to the association identified by <code>sAssociationName</code> and
  	 * marks this ManagedObject as changed.
  	 *
  	 * This method does not avoid duplicates.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically add an object to an association.
  	 * Use the concrete method add<i>XYZ</i> for association 'XYZ' or the generic {@link #applySettings} instead.
  	 *
  	 * @param {string}
  	 *            sAssociationName the string identifying the association the object should be added to.
  	 * @param {string | sap.ui.base.ManagedObject}
  	 *            sId the ID of the ManagedObject object to add; if empty, nothing is added; if a <code>sap.ui.base.ManagedObject</code> is given, its ID is added
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, this managed object as well as the newly associated object are not marked as changed
  	 * @return {sap.ui.base.ManagedObject} Returns <code>this</code> to allow method chaining
  	 * @protected
  	 */
  	ManagedObject.prototype.addAssociation = function(sAssociationName, sId, bSuppressInvalidate) {
  		if (sId instanceof ManagedObject) {
  			sId = sId.getId();
  		} else if (typeof sId !== "string") {
  			// TODO what about empty string?
  			jQuery.sap.assert(false, "addAssociation(): sId must be a string or an instance of sap.ui.base.ManagedObject");
  			return this;
  		}
  
  		// set suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate++;
  		}
  
  		var aIds = this.mAssociations[sAssociationName];
  		if (!aIds) {
  			aIds = this.mAssociations[sAssociationName] = [sId];
  		} else {
  			aIds.push(sId);
  		}
  
  		if (!this.isInvalidateSuppressed()) {
  			this.invalidate();
  		}
  
  		// reset suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate--;
  		}
  
  		return this;
  	};
  
  	/**
  	 * Removes a ManagedObject from the association named <code>sAssociationName</code>.
  	 *
  	 * If an object is removed, the Id of that object is returned and this ManagedObject is
  	 * marked as changed. Otherwise <code>undefined</code> is returned.
  	 *
  	 * If the same object was added multiple times to the same association, only a single
  	 * occurence of it will be removed by this method. If the object is not found or if the
  	 * parameter can't be interpreted neither as a ManagedObject (or id) nor as an index in
  	 * the assocation, nothing will be removed. The same is true if an index is given and if
  	 * that index is out of range for the association.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically remove an object from an association.
  	 * Use the concrete method remove<i>XYZ</i> for association 'XYZ' instead.
  	 *
  	 * @param {string}
  	 *            sAssociationName the string identifying the association the ManagedObject should be removed from.
  	 * @param {int | string | sap.ui.base.ManagedObject}
  	 *            vObject the position or ID of the ManagedObject to remove or the ManagedObject itself; if <code>vObject</code> is invalid input,
  	 *            a negative value or a value greater or equal than the current size of the association, nothing is removed
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, the managed object is not marked as changed
  	 * @return the ID of the removed ManagedObject or null
  	 * @protected
  	 */
  	ManagedObject.prototype.removeAssociation = function(sAssociationName, vObject, bSuppressInvalidate) {
  		var aIds = this.mAssociations[sAssociationName];
  		var sId = null;
  
  		if (!aIds) {
  			return null;
  		}
  
  		// set suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate++;
  		}
  
  		if (typeof (vObject) == "object" && vObject.getId) { // object itself is given
  			vObject = vObject.getId();
  		}
  
  		if (typeof (vObject) == "string") { // ID of the object is given or has just been retrieved
  			for (var i = 0; i < aIds.length; i++) {
  				if (aIds[i] == vObject) {
  					vObject = i;
  					break;
  				}
  			}
  		}
  
  		if (typeof (vObject) == "number") { // "object" is the index now
  			if (vObject < 0 || vObject >= aIds.length) {
  				jQuery.sap.log.warning("ManagedObject.removeAssociation called with invalid index: " + sAssociationName + ", " + vObject);
  			} else {
  				sId = aIds[vObject];
  				aIds.splice(vObject, 1);
  				if (!this.isInvalidateSuppressed()) {
  					this.invalidate();
  				}
  			}
  		}
  
  		// reset suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate--;
  		}
  
  		return sId;
  	};
  
  	/**
  	 * Removes all the objects in the 0..n-association named <code>sAssociationName</code> and returns an array
  	 * with their IDs. This ManagedObject is marked as changed, if the association contained any objects.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically remove all object from an association.
  	 * Use the concrete method removeAll<i>XYZ</i> for association 'XYZ' instead.
  	 *
  	 * @param {string}
  	 *            sAssociationName the name of the association
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, this ManagedObject is not marked as changed
  	 * @type Array
  	 * @return an array with the IDs of the removed objects (might be empty)
  	 * @protected
  	 */
  	ManagedObject.prototype.removeAllAssociation = function(sAssociationName, bSuppressInvalidate){
  		var aIds = this.mAssociations[sAssociationName];
  		if (!aIds)	{
  			return [];
  		}
  
  		// set suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate++;
  		}
  
  		delete this.mAssociations[sAssociationName];
  		if (!this.isInvalidateSuppressed()) {
  			this.invalidate();
  		}
  
  		// reset suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate--;
  		}
  
  		return aIds;
  	};
  
  	// ######################################################################################################
  	// Aggregations
  	// ######################################################################################################
  
  	/**
  	 * Checks whether the given value is of the proper type for the given aggregation name.
  	 *
  	 * This method is already called by {@link #setAggregation}, {@link #addAggregation} and {@link #insertAggregation}.
  	 * In many cases, subclasses of ManagedObject don't need to call it again in their mutator methods.
  	 *
  	 * @param {string} sAggregationName the name of the aggregation
  	 * @param {sap.ui.base.ManagedObject|any} oObject the aggregated object or a primitive value
  	 * @param {boolean} bMultiple whether the caller assumes the aggregation to have cardinality 0..n
  	 * @return {sap.ui.base.ManagedObject|any} the passed object
  	 * @throws Error if no aggregation with the given name is found or the given value does not fit to the aggregation type
  	 * @protected
  	 */
  	ManagedObject.prototype.validateAggregation = function(sAggregationName, oObject, bMultiple) {
  		var oMetadata = this.getMetadata(),
  			oAggregation = oMetadata.getManagedAggregation(sAggregationName), // public or private
  			aAltTypes,
  			oType,
  			i,
  			msg;
  
  		if (!oAggregation) {
  			throw new Error("Aggregation \"" + sAggregationName + "\" does not exist in " + this);
  		}
  
  		if (oAggregation.multiple !== bMultiple ) {
  			throw new Error("Aggregation '" + sAggregationName + "' of " + this + " used with wrong cardinality (declared as " + (oAggregation.multiple ? "0..n" : "0..1") + ")");
  		}
  
  		//Null is a valid value for 0..1 aggregations
  		if (!oAggregation.multiple && !oObject) {
  			return oObject;
  		}
  
  		oType = jQuery.sap.getObject(oAggregation.type);
  		// class types
  		if ( typeof oType === "function" && oObject instanceof oType ) {
  			return oObject;
  		}
  		// interfaces
  		if ( oObject && oObject.getMetadata && oObject.getMetadata().isInstanceOf(oAggregation.type) ) {
  			return oObject;
  		}
  		// alternative types
  		aAltTypes = oAggregation.altTypes;
  		if ( aAltTypes && aAltTypes.length ) {
  			// for primitive types, null or undefined is valid as well
  			if ( oObject == null ) {
  				return oObject;
  			}
  			for (i = 0; i < aAltTypes.length; i++) {
  				oType = DataType.getType(aAltTypes[i]);
  				if (oType instanceof DataType) {
  					if (oType.isValid(oObject)) {
  						return oObject;
  					}
  				}
  			}
  		}
  
  		// TODO make this stronger again (e.g. for FormattedText)
  		msg = "\"" + oObject + "\" is not valid for aggregation \"" + sAggregationName + "\" of " + this;
  		if ( DataType.isInterfaceType(oAggregation.type) ) {
  			jQuery.sap.assert(false, msg);
  			return oObject;
  		} else {
  		  throw new Error(msg);
  		}
  	};
  
  	/**
  	 * Sets a new object in the named 0..1 aggregation of this ManagedObject and
  	 * marks this ManagedObject as changed.
  	 *
  	 * If the given object is not valid with regard to the aggregation (if it is not an instance
  	 * of the type specified for that aggregation) or when the method is called for an aggregation
  	 * of cardinality 0..n, then an Error is thrown (see {@link #validateAggregation}.
  	 *
  	 * If the new object is the same as the currently aggregated object, then the internal state
  	 * is not modified and this ManagedObject is not marked as changed.
  	 *
  	 * If the given object is different, the parent of a previously aggregated object is cleared
  	 * (it must have been this ManagedObject before), the parent of the given object is set to this
  	 * ManagedObject and {@link #invalidate} is called for this object.
  	 *
  	 * Note that this method does neither return nor destroy the previously aggregated object.
  	 * This behavior is inherited by named set methods (see below) in subclasses.
  	 * To avoid memory leaks, applications therefore should first get the aggregated object,
  	 * keep a reference to it or destroy it, depending on their needs, and only then set a new
  	 * object.
  	 *
  	 * Note that ManagedObject only implements a single level of change tracking: if a first
  	 * call to setAggregation recognizes a change, 'invalidate' is called. If another call to
  	 * setAggregation reverts that change, invalidate() will be called again, the new status
  	 * is not recognized as being 'clean' again.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically set an object in an aggregation.
  	 * Use the concrete method set<i>XYZ</i> for aggregation 'XYZ' or the generic {@link #applySettings} instead.
  	 *
  	 * @param {string}
  	 *            sAggregationName name of an 0..1 aggregation
  	 * @param {object}
  	 *            oObject the managed object that is set as aggregated object
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, this ManagedObject is not marked as changed
  	 * @return {sap.ui.base.ManagedObject} Returns <code>this</code> to allow method chaining
  	 * @throws {Error}
  	 * @protected
  	 */
  	ManagedObject.prototype.setAggregation = function(sAggregationName, oObject, bSuppressInvalidate) {
  		var oOldChild = this.mAggregations[sAggregationName];
  		if (oOldChild === oObject) {
  			return this;
  		} // no change
  		oObject = this.validateAggregation(sAggregationName, oObject, /* multiple */ false);
  
  		// set suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate++;
  		}
  
  		if (oOldChild instanceof ManagedObject) { // remove old child
  			oOldChild.setParent(null);
  		}
  		this.mAggregations[sAggregationName] = oObject;
  		if (oObject instanceof ManagedObject) { // adopt new child
  			oObject.setParent(this, sAggregationName, bSuppressInvalidate);
  		} else {
  			if (!this.isInvalidateSuppressed()) {
  				this.invalidate();
  			}
  		}
  
  		// reset suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate--;
  		}
  
  		return this;
  	};
  
  	/**
  	 * Returns the aggregated object(s) for the named aggregation of this ManagedObject.
  	 *
  	 * If the aggregation does not contain any objects(s), the given <code>oDefaultForCreation</code>
  	 * (or <code>null</code>) is set as new value of the aggregation and returned to the caller.
  	 *
  	 * <b>Note:</b> the need to specify a default value and the fact that it is stored as
  	 * new value of a so far empty aggregation is recognized as a shortcoming of this API
  	 * but can no longer be changed for compatibility reasons.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically read the content of an aggregation.
  	 * Use the concrete method get<i>XYZ</i> for aggregation 'XYZ' instead.
  	 *
  	 * @param {string}
  	 *            sAggregationName the name of the aggregation
  	 * @param {sap.ui.base.ManagedObject | Array}
  	 *			  oDefaultForCreation the object that is used in case the current aggregation is empty
  	 * @type sap.ui.base.ManagedObject|Array
  	 * @return the aggregation array in case of 0..n-aggregations or the managed object or null in case of 0..1-aggregations
  	 * @protected
  	 */
  	ManagedObject.prototype.getAggregation = function(sAggregationName, oDefaultForCreation) {
  		var aChildren = this.mAggregations[sAggregationName];
  		if (!aChildren) {
  			aChildren = this.mAggregations[sAggregationName] = oDefaultForCreation || null;
  		}
  		if (aChildren) {
  			if (typeof aChildren.length === 'number' && !(aChildren.propertyIsEnumerable('length')) ) {
  				// Return a copy of the array instead of the array itself as reference!!
  				return aChildren.slice();
  			}
  			// simple type or ManagedObject
  			return aChildren;
  		} else {
  			return null;
  		}
  	};
  
  	/**
  	 * Searches for the provided ManagedObject in the named aggregation and returns its
  	 * 0-based index if found, or -1 otherwise. Returns -2 if the given named aggregation
  	 * is of cardinality 0..1 and doesn't reference the given object.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically determine the position of an object in an aggregation.
  	 * Use the concrete method indexOf<i>XYZ</i> for aggregation 'XYZ' instead.
  	 *
  	 * @param {string}
  	 *            sAggregationName the name of the aggregation
  	 * @param {sap.ui.base.ManagedObject}
  	 *            oObject the ManagedObject whose index is looked for.
  	 * @return {int} the index of the provided managed object in the aggregation.
  	 * @protected
  	 */
  	ManagedObject.prototype.indexOfAggregation = function(sAggregationName, oObject) {
  		var aChildren = this.mAggregations[sAggregationName];
  		if (aChildren) {
  			if (aChildren.length == undefined) {
  				return -2;
  			} // not a multiple aggregation
  
  			for (var i = 0; i < aChildren.length; i++) {
  				if (aChildren[i] == oObject) {
  					return i;
  				}
  			}
  		}
  		return -1;
  	};
  
  	/**
  	 * Inserts managed object <code>oObject</code> to the aggregation named <code>sAggregationName</code> at
  	 * position <code>iIndex</code>.
  	 *
  	 * If the given object is not valid with regard to the aggregation (if it is not an instance
  	 * of the type specified for that aggregation) or when the method is called for an aggregation
  	 * of cardinality 0..1, then an Error is thrown (see {@link #validateAggregation}.
  	 *
  	 * If the given index is out of range with respect to the current content of the aggregation,
  	 * it is clipped to that range (0 for iIndex < 0, n for iIndex > n).
  	 *
  	 * Please note that this method does not work as expected when an object is added
  	 * that is already part of the aggregation. In order to change the index of an object
  	 * inside an aggregation, first remove it, then insert it again.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically insert an object into an aggregation.
  	 * Use the concrete method insert<i>XYZ</i> for aggregation 'XYZ' instead.
  	 *
  	 * @param {string}
  	 *            sAggregationName the string identifying the aggregation the managed object <code>oObject</code>
  	 *            should be inserted into.
  	 * @param {sap.ui.base.ManagedObject}
  	 *            oObject the ManagedObject to add; if empty, nothing is inserted.
  	 * @param {int}
  	 *            iIndex the <code>0</code>-based index the managed object should be inserted at; for a negative
  	 *            value <code>iIndex</code>, <code>oObject</code> is inserted at position 0; for a value
  	 *            greater than the current size of the aggregation, <code>oObject</code> is inserted at
  	 *            the last position
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, this ManagedObject as well as the added child are not marked as changed
  	 * @return {sap.ui.base.ManagedObject} Returns <code>this</code> to allow method chaining
  	 * @protected
  	 */
  	ManagedObject.prototype.insertAggregation = function(sAggregationName, oObject, iIndex, bSuppressInvalidate) {
  		if (!oObject) {
  			return this;
  		}
  		oObject = this.validateAggregation(sAggregationName, oObject, /* multiple */ true);
  
  		var aChildren = this.mAggregations[sAggregationName] || (this.mAggregations[sAggregationName] = []);
  		// force index into valid range
  		var i;
  		if (iIndex < 0) {
  			i = 0;
  		} else if (iIndex > aChildren.length) {
  			i = aChildren.length;
  		} else {
  			i = iIndex;
  		}
  		if (i !== iIndex) {
  			jQuery.sap.log.warning("ManagedObject.insertAggregation: index '" + iIndex + "' out of range [0," + aChildren.length + "], forced to " + i);
  		}
  		aChildren.splice(i, 0, oObject);
  		oObject.setParent(this, sAggregationName, bSuppressInvalidate);
  
  		return this;
  	};
  
  	/**
  	 * Adds some entity <code>oObject</code> to the aggregation identified by <code>sAggregationName</code>.
  	 *
  	 * If the given object is not valid with regard to the aggregation (if it is not an instance
  	 * of the type specified for that aggregation) or when the method is called for an aggregation
  	 * of cardinality 0..1, then an Error is thrown (see {@link #validateAggregation}.
  	 *
  	 * If the aggregation already has content, the new object will be added after the current content.
  	 * If the new object was already contained in the aggregation, it will be moved to the end.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically add an object to an aggregation.
  	 * Use the concrete method add<i>XYZ</i> for aggregation 'XYZ' or the generic {@link #applySettings} instead.
  	 *
  	 * @param {string}
  	 *            sAggregationName the string identifying the aggregation that <code>oObject</code> should be added to.
  	 * @param {sap.ui.base.ManagedObject}
  	 *            oObject the object to add; if empty, nothing is added
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, this ManagedObject as well as the added child are not marked as changed
  	 * @return {sap.ui.base.ManagedObject} Returns <code>this</code> to allow method chaining
  	 * @protected
  	 */
  	ManagedObject.prototype.addAggregation = function(sAggregationName, oObject, bSuppressInvalidate) {
  		if (!oObject) {
  			return this;
  		}
  		oObject = this.validateAggregation(sAggregationName, oObject, /* multiple */ true);
  
  		var aChildren = this.mAggregations[sAggregationName];
  		if (!aChildren) {
  			aChildren = this.mAggregations[sAggregationName] = [oObject];
  		} else {
  			aChildren.push(oObject);
  		}
  		oObject.setParent(this, sAggregationName, bSuppressInvalidate);
  		return this;
  	};
  
  	/**
  	 * Removes an object from the aggregation named <code>sAggregationName</code> with cardinality 0..n.
  	 *
  	 * The removed object is not destroyed nor is it marked as changed.
  	 *
  	 * If the given object is found in the aggreation, it is removed, it's parent relationship
  	 * is unset and this ManagedObject is marked as changed. The removed object is returned as
  	 * result of this method. If the object could not be found, <code>undefined</code> is returned.
  	 *
  	 * This method must only be called for aggregations of cardinality 0..n. The only way to remove objects
  	 * from a 0..1 aggregation is to set a <code>null</code> value for them.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically remove an object from an aggregation.
  	 * Use the concrete method remove<i>XYZ</i> for aggregation 'XYZ' instead.
  	 *
  	 * @param {string}
  	 *            sAggregationName the string identifying the aggregation that the given object should be removed from
  	 * @param {int | string | sap.ui.base.ManagedObject}
  	 *            vObject the position or ID of the ManagedObject that should be removed or that ManagedObject itself;
  	 *            if <code>vObject</code> is invalid, a negative value or a value greater or equal than the current size
  	 *            of the aggregation, nothing is removed.
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, this ManagedObject is not marked as changed
  	 * @return {sap.ui.base.ManagedObject} the removed object or null
  	 * @protected
  	 */
  	ManagedObject.prototype.removeAggregation = function(sAggregationName, vObject, bSuppressInvalidate) {
  		var aChildren = this.mAggregations[sAggregationName],
  			oChild = null,
  			i;
  
  		if ( !aChildren ) {
  			return null;
  		}
  
  		// set suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate++;
  		}
  
  		if (typeof (vObject) == "string") { // ID of the object is given
  			// Note: old lookup via sap.ui.getCore().byId(vObject) only worked for Elements, not for managed objects in general!
  			for (i = 0; i < aChildren.length; i++) {
  				if (aChildren[i] && aChildren[i].getId() === vObject) {
  					vObject = i;
  					break;
  				}
  			}
  		}
  
  		if (typeof (vObject) == "object") { // the object itself is given or has just been retrieved
  			for (i = 0; i < aChildren.length; i++) {
  				if (aChildren[i] == vObject) {
  					vObject = i;
  					break;
  				}
  			}
  		}
  
  		if (typeof (vObject) == "number") { // "vObject" is the index now
  			if (vObject < 0 || vObject >= aChildren.length) {
  				jQuery.sap.log.warning("ManagedObject.removeAggregation called with invalid index: " + sAggregationName + ", " + vObject);
  
  			} else {
  				oChild = aChildren[vObject];
  				aChildren.splice(vObject, 1); // first remove it from array, then call setParent (avoids endless recursion)
  				oChild.setParent(null);
  				if (!this.isInvalidateSuppressed()) {
  					this.invalidate();
  				}
  			}
  		}
  
  		// reset suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate--;
  		}
  
  		return oChild;
  	};
  
  	/**
  	 * Removes all objects from the 0..n-aggregation named <code>sAggregationName</code>.
  	 *
  	 * The removed objects are not destroyed nor are they marked as changed.
  	 *
  	 * Additionally, it clears the parent relationship of all removed objects, marks this
  	 * ManagedObject as changed and returns an array with the removed objects.
  	 *
  	 * If the aggregation did not contain any objects, an empty array is returned and this
  	 * ManagedObject is not marked as changed.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically remove all objects from an aggregation.
  	 * Use the concrete method removeAll<i>XYZ</i> for aggregation 'XYZ' instead.
  	 *
  	 * @param {string}
  	 *            sAggregationName the name of the aggregation
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, this ManagedObject is not marked as changed
  	 * @type Array
  	 * @return an array of the removed elements (might be empty)
  	 * @protected
  	 */
  	ManagedObject.prototype.removeAllAggregation = function(sAggregationName, bSuppressInvalidate){
  		var aChildren = this.mAggregations[sAggregationName];
  		if (!aChildren)	{
  			return [];
  		}
  
  		// set suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate++;
  		}
  
  		delete this.mAggregations[sAggregationName];
  		for (var i = 0; i < aChildren.length; i++) {
  			aChildren[i].setParent(null);
  		}
  		if (!this.isInvalidateSuppressed()) {
  			this.invalidate();
  		}
  
  		// reset suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate--;
  		}
  
  		return aChildren;
  	};
  
  	/**
  	 * Destroys (all) the managed object(s) in the aggregation named <code>sAggregationName</code> and empties the
  	 * aggregation. If the aggregation did contain any object, this ManagedObject is marked as changed.
  	 *
  	 * <b>Note:</b> This method is a low-level API as described in <a href="#lowlevelapi">the class documentation</a>.
  	 * Applications or frameworks must not use this method to generically destroy all objects in an aggregation.
  	 * Use the concrete method destroy<i>XYZ</i> for aggregation 'XYZ' instead.
  	 *
  	 * @param {string}
  	 *            sAggregationName the name of the aggregation
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, this ManagedObject is not marked as changed
  	 * @return {sap.ui.base.ManagedObject} Returns <code>this</code> to allow method chaining
  	 * @protected
  	 */
  	ManagedObject.prototype.destroyAggregation = function(sAggregationName, bSuppressInvalidate){
  		var aChildren = this.mAggregations[sAggregationName],
  			i, aChild;
  
  		// destroy surrogates in this aggregation
  		getStashedControls(this.getId()).forEach(function(c) {
  			if (c.sParentAggregationName === sAggregationName) {
  				c.destroy();
  			}
  		});
  
  		if (!aChildren) {
  			return this;
  		}
  
  		// set suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate++;
  		}
  
  		// Deleting the aggregation here before destroying the children is a BUG:
  		//
  		// The destroy() method on the children calls _removeChild() on this instance
  		// to properly remove each child from the bookkeeping by executing the named
  		// removeXYZ() method. But as the aggegation is deleted here already,
  		// _removeChild() doesn't find the child in the bookkeeping and therefore
  		// refuses to work. As a result, side effects from removeXYZ() are missing.
  		//
  		// The lines below marked with 'FIXME DESTROY' sketch a potential fix, but
  		// that fix has proven to be incompatible for several controls that don't
  		// properly implement removeXYZ(). As this might affect custom controls
  		// as well, the fix has been abandoned.
  		//
  		delete this.mAggregations[sAggregationName]; //FIXME DESTROY: should be removed here
  
  		if (aChildren instanceof ManagedObject) {
  			// FIXME DESTROY: this._removeChild(aChildren, sAggregationName, bSuppressInvalidate); // (optional, done by destroy())
  			aChildren.destroy(bSuppressInvalidate);
  		} else if (jQuery.isArray(aChildren)) {
  			for (i = aChildren.length - 1; i >= 0; i--) {
  				aChild = aChildren[i];
  				if (aChild) {
  					// FIXME DESTROY: this._removeChild(aChild, sAggregationName, bSuppressInvalidate); // (optional, done by destroy())
  					aChild.destroy(bSuppressInvalidate);
  				}
  			}
  		}
  
  		// FIXME DESTROY: // 'delete' aggregation only now so that _removeChild() can still do its cleanup
  		// FIXME DESTROY: delete this.mAggregations[sAggregationName];
  
  		if (!this.isInvalidateSuppressed()) {
  			this.invalidate();
  		}
  
  		// reset suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate--;
  		}
  
  		return this;
  	};
  
  	// ######################################################################################################
  	// End of Aggregations
  	// ######################################################################################################
  
  
  	/**
  	 * This triggers rerendering of itself and its children.<br/> As <code>sap.ui.base.ManagedObject</code> "bubbles up" the
  	 * invalidate, changes to child-<code>Elements</code> will also result in rerendering of the whole sub tree.
  	 * @protected
  	 */
  	ManagedObject.prototype.invalidate = function() {
  		if (this.oParent) {
  			this.oParent.invalidate(this);
  		}
  	};
  
  
  	/**
  	 * Returns whether rerendering is currently suppressed on this ManagedObject
  	 * @return boolean
  	 * @protected
  	 */
  	ManagedObject.prototype.isInvalidateSuppressed = function() {
  		var bInvalidateSuppressed = this.iSuppressInvalidate > 0;
  		if (this.oParent && this.oParent instanceof ManagedObject) {
  			bInvalidateSuppressed = bInvalidateSuppressed || this.oParent.isInvalidateSuppressed();
  		}
  		return bInvalidateSuppressed;
  	};
  
  	/**
  	 * Removes the given child from this object's named aggregation.
  	 * @see sap.ui.core.UIArea#_removeChild
  	 * @see sap.ui.base.ManagedObject#setParent
  	 *
  	 * @param {sap.ui.base.ManagedObject}
  	 *            oChild the child object to be removed
  	 * @param {string}
  	 *            sAggregationName the name of this object's aggregation
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, this ManagedObject is not marked as changed
  	 * @private
  	 */
  	ManagedObject.prototype._removeChild = function(oChild, sAggregationName, bSuppressInvalidate) {
  		if (!sAggregationName) {
  			// an aggregation name has to be specified!
  			jQuery.sap.log.error("Cannot remove aggregated child without aggregation name.", null, this);
  		} else {
  			// set suppress invalidate flag
  			if (bSuppressInvalidate) {
  				this.iSuppressInvalidate++;
  			}
  
  			var iIndex = this.indexOfAggregation(sAggregationName, oChild);
  			var oAggregationInfo = this.getMetadata().getAggregation(sAggregationName);
  			// Note: we assume that this is the given child's parent, i.e. -1 not expected!
  			if (iIndex == -2) { // 0..1
  				if (oAggregationInfo && this[oAggregationInfo._sMutator]) { // TODO properly deal with hidden aggregations
  					this[oAggregationInfo._sMutator](null);
  				} else {
  					this.setAggregation(sAggregationName, null, bSuppressInvalidate);
  				}
  			} else if (iIndex > -1 ) { // 0..n
  				if (oAggregationInfo && this[oAggregationInfo._sRemoveMutator]) { // TODO properly deal with hidden aggregations
  					this[oAggregationInfo._sRemoveMutator](iIndex);
  				} else {
  					this.removeAggregation(sAggregationName, iIndex, bSuppressInvalidate);
  				}
  			} //else {
  				// already removed!?
  				// this is the unexpected -1
  				// TODO: What would be better? Explicit removeCompositeChild callback on subclass?
  			//}
  			if (!this.isInvalidateSuppressed()) {
  				this.invalidate();
  			}
  
  			// reset suppress invalidate flag
  			if (bSuppressInvalidate) {
  				this.iSuppressInvalidate--;
  			}
  		}
  	};
  
  	/**
  	 * Defines this object's new parent. If no new parent is given, the parent is
  	 * just unset and we assume that the old parent has removed this child from its
  	 * aggregation. But if a new parent is given, this child is first removed from
  	 * its old parent.
  	 *
  	 * @param {sap.ui.base.ManagedObject}
  	 *            oParent the object that becomes this objects's new parent
  	 * @param {string}
  	 *            sAggregationName the name of the parent objects's aggregation
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, this ManagedObject is not marked as changed. The old parent, however, is marked.
  	 * @return {sap.ui.base.ManagedObject}
  	 *            Returns <code>this</code> to allow method chaining
  	 * @private
  	 */
  	ManagedObject.prototype.setParent = function(oParent, sAggregationName, bSuppressInvalidate) {
  		if ( !oParent ) {
  			this.oParent = null;
  			this.sParentAggregationName = null;
  			this.oPropagatedProperties = {oModels:{}, oBindingContexts:{}};
  
  			jQuery.sap.act.refresh();
  
  			// Note: no need (and no way how) to invalidate
  			return;
  		}
  
  		// set suppress invalidate flag
  		if (bSuppressInvalidate) {
  			//Refresh only for changes with suppressed invalidation (others lead to rerendering and refresh is handled there)
  			jQuery.sap.act.refresh();
  			this.iSuppressInvalidate++;
  		}
  
  		var oOldParent = this.getParent();
  		if (oOldParent) { // remove this object from its old parent
  			// Note: bSuppressInvalidate  by intention is not propagated to the old parent.
  			// It is not sure whether the (direct or indirect) caller of setParent
  			// has enough knowledge about the old parent to automatically propagate this.
  			// If needed, callers can first remove the object from the oldParent (specifying a
  			// suitable value for bSuppressInvalidate there) and only then call setParent.
  			oOldParent._removeChild(this, this.sParentAggregationName);
  		}
  		// adopt new parent
  		this.oParent = oParent;
  		this.sParentAggregationName = sAggregationName;
  
  		//get properties to propagate
  		this.oPropagatedProperties = oParent._getPropertiesToPropagate();
  
  		// update bindings
  		if (this.hasModel()) {
  			this.updateBindingContext(false, true, undefined, true);
  			this.updateBindings(true,null); // TODO could be restricted to models that changed
  			this.propagateProperties(true);
  		}
  
  		// only the parent knows where to render us, so we have to invalidate it
  		if ( oParent && !this.isInvalidateSuppressed() ) {
  			oParent.invalidate(this);
  		}
  
  		// reset suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate--;
  		}
  
  		return this;
  	};
  
  	/**
  	 * Returns the parent managed object or <code>null</code> if this object hasn't been added to a parent yet.
  	 *
  	 * @return {sap.ui.base.ManagedObject} The parent managed object or <code>null</code>
  	 * @public
  	 */
  	ManagedObject.prototype.getParent = function() {
  		/* Be aware that internally this.oParent is used to reduce method calls.
  		 * Check for side effects when overriding this method */
  		return this.oParent;
  	};
  
  	/**
  	 * Cleans up the resources associated with this object and all its aggregated children.
  	 *
  	 * After an object has been destroyed, it can no longer be used in!
  	 *
  	 * Applications should call this method if they don't need the object any longer.
  	 *
  	 * @param {boolean}
  	 *            [bSuppressInvalidate] if true, this ManagedObject is not marked as changed
  	 * @public
  	 */
  	ManagedObject.prototype.destroy = function(bSuppressInvalidate) {
  		var that = this;
  
  		// set suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate++;
  		}
  
  		if (this.exit) {
  			this.exit();
  		}
  
  		// TODO: generic concept for exit hooks?
  		if ( this._exitCompositeSupport ) {
  			this._exitCompositeSupport();
  		}
  
  		// ensure that also our children are destroyed!!
  		for (var oAggr in this.mAggregations) {
  			this.destroyAggregation(oAggr, bSuppressInvalidate);
  		}
  
  		// destroy all inactive children
  		getStashedControls(this.getId()).forEach(function(c) {
  			c.destroy();
  		});
  
  		// Deregister, if available
  		if (this.deregister) {
  			this.deregister();
  		}
  
  		// remove this child from parent aggregation
  		if (this.oParent && this.sParentAggregationName) {
  			this.oParent._removeChild(this, this.sParentAggregationName, bSuppressInvalidate);
  		}
  		// for robustness only - should have been cleared by _removeChild already
  		delete this.oParent;
  
  		// Data Binding
  		jQuery.each(this.mBindingInfos, function(sName, oBindingInfo) {
  			if (oBindingInfo.factory) {
  				that.unbindAggregation(sName, true);
  			} else {
  				that.unbindProperty(sName, true);
  			}
  		});
  
  		jQuery.each(this.mBoundObjects, function(sName, oBoundObject) {
  			that.unbindObject(sName, /* _bSkipUpdateBindingContext */ true);
  		});
  
  		// reset suppress invalidate flag
  		if (bSuppressInvalidate) {
  			this.iSuppressInvalidate--;
  		}
  
  		sap.ui.getCore().getMessageManager().removeMessages(this._aMessages);
  		this._aMessages = undefined;
  
  		EventProvider.prototype.destroy.apply(this, arguments);
  
  		// finally make the object unusable
  		this.setParent = function(){
  			throw Error("The object with ID " + that.getId() + " was destroyed and cannot be used anymore.");
  		};
  
  		// make visible that it's been destroyed.
  		this.bIsDestroyed = true;
  	};
  
  
  	// DataBinding
  	/**
  	 * Binding parser to use.
  	 */
  	ManagedObject.bindingParser = BindingParser.simpleParser;
  
  	/**
  	 * Determines whether a given object contains binding information instead of a
  	 * value or aggregated controls. The method is used in applySettings for processing
  	 * the JSON notation of properties/aggregations in the constructor.
  	 *
  	 * @param {object} oValue the value
  	 * @param {object} oKeyInfo the metadata of the property
  	 *
  	 * @returns {boolean} whether the value contains binding information
  	 *
  	 * @private
  	 * @deprecated
  	 */
  	ManagedObject.prototype.isBinding = function(oValue, oKeyInfo) {
  		return typeof this.extractBindingInfo(oValue) === "object";
  	};
  
  	/**
  	 * Checks whether the given value can be interpreted as a binding info and
  	 * returns that binding info or an unescaped string or undefined when it is not.
  	 *
  	 * When the 'complex' binding syntax is enabled, the function might also return
  	 * a string value in case the given value was a string, did not represent a binding
  	 * but contained escaped special characters.
  	 *
  	 * There are two possible notations for binding information in the object literal notation
  	 * of the ManagedObject constructor and ManagedObject.applySettings:
  	 * <ul>
  	 *   <li>property: "{path}"
  	 *   This is used for property binding and can only contain the path.
  	 *   </li>
  	 *   <li>property:{path:"path", template:oTemplate}
  	 *   This is used for aggregation binding, where a template is required or can
  	 *   be used for property binding when additional data is required (e.g. formatter).
  	 *   </li>
  	 * </ul>
  	 *
  	 * @param {object} oValue
  	 * @param {object} oScope
  	 *
  	 * @returns {object} the binding info object or an unescaped string or undefined.
  	 *     If a binding info is returned, it contains at least a path property
  	 *     or nested bindings (parts) and, dependant of the binding type,
  	 *     additional properties
  	 *
  	 * @private
  	 */
  	ManagedObject.prototype.extractBindingInfo = function(oValue, oScope) {
  
  		// property:{path:"path", template:oTemplate}
  		if (oValue && typeof oValue === "object") {
  			if (oValue.ui5object) {
  				// if value contains ui5object property, this is not a binding info,
  				// remove it and not check for path or parts property
  				delete oValue.ui5object;
  			} else if (oValue.path != undefined || oValue.parts) {
  				// allow JSON syntax for templates
  				if (oValue.template) {
  					oValue.template = ManagedObject.create(oValue.template);
  				}
  				return oValue;
  			}
  		}
  
  		// property:"{path}" or "\{path\}"
  		if (typeof oValue === "string") {
  			// either returns a binding info or an unescaped string or undefined - depending on binding syntax
  			return ManagedObject.bindingParser(oValue, oScope, true);
  		}
  
  		// return undefined;
  	};
  
  	/**
  	 * Returns the binding infos for the given property or aggregation. The binding info contains information about path, binding object, format options,
  	 * sorter, filter etc. for the property or aggregation.
  	 *
  	 * @param {string} sName the name of the property or aggregation
  	 *
  	 * @returns {object} the binding info object, containing at least a path property
  	 *                   and, dependant of the binding type, additional properties
  	 *
  	 * @protected
  	 */
  	ManagedObject.prototype.getBindingInfo = function(sName) {
  		return this.mBindingInfos[sName];
  	};
  
  	/**
  	 * Bind the object to the referenced entity in the model, which is used as the binding context
  	 * to resolve bound properties or aggregations of the object itself and all of its children
  	 * relatively to the given path.
  	 * If a relative binding path is used, this will be applied whenever the parent context changes.
  	 * @param {string|object} vPath the binding path or an object with more detailed binding options
  	 * @param {string} vPath.path the binding path
  	 * @param {object} [vPath.parameters] map of additional parameters for this binding
  	 * @param {string} [vPath.model] name of the model
  	 * @param {object} [vPath.events] map of event listeners for the binding events
  	 * @param {object} [mParameters] map of additional parameters for this binding (only taken into account when vPath is a string).
  	 * The supported parameters are listed in the corresponding model-specific implementation of <code>sap.ui.model.ContextBinding</code>.
  	 *
  	 * @return {sap.ui.base.ManagedObject} reference to the instance itself
  	 * @public
  	 */
  	ManagedObject.prototype.bindObject = function(sPath, mParameters) {
  		var boundObject = {},
  			sModelName,
  			iSeparatorPos;
  		// support object notation
  		if (typeof sPath == "object") {
  			var oBindingInfo = sPath;
  			sPath = oBindingInfo.path;
  			mParameters = oBindingInfo.parameters;
  			sModelName = oBindingInfo.model;
  			boundObject.events = oBindingInfo.events;
  		}
  		// if a model separator is found in the path, extract model name and path
  		iSeparatorPos = sPath.indexOf(">");
  		boundObject.sBindingPath = sPath;
  		boundObject.mBindingParameters = mParameters;
  		if (iSeparatorPos > 0) {
  			sModelName = sPath.substr(0, iSeparatorPos);
  			boundObject.sBindingPath = sPath.substr(iSeparatorPos + 1);
  		}
  
  		// if old binding exists, clean it up
  		if ( this.mBoundObjects[sModelName] ) {
  			this.unbindObject(sModelName, /* _bSkipUpdateBindingContext */ true);
  			// We don't push down context changes here
  			// Either this will happen with the _bindObject call below or the model
  			// is not available yet and wasn't available before -> no change of contexts
  		}
  
  		this.mBoundObjects[sModelName] = boundObject;
  
  		// if the models are already available, create the binding
  		if (this.getModel(sModelName)) {
  			this._bindObject(sModelName, boundObject);
  		}
  
  		return this;
  	};
  
  	/**
  	 * Create object binding
  	 *
  	 * @private
  	 */
  	ManagedObject.prototype._bindObject = function(sModelName, oBoundObject) {
  		var oBinding,
  			oContext,
  			oModel,
  			that = this;
  
  		var fChangeHandler = function(oEvent) {
  			/* as we reuse the context objects we need to ensure an update of relative bindings. Therefore we set
  			   the context to null so relative bindings will detect a context change */
  			if (oBinding.getBoundContext() === that.getBindingContext(sModelName)) {
  				that.setElementBindingContext(null, sModelName);
  			}
  			that.setElementBindingContext(oBinding.getBoundContext(), sModelName);
  		};
  
  		oModel = this.getModel(sModelName);
  
  		oContext = this.getBindingContext(sModelName);
  
  		oBinding = oModel.bindContext(oBoundObject.sBindingPath, oContext, oBoundObject.mBindingParameters);
  		oBinding.attachChange(fChangeHandler);
  		oBoundObject.binding = oBinding;
  		oBoundObject.fChangeHandler = fChangeHandler;
  
  		oBinding.attachEvents(oBoundObject.events);
  
  		oBinding.initialize();
  	};
  
  	/**
  	 * Bind the object to the referenced entity in the model, which is used as the binding context
  	 * to resolve bound properties or aggregations of the object itself and all of its children
  	 * relatively to the given path.
  	 *
  	 * @deprecated Since 1.11.1, please use bindElement instead.
  	 * @param {string} sPath the binding path
  	 * @return {sap.ui.base.ManagedObject} reference to the instance itself
  	 * @public
  	 */
  	ManagedObject.prototype.bindContext = function(sPath) {
  		return this.bindObject(sPath);
  	};
  
  	/**
  	 * Removes the defined binding context of this object, all bindings will now resolve
  	 * relative to the parent context again.
  	 *
  	 * @deprecated Since 1.11.1, please use unbindElement instead.
  	 * @param {string} [sModelName] name of the model to remove the context for.
  	 * @return {sap.ui.base.ManagedObject} reference to the instance itself
  	 * @public
  	 */
  	ManagedObject.prototype.unbindContext = function(sModelName) {
  		return this.unbindObject(sModelName);
  	};
  
  	/**
  	 * Removes the defined binding context of this object, all bindings will now resolve
  	 * relative to the parent context again.
  	 *
  	 * @param {string} [sModelName] name of the model to remove the context for.
  	 * @return {sap.ui.base.ManagedObject} reference to the instance itself
  	 * @public
  	 */
  	ManagedObject.prototype.unbindObject = function(sModelName, /* internal use only */ _bSkipUpdateBindingContext) {
  		var oBoundObject = this.mBoundObjects[sModelName];
  		if (oBoundObject) {
  			if (oBoundObject.binding) {
  				oBoundObject.binding.detachChange(oBoundObject.fChangeHandler);
  				oBoundObject.binding.detachEvents(oBoundObject.events);
  				oBoundObject.binding.destroy();
  			}
  			delete this.mBoundObjects[sModelName];
  			delete this.mElementBindingContexts[sModelName];
  			if ( !_bSkipUpdateBindingContext ) {
  				this.updateBindingContext(false, false, sModelName);
  			}
  		}
  		return this;
  	};
  
  	/**
  	 * Bind a property to the model.
  	 * The Setter for the given property will be called with the value retrieved
  	 * from the data model.
  	 * This is a generic method which can be used to bind any property to the
  	 * model. A managed object may flag properties in the metamodel with
  	 * bindable="bindable" to get typed bind methods for a property.
  	 * A composite property binding which may have multiple paths (also known as Calculated Fields) can be declared using the parts parameter.
  	 * Note a composite binding is read only (One Way).
  	 *
  	 * @param {string} sName the name of the property
  	 * @param {object} oBindingInfo the binding information
  	 * @param {string} oBindingInfo.path the binding path
  	 * @param {string} [oBindingInfo.model] the model identifier
  	 * @param {function} [oBindingInfo.formatter] the formatter function
  	 * @param {boolean} [oBindingInfo.useRawValues] determines if the parameters in the formatter functions should be passed as raw values or not. In this case
  	 *                  the specified type for the binding is not used and the values are not formatted. Note: use this flag only when using multiple bindings.
  	 *                  If you use only one binding and want raw values then simply don't specify a type for that binding.
  	 * @param {sap.ui.model.Type|string} [oBindingInfo.type] the sap.ui.model.Type object or class name
  	 * @param {object} [oBindingInfo.formatOptions] the format options to be used
  	 * @param {object} [oBindingInfo.constraints] the constraints for this value
  	 * @param {sap.ui.model.BindingMode} [oBindingInfo.mode=Default] the binding mode to be used for this property binding (e.g. one way)
  	 * @param {object} [oBindingInfo.parameters] a map of parameters which is passed to the binding.
  	 * The supported parameters are listed in the corresponding model-specific implementation of <code>sap.ui.model.PropertyBinding</code>.
  	 * @param {object} [oBindingInfo.parts] object for definding a read only composite binding which may have multiple binding paths also in different models.
  	 * <pre>
  	 *   oTxt.bindValue({
  	 *     parts: [
  	 *       {path: "/firstName", type: new sap.ui.model.type.String()},
  	 *       {path: "myModel2>/lastName"}
  	 *     ]
  	 *   });
  	 * </pre>
  	 * @return {sap.ui.base.ManagedObject} reference to the instance itself
  	 * @public
  	 */
  	ManagedObject.prototype.bindProperty = function(sName, oBindingInfo, /* undocumented, old API only: */ _vFormat, _sMode) {
  		var iSeparatorPos,
  			bAvailable = true,
  			oProperty = this.getMetadata().getPropertyLikeSetting(sName);
  
  		// check whether property or alternative type on aggregation exists
  		if (!oProperty) {
  			throw new Error("Property \"" + sName + "\" does not exist in " + this);
  		}
  
  		// old API compatbility (sName, sPath, _vFormat, _sMode)
  		if (typeof oBindingInfo == "string") {
  			oBindingInfo = {
  				parts: [ {
  					path: oBindingInfo,
  					type: _vFormat instanceof Type ? _vFormat : undefined,
  					mode: _sMode
  				} ],
  				formatter: typeof _vFormat === 'function' ? _vFormat : undefined
  			};
  		}
  
  		// only one binding object with one binding specified
  		if (!oBindingInfo.parts) {
  			oBindingInfo.parts = [];
  			oBindingInfo.parts[0] = {
  				path: oBindingInfo.path,
  				type: oBindingInfo.type,
  				formatOptions: oBindingInfo.formatOptions,
  				constraints: oBindingInfo.constraints,
  				model: oBindingInfo.model,
  				mode: oBindingInfo.mode
  			};
  			delete oBindingInfo.path;
  			delete oBindingInfo.mode;
  			delete oBindingInfo.model;
  		}
  
  		for ( var i = 0; i < oBindingInfo.parts.length; i++ ) {
  
  			var oPart = oBindingInfo.parts[i];
  			if (typeof oPart == "string") {
  				oPart = { path: oPart };
  				oBindingInfo.parts[i] = oPart;
  			}
  
  			// if a model separator is found in the path, extract model name and path
  			iSeparatorPos = oPart.path.indexOf(">");
  			if (iSeparatorPos > 0) {
  				oPart.model = oPart.path.substr(0, iSeparatorPos);
  				oPart.path = oPart.path.substr(iSeparatorPos + 1);
  			}
  			// if a formatter exists the binding mode can be one way or one time only
  			if (oBindingInfo.formatter && oPart.mode != BindingMode.OneWay && oPart.mode != BindingMode.OneTime) {
  				oPart.mode = BindingMode.OneWay;
  			}
  
  			if (!this.getModel(oPart.model)) {
  				bAvailable = false;
  			}
  
  		}
  
  		// if property is already bound, unbind it first
  		if (this.isBound(sName)) {
  			this.unbindProperty(sName, true);
  		}
  
  		// store binding info to create the binding, as soon as the model is available, or when the model is changed
  		this.mBindingInfos[sName] = oBindingInfo;
  
  		// if the models are already available, create the binding
  		if (bAvailable) {
  			this._bindProperty(sName, oBindingInfo);
  		}
  		return this;
  	};
  
  	ManagedObject.prototype._bindProperty = function(sName, oBindingInfo) {
  		var oModel,
  			oContext,
  			oBinding,
  			sMode,
  			sCompositeMode = BindingMode.TwoWay,
  			oType,
  			clType,
  			oPropertyInfo = this.getMetadata().getPropertyLikeSetting(sName), // TODO fix handling of hidden entitites?
  			sInternalType = oPropertyInfo._iKind === /* PROPERTY */ 0 ? oPropertyInfo.type : oPropertyInfo.altTypes[0],
  			that = this,
  			aBindings = [],
  			fModelChangeHandler = function(oEvent){
  				that.updateProperty(sName);
  				//clear Messages from messageManager
  				var oDataState = oBinding.getDataState();
  				if (oDataState) {
  					var oControlMessages = oDataState.getControlMessages();
  					if (oControlMessages && oControlMessages.length > 0) {
  						var oMessageManager = sap.ui.getCore().getMessageManager();
  						oDataState.setControlMessages([]); //remove the controlMessages before informing manager to avoid DataStateChange event to fire
  						if (oControlMessages) {
  							oMessageManager.removeMessages(oControlMessages);
  						}
  					}
  					oDataState.setInvalidValue(null); //assume that the model always sends valid data
  				}
  				if (oBinding.getBindingMode() === BindingMode.OneTime && oBinding.isResolved()) {
  					// if binding is one time but not resolved yet we don't destroy it yet.
  					oBinding.detachChange(fModelChangeHandler);
  					oBinding.detachEvents(oBindingInfo.events);
  					oBinding.destroy();
  					// TODO remove the binding from the binding info or mark it somehow as "deactivated"?
  				}
  			},
  			fDataStateChangeHandler = function(){
  				var oDataState = oBinding.getDataState();
  				if (!oDataState) {
  					return;
  				}
  				//inform generic refreshDataState method
  				if (that.refreshDataState) {
  					that.refreshDataState(sName, oDataState);
  				}
  			};
  
  		// Only use context for bindings on the primary model
  		oContext = this.getBindingContext(oBindingInfo.model);
  
  		jQuery.each(oBindingInfo.parts, function(i, oPart) {
  			// Only use context for bindings on the primary model
  			oContext = that.getBindingContext(oPart.model);
  			// Create binding object
  			oModel = that.getModel(oPart.model);
  			// Create type instance if needed
  			oType = oPart.type;
  			if (typeof oType == "string") {
  				clType = jQuery.sap.getObject(oType);
  				oType = new clType(oPart.formatOptions, oPart.constraints);
  			}
  
  			oBinding = oModel.bindProperty(oPart.path, oContext, oBindingInfo.parameters);
  			oBinding.setType(oType, sInternalType);
  			oBinding.setFormatter(oPart.formatter);
  
  			sMode = oPart.mode || oModel.getDefaultBindingMode();
  			oBinding.setBindingMode(sMode);
  
  			// Only if all parts have twoway binding enabled, the composite binding will also have twoway binding
  			if (sMode != BindingMode.TwoWay) {
  				sCompositeMode = BindingMode.OneWay;
  			}
  
  			aBindings.push(oBinding);
  		});
  
  		// check if we have a composite binding or a formatter function created by the BindingParser which has property textFragments
  		if (aBindings.length > 1 || ( oBindingInfo.formatter && oBindingInfo.formatter.textFragments )) {
  			// Create type instance if needed
  			oType = oBindingInfo.type;
  			if (typeof oType == "string") {
  				clType = jQuery.sap.getObject(oType);
  				oType = new clType(oBindingInfo.formatOptions, oBindingInfo.constraints);
  			}
  			oBinding = new CompositeBinding(aBindings, oBindingInfo.useRawValues);
  			oBinding.setType(oType, sInternalType);
  			oBinding.setBindingMode(oBindingInfo.mode || sCompositeMode);
  		} else {
  			oBinding = aBindings[0];
  		}
  
  		oBinding.attachChange(fModelChangeHandler);
  		if (this.refreshDataState) {
  			oBinding.attachAggregatedDataStateChange(fDataStateChangeHandler);
  		}
  
  		// set only one formatter function if any
  		// because the formatter gets the context of the element we have to set the context via proxy to ensure compatibility
  		// for formatter function which is now called by the property binding
  		// proxy formatter here because "this" is the correct cloned object
  		oBinding.setFormatter(jQuery.proxy(oBindingInfo.formatter, this));
  
  		// Set additional information on the binding info
  		oBindingInfo.binding = oBinding;
  		oBindingInfo.modelChangeHandler = fModelChangeHandler;
  		oBindingInfo.dataStateChangeHandler = fDataStateChangeHandler;
  		oBinding.attachEvents(oBindingInfo.events);
  
  		oBinding.initialize();
  	};
  
  	/**
  	 * Unbind the property from the model
  	 *
  	 * @param {string} sName the name of the property
  	 * @param {boolean} bSuppressReset whether the reset to the default value when unbinding should be suppressed
  	 * @return {sap.ui.base.ManagedObject} reference to the instance itself
  	 * @public
  	 */
  	ManagedObject.prototype.unbindProperty = function(sName, bSuppressReset){
  		var oBindingInfo = this.mBindingInfos[sName],
  			oPropertyInfo = this.getMetadata().getPropertyLikeSetting(sName);
  		if (oBindingInfo) {
  			if (oBindingInfo.binding) {
  				oBindingInfo.binding.detachChange(oBindingInfo.modelChangeHandler);
  				if (this.refreshDataState) {
  					oBindingInfo.binding.detachAggregatedDataStateChange(oBindingInfo.dataStateChangeHandler);
  				}
  				oBindingInfo.binding.detachEvents(oBindingInfo.events);
  				oBindingInfo.binding.destroy();
  			}
  			delete this.mBindingInfos[sName];
  			if (!bSuppressReset) {
  				this[oPropertyInfo._sMutator](null);
  			}
  		}
  		return this;
  	};
  
  	/**
  	 * Generic method which is called, whenever an property binding is changed.
  	 * This method gets the external format from the property binding and applies
  	 * it to the setter.
  	 *
  	 * @private
  	 */
  	ManagedObject.prototype.updateProperty = function(sName) {
  		var oBindingInfo = this.mBindingInfos[sName],
  			oBinding = oBindingInfo.binding,
  			oPropertyInfo = this.getMetadata().getPropertyLikeSetting(sName);
  
  		// If model change was triggered by the property itself, don't call the setter again
  		if (oBindingInfo.skipPropertyUpdate) {
  			return;
  		}
  
  		try {
  			var oValue = oBinding.getExternalValue();
  			oBindingInfo.skipModelUpdate = true;
  			this[oPropertyInfo._sMutator](oValue);
  			oBindingInfo.skipModelUpdate = false;
  		} catch (oException) {
  			oBindingInfo.skipModelUpdate = false;
  			if (oException instanceof FormatException) {
  				this.fireFormatError({
  					element : this,
  					property : sName,
  					type : oBinding.getType(),
  					newValue : oBinding.getValue(),
  					oldValue : this[oPropertyInfo._sGetter](),
  					exception: oException,
  					message: oException.message
  				}, false, true); // bAllowPreventDefault, bEnableEventBubbling
  				oBindingInfo.skipModelUpdate = true;
  				this[oPropertyInfo._sMutator](null);
  				oBindingInfo.skipModelUpdate = false;
  			} else {
  				throw oException;
  			}
  		}
  	};
  
  	/**
  	 * Update the property in the model if two way data binding mode is enabled
  	 *
  	 * @param sName the name of the property to update
  	 * @param oValue the new value to set for the property in the model
  	 * @private
  	 */
  	ManagedObject.prototype.updateModelProperty = function(sName, oValue, oOldValue){
  		if (this.isBound(sName)) {
  			var oBindingInfo = this.mBindingInfos[sName],
  				oBinding = oBindingInfo.binding;
  
  			// If property change was triggered by the model, don't update the model again
  			if (oBindingInfo.skipModelUpdate) {
  				return;
  			}
  
  			// only one property binding should work with two way mode...composite binding does not work with two way binding
  			if (oBinding && oBinding.getBindingMode() == BindingMode.TwoWay) {
  				try {
  					// Set flag to avoid originating property to be updated from the model
  					oBindingInfo.skipPropertyUpdate = true;
  					oBinding.setExternalValue(oValue);
  					oBindingInfo.skipPropertyUpdate = false;
  
  					// If external value differs from own value after model update,
  					// update property again
  					var oExternalValue = oBinding.getExternalValue();
  					if (oValue != oExternalValue) {
  						this.updateProperty(sName);
  					}
  
  					// Only fire validation success, if a type is used
  					if (oBinding.hasValidation()) {
  						this.fireValidationSuccess({
  							element: this,
  							property: sName,
  							type: oBinding.getType(),
  							newValue: oValue,
  							oldValue: oOldValue
  						}, false, true); // bAllowPreventDefault, bEnableEventBubbling
  					}
  				} catch (oException) {
  					oBindingInfo.skipPropertyUpdate = false;
  					if (oException instanceof ParseException) {
  						this.fireParseError({
  							element: this,
  							property: sName,
  							type: oBinding.getType(),
  							newValue: oValue,
  							oldValue: oOldValue,
  							exception: oException,
  							message: oException.message
  						}, false, true); // bAllowPreventDefault, bEnableEventBubbling
  					} else if (oException instanceof ValidateException) {
  						this.fireValidationError({
  							element: this,
  							property: sName,
  							type: oBinding.getType(),
  							newValue: oValue,
  							oldValue: oOldValue,
  							exception: oException,
  							message: oException.message
  						}, false, true); // bAllowPreventDefault, bEnableEventBubbling
  					} else {
  						throw oException;
  					}
  				}
  			}
  		}
  	};
  
  	// a non-falsy value used as default for 'templateShareable'.
  	var MAYBE_SHAREABLE_OR_NOT = 1;
  
  	/**
  	 * Bind an aggregation to the model.
  	 *
  	 * The bound aggregation will use the given template, clone it for each item
  	 * which exists in the bound list and set the appropriate binding context.
  	 * This is a generic method which can be used to bind any aggregation to the
  	 * model. A managed object may flag aggregations in the metamodel with
  	 * bindable="bindable" to get typed bind<i>Something</i> methods for those aggregations.
  	 *
  	 * @param {string} sName the aggregation to bind
  	 * @param {object} oBindingInfo the binding info
  	 * @param {string} oBindingInfo.path the binding path
  	 * @param {sap.ui.base.ManagedObject} oBindingInfo.template the template to clone for each item in the aggregation
  	 * @param {boolean} [oBindingInfo.templateShareable=true] option to enable that the template will be shared which means that it won't be destroyed or cloned automatically
  	 * @param {function} oBindingInfo.factory the factory function
  	 * @param {number} oBindingInfo.startIndex the first entry of the list to be created
  	 * @param {number} oBindingInfo.length the amount of entries to be created (may exceed the sizelimit of the model)
  	 * @param {sap.ui.model.Sorter|sap.ui.model.Sorter[]} [oBindingInfo.sorter] the initial sort order (optional)
  	 * @param {sap.ui.model.Filter[]} [oBindingInfo.filters] the predefined filters for this aggregation (optional)
  	 * @param {object} [oBindingInfo.parameters] a map of parameters which is passed to the binding.
  	 * The supported parameters are listed in the corresponding model-specific implementation of <code>sap.ui.model.ListBinding</code> or <code>sap.ui.model.TreeBinding</code>.
  	 * @param {function} [oBindingInfo.groupHeaderFactory] a factory function to generate custom group visualization (optional)
  	 *
  	 * @return {sap.ui.base.ManagedObject} reference to the instance itself
  	 * @public
  	 */
  	ManagedObject.prototype.bindAggregation = function(sName, oBindingInfo) {
  		var sPath,
  			oTemplate,
  			aSorters,
  			aFilters,
  			oMetadata = this.getMetadata(),
  			oAggregationInfo = oMetadata.getAggregation(sName);
  
  		// check whether aggregation exists
  		if (!oAggregationInfo) {
  			throw new Error("Aggregation \"" + sName + "\" does not exist in " + this);
  		}
  		if (!oAggregationInfo.multiple) {
  			jQuery.sap.log.error("Binding of single aggregation \"" + sName + "\" of " + this + " is not supported!");
  		}
  
  		// Old API compatibility (sName, sPath, oTemplate, oSorter, aFilters)
  		if (typeof oBindingInfo == "string") {
  			sPath = arguments[1];
  			oTemplate = arguments[2];
  			aSorters = arguments[3];
  			aFilters = arguments[4];
  			oBindingInfo = {path: sPath, sorter: aSorters, filters: aFilters};
  			// allow either to pass the template or the factory function as 3rd parameter
  			if (oTemplate instanceof ManagedObject) {
  				oBindingInfo.template = oTemplate;
  			} else if (typeof oTemplate === "function") {
  				oBindingInfo.factory = oTemplate;
  			}
  		}
  
  		// if aggregation is already bound, unbind it first
  		if (this.isBound(sName)) {
  			this.unbindAggregation(sName);
  		}
  
  		// check whether a template has been provided, which is required for proper processing of the binding
  		// If aggregation is marked correspondingly in the metadata, factory can be omitted (usually requires an updateXYZ method)
  		if (!(oBindingInfo.template || oBindingInfo.factory)) {
  			if ( oAggregationInfo._doesNotRequireFactory ) {
  				// add a dummy factory as property 'factory' is used to distinguish between property- and list-binding
  				oBindingInfo.factory = function() {
  					throw new Error("dummy factory called unexpectedly ");
  				};
  			} else {
  				throw new Error("Missing template or factory function for aggregation " + sName + " of " + this + " !");
  			}
  		}
  
  		// if we have a template we will create a factory function
  		if (oBindingInfo.template) {
  			// set default for templateShareable
  			if ( oBindingInfo.template._sapui_candidateForDestroy ) {
  				// template became active again, we should no longer consider to destroy it
  				jQuery.sap.log.warning("A template was reused in a binding, but was already marked as candidate for destroy. You better should declare such a usage with templateShareable:true in the binding configuration.");
  				delete oBindingInfo.template._sapui_candidateForDestroy;
  			}
  			if (oBindingInfo.templateShareable === undefined) {
  				oBindingInfo.templateShareable = MAYBE_SHAREABLE_OR_NOT;
  			}
  			oBindingInfo.factory = function(sId) {
  				return oBindingInfo.template.clone(sId);
  			};
  		}
  
  		// if a model separator is found in the path, extract model name and path
  		var iSeparatorPos = oBindingInfo.path.indexOf(">");
  		if (iSeparatorPos > 0) {
  			oBindingInfo.model = oBindingInfo.path.substr(0, iSeparatorPos);
  			oBindingInfo.path = oBindingInfo.path.substr(iSeparatorPos + 1);
  		}
  
  		// store binding info to create the binding, as soon as the model is available, or when the model is changed
  		this.mBindingInfos[sName] = oBindingInfo;
  
  		// if the model is already available create the binding
  		if (this.getModel(oBindingInfo.model)) {
  			this._bindAggregation(sName, oBindingInfo);
  		}
  		return this;
  	};
  
  	ManagedObject.prototype._bindAggregation = function(sName, oBindingInfo) {
  		var that = this,
  			oBinding,
  			fModelChangeHandler = function(oEvent){
  				var sUpdater = "update" + sName.substr(0,1).toUpperCase() + sName.substr(1);
  				if (that[sUpdater]) {
  					var sChangeReason = oEvent && oEvent.getParameter("reason");
  					if (sChangeReason) {
  						that[sUpdater](sChangeReason);
  					} else {
  						that[sUpdater]();
  					}
  				} else {
  					that.updateAggregation(sName);
  				}
  			},
  			fModelRefreshHandler = function(oEvent){
  				var sRefresher = "refresh" + sName.substr(0,1).toUpperCase() + sName.substr(1);
  				if (that[sRefresher]) {
  					that[sRefresher](oEvent.getParameter("reason"));
  				} else {
  					fModelChangeHandler(oEvent);
  				}
  			};
  			var oModel = this.getModel(oBindingInfo.model);
  			if (this.isTreeBinding(sName)) {
  				oBinding = oModel.bindTree(oBindingInfo.path, this.getBindingContext(oBindingInfo.model), oBindingInfo.filters, oBindingInfo.parameters, oBindingInfo.sorter);
  			} else {
  				oBinding = oModel.bindList(oBindingInfo.path, this.getBindingContext(oBindingInfo.model), oBindingInfo.sorter, oBindingInfo.filters, oBindingInfo.parameters);
  			}
  
  		if (this.bUseExtendedChangeDetection === true) {
  			oBinding.enableExtendedChangeDetection();
  		}
  
  		oBindingInfo.binding = oBinding;
  		oBindingInfo.modelChangeHandler = fModelChangeHandler;
  		oBindingInfo.modelRefreshHandler = fModelRefreshHandler;
  
  		oBinding.attachChange(fModelChangeHandler);
  
  		oBinding.attachRefresh(fModelRefreshHandler);
  
  		oBinding.attachEvents(oBindingInfo.events);
  
  		oBinding.initialize();
  	};
  
  	/**
  	 * Unbind the aggregation from the model
  	 *
  	 * @param {string} sName the name of the aggregation
  	 * @param {boolean} bSuppressReset whether the reset to empty aggregation when unbinding should be suppressed
  	 * @return {sap.ui.base.ManagedObject} reference to the instance itself
  	 * @public
  	 */
  	ManagedObject.prototype.unbindAggregation = function(sName, bSuppressReset){
  		var oBindingInfo = this.mBindingInfos[sName],
  			oAggregationInfo = this.getMetadata().getAggregation(sName);
  		if (oBindingInfo) {
  			if (oBindingInfo.binding) {
  				oBindingInfo.binding.detachChange(oBindingInfo.modelChangeHandler);
  				oBindingInfo.binding.detachRefresh(oBindingInfo.modelRefreshHandler);
  				oBindingInfo.binding.detachEvents(oBindingInfo.events);
  				oBindingInfo.binding.destroy();
  			}
  			// remove template if any
  			if (oBindingInfo.template ) {
  				if ( !oBindingInfo.templateShareable && oBindingInfo.template.destroy ) {
  					oBindingInfo.template.destroy();
  				}
  				if ( oBindingInfo.templateShareable === MAYBE_SHAREABLE_OR_NOT ) {
  					oBindingInfo.template._sapui_candidateForDestroy = true;
  				}
  			}
  
  			delete this.mBindingInfos[sName];
  			if (!bSuppressReset) {
  				this[oAggregationInfo._sDestructor]();
  			}
  		}
  		return this;
  	};
  
  	/**
  	 * Generic method which is called, whenever an aggregation binding is changed.
  	 * This method deletes all elements in this aggregation and recreates them
  	 * according to the data model.
  	 * In case a managed object needs special handling for a aggregation binding, it can create
  	 * a typed update-method (e.g. "updateRows") which will be used instead of the
  	 * default behaviour.
  	 *
  	 * @private
  	 */
  	ManagedObject.prototype.updateAggregation = function(sName) {
  		var oBindingInfo = this.mBindingInfos[sName],
  			oBinding = oBindingInfo.binding,
  			fnFactory = oBindingInfo.factory,
  			oAggregationInfo = this.getMetadata().getAggregation(sName),  // TODO fix handling of hidden aggregations
  			sGroup,
  			bGrouped,
  			aContexts,
  			sGroupFunction = oAggregationInfo._sMutator + "Group",
  			that = this;
  
  		// Update a single aggregation with the array of contexts. Reuse existing children
  		// and just append or remove at the end, if some are missing or too many.
  		function update(oControl, aContexts, fnBefore, fnAfter) {
  			var aChildren = oControl[oAggregationInfo._sGetter]() || [],
  				oContext,
  				oClone;
  			if (aChildren.length > aContexts.length) {
  				for (var i = aContexts.length; i < aChildren.length; i++) {
  					oControl[oAggregationInfo._sRemoveMutator](aChildren[i]);
  					aChildren[i].destroy();
  				}
  			}
  			for (var i = 0; i < aContexts.length; i++) {
  				oContext = aContexts[i];
  				oClone = aChildren[i];
  				if (fnBefore) {
  					fnBefore(oContext);
  				}
  				if (oClone) {
  					oClone.setBindingContext(oContext, oBindingInfo.model);
  				} else {
  					var sId = oControl.getId() + "-" + i;
  					oClone = fnFactory(sId, oContext);
  					oClone.setBindingContext(oContext, oBindingInfo.model);
  					oControl[oAggregationInfo._sMutator](oClone);
  				}
  				if (fnAfter) {
  					fnAfter(oContext, oClone);
  				}
  			}
  		}
  
  		// Check the current context for its group. If the group key changes, call the
  		// group function on the control.
  		function updateGroup(oContext) {
  			var oNewGroup = oBinding.getGroup(oContext);
  			if (oNewGroup.key !== sGroup) {
  				var oGroupHeader;
  				//If factory is defined use it
  				if (oBindingInfo.groupHeaderFactory) {
  					oGroupHeader = oBindingInfo.groupHeaderFactory(oNewGroup);
  				}
  				that[sGroupFunction](oNewGroup, oGroupHeader);
  				sGroup = oNewGroup.key;
  			}
  		}
  
  		// Update the tree recursively
  		function updateRecursive(oControl, oContexts) {
  			update(oControl, oContexts, null, function(oContext, oClone) {
  				updateRecursive(oClone, oBinding.getNodeContexts(oContext));
  			});
  		}
  
  		// If a factory function is used, aggregation must be completely rebuild
  		if (!oBindingInfo.template) {
  			this[oAggregationInfo._sDestructor]();
  		}
  
  		if (oBinding instanceof ListBinding) {
  			// If grouping is enabled, use updateGroup as fnBefore to create groups
  			bGrouped = oBinding.isGrouped() && sGroupFunction;
  			// Destroy children if binding is grouped or was grouped last time
  			if (bGrouped || oBinding.bWasGrouped) {
  				this[oAggregationInfo._sDestructor]();
  			}
  			oBinding.bWasGrouped = bGrouped;
  			aContexts = oBinding.getContexts(oBindingInfo.startIndex, oBindingInfo.length);
  			update(this, aContexts, bGrouped ? updateGroup : null);
  		} else if (oBinding instanceof TreeBinding) {
  			// In fnAfter call update recursively for the child nodes of the current tree node
  			updateRecursive(this, oBinding.getRootContexts());
  		}
  	};
  
  	/**
  	 * Generic method which can be called, when an aggregation needs to be refreshed.
  	 * This method does not make any change on the aggregtaion, but just calls the
  	 * getContexts method to trigger fetching of new data.
  	 *
  	 * @private
  	 */
  	ManagedObject.prototype.refreshAggregation = function(sName) {
  		var oBindingInfo = this.mBindingInfos[sName],
  			oBinding = oBindingInfo.binding;
  		oBinding.getContexts(oBindingInfo.startIndex, oBindingInfo.length);
  	};
  
  	/**
  	* Generic method which is called, whenever messages for this object exists.
  	*
  	* @param {string} sName The property name
  	* @param {array} aMessages The messages
  	* @protected
  	* @since 1.28
  	*/
  	ManagedObject.prototype.propagateMessages = function(sName, aMessages) {
  		jQuery.sap.log.warning("Message for " + this + ", Property " + sName);
  	};
  
  	/**
  	 *  This method is used internally and should only be overridden by a tree managed object which utilizes the tree binding.
  	 *  In this case and if the aggregation is a tree node the overridden method should then return true.
  	 *  If true is returned the tree binding will be used instead of the list binding.
  	 *
  	 *  @param {string} sName the aggregation to bind (e.g. nodes for a tree managed object)
  	 *  @return {boolean} whether tree binding should be used or list binding. Default is false. Override method to change this behavior.
  	 *
  	 *  @protected
  	 */
  	ManagedObject.prototype.isTreeBinding = function(sName) {
  		return false;
  	};
  
  	/**
  	 * Create or update local bindings.
  	 *
  	 * Called when model or binding contexts have changed. Creates bindings when the model was not available
  	 * at the time bindProperty or bindAggregation was called. Recreates the bindings when they exist already
  	 * and when the model has changed.
  	 *
  	 * @param {boolean} bUpdateAll forces an update of all bindings, sModelName will be ignored
  	 * @param {string|undefined} sModelName name of a model whose bindings should be updated
  	 *
  	 * @private
  	 */
  	ManagedObject.prototype.updateBindings = function(bUpdateAll, sModelName) {
  		var that = this,
  			sName,
  			oBindingInfo;
  
  		/*
  		 * Checks whether the binding for the given oBindingInfo became invalid because
  		 * of the current model change (as identified by bUpdateAll and sModelName).
  		 *
  		 * Precondition: oBindingInfo contains a 'binding' object
  		 *
  		 * @param oBindingInfo
  		 * @returns {boolean}
  		 */
  		function becameInvalid(oBindingInfo) {
  			var aParts = oBindingInfo.parts,
  				i;
  
  			if (aParts && aParts.length > 1) {
  				// composite binding: invalid when for any part the model has the same name (or updateall) and when the model instance for that part differs
  				for (i = 0; i < aParts.length; i++) {
  					if ( (bUpdateAll || aParts[i].model == sModelName) && !oBindingInfo.binding.aBindings[i].updateRequired(that.getModel(aParts[i].model)) ) {
  						return true;
  					}
  				}
  			} else if (oBindingInfo.factory) {
  				// list binding: invalid when  the model has the same name (or updateall) and when the model instance differs
  				return (bUpdateAll || oBindingInfo.model == sModelName) && !oBindingInfo.binding.updateRequired(that.getModel(oBindingInfo.model));
  			} else {
  				// simple property binding: invalid when the model has the same name (or updateall) and when the model instance differs
  				return (bUpdateAll || aParts[0].model == sModelName) && !oBindingInfo.binding.updateRequired(that.getModel(aParts[0].model));
  			}
  			return false;
  		}
  
  		/*
  		 * Checks whether a binding can be created for the given oBindingInfo
  		 * @param oBindingInfo
  		 * @returns {boolean}
  		 */
  		function canCreate(oBindingInfo) {
  			var aParts = oBindingInfo.parts,
  				i;
  
  			if (aParts) {
  				for (i = 0; i < aParts.length; i++) {
  					if ( !that.getModel(aParts[i].model) ) {
  						return false;
  					}
  				}
  				return true;
  			} else if (oBindingInfo.factory) { // List binding check
  				return !!that.getModel(oBindingInfo.model);
  			}
  			// there should be no other cases
  			return false;
  		}
  
  		// create property and aggregation bindings if they don't exist yet
  		for ( sName in this.mBindingInfos ) {
  
  			oBindingInfo = this.mBindingInfos[sName];
  
  			// if there is a binding and if it became invalid through the current model change, then remove it
  			if ( oBindingInfo.binding && becameInvalid(oBindingInfo) ) {
  				// Remove the validation controlMessages for this Binding from the MessageManager so they will not be propagated again
  				var oDataState = oBindingInfo.binding.getDataState();
  				sap.ui.getCore().getMessageManager().removeMessages(oDataState.getControlMessages(), true);
  				// Also tell the Control that the messages have been removed (if any)
  				if (this.refreshDataState) {
  					this.refreshDataState(sName, oDataState);
  				}
  
  				oBindingInfo.binding.detachChange(oBindingInfo.modelChangeHandler);
  				if (oBindingInfo.modelRefreshHandler) { // only list bindings currently have a refresh handler attached
  					oBindingInfo.binding.detachRefresh(oBindingInfo.modelRefreshHandler);
  				}
  				oBindingInfo.binding.detachEvents(oBindingInfo.events);
  				oBindingInfo.binding.destroy();
  				delete oBindingInfo.binding;
  			}
  
  			// if there is no binding and if all required information is available, create a binding object
  			if ( !oBindingInfo.binding && canCreate(oBindingInfo) ) {
  				if (oBindingInfo.factory) {
  					this._bindAggregation(sName, oBindingInfo);
  				} else {
  					this._bindProperty(sName, oBindingInfo);
  				}
  			}
  
  		}
  
  	};
  
  
  	/**
  	 * Find out whether a property or aggregation is bound
  	 *
  	 * @param {string} sName the name of the property or aggregation
  	 * @return {boolean} whether a binding exists for the given name
  	 * @public
  	 */
  	ManagedObject.prototype.isBound = function(sName){
  		return (sName in this.mBindingInfos);
  	};
  
  	/**
  	 * Get the object binding object for a specific model
  	 *
  	 * @param {string} sModelName the name of the model
  	 * @return {sap.ui.model.Binding} the element binding for the given model name
  	 * @public
  	 */
  	ManagedObject.prototype.getObjectBinding = function(sModelName){
  		return this.mBoundObjects[sModelName] && this.mBoundObjects[sModelName].binding;
  	};
  
  	/**
  	 * Returns the parent managed object as new eventing parent to enable control event bubbling
  	 * or <code>null</code> if this object hasn't been added to a parent yet.
  	 *
  	 * @return {sap.ui.base.EventProvider} the parent event provider
  	 * @protected
  	 */
  	ManagedObject.prototype.getEventingParent = function() {
  		return this.oParent;
  	};
  
  	/**
  	 * Get the binding object for a specific aggregation/property
  	 *
  	 * @param {string} sName the name of the property or aggregation
  	 * @return {sap.ui.model.Binding} the binding for the given name
  	 * @public
  	 */
  	ManagedObject.prototype.getBinding = function(sName){
  		return this.mBindingInfos[sName] && this.mBindingInfos[sName].binding;
  	};
  
  	/**
  	 * Get the binding path for a specific aggregation/property
  	 *
  	 * @param {string} sName the name of the property or aggregation
  	 * @return {string} the binding path for the given name
  	 * @protected
  	 */
  	ManagedObject.prototype.getBindingPath = function(sName){
  		var oInfo = this.mBindingInfos[sName];
  		return oInfo && (oInfo.path || (oInfo.parts && oInfo.parts[0] && oInfo.parts[0].path));
  	};
  
  	/**
  	 * Set the binding context for this ManagedObject for the model with the given name.
  	 *
  	 * Note: to be compatible with future versions of this API, applications must not use the value <code>null</code>,
  	 * the empty string <code>""</code> or the string literals <code>"null"</code> or <code>"undefined"</code> as model name.
  	 *
  	 * Note: A ManagedObject inherits binding contexts from the Core only when it is a descendant of an UIArea.
  	 *
  	 * @param {Object} oContext the new binding context for this object
  	 * @param {string} [sModelName] the name of the model to set the context for or <code>undefined</code>
  	 *
  	 * @return {sap.ui.base.ManagedObject} reference to the instance itself
  	 * @public
  	 */
  	ManagedObject.prototype.setBindingContext = function(oContext, sModelName){
  		jQuery.sap.assert(sModelName === undefined || (typeof sModelName === "string" && !/^(undefined|null)?$/.test(sModelName)), "sModelName must be a string or omitted");
  		var oOldContext = this.oBindingContexts[sModelName];
  
  		if (oOldContext !== oContext) {
  			this.oBindingContexts[sModelName] = oContext;
  			this.updateBindingContext(false, true, sModelName);
  			this.propagateProperties(sModelName);
  		}
  		return this;
  	};
  
  	/**
  	 * @private
  	 */
  	ManagedObject.prototype.setElementBindingContext = function(oContext, sModelName){
  		jQuery.sap.assert(sModelName === undefined || (typeof sModelName === "string" && !/^(undefined|null)?$/.test(sModelName)), "sModelName must be a string or omitted");
  		var oOldContext = this.mElementBindingContexts[sModelName];
  
  		if (oOldContext !== oContext) {
  			this.mElementBindingContexts[sModelName] = oContext;
  			this.updateBindingContext(true, true, sModelName);
  			this.propagateProperties(sModelName);
  		}
  		return this;
  	};
  
  	/**
  	 * Update the binding context in this object and all aggregated children
  	 * @private
  	 */
  	ManagedObject.prototype.updateBindingContext = function(bSkipLocal, bSkipChildren, sFixedModelName, bUpdateAll){
  
  		var oModel,
  			oModelNames = {},
  			sModelName,
  			oContext,
  			sName,
  			oBoundObject,
  			i;
  
  		// find models that need an context update
  		if (bUpdateAll) {
  			for (sModelName in this.oModels) {
  				if ( this.oModels.hasOwnProperty(sModelName) ) {
  					oModelNames[sModelName] = sModelName;
  				}
  			}
  			for (sModelName in this.oPropagatedProperties.oModels) {
  				if ( this.oPropagatedProperties.oModels.hasOwnProperty(sModelName) ) {
  					oModelNames[sModelName] = sModelName;
  				}
  			}
  		} else {
  			oModelNames[sFixedModelName] = sFixedModelName;
  		}
  
  		for (sModelName in oModelNames ) {
  			if ( oModelNames.hasOwnProperty(sModelName) ) {
  				sModelName = sModelName === "undefined" ? undefined : sModelName;
  				oModel = this.getModel(sModelName);
  				oBoundObject = this.mBoundObjects[sModelName];
  
  				if (oModel && oBoundObject && oBoundObject.sBindingPath && !bSkipLocal) {
  					if (!oBoundObject.binding) {
  						this._bindObject(sModelName, oBoundObject);
  					} else {
  						oContext = this._getBindingContext(sModelName);
  						if (oContext !== oBoundObject.binding.getContext()) {
  							oBoundObject.binding.setContext(oContext);
  						}
  					}
  					continue;
  				}
  
  				oContext = this.getBindingContext(sModelName);
  
  				// update context in existing bindings
  				for ( sName in this.mBindingInfos ){
  					var oBindingInfo = this.mBindingInfos[sName],
  						oBinding = oBindingInfo.binding,
  						aParts = oBindingInfo.parts;
  
  					if (!oBinding) {
  						continue;
  					}
  					if (aParts && aParts.length > 1) {
  						// composite binding: update required  when a part use the model with the same name
  						for (i = 0; i < aParts.length; i++) {
  							if ( aParts[i].model == sModelName ) {
  								oBinding.aBindings[i].setContext(oContext);
  							}
  						}
  					} else if (oBindingInfo.factory) {
  						// list binding: update required when the model has the same name (or updateall)
  						if ( oBindingInfo.model == sModelName) {
  							oBinding.setContext(oContext);
  						}
  
  					} else {
  						// simple property binding: update required when the model has the same name
  						if ( aParts[0].model == sModelName) {
  							oBinding.setContext(oContext);
  						}
  					}
  				}
  				if (!bSkipChildren) {
  					// also update context in all child elements
  					for ( sName in this.mAggregations ) {
  						var oAggregation = this.mAggregations[sName];
  						if (oAggregation instanceof ManagedObject) {
  							oAggregation.oPropagatedProperties.oBindingContexts[sModelName] = oContext;
  							oAggregation.updateBindingContext(false,false,sModelName);
  						} else if (oAggregation instanceof Array) {
  							for (i = 0; i < oAggregation.length; i++) {
  								oAggregation[i].oPropagatedProperties.oBindingContexts[sModelName] = oContext;
  								oAggregation[i].updateBindingContext(false,false,sModelName);
  							}
  						}
  					}
  				}
  			}
  		}
  
  	};
  
  
  	/**
  	 * Get the binding context of this object for the given model name.
  	 *
  	 * If the object does not have a binding context set on itself and has no own Model set,
  	 * it will use the first binding context defined in its parent hierarchy.
  	 *
  	 * Note: to be compatible with future versions of this API, applications must not use the value <code>null</code>,
  	 * the empty string <code>""</code> or the string literals <code>"null"</code> or <code>"undefined"</code> as model name.
  	 *
  	 * Note: A ManagedObject inherits binding contexts from the Core only when it is a descendant of an UIArea.
  	 *
  	 * @param {string} [sModelName] the name of the model or <code>undefined</code>
  	 * @return {Object} the binding context of this object
  	 * @public
  	 */
  	ManagedObject.prototype.getBindingContext = function(sModelName){
  		if (this.mElementBindingContexts[sModelName]) {
  			return this.mElementBindingContexts[sModelName];
  		}
  		return this._getBindingContext(sModelName);
  	};
  
  	/**
  	 * Get the binding context of this object for the given model name. The elementBindingContext will not be considered
  	 * @private
  	 */
  	ManagedObject.prototype._getBindingContext = function(sModelName){
  		var oModel = this.getModel(sModelName);
  		if (this.oBindingContexts[sModelName]) {
  			return this.oBindingContexts[sModelName];
  		} else if (oModel && this.oParent && this.oParent.getModel(sModelName) && oModel != this.oParent.getModel(sModelName)) {
  			return undefined;
  		} else {
  			return this.oPropagatedProperties.oBindingContexts[sModelName];
  		}
  	};
  
  	/**
  	 * Sets or unsets a model for the given model name for this ManagedObject.
  	 *
  	 * The <code>sName</code> must either be <code>undefined</code> (or omitted) or a non-empty string.
  	 * When the name is omitted, the default model is set/unset.
  	 *
  	 * When <code>oModel</code> is <code>null</code> or <code>undefined</code>, a previously set model
  	 * with that name is removed from this ManagedObject. If an ancestor (parent, UIArea or Core) has a model
  	 * with that name, this ManagedObject will immediately inherit that model from its ancestor.
  	 *
  	 * All local bindings that depend on the given model name, are updated (created if the model references
  	 * became complete now; updated, if any model reference has changed; removed if the model references
  	 * became incomplete now).
  	 *
  	 * Any change (new model, removed model, inherited model) is also applied to all aggregated descendants
  	 * as long as a descendant doesn't have its own model set for the given name.
  	 *
  	 * Note: to be compatible with future versions of this API, applications must not use the value <code>null</code>,
  	 * the empty string <code>""</code> or the string literals <code>"null"</code> or <code>"undefined"</code> as model name.
  	 *
  	 * Note: By design, it is not possible to hide an inherited model by setting a <code>null</code> or
  	 * <code>undefined</code> model. Applications can set an empty model to achieve the same.
  	 *
  	 * Note: A ManagedObject inherits models from the Core only when it is a descendant of an UIArea.
  	 *
  	 * @param {sap.ui.model.Model} oModel the model to be set or <code>null</code> or <code>undefined</code>
  	 * @param {string} [sName] the name of the model or <code>undefined</code>
  	 * @return {sap.ui.base.ManagedObject} <code>this</code> to allow method chaining
  	 * @public
  	 */
  	ManagedObject.prototype.setModel = function(oModel, sName) {
  		jQuery.sap.assert(oModel == null || oModel instanceof Model, "oModel must be an instance of sap.ui.model.Model, null or undefined");
  		jQuery.sap.assert(sName === undefined || (typeof sName === "string" && !/^(undefined|null)?$/.test(sName)), "sName must be a string or omitted");
  		if (!oModel && this.oModels[sName]) {
  			delete this.oModels[sName];
  			// propagate Models to children
  			// model changes are propagated until (including) the first descendant that has its own model with the same name
  			this.propagateProperties(sName);
  			// if the model instance for a name changes, all bindings for that model name have to be updated
  			this.updateBindings(false, sName);
  		} else if ( oModel && oModel !== this.oModels[sName] ) {
  			//TODO: handle null!
  			this.oModels[sName] = oModel;
  			// propagate Models to children
  			// model changes are propagated until (including) the first descendant that has its own model with the same name
  			this.propagateProperties(sName);
  			// update binding context, for primary model only
  			this.updateBindingContext(false, true, sName);
  			// if the model instance for a name changes, all bindings for that model name have to be updated
  			this.updateBindings(false, sName);
  		} // else nothing to do
  		return this;
  	};
  
  	/**
  	 * Propagate Properties (models and bindingContext) to aggregated objects.
  	 * @param {string|undefined|true} sName when <code>true</code>, all bindings are updated.
  	 *           Otherwise only those for the given model name (undefined == name of default model)
  	 *
  	 * @private
  	 */
  	ManagedObject.prototype.propagateProperties = function(vName) {
  		var oProperties = this._getPropertiesToPropagate(),
  			bUpdateAll = vName === true, // update all bindings when no model name parameter has been specified
  			sName = bUpdateAll ? undefined : vName,
  			sAggregationName, oAggregation, i;
  
  		for (sAggregationName in this.mAggregations) {
  			if (this.mSkipPropagation[sAggregationName]) {
  				continue;
  			}
  			oAggregation = this.mAggregations[sAggregationName];
  			if (oAggregation instanceof ManagedObject) {
  				this._propagateProperties(vName, oAggregation, oProperties, bUpdateAll, sName);
  			} else if (oAggregation instanceof Array) {
  				for (i = 0; i < oAggregation.length; i++) {
  					if (oAggregation[i] instanceof ManagedObject) {
  						this._propagateProperties(vName, oAggregation[i], oProperties, bUpdateAll, sName);
  					}
  				}
  			}
  		}
  	};
  
  	ManagedObject.prototype._propagateProperties = function(vName, oObject, oProperties, bUpdateAll, sName) {
  		if (!oProperties) {
  			oProperties = this._getPropertiesToPropagate();
  			bUpdateAll = vName === true;
  			sName = bUpdateAll ? undefined : vName;
  		}
  		oObject.oPropagatedProperties = oProperties;
  		oObject.updateBindings(bUpdateAll,sName);
  		oObject.updateBindingContext(false, true, sName, bUpdateAll);
  		oObject.propagateProperties(vName);
  	};
  
  	/**
  	 * Get properties for propagation
  	 * @return {object} oProperties
  	 * @private
  	 */
  	ManagedObject.prototype._getPropertiesToPropagate = function() {
  		var bNoOwnModels = jQuery.isEmptyObject(this.oModels),
  			bNoOwnContexts = jQuery.isEmptyObject(this.oBindingContexts),
  			bNoOwnElementContexts = jQuery.isEmptyObject(this.mElementBindingContexts);
  
  		function merge(empty,o1,o2,o3) {
  			return empty ? o1 : jQuery.extend({}, o1, o2, o3);
  		}
  
  		if (bNoOwnContexts && bNoOwnModels && bNoOwnElementContexts) {
  			//propagate the existing container
  			return this.oPropagatedProperties;
  		} else {
  			//merge propagated and own properties
  			return {
  					oModels : merge(bNoOwnModels, this.oPropagatedProperties.oModels, this.oModels),
  					oBindingContexts : merge((bNoOwnContexts && bNoOwnElementContexts), this.oPropagatedProperties.oBindingContexts, this.oBindingContexts, this.mElementBindingContexts)
  			};
  		}
  	};
  
  	/**
  	 * Get the model to be used for data bindings with the given model name.
  	 * If the object does not have a model set on itself, it will use the first
  	 * model defined in its parent hierarchy.
  	 *
  	 * The name can be omitted to reference the default model or it must be a non-empty string.
  	 *
  	 * Note: to be compatible with future versions of this API, applications must not use the value <code>null</code>,
  	 * the empty string <code>""</code> or the string literals <code>"null"</code> or <code>"undefined"</code> as model name.
  	 *
  	 * @param {string|undefined} [sName] name of the model to be retrieved
  	 * @return {sap.ui.model.Model} oModel
  	 * @public
  	 */
  	ManagedObject.prototype.getModel = function(sName) {
  		jQuery.sap.assert(sName === undefined || (typeof sName === "string" && !/^(undefined|null)?$/.test(sName)), "sName must be a string or omitted");
  		return this.oModels[sName] || this.oPropagatedProperties.oModels[sName];
  	};
  
  	/**
  	 * Check if any model is set to the ManagedObject or to one of its parents (including UIArea and Core).
  	 *
  	 * Note: A ManagedObject inherits models from the Core only when it is a descendant of an UIArea.
  	 *
  	 * @return {boolean} whether a model reference exists or not
  	 * @public
  	 */
  	ManagedObject.prototype.hasModel = function() {
  		return !(jQuery.isEmptyObject(this.oModels) && jQuery.isEmptyObject(this.oPropagatedProperties.oModels));
  	};
  
  	/**
  	 * Clones a tree of objects starting with the object on which clone is called first (root object).
  	 *
  	 * The ids within the newly created clone tree are derived from the original ids by appending
  	 * the given <code>sIdSuffix</code> (if no suffix is given, one will be created; it will be
  	 * unique across multiple clone calls).
  	 *
  	 * The <code>oOptions</code> configuration object can have the following properties:
  	 * <ul>
  	 * <li>The boolean value <code>cloneChildren</code> specifies wether associations/aggregations will be cloned</li>
  	 * <li>The boolean value <code>cloneBindings</code> specifies if bindings will be cloned</li>
  	 * </ul>
  	 *
  	 * For each cloned object the following settings are cloned based on the metadata of the object and the defined options:
  	 * <ul>
  	 * <li>all properties that are not bound. If cloneBinding is false even these properties will be cloned;
  	 * the values are used by reference, they are not cloned</li>
  	 * <li>all aggregated objects that are not bound. If cloneBinding is false even the ones that are bound will be cloned;
  	 * they are all cloned recursively using the same <code>sIdSuffix</code></li>
  	 * <li>all associated controls; when an association points to an object inside the cloned object tree,
  	 *     then the cloned association will be modified to that it points to the clone of the target object.
  	 *     When the association points to a managed object outside of the cloned object tree, then its
  	 *     target won't be changed.</li>
  	 * <li>all models set via setModel(); used by reference </li>
  	 * <li>all property and aggregation bindings (if cloneBindings is true); the pure binding infos (path, model name) are
  	 *     cloned, but all other information like template control or factory function,
  	 *     data type or formatter function are copied by reference. The bindings themselves
  	 *     are created anew as they are specific for the combination (object, property, model).
  	 *     As a result, any later changes to a binding of the original object are not reflected
  	 *     in the clone, but changes to e.g the type or template etc. are.</li>
  	 * </ul>
  	 *
  	 * Each clone is created by first collecting the above mentioned settings and then creating
  	 * a new instance with the normal constructor function. As a result, any side effects of
  	 * mutator methods (setProperty etc.) or init hooks are repeated during clone creation.
  	 * There is no need to override <code>clone()</code> just to reproduce these internal settings!
  	 *
  	 * Custom controls however can override <code>clone()</code> to implement additional clone steps.
  	 * They usually will first call <code>clone()</code> on the super class and then modify the
  	 * returned clone accordingly.
  	 *
  	 * Applications <b>must never provide</b> the second parameter <code>aLocaleIds</code>.
  	 * It is determined automatically for the root object (and its non-existance also serves as
  	 * an indicator for the root object). Specifying it will break the implementation of <code>clone()</code>.
  	 *
  	 * @param {string} [sIdSuffix] a suffix to be appended to the cloned object id
  	 * @param {string[]} [aLocalIds] an array of local IDs within the cloned hierarchy (internally used)
  	 * @param {Object} [oOptions] configuration object
  	 * @return {sap.ui.base.ManagedObject} reference to the newly created clone
  	 * @protected
  	 */
  	ManagedObject.prototype.clone = function(sIdSuffix, aLocalIds, oOptions) {
  		var bCloneChildren = true,
  			bCloneBindings = true;
  
  		if (oOptions) {
  			bCloneChildren = !!oOptions.cloneChildren;
  			bCloneBindings = !!oOptions.cloneBindings;
  		}
  		// if no id suffix has been provided use a generated UID
  		if (!sIdSuffix) {
  			sIdSuffix = ManagedObjectMetadata.uid("clone") || jQuery.sap.uid();
  		}
  		// if no local ID array has been passed, collect IDs of all aggregated objects to
  		// be able to properly adapt associations, which are within the cloned object hierarchy
  		if (!aLocalIds && bCloneChildren) {
  			aLocalIds = jQuery.map(this.findAggregatedObjects(true), function(oObject) {
  				return oObject.getId();
  			});
  		}
  
  		var oMetadata = this.getMetadata(),
  			oClass = oMetadata._oClass,
  			sId = this.getId() + "-" + sIdSuffix,
  			mSettings = {},
  			mProps = this.mProperties,
  			sKey,
  			sName,
  			oClone,
  			escape = ManagedObject.bindingParser.escape,
  			i;
  
  		// Clone properties (only those with non-default value)
  		var aKeys = Object.keys(mProps);
  		i = aKeys.length;
  		while ( i > 0 ) {
  			sKey = aKeys[--i];
  			//do not clone properties if property is bound and bindings are cloned; Property is set on update
  			if ( /*mProps.hasOwnProperty(sKey) && */ !(this.isBound(sKey) && bCloneBindings)) {
  				// Note: to avoid double resolution of binding expressions, we have to escape string values once again
  				if (typeof mProps[sKey] === "string") {
  					mSettings[sKey] = escape(mProps[sKey]);
  				} else {
  					mSettings[sKey] = mProps[sKey];
  				}
  			}
  		}
  
  		// Clone models
  		mSettings["models"] = this.oModels;
  
  		// Clone BindingContext
  		mSettings["bindingContexts"] = this.oBindingContexts;
  
  		if (bCloneChildren) {
  			// Clone aggregations
  			for (sName in this.mAggregations) {
  				var oAggregation = this.mAggregations[sName];
  				//do not clone aggregation if aggregation is bound and bindings are cloned; aggregation is filled on update
  				if (oMetadata.hasAggregation(sName) && !(this.isBound(sName) && bCloneBindings)) {
  					if (oAggregation instanceof ManagedObject) {
  						mSettings[sName] = oAggregation.clone(sIdSuffix, aLocalIds);
  					} else if (jQuery.isArray(oAggregation)) {
  						mSettings[sName] = [];
  						for (var i = 0; i < oAggregation.length; i++) {
  							mSettings[sName].push(oAggregation[i].clone(sIdSuffix, aLocalIds));
  						}
  					} else {
  						// must be an alt type
  						mSettings[sName] = oAggregation;
  					}
  				}
  			}
  
  			// clone inactive children
  			var aInactiveChildren = getStashedControls(this.getId());
  			for (var i = 0, l = aInactiveChildren.length; i < l; i++) {
  					var oClonedChild = aInactiveChildren[i].clone(sIdSuffix);
  					oClonedChild.sParentId = sId;
  					oClonedChild.sParentAggregationName = aInactiveChildren[i].sParentAggregationName;
  			}
  
  			// Clone associations
  			for (sName in this.mAssociations) {
  				var oAssociation = this.mAssociations[sName];
  				// Check every associated ID against the ID array, to make sure associations within
  				// the template are properly converted to associations within the clone
  				if (jQuery.isArray(oAssociation)) {
  					oAssociation = oAssociation.slice(0);
  					for (var i = 0; i < oAssociation.length; i++) {
  						if (jQuery.inArray(oAssociation[i], aLocalIds) >= 0) {
  							oAssociation[i] += "-" + sIdSuffix;
  						}
  					}
  				} else if (jQuery.inArray(oAssociation, aLocalIds) >= 0) {
  					oAssociation += "-" + sIdSuffix;
  				}
  				mSettings[sName] = oAssociation;
  			}
  		}
  		// Create clone instance
  		oClone = new oClass(sId, mSettings);
  
  		/* Clone element bindings: Clone the objects not the parameters
  		 * Context will only be updated when adding the control to the control tree;
  		 * Maybe we have to call updateBindingcontext() here?
  		 */
  		for (sName in this.mBoundObjects) {
  			oClone.mBoundObjects[sName] = jQuery.extend({}, this.mBoundObjects[sName]);
  		}
  
  		// Clone events
  		for (sName in this.mEventRegistry) {
  			oClone.mEventRegistry[sName] = this.mEventRegistry[sName].slice();
  		}
  
  		// Clone bindings
  		if (bCloneBindings) {
  			for (sName in this.mBindingInfos) {
  				var oBindingInfo = this.mBindingInfos[sName];
  				var oCloneBindingInfo = jQuery.extend({}, oBindingInfo);
  
  				// clone the template if it is not sharable
  				if (!oBindingInfo.templateShareable && oBindingInfo.template && oBindingInfo.template.clone) {
  					oCloneBindingInfo.template = oBindingInfo.template.clone(sIdSuffix,	aLocalIds);
  					delete oCloneBindingInfo.factory;
  				} else if ( oBindingInfo.templateShareable === MAYBE_SHAREABLE_OR_NOT ) {
  					// a 'clone' operation implies sharing the template (if templateShareable is not set to false)
  					oBindingInfo.templateShareable = oCloneBindingInfo.templateShareable = true;
  					jQuery.sap.log.error("A shared template must be marked with templateShareable:true in the binding info");
  				}
  
  				delete oCloneBindingInfo.binding; // remove the runtime binding info (otherwise the property will not be connected again!)
  				if (oBindingInfo.factory || oBindingInfo.template) {
  					oClone.bindAggregation(sName, oCloneBindingInfo);
  				} else {
  					oClone.bindProperty(sName, oCloneBindingInfo);
  				}
  			}
  		}
  		return oClone;
  	};
  
  	/**
  	 * Update all localization dependant objects that this managedObject can reach,
  	 * except for its children (which will be updated from the Core).
  	 *
  	 * To make the update work as smooth as possible, it happens in two phases:
  	 * <ol>
  	 *  <li>In phase 1 all known models are updated.
  	 *  <li>In phase 2 all bindings are updated.
  	 * </ol>
  	 * This separation is necessary as the models for the bindings might be updated
  	 * in some ManagedObject or in the Core and the order in which the objects are visited
  	 * is not defined (Core.mElements order)
  	 *
  	 * @private
  	 */
  	ManagedObject._handleLocalizationChange = function(iPhase) {
  		var i;
  
  		if ( iPhase === 1 ) {
  
  			/*
  			 * phase 1: update the models
  			 */
  			jQuery.each(this.oModels, function(sName, oModel) {
  				if ( oModel && oModel._handleLocalizationChange ) {
  					oModel._handleLocalizationChange();
  				}
  			});
  
  		} else if ( iPhase === 2 ) {
  
  			/*
  			 * phase 2: update bindings and types
  			 */
  			jQuery.each(this.mBindingInfos, function(sName, oBindingInfo) {
  				var aParts = oBindingInfo.parts;
  				if (aParts) {
  					// property or composite binding: visit all parts
  					for (i = 0; i < aParts.length; i++) {
  						if ( oBindingInfo.type && oBindingInfo.type._handleLocalizationChange ) {
  							oBindingInfo.type._handleLocalizationChange();
  						}
  					}
  					if ( oBindingInfo.modelChangeHandler ) {
  						oBindingInfo.modelChangeHandler();
  					}
  				} // else: don't update list bindings
  				// Note: the template for a list binding will be visited by the core!
  			});
  
  		}
  	};
  
  
  	/**
  	 * Searches and returns an array of child elements and controls which are
  	 * referenced within an aggregation or aggregations of child elements/controls.
  	 * This can be either done recursive or not. Optionally a condition function can be passed that
  	 * returns true if the object should be added to the array.
  	 * <br>
  	 * <b>Take care: this operation might be expensive.</b>
  	 * @param {boolean}
  	 *          bRecursive true, if all nested children should be returned.
  	 * @param {boolean}
  	 *          fnCondition if given, the object is passed as a parameter to the.
  	 * @return {sap.ui.base.ManagedObject[]} array of child elements and controls
  	 * @public
  	 */
  	ManagedObject.prototype.findAggregatedObjects = function(bRecursive, fnCondition) {
  
  		var aAggregatedObjects = [];
  		if (fnCondition && !typeof fnCondition === "function") {
  			fnCondition = null;
  		}
  		function fFindObjects(oObject) {
  			for (var n in oObject.mAggregations) {
  				var a = oObject.mAggregations[n];
  				if (jQuery.isArray(a)) {
  					for (var i = 0; i < a.length; i++) {
  						if (!fnCondition || fnCondition(a[i])) {
  							aAggregatedObjects.push(a[i]);
  						}
  						if (bRecursive) {
  							fFindObjects(a[i]);
  						}
  					}
  				} else if (a instanceof ManagedObject) {
  					if (!fnCondition || fnCondition(a)) {
  						aAggregatedObjects.push(a);
  					}
  					if (bRecursive) {
  						fFindObjects(a);
  					}
  				}
  			}
  		}
  		fFindObjects(this);
  		return aAggregatedObjects;
  
  	};
  
  	return ManagedObject;
  
  });
  