/**
* @copyright 2015 Tridium, Inc. All Rights Reserved.
* @author Gareth Johnson
*/
/**
* Defines {@link baja.NameMap}
* @module baja/obj/NameMap
*/
define([
"bajaScript/sys",
"bajaScript/baja/obj/Simple",
"bajaScript/baja/obj/objUtil" ], function (
baja,
Simple,
objUtil) {
"use strict";
var subclass = baja.subclass,
callSuper = baja.callSuper,
strictArg = baja.strictArg,
cacheDecode = objUtil.cacheDecode,
cacheEncode = objUtil.cacheEncode;
/**
* `NameMap` used for managing a list of `String` names to `Format` values.
*
* This Constructor shouldn't be invoked directly. Please use the `make()`
* methods to create an instance of a `NameMap` Object.
*
* @class
* @alias baja.NameMap
* @extends baja.Simple
*/
var NameMap = function NameMap(map, $fromDecode) {
callSuper(NameMap, this, arguments);
if ($fromDecode) {
this.$map = map;
} else {
strictArg(map, Object);
this.$map = {};
// Copy over Properties into this map
var p,
v;
for (p in map) {
if (map.hasOwnProperty(p)) {
v = map[p];
this.$map[p] = v instanceof baja.Format ? v : baja.Format.make(v);
}
}
}
};
subclass(NameMap, Simple);
/**
* `NameMap` default instance
* @type {baja.NameMap}
*/
NameMap.DEFAULT = new NameMap({});
/**
* Make a `NameMap` object.
*
* @param {Object} map an object containing key/value pairs.
* @returns {baja.NameMap}
*/
NameMap.prototype.make = function (map, $fromDecode) {
if (!map) {
return NameMap.DEFAULT;
}
return new NameMap(map, $fromDecode);
};
/**
* Make a `NameMap` object.
*
* @param {Object} map an object containing key/value pairs.
* @returns {baja.NameMap}
*/
NameMap.make = function (map) {
return NameMap.DEFAULT.make.apply(NameMap.DEFAULT, arguments);
};
/**
* Decode `NameMap` from a `String`.
*
* @method
* @returns {baja.NameMap}
*/
NameMap.prototype.decodeFromString = cacheDecode(function (s) {
if (s === "{}") {
return NameMap.DEFAULT;
}
// Parse everything between {...}
var res = /^{(.*)}$/.exec(s),
map,
i = 0,
buf = "",
lastDelim = ";",
key,
c,
body;
if (!res) {
throw new Error("Invalid NameMap");
}
if (!res[1]) {
return NameMap.DEFAULT;
}
// Parse each key value pair (key=value;)
map = {};
body = res[1];
// Due to the escaping, this is very difficult to do with regular expressions so we're just
// going to do this the old fashioned way.
for (i = 0; i < body.length; ++i) {
c = body.charAt(i);
if (c === "\\") {
buf += body.charAt(++i);
} else if (c !== "=" && c !== ";") {
buf += c;
} else {
if (c === lastDelim) {
throw new Error("Invalid NameMap Encoding");
}
lastDelim = c;
if (!key) {
key = buf;
} else {
map[key] = baja.Format.make(buf);
key = undefined;
}
buf = "";
}
}
return this.make(map, /*$fromDecode*/true);
});
function escapeNameMapReplace(match) {
return "\\" + match;
}
function escapeNameMapValue(val) {
return val.replace(/[=\\{};]/g, escapeNameMapReplace);
}
/**
* Encode `NameMap` to a `String`.
*
* @method
* @returns {String}
*/
NameMap.prototype.encodeToString = cacheEncode(function () {
var s = "{",
p,
map = this.$map;
for (p in map) {
if (map.hasOwnProperty(p)) {
s += escapeNameMapValue(p);
s += "=";
s += escapeNameMapValue(map[p].encodeToString());
s += ";";
}
}
s += "}";
return s;
});
/**
* Return a `String` representation of the `NameMap`.
*
* @returns {String}
*/
NameMap.prototype.toString = function () {
return this.encodeToString();
};
/**
* Return a `Format` from the Map or null if an entry can't be found.
*
* @returns {baja.Format|null} or null if an entry can't be found.
*/
NameMap.prototype.get = function (name) {
return this.$map[name] || null;
};
/**
* Return a list of all the keys in the Map.
*
* @returns {string[]} an array of String key names.
*/
NameMap.prototype.list = function () {
return Object.keys(this.$map);
};
/**
* @returns {Object.<string, baja.Format>} an object literal, where the keys
* are the NameMap keys and the values are the corresponding formats.
* @since Niagara 4.11
*/
NameMap.prototype.toObject = function () {
return Object.assign({}, this.$map);
};
/**
* @returns {boolean} true if the NameMap is empty
* @since Niagara 4.15
*/
NameMap.prototype.isNull = function () {
return !this.list().length;
};
return NameMap;
});