/** * This module representing a Context Widget. * * @module Widget * @fileOverview */ define([ 'easejs', 'MathUuid', 'callback', 'callbackList', 'attributeType', 'attributeValue', 'attributeTypeList', 'attributeValueList', 'conditionList', 'subscriber', 'subscriberList', 'widgetDescription'], function(easejs, MathUuid, Callback, CallbackList, AttributeType, AttributeValue, AttributeTypeList, AttributeValueList, ConditionList, Subscriber, SubscriberList, WidgetDescription) { var AbstractClass = easejs.AbstractClass; var Class = easejs.Class; var Widget = AbstractClass('Widget',{ /** * @alias name * @public * @type {string} * @memberof Widget# * @desc Name of the Widget. */ 'public name' : 'Widget', /** * @alias id * @public * @type {string} * @memberof Widget# * @desc ID of the Widget. Will be generated. */ 'public id' : '', /** * @alias attributeTypes * @protected * @type {AttributeTypeList} * @memberof Widget# * @desc Types of all available attributes. */ 'protected attributeTypes' : [], /** * @alias constantAttributeTypes * @protected * @type {AttributeTypeList} * @memberof Widget# * @desc Types of all available ConstantAttributes. */ 'protected constantAttributeTypes' : [], /** * @alias attributes * @protected * @type {AttributeValueList} * @memberof Widget# * @desc All available Attributes and their values. */ 'protected attributes' : [], /** * @alias oldAttributes * @protected * @type {AttributeValueList} * @memberof Widget# * @desc This temporary variable is used for storing the old attribute values. * So these can be used to check conditions. */ 'protected oldAttributes' : [], /** * @alias constantAttributes * @protected * @type {AttributeValueList} * @memberof Widget# * @desc All available constant Attributes and their values. */ 'protected constantAttributes' : [], /** * @alias callbacks * @protected * @type {CallbackList} * @memberof Widget# * @desc List of Callbacks. */ 'protected callbacks' : [], /** * @alias subscribers * @protected * @type {SubscriberList} * @memberof Widget# * @desc List of Subscriber. */ 'protected subscribers' : [], /** * @alias discoverer * @protected * @type {Discoverer} * @memberof Widget# * @desc Associated discoverer. */ 'protected discoverer' : '', /** * Constructor: Generates the ID and initializes the * Widget with attributes, callbacks and subscriber * that are specified in the provided functions. * * @abstract * @class Widget * @classdesc The Widget handles the access to sensors. * @requires easejs * @requires MathUuid * @requires Callback * @requires CallbackList * @requires AttributeType * @requires AttributeValue * @requires AttributeTypeList * @requires AttributeValueList * @requires ConditionList * @requires Subscriber * @requires SubscriberList * @requires WidgetDescription * @requires Discoverer * @constructs Widget */ 'virtual public __construct' : function(_discoverer, _attributeTypes) { this.id = Math.uuid(); this.discoverer = _discoverer; this.register(); this.attributeTypes = new AttributeTypeList(); this.constantAttributeTypes = new AttributeTypeList(); this.attributes = new AttributeValueList(); this.constantAttributes = new AttributeValueList(); this.subscribers = new SubscriberList(); this.callbacks = new CallbackList(); this.init(_attributeTypes); }, /** * Returns the name of the widget. * * @public * @alias getName * @memberof Widget# * @returns {string} */ 'public getName' : function() { return this.name; }, /** * Returns the id of the widget. * * @public * @alias getId * @memberof Widget# * @returns {string} */ 'public getId' : function() { return this.id; }, /** * Returns the type of this class, in this case * "Widget". * * @virtual * @public * @alias getType * @memberof Widget# * @returns {string} */ 'virtual public getType' : function() { return 'Widget'; }, /** * Returns the available AttributeTypes. * * @public * @alias getAttributeTypes * @memberof Widget# * @returns {AttributeTypeList} */ 'public getAttributeTypes' : function() { return this.attributeTypes; }, /** * Returns the available ConstantAttributeTypes * (attributes that do not change). * * @public * @alias getWidgetConstantAttributeTypes * @memberof Widget# * @returns {AttributeTypeList} */ 'public getWidgetConstantAttributeTypes' : function() { return this.constantAttributeTypes; }, /** * Returns the last acquired attribute values. * * @public * @alias getAttributes * @memberof Widget# * @param {AttributeTypeList} _attributeTypeList * @returns {AttributeValueList} */ 'public getAttributeValues' : function(_attributeTypeList) { if (Class.isA(AttributeTypeList, _attributeTypeList)) { return this.attributes.getSubset(_attributeTypeList); } else { return this.attributes; } }, /** * Returns the last acquired attribute value with the given attribute type. * * @param {AttributeType} _attributeType The attribute type to return the last value for. * @returns {*} */ 'public getAttributeValue': function(_attributeType) { return this.getAttributeValues().getItem(_attributeType.getIdentifier()).getValue(); }, /** * Returns the old Attributes. * * @private * @alias getOldAttributes * @memberof Widget# * @returns {AttributeValueList} */ 'public getOldAttributes' : function() { return this.oldAttributes; }, /** * Returns the ConstantAttributes. * * @public * @alias getConstantAttributes * @memberof Widget# * @returns {AttributeValueList} */ 'public getConstantAttributes' : function() { return this.constantAttributes; }, /** * Returns a list of callbacks that can be * subscribed to. * * @public * @alias getCallbacks * @memberof Widget# * @returns {CallbackList} */ 'public getCallbackList' : function() { return this.callbacks; }, /** * Returns the specified callbacks that can be * subscribed to. * * @public * @alias getCallbacks * @memberof Widget# * @returns {Array} */ 'public getCallbacks' : function() { return this.callbacks.getItems(); }, 'public queryServices' : function() { return this.services; }, /** * Returns the Subscriber. * * @public * @alias getSubscriber * @memberof Widget# * @returns {SubscriberList} */ 'public getSubscriber' : function() { return this.subscribers; }, /** * Sets the name of the Widget. * * @protected * @alias setName * @memberof Widget# * @param {string} * _name Name of the Widget. */ 'protected setName' : function(_name) { if (typeof _name === 'string') { this.name = _name; } }, /** * Sets the id of the Widget. * * @protected * @alias setId * @memberof Widget# * @param {string} * _id Id of the Widget. */ 'protected setId' : function(_id) { if (typeof _id === 'string') { this.id = _id; } }, /** * Sets the AttributeValueList and also the associated * AttributeTypes. * * @protected * @alias setAttributes * @memberof Widget# * @param {(AttributeValueList|Array)} * _attributes List or Array of * AttributeValues */ 'protected setAttributes' : function(_attributes) { var list = new Array(); if (_attributes instanceof Array) { list = _attributes.reduce(function(o, v, i) { o[i] = v; return o; }, {}); } else if (Class.isA(AttributeValueList,_attributes)) { list = _attributes.getItems(); } this.oldAttributes = this.attributes; for ( var i in list) { var attribute = list[i]; if (Class.isA(AttributeValue, attribute)) { attribute.setTimestamp(this.getCurrentTime()); this.attributes.put(attribute); var type = new AttributeType().withName(attribute.getName()) .withType(attribute.getType()) .withParameters(attribute.getParameters()); this.attributeTypes.put(type); } } }, /** * Adds a new AttributeValue. If the given value is * not included in the list, the associated type will * be also added. Otherwise, only the value will be * updated. * * @public * @alias addAttribute * @memberof Widget# * @param {AttributeValue} * _attribute AttributeValue */ 'public addAttribute' : function(_attribute) { if (Class.isA(AttributeValue, _attribute)) { if (!this.attributes.contains(_attribute)) { var type = new AttributeType().withName(_attribute.getName()) .withType(_attribute.getType()) .withParameters(_attribute.getParameters()); this.attributeTypes.put(type); } this.oldAttributes = this.attributes; _attribute.setTimestamp(this.getCurrentTime()); this.attributes.put(_attribute); } }, /** * Sets the ConstantAttributeValueList and also the * associated AttributeTypes. * * @protected * @alias setConstantAttributes * @memberof Widget# * @param {(AttributeValueList|Array)} * _constantAttributes List or Array of * AttributeValues */ 'protected setConstantAttributes' : function(_constantAttributes) { var list = new Array(); if (_constantAttributes instanceof Array) { list = _constantAttributes; } else if (Class.isA(AttributeValueList,_constantAttributes)) { list = _constantAttributes.getItems(); } for ( var i in list) { var constantAttribute = list[i]; if (Class.isA(AttributeValue, constantAttribute)) { constantAttribute.setTimestamp(this.getCurrentTime()); this.constantAttributes.put(constantAttribute); var type = new AttributeType().withName(constantAttribute.getName()) .withType(constantAttribute.getType()) .withParameters(constantAttribute.getParameters()); this.constantAttributeTypes.put(type); } } }, /** * Adds a new constantAttributeValue. If the given value is * not included in the list, the associated type will * be also added. Otherwise, only the value will be * updated. * * @protected * @alias addConstantAttribute * @memberof Widget# * @param {AttributeValue} * _constantAttribute AttributeValue */ 'protected addConstantAttribute' : function(_constantAttribute) { if (Class.isA(AttributeValue, _constantAttribute)) { if (!this.constantAttributes .contains(_constantAttribute)) { var type = new AttributeType().withName(_constantAttribute.getName()) .withType(_constantAttribute.getType()) .withParameters(_constantAttribute.getParameters()); this.constantAttributeTypes.put(type); } _attribute.setTimestamp(this.getCurrentTime()); this.constantAttributes.put(_constantAttribute); } }, /** * Sets Callbacks. * * @protected * @alias setCallbacks * @memberof Widget# * @param {(CallbackList|Array)} _callbacks List or Array of Callbacks. */ 'protected setCallbacks' : function(_callbacks) { var list = new Array(); if (_callbacks instanceof Array) { list = _subscriber; } else if (Class.isA(CallbackList, _callbacks)) { list = _callbacks.getItems(); } for ( var i in list) { var callback = list[i]; if (Class.isA(Callback, callback)) { this.callbacks.put(callback); } } }, /** * Adds a new Callback. * * @protected * @alias addCallback * @memberof Widget# * @param {Callback} _callback List or Array of AttributeValues. */ 'protected addCallback' : function(_callback) { if (Class.isA(Callback, _callback)) { this.callbacks.put(_callback); } }, 'protected setServices' : function(_services) { this.services = _services; }, /** * Sets SubscriberList. * * @protected * @alias setSubscriber * @memberof Widget# * @param {(SubscriberList|Array)} _subscriber List or Array of Subscriber. */ 'protected setSubscriber' : function(_subscriber) { var list = new Array(); if (_subscriber instanceof Array) { list = _subscriber; } else if (Class.isA(SubscriberList, _subscriber)) { list = _subscriber.getItems(); } for ( var i in list) { var singleSubscriber = list[i]; if (Class.isA(Subscriber, singleSubscriber)) { this.subscribers.put(singleSubscriber); } } }, /** * Adds a new Subscriber. * * @public * @alias addSubscriber * @memberof Widget# * @param {Subscriber} _subscriber Subscriber */ 'public addSubscriber' : function(_subscriber) { if (Class.isA(Subscriber, _subscriber)) { this.subscribers.put(_subscriber); } }, /** * Removes the specified Subscriber. * * @public * @alias removeSubscriber * @memberof Widget# * @param {Subscriber} _subscriber Subscriber */ 'public removeSubscriber' : function(_subscriberId) { this.subscribers.removeItem(_subscriberId); }, /** * Returns the current time. * * @private * @alias getCurrentTime * @memberof Widget# * @returns {Date} */ 'private getCurrentTime' : function() { return new Date(); }, /** * Verifies whether the specified attributes is a * provided Attribute. * * @protected * @alias isAttribute * @memberof Widget# * @param {AttributeValue} * _attribute * @returns {boolean} */ 'protected isAttribute' : function(_attribute) { return !!this.attributeTypes.contains(_attribute.getAttributeType()); }, /** * Initializes the provided Attributes. * * @function * @abstract * @protected * @alias initAttributes * @memberof Widget# */ 'abstract protected initAttributes' : [], /** * Initializes the provided ConstantAttributes. * * @function * @abstract * @protected * @alias initConstantAttributes * @memberof Widget# */ 'abstract protected initConstantAttributes' : [], /** * Initializes the provided Callbacks. * * @function * @abstract * @protected * @alias initCallbacks * @memberof Widget# */ 'abstract protected initCallbacks' : [], /** * Function for initializing. Calls all initFunctions * and will be called by the constructor. * * @protected * @alias init * @memberof Widget# */ 'protected init' : function(_attributeTypes) { this.initAttributes(); this.initConstantAttributes(); this.initCallbacks(); this.didFinishInitialization(_attributeTypes); }, /** * Method will be invoked after the initialization of the widget finished. * Can be overridden by inheriting classes to take action after initialization. * * @public * @virtual * @alias didFinishInitialization * @memberof Widget# * @param _attributeTypes */ 'public virtual didFinishInitialization' : function(_attributeTypes) { }, /** * Notifies other components and sends the attributes. * * @virtual * @public * @alias initCallbacks * @memberof Widget# */ 'virtual public notify' : function() { var callbacks = this.getCallbacks(); for (var i in callbacks) { this.sendToSubscriber(callbacks[i]); } }, /** * Queries the associated sensor and updates the attributes with new values. * Must be overridden by the subclasses. Overriding subclasses can call * this.__super(_function) to invoke the provided callback function. * * @virtual * @public * @alias queryGenerator * @memberof Widget# * @param {?function} _function For alternative actions, because an asynchronous function can be used. */ 'virtual protected queryGenerator' : function(_function) { if (_function && typeof(_function) == 'function') { _function(); } }, /** * Updates the attributes by calling queryGenerator. * * @public * @alias updateWidgetInformation * @memberof Widget# * @param {?function} _function For alternative actions, because an asynchronous function can be used. * */ 'public updateWidgetInformation' : function(_function) { this.queryGenerator(_function); }, /** * Updates the Attributes by external components. * * @virtual * @public * @alias putData * @memberof Widget# * @param {(AttributeValueList|Array)} _data Data that should be entered. * */ 'virtual public putData' : function(_data) { var list = new Array(); if (_data instanceof Array) { list = _data; } else if (Class.isA(AttributeValueList, _data)) { list = _data.getItems(); } for ( var i in list) { var x = list[i]; if (Class.isA(AttributeValue, x) && this.isAttribute(x)) { this.addAttribute(x); } } }, /** * Returns all available AttributeValues, Attributes and * ConstantAtrributes. * * @public * @alias queryWidget * @memberof Widget# * @returns {AttributeValueList} */ 'public queryWidget' : function() { var response = new AttributeValueList(); response.putAll(this.getAttributeValues()); response.putAll(this.getConstantAttributes()); return response; }, /** * Updates and returns all available AttributeValues, * Attributes and ConstantAtrributes. * * @public * @alias updateAndQueryWidget * @memberof Widget# * @param {?function} _function For alternative actions, because an asynchronous function can be used. * @returns {?AttributeValueList} */ 'virtual public updateAndQueryWidget' : function(_function) { if(_function && typeof(_function) === 'function'){ this.queryGenerator(_function); } else { this.queryGenerator(); var response = new AttributeValueList(); response.putAll(this.getAttributeValues()); response.putAll(this.getConstantAttributes()); return response; } }, /** * Sends all Attributes, specified in the given callback, * to components which are subscribed to this Callback. * @protected * @alias sendToSubscriber * @memberof Widget# * @param {string} _callbackName Name of the searched Callback. */ 'protected sendToSubscriber' : function(_callback) { if (_callback && Class.isA(Callback, _callback)) { var subscriberList = this.subscribers.getItems(); for ( var i in subscriberList) { var subscriber = subscriberList[i]; if (subscriber.getSubscriptionCallbacks().containsKey( _callback.getName())) { if(this.dataValid(subscriber.getConditions())){ var subscriberInstance = this.discoverer.getComponent(subscriber.getSubscriberId()); var callSubset = _callback.getAttributeTypes(); var subscriberSubset = subscriber.getAttributesSubset(); var data = this.attributes.getSubset(callSubset); if (subscriberSubset && subscriberSubset.size() > 0) { data = data.getSubset(subscriberSubset); } } if (data) { subscriberInstance.putData(data); } } } } }, /** * Verifies if the attributes match to the specified conditions in case any exists. * * @private * @alias dataValid * @memberof Widget# * @param {string} _conditions List of Conditions that will be verified. * @returns {boolean} */ 'private dataValid' : function(_conditions) { if (Class.isA(ConditionList, _conditions)) { return true; } if (!_conditions.isEmpty()) { var items = _condition.getItems(); for ( var i in items) { var condition = items[i]; var conditionAttributeType = condition.getAttributeType(); var conditionAttributeTypeList = new AttributeTypeList() .withItems(new Array(conditionAttributeType)); var newValue = this.getAttributes().getSubset(conditionAttributeTypeList); var oldValue = this.getOldAttributes.getSubset(conditionAttributeTypeList); return condition.compare(newValue, oldValue); } } return false; }, /** * Returns the description of this component. * @virtual * @public * @alias getDescription * @memberof Widget# * @returns {WidgetDescription} */ 'virtual public getDescription' : function() { var description = new WidgetDescription().withId(this.id).withName(this.name); description.addOutAttributeTypes(this.attributeTypes); description.addOutAttributeTypes(this.constantAttributeTypes); var widgetCallbacks = this.callbacks.getItems(); for(var i in widgetCallbacks) { description.addCallbackName(widgetCallbacks[i].getName()); } return description; }, /** * Runs the context acquisition constantly in an interval. * Can be called by init. * * @virtual * @protected * @alias intervalRunning * @memberof Widget# * @param {integer} _interval Interval in ms */ 'virtual protected intervalRunning' : function(_interval) { var self = this; if (_interval === parseInt(_interval)) { setInterval(function() {self.queryGenerator();}, _interval); } }, /** * Sets the associated Discoverer and registers to that. * @public * @alias setDiscoverer * @memberof Widget# * @param {Discoverer} _discoverer Discoverer */ 'public setDiscoverer' : function(_discoverer) { if (!this.discoverer) { this.discoverer = _discoverer; this.register(); } }, /** * Registers the component to the associated Discoverer. * * @public * @alias register * @memberof Widget# */ 'protected register' : function() { if (this.discoverer) { this.discoverer.registerNewComponent(this); } } // /** // * Unregisters the component to the associated discoverer // * and deletes the reference. // * // * @public // * @alias register // * @memberof Widget# // */ // 'protected unregister' : function() { // if (this.discoverer) { // this.discoverer.unregisterComponent(this.getId()); // this.discoverer = null; // } // }, }); return Widget; });