kevoree-entities
Version:
Kevoree Entities - Set of abstract Kevoree entities (group, node, channel, component)
244 lines (221 loc) • 6.83 kB
JavaScript
const kevoree = require('kevoree-library');
const events = require('events');
/**
* Dictionary class use to handle KevoreeEntities dictionary attributes
* <br/>
* Each KevoreeEntity can create a dictionary attribute by adding a new <strong>dic_field</strong> to their class:
* <br/>
* <pre>
* dic_myAttr: {
* optional: true,
* defaultValue: 'foo',
* fragmentDependant: false
* }
* </pre>
* Dictionary attribute API follows those guidelines:
* <ul>
* <li>"defaultValue" attribute is <b>optional</b>, type is <b>string|boolean</b></li>
* <li>"optional" attribute is <b>optional</b>, type is <b>boolean</b> (default: true)</li>
* <li>"fragmentDependant" attribute is <b>optional</b>, type is <b>boolean</b> (default: false)</li>
* <li>"datatype" attribute is <b>optional</b>, type is <b>string|org.kevoree.Datatype</b></li>
* </ul>
*
* Once your entity is started, you will be able to retrieve your attribute value by calling one of those methods:
* <ul>
* <li>this.dictionary.getValue('myAttr')</li>
* <li>this.dictionary.getString('myAttr')</li>
* <li>this.dictionary.getNumber('myAttr')</li>
* <li>this.dictionary.getBoolean('myAttr')</li>
* </ul>
*
* @param entity
*
* @class
*/
function Dictionary(entity) {
this.entity = entity;
this.emitter = new events.EventEmitter();
this.map = {};
}
Dictionary.prototype = {
/**
* Adds a listener on dictionary changes or on a particular attribute changes
* dictionary.on('myAttr', (newVal, oldVal) => { ... });
*
* @param attrName name of the attribute you want to add a listener on
* @param callback function (attrNewValue, attrOldValue)
*/
on(attrName, callback) {
this.emitter.addListener(attrName, callback.bind(this.entity));
},
/**
* Removes a listener
* @param event
* @param callback
*/
off(event, callback) {
this.emitter.removeListener(event, callback);
},
/**
* Retrieve a value mapped by the key "name"
* @param {String} name the key
* @returns {*}
*/
getValue(name) {
return this.map[name];
},
/**
* Returns a boolean for the given dictionary attribute name.
* If no value is found and no defaultVal is given, it will return "false"
* If a defaultVal is given, and no value is found in dictionary, then defaultVal is returned
* @param name
* @param [defaultVal] a default boolean to return if no value is found in the dictionary using the given name
* @returns {Boolean}
*/
getBoolean(name, defaultVal) {
const val = this.map[name];
if (val === 'true' || val === 'false') {
return val === 'true';
}
if (typeof (defaultVal) === 'undefined') {
defaultVal = false;
}
return defaultVal;
},
/**
* Returns a string for the given dictionary attribute name.
* If no value is found and no defaultVal is given, it will return "null"
* (nb: it will also return "null" if the given defaultVal is not a string)
* If a defaultVal is given, and no value is found in dictionary, then defaultVal is returned
* @param name
* @param [defaultVal] a default string to return if no value is found in the dictionary using the given name
* @returns {String}
*/
getString(name, defaultVal) {
const val = this.map[name];
if (typeof (val) === 'string') {
return val;
}
if (typeof (defaultVal) !== 'string') {
defaultVal = null;
}
return defaultVal;
},
/**
* Returns a number for the given dictionary attribute name.
* If no value is found and no defaultVal is given, it will return "null"
* (nb: it will also return "null" if the given defaultVal is not a number)
* If a defaultVal is given, and no value is found in dictionary, then defaultVal is returned
* @param name
* @param [defaultVal] a default number to return if no value is found in the dictionary using the given name
* @returns {Number}
*/
getNumber(name, defaultVal) {
let val;
if (this.map[name] && this.map[name].length === 0) {
val = null;
} else {
val = +this.map[name];
}
if (isNaN(val)) {
if (typeof defaultVal !== 'number') {
return null;
} else {
return defaultVal;
}
} else {
return val;
}
},
/**
*
* @param name
* @param value
*/
setValue(name, value) {
const factory = new kevoree.factory.DefaultKevoreeFactory();
const entity = this.entity.getModelEntity();
if (!entity.dictionary) {
entity.dictionary = factory.createDictionary();
}
value = entity.dictionary.findValuesByID(name);
if (!value) {
value = factory.createDictionaryValue();
value.name = name;
entity.dictionary.addValues(value);
}
value.value = value;
this.setEntry(name, value);
},
/**
* Called by the platform to update the state of the dictionary
* Triggers a call to dic_<name>.update() and a call to on(<name>, function)
* @param name attribute name
* @param value new attribute value
*/
setEntry(name, value) {
const oldValue = this.map[name];
this.map[name] = value;
// emit update event with the name, oldValue and newValue
if (this.entity.isStarted()) {
// if (this.entity['dic_'+name].update && (typeof this.entity['dic_'+name].update === 'function')) {
// this.entity['dic_'+name].update.bind(this.entity)(value, oldValue);
// }
this.emitter.emit(name, value, oldValue);
}
},
/**
*
* @param map
*/
setMap(map) {
let name;
if (Object.keys(this.map).length > 0) {
// current map is not empty
for (const newName in map) {
let alreadyAdded = false;
for (name in this.map) {
if (newName === name) {
// oldMap and newMap both have this attribute : update needed ?
const oldValue = this.map[name];
if (oldValue !== map[name]) {
// map[name] value is different from current value => update
this.map[name] = map[name];
this.emitter.emit(name, this.map[name], oldValue);
}
alreadyAdded = true;
}
}
if (!alreadyAdded) {
// newMap has a new attribute to add to currentMap : ADD event
this.map[newName] = map[newName];
}
}
} else {
// dictionary was empty : set it from scratch
this.map = map;
}
},
/**
*
* @returns {{}|*}
*/
getMap() {
return this.map;
},
/**
* Returns this dictionary current cloned map
* @returns {{}}
*/
cloneMap() {
const clonedMap = {};
for (const name in this.map) {
clonedMap[name] = this.map[name];
}
return clonedMap;
},
toString() {
return 'Dictionary';
}
};
module.exports = Dictionary;