
registerType('Core', (function () { function BindingsContext() {} var __super = null;


	
	
BindingsContext.prototype.initFromData = function BindingsContext_initFromData(options) {
		this.init();
		this.initPropertiesFromData(options);
		return this;};
	
	
BindingsContext.prototype.init = function BindingsContext_init() {
		this.reset();
		return this;};
	
	
BindingsContext.prototype.initPropertiesFromData = function BindingsContext_initPropertiesFromData(options) {
		if (options.$id) {
			this.$id = options.$id;
			this.connectableObjects[options.$id] = this;
		}
		if (options.globalBindingsSymbol) {
			this.registerGlobal(options.globalBindingsSymbol, this);
		}};
	
	
BindingsContext.prototype.reset = function BindingsContext_reset() {
		this.globals = {};
		this.connectableObjects = { 'null': {} };
		this.observations = {};
		this.bindings = {};
		this.bindingsCount = 0;};
	


	

// role BindingsContext 

		
	
BindingsContext.prototype.registerGlobal = function BindingsContext_registerGlobal(symbol, obj) {
			this.globals[symbol] = obj;};
		
	
BindingsContext.prototype.unregisterGlobal = function BindingsContext_unregisterGlobal(symbol) {
			delete this.globals[symbol];};
		

	
		
		
BindingsContext.prototype.identify = function BindingsContext_identify(obj, prefix) {
		
			if (!obj) {
				console.warn('identify(): obj is '+obj);
				console.trace();
				return;
			}

			if (obj.Name) {
				console.log('identify', obj);
				console.trace();
			}
		
			
			if (!obj.$id) {
				obj.$id = this.createUID(prefix || obj.constructor.name || "object");
			}
			
			this.globals[obj.$id] = obj;
			this.connectableObjects[obj.$id] = obj;
			
			return obj.$id;
			};
		
		
BindingsContext.prototype.unidentify = function BindingsContext_unidentify(obj) {
			if (obj.$id) {
				delete this.globals[obj.$id];
				delete this.connectableObjects[obj.$id];
			}};
		


		

BindingsContext.prototype.dissolveKeyPathWithContextObject = function BindingsContext_dissolveKeyPathWithContextObject(keyPath, obj) {
		
			if (!keyPath) {
				console.warn('No keyPath provided.');
				return;
			}

			if (!obj) {
				console.warn('No object provided.');
				return;
			}
			
			
			var pathComponents = keyPath.split('.'),
				root = obj[pathComponents[0]] || this.globals[pathComponents[0]];
			
			try {
				
				
			
				if (pathComponents.length === 1) {
					return root;
				}
				else if (pathComponents.length === 2) {
					return root[pathComponents[1]];
				}
				else if (pathComponents.length === 3) {
					var targetObj = root[pathComponents[1]];
					return targetObj[pathComponents[2]];
				}
				else if (pathComponents.length === 4) {
					var targetObj = root[pathComponents[1]][pathComponents[2]];
					return targetObj[pathComponents[3]];
				}
				else if (pathComponents.length === 5) {
					var targetObj = root[pathComponents[1]][pathComponents[2]][pathComponents[3]];
					return targetObj[pathComponents[4]];
				}
				else if (pathComponents.length === 6) {
					var targetObj = root[pathComponents[1]][pathComponents[2]][pathComponents[3]][pathComponents[4]];
					return targetObj[pathComponents[5]];
				}
				else if (pathComponents.length === 7) {
					return root[pathComponents[1]][pathComponents[2]][pathComponents[3]][pathComponents[4]][pathComponents[5]][pathComponents[6]];
				}
				else if (pathComponents.length === 8) {
					return root[pathComponents[1]][pathComponents[2]][pathComponents[3]][pathComponents[4]][pathComponents[5]][pathComponents[6]][pathComponents[7]];
				}
				else {
					console.warn('Missing implementation.');
				}
			} catch (err) {
				console.error('dissolveKeyPathWithContextObject() failed with', root, keyPath, obj, err);
				console.trace();
			}
	};
		


		

BindingsContext.prototype.getValueForKeyPathInObject = function BindingsContext_getValueForKeyPathInObject(keyPath, obj) {

			if (keyPath === '') return obj;
			if (typeof keyPath !== 'string' && typeof keyPath !== 'number') {
				
				
				return;
			}

			var f = keyPath.toString().split('.'),
				value = obj[f[0]],
				c = f.length;
	
			if (value !== undefined) {
				for (var i = 1; i != c; i++) {
					if (f[i] === '') continue;
					var _value = value[f[i]];
					if (_value === undefined) {
						return undefined;
					}
					else value = _value;
				}
			}
	
			return value;
		};
		
		
BindingsContext.prototype.setValueForKeyPathInObject = function BindingsContext_setValueForKeyPathInObject(value, keyPath, obj) {
			if (typeof keyPath !== 'string') {
				console.warn('setValueForKeyPathInObject(): keyPath is not a string:', keyPath, typeof keyPath);
				console.trace();
				return;
			}

			
			
			try {
				var f = keyPath.toString().split('.');
				if (f.length === 1)
					obj[keyPath] = value;
				else if (f.length === 2)
					obj[f[0]][f[1]] = value;
				else if (f.length === 3)
					obj[f[0]][f[1]][f[2]] = value;
				else if (f.length === 4)
					obj[f[0]][f[1]][f[2]][f[3]] = value;
				else {
					console.warn('Missing implementation!');
				}
			} catch (err) {
				console.warn('setValueForKeyPathInObject() failed with keypath «'+keyPath+'».', err, value, obj);
			}};
		
	
	
		
		
BindingsContext.prototype.registerObservation = function BindingsContext_registerObservation(observer, observedObject) {
		
			if (!observedObject) {
				console.warn('in registerObservation(): observedObject is', observedObject);
				return;
			}
		
			this.addArrayObjectValue('observations', observedObject.$id, observer);
	};
		
		
BindingsContext.prototype.unregisterObservation = function BindingsContext_unregisterObservation(observer, observedObject) {
			
			if (!observedObject) return;
			
			this.removeArrayObjectValue('observations', observedObject.$id, observer);
			
			
			
};
		
		
		
		
		
BindingsContext.prototype.registerBinding = function BindingsContext_registerBinding(binding) {

			if (this.addArrayObjectValue('bindings', this.identify(binding.destinationObject), binding))
				this.bindingsCount++;
			
			if (binding.bidirectional === true) {
				binding.reverseBinding = this.createReverseBinding(binding);
				if (this.addArrayObjectValue('bindings', this.identify(binding.sourceObject), binding.reverseBinding))
					this.bindingsCount++;
			}
};
		
		
BindingsContext.prototype.registerBindingForObject = function BindingsContext_registerBindingForObject(binding, obj) {
		
			if (binding.enumerableItemAccess) return;

			Object.defineProperty(binding, 'sourceObject', {
				value: obj,
				configurable: true,
				enumerable: false
			});

			if (binding.destinationObject === undefined) {

				Object.defineProperty(binding, 'destinationObject', {
					enumerable: false,
					value: this.connectableObjects[binding.destination],
				    configurable: true
				});

			}

			if (binding.destinationObject === undefined) {
				
				return;
			}

			if (typeof binding.valueTransformer === 'string') {
				binding.valueTransformer = new Function ("a", binding.valueTransformer);
			}

			this.registerBinding(binding);
};
		
		
BindingsContext.prototype.unregisterBinding = function BindingsContext_unregisterBinding(binding) {

			if (binding.enumerableItemAccess === true || !binding.destinationObject) return;
			
			if (binding.context && binding.context !== this) {
				return binding.context.unregisterBinding(binding);
			}

			if (this.removeArrayObjectValue('bindings', binding.destinationObject.$id, binding))
				this.bindingsCount--;

			if (binding.reverseBinding !== undefined) {
				if (this.removeArrayObjectValue('bindings', binding.sourceObject.$id, binding.reverseBinding))
					this.bindingsCount--;
			}
						
			delete binding.destinationObject;
};
		
		
BindingsContext.prototype.applyBinding = function BindingsContext_applyBinding(binding, dump) {
		
			
			if (binding.sourceObject && !binding.destinationObject) {
				this.registerBindingForObject(binding, binding.sourceObject);
			}
			
			if (!binding.destinationObject || binding.destinationObject._isDestroyed) {
				delete binding.destinationObject;
				return;
			}

			var value;
			
			if (binding.destinationObject.get !== undefined)
				value = binding.destinationObject.get(binding.destinationKeyPath);
			else
				value = this.getValueForKeyPathInObject(binding.destinationKeyPath, binding.destinationObject);


			value = this.applyValueTransformerFromBindingToValue(binding, value);
			
			if (dump) console.log('applying binding', binding, binding.destinationObject, value);
			
			
			binding.sourceObject.valueShouldChangeForKeyPath(value, binding.sourceKeyPath);};
		

BindingsContext.prototype.applyBindingsForObject = function BindingsContext_applyBindingsForObject(obj) {

			var bindings = this.bindings[obj.$id];
			
			if (bindings === undefined)
				return;
			
			if (Array.isArray(bindings)) bindings.every(function (binding) {
				this.applyBinding(binding);return true; }, this);
			
};
		
		
		
		

		

		
BindingsContext.prototype.broadcastValueChangeForObject = function BindingsContext_broadcastValueChangeForObject(object, sender) {
		
			this.notifyObservers(object.$id, null,
				object, sender);
			
			this.applyBindingsForObject(object);
		};
		
		
		
BindingsContext.prototype.broadcastInsertionForObject = function BindingsContext_broadcastInsertionForObject(insertedKey, object, sender) {
		
			if (!object) { console.warn('broadcastInsertionForObject(): No object provided.'); console.trace(); return; }

			this.notifyObservers(object.$id, 'observedObjectValueDidAppearForKey',
				object, sender,
				insertedKey, sender);
				
			this.applyBindingsForObject(object);
	};
		
	
		
BindingsContext.prototype.broadcastDeletionForObject = function BindingsContext_broadcastDeletionForObject(deletedKey, deletedValue, object, sender) {
		
			this.notifyObservers(object.$id, 'observedObjectValueDidDisappearForKey',
				object, sender,
				deletedValue, deletedKey, sender);
};
		

BindingsContext.prototype.broadcastDeletionAnnouncementForObject = function BindingsContext_broadcastDeletionAnnouncementForObject(deletedKey, deletedValue, object, sender) {
		
			this.notifyObservers(object.$id, 'observedObjectValueWillDisappearForKey',
				object, sender,
				deletedValue, deletedKey, sender);
};
		
	
		
BindingsContext.prototype.broadcastKeyChangeForKeyPathInObject = function BindingsContext_broadcastKeyChangeForKeyPathInObject(oldKey, newKey, keyPath, object, sender) {
		
			this.notifyObservers(object.$id, 'observedObjectValueDidChangeKey',
				object, sender,
				oldKey, newKey, keyPath, sender);
};
		
	
		
BindingsContext.prototype.broadcastValueReplacementForObject = function BindingsContext_broadcastValueReplacementForObject(object, sender) {
		
			this.notifyObservers(object.$id, 'observedObjectValuesDidReplace',
				object, sender,
				sender);

			this.applyBindingsForObject(object);
		};
		
	
		
BindingsContext.prototype.broadcastValueChangeAnnouncementForKeyPathInObject = function BindingsContext_broadcastValueChangeAnnouncementForKeyPathInObject(keyPath, object, sender) {
			this.notifyObservers(object.$id, "observedObjectValueWillChangeForKeyPath",
				object, sender,
				keyPath, sender);};
		

		
BindingsContext.prototype.broadcastValueChangeForKeyPathInObject = function BindingsContext_broadcastValueChangeForKeyPathInObject(keyPath, object, sender) {

			this.notifyObservers(object.$id, "observedObjectValueDidChangeForKeyPath",
				object, sender,
				keyPath, sender);

			var value = object.get(keyPath);
			this.applyBindingsToObjectAndKeyPathWithValue(object, keyPath, value, sender);
};
		
		
		
BindingsContext.prototype.broadcastSelectionChangeForKeyPathInObject = function BindingsContext_broadcastSelectionChangeForKeyPathInObject(key, isSelected, object, sender) {

			this.notifyObservers(object.$id, "observedObjectSelectionDidChangeForKeyPath",
				object, sender,
				key, isSelected, sender);
		};
		
		
		
BindingsContext.prototype.broadcastSelectionChangeForObject = function BindingsContext_broadcastSelectionChangeForObject(object, sender) {

			this.notifyObservers(object.$id, 'observedObjectSelectionDidChange',
				object, sender,
				sender);
};
		

	


	

BindingsContext.prototype.createUID = function BindingsContext_createUID(suggestedName, useThisLookUpTable) {
	
		var lookUpTable = useThisLookUpTable || this.globals;
	
		var UID;

		do {
			UID = suggestedName + parseInt(Math.random() * 10000);
		}
		while (lookUpTable[UID] !== undefined);
		
		if (useThisLookUpTable) useThisLookUpTable[UID] = true;

		return UID;
};
	


	

BindingsContext.prototype.addArrayObjectValue = function BindingsContext__addArrayObjectValue(key, id, value) {

		var obj = this[key];
		if (obj[id] === undefined)
			obj[id] = [value];
		else
			obj[id].push(value);
		
		return true;
};
	
	
BindingsContext.prototype.removeArrayObjectValue = function BindingsContext__removeArrayObjectValue(key, id, value) {

		var obj = this[key];
		if (obj[id] === undefined) {
			return;
		}
		var index = obj[id].indexOf(value);
		if (index === -1) {
			return;
		}
		obj[id].splice(index, 1);

		if (obj[id].length === 0) delete obj[id];

		return true;
		};
	


	
	
BindingsContext.prototype.notifyObservers = function BindingsContext__notifyObservers(objectId, callbackName, obj, sender, arg1, arg2, arg3, arg4) {

		var observers = this.observations[objectId];

		if (observers === undefined) return;

		if (Array.isArray(observers)) observers.every(function (observer) {
		
			if (observer === sender)
				return true;

			if (callbackName !== null) {
				observer[callbackName](obj, arg1, arg2, arg3, arg4);

			}
			return true; }, this);
		
	};
	


BindingsContext.prototype.createReverseBinding = function BindingsContext__createReverseBinding(binding) {

		var _binding = {
			source: binding.destination,
			sourceKeyPath: binding.destinationKeyPath,
			destinationKeyPath: binding.sourceKeyPath,
			valueTransformer: binding.valueTransformer
		};

		Object.defineProperty(_binding, 'sourceObject', {
			value: binding.destinationObject,
			configurable: true,
			enumerable: false
		});

		Object.defineProperty(_binding, 'destinationObject', {
			value: binding.sourceObject,
			enumerable: false,
			configurable: true
		});
		
		return _binding;};
	

BindingsContext.prototype.applyBindingsToObjectAndKeyPathWithValue = function BindingsContext__applyBindingsToObjectAndKeyPathWithValue(obj, keyPath, value, sender) {
	
		var bindings = this.bindings[obj.$id];

		if (bindings === undefined) {
			return;
		}
		
		if (Array.isArray(bindings)) bindings.every(function (binding) {
			if (binding.destinationKeyPath !== keyPath) return true;
			if (sender === binding.sourceObject) return;

			var _value = value;
			_value = this.applyValueTransformerFromBindingToValue(binding, _value);
			
			
			

			if (binding.sourceObject.valueShouldChangeForKeyPath) {
				binding.sourceObject.valueShouldChangeForKeyPath(_value, binding.sourceKeyPath, sender);
			}
			else
				this.setValueForKeyPathInObject(_value, binding.sourceKeyPath, binding.sourceObject);return true; }, this);
		
};
	
	
BindingsContext.prototype.applyValueTransformerFromBindingToValue = function BindingsContext_applyValueTransformerFromBindingToValue(binding, _value) {
		if (binding.valueTransformer !== undefined) {
			_value = binding.valueTransformer.call(binding.sourceObject, _value);
		}
		if (binding.valueTransformerIsBooleanInverter === true) {
			_value = !_value;
		}
		return _value;};
	
	
BindingsContext.prototype.convertEnumerableItemBindingToPermanentFromObjectInLocalContext = function BindingsContext_convertEnumerableItemBindingToPermanentFromObjectInLocalContext(binding, obj, localContext) {

		var _binding = clone(binding);
		
		var destinationObject = this.dissolveKeyPathWithContextObject(binding.destination, localContext);

			
			
			
			
			
			if (_binding.staticKeyPathDissolving) {
				var lastDot = binding.destinationKeyPath.lastIndexOf('.');
				var keyPathPrefix = binding.destinationKeyPath.substr(0, lastDot);
				
				_binding.destination += '.'+keyPathPrefix;
				_binding.destinationKeyPath = _binding.destinationKeyPath.substr(lastDot+1);
				
				destinationObject = this.dissolveKeyPathWithContextObject(keyPathPrefix, destinationObject);

			}

		Object.defineProperty(_binding, 'destinationObject', {
			value: destinationObject,
			enumerable: false
		});
		Object.defineProperty(_binding, 'sourceObject', {
			value: obj,
			configurable: true,
			enumerable: false
		});
		_binding.enumerableItemAccess = false;
		delete _binding.destination;
		
		if (!_binding.destinationObject) {
			console.warn('The binding’s destination was not found in the object’s context:', binding.destination, obj);
			return;
		}
		
		
		
		if (_binding.destinationObject && _binding.destinationObject.$id) {

			
			var bindingContext = _binding.destinationObject.context ? _binding.destinationObject.context : this;
			bindingContext.registerBindingForObject(_binding, obj);

			Object.defineProperty(_binding, 'context', {
				configurable: true,
				value: bindingContext
			});
		}
		
		return _binding;
	};
	

BindingsContext.prototype.expectedTypeForProperty = function BindingsContext_expectedTypeForProperty(key) {
	if (__super) return __super.prototype.expectedTypeForProperty(key);
};

return BindingsContext; }()));