/src/utils/operator.js
https://github.com/ivmartel/dwv · JavaScript · 220 lines · 138 code · 7 blank · 75 comment · 42 complexity · f041b6d4049b7653b26a5fec39ded34a MD5 · raw file
- // namespaces
- var dwv = dwv || {};
- dwv.utils = dwv.utils || {};
- /**
- * Check if the input is a generic object, including arrays.
- *
- * @param {*} unknown The input to check.
- * @returns {boolean} True if the input is an object.
- * ref: https://github.com/jashkenas/underscore/blob/1.9.1/underscore.js#L1319-L1323
- */
- dwv.utils.isObject = function (unknown) {
- var type = typeof unknown;
- return type === 'function' || type === 'object' && !!unknown;
- };
- /**
- * Check if the input is an array.
- *
- * @param {*} unknown The input to check.
- * @returns {boolean} True if the input is an array.
- * ref: https://github.com/jashkenas/underscore/blob/1.9.1/underscore.js#L1313-L1317
- */
- dwv.utils.isArray = function (unknown) {
- return Array.isArray(unknown);
- };
- /**
- * Dump an object to an array.
- *
- * @param {object} obj The input object as: {key0: {}, key1: {}}
- * @returns {Array} The corresponding array:
- * [{name: key0, {}}, {name: key1, {}}]
- */
- dwv.utils.objectToArray = function (obj) {
- var array = [];
- var keys = Object.keys(obj);
- for (var i = 0; i < keys.length; ++i) {
- var key = keys[i];
- var row = {name: key};
- var innerKeys = Object.keys(obj[key]);
- for (var j = 0; j < innerKeys.length; ++j) {
- var innerKey = innerKeys[j];
- var value = obj[key][innerKey];
- if (dwv.utils.isArray(value)) {
- var arrayValues = [];
- for (var k = 0; k < value.length; ++k) {
- if (dwv.utils.isObject(value[k])) {
- arrayValues.push(dwv.utils.objectToArray(value[k]));
- } else {
- arrayValues.push(value[k]);
- }
- }
- value = arrayValues;
- } else if (dwv.utils.isObject(value)) {
- value = dwv.utils.objectToArray(value);
- }
- row[innerKey] = value;
- }
- array.push(row);
- }
- return array;
- };
- /**
- * Merge two similar objects.
- * Objects need to be in the form of:
- * <code>
- * {
- * idKey: {valueKey: 0},
- * key0: {valueKey: "abc"},
- * key1: {valueKey: 33}
- * }
- * </code>
- * Merged objects will be in the form of:
- * <code>
- * {
- * idKey: {valueKey: [0,1,2], merged: true},
- * key0: {valueKey: {
- * 0: {valueKey: "abc"},
- * 1: {valueKey: "def"},
- * 2: {valueKey: "ghi"}
- * }},
- * key1: {valueKey: {
- * 0: {valueKey: 33},
- * 1: {valueKey: 44},
- * 2: {valueKey: 55}
- * }}
- * }
- * </code>
- *
- * @param {object} obj1 The first object, can be the result of a previous merge.
- * @param {object} obj2 The second object.
- * @param {string} idKey The key to use as index for duplicate values.
- * @param {string} valueKey The key to use to access object values.
- * @returns {object} The merged object.
- */
- dwv.utils.mergeObjects = function (obj1, obj2, idKey, valueKey) {
- var res = {};
- // check id key
- if (!idKey) {
- throw new Error('Cannot merge object with an undefined id key: ' + idKey);
- } else {
- if (!Object.prototype.hasOwnProperty.call(obj1, idKey)) {
- throw new Error('Id key not found in first object while merging: ' +
- idKey + ', obj: ' + obj1);
- }
- if (!Object.prototype.hasOwnProperty.call(obj2, idKey)) {
- throw new Error('Id key not found in second object while merging: ' +
- idKey + ', obj: ' + obj2);
- }
- }
- // check value key
- if (!valueKey) {
- throw new Error('Cannot merge object with an undefined value key: ' +
- valueKey);
- }
- // check if merged object
- var mergedObj1 = false;
- if (Object.prototype.hasOwnProperty.call(obj1[idKey], 'merged') &&
- obj1[idKey].merged) {
- mergedObj1 = true;
- }
- // handle the id part
- if (!Object.prototype.hasOwnProperty.call(obj1[idKey], valueKey)) {
- throw new Error('Id value not found in first object while merging: ' +
- idKey + ', valueKey: ' + valueKey + ', ojb: ' + obj1);
- }
- if (!Object.prototype.hasOwnProperty.call(obj2[idKey], valueKey)) {
- throw new Error('Id value not found in second object while merging: ' +
- idKey + ', valueKey: ' + valueKey + ', ojb: ' + obj2);
- }
- var id1 = obj1[idKey][valueKey];
- var id2 = obj2[idKey][valueKey];
- // for merged object, id1 is an array
- if (mergedObj1) {
- // check if array does not include id2
- for (var k = 0; k < id1.length; ++k) {
- if (id1[k] === id2) {
- throw new Error('The first object already contains id2: ' +
- id2 + ', id1: ' + id1);
- }
- }
- res[idKey] = obj1[idKey];
- res[idKey][valueKey].push(id2);
- } else {
- if (id1 === id2) {
- throw new Error('Cannot merge object with same ids: ' +
- id1 + ', id2: ' + id2);
- }
- // create merge object
- res[idKey] = {value: [id1, id2], merged: true};
- }
- // get keys
- var keys1 = Object.keys(obj1);
- // keys2 without duplicates of keys1
- var keys2 = Object.keys(obj2).filter(function (item) {
- return keys1.indexOf(item) < 0;
- });
- var keys = keys1.concat(keys2);
- // loop through keys
- for (var i = 0, leni = keys.length; i < leni; ++i) {
- var key = keys[i];
- if (key !== idKey) {
- // first
- var value1 = null;
- var subValue1 = null;
- if (Object.prototype.hasOwnProperty.call(obj1, key)) {
- value1 = obj1[key];
- if (Object.prototype.hasOwnProperty.call(value1, valueKey)) {
- subValue1 = value1[valueKey];
- }
- }
- // second
- var value2 = null;
- var subValue2 = null;
- if (Object.prototype.hasOwnProperty.call(obj2, key)) {
- value2 = obj2[key];
- if (Object.prototype.hasOwnProperty.call(value2, valueKey)) {
- subValue2 = value2[valueKey];
- }
- }
- // result value
- var value;
- // create merge object if different values
- if (subValue2 !== subValue1) {
- value = {};
- // add to merged object or create new
- if (mergedObj1) {
- if (dwv.utils.isObject(subValue1)) {
- value[valueKey] = subValue1;
- } else {
- // merged object with repeated value
- // copy it with the index list
- value[valueKey] = {};
- for (var j = 0; j < id1.length; j++) {
- value[valueKey][id1[j]] = value1;
- }
- }
- // add obj2 value
- value[valueKey][id2] = value2;
- } else {
- // create merge object
- var newValue = {};
- newValue[id1] = value1;
- newValue[id2] = value2;
- value[valueKey] = newValue;
- }
- } else {
- value = value1;
- }
- // store value in result object
- res[key] = value;
- }
- }
- return res;
- };