UNPKG

judpack-common

Version:
164 lines (148 loc) 5.98 kB
/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /* jshint sub:true */ var _ = require('underscore'); // add the count of [key1][key2]...[keyN] to obj // return true if it didn't exist before exports.deep_add = function deep_add(obj, keys /* or key1, key2 .... */ ) { if ( !Array.isArray(keys) ) { keys = Array.prototype.slice.call(arguments, 1); } return exports.process_munge(obj, true/*createParents*/, function (parentArray, k) { var found = _.find(parentArray, function(element) { return element.xml == k.xml; }); if (found) { found.after = found.after || k.after; found.count += k.count; } else { parentArray.push(k); } return !found; }, keys); }; // decrement the count of [key1][key2]...[keyN] from obj and remove if it reaches 0 // return true if it was removed or not found exports.deep_remove = function deep_remove(obj, keys /* or key1, key2 .... */ ) { if ( !Array.isArray(keys) ) { keys = Array.prototype.slice.call(arguments, 1); } var result = exports.process_munge(obj, false/*createParents*/, function (parentArray, k) { var index = -1; var found = _.find(parentArray, function (element) { index++; return element.xml == k.xml; }); if (found) { if (parentArray[index].oldAttrib) { k.oldAttrib = _.extend({}, parentArray[index].oldAttrib); } found.count -= k.count; if (found.count > 0) { return false; } else { parentArray.splice(index, 1); } } return undefined; }, keys); return typeof result === 'undefined' ? true : result; }; // search for [key1][key2]...[keyN] // return the object or undefined if not found exports.deep_find = function deep_find(obj, keys /* or key1, key2 .... */ ) { if ( !Array.isArray(keys) ) { keys = Array.prototype.slice.call(arguments, 1); } return exports.process_munge(obj, false/*createParents?*/, function (parentArray, k) { return _.find(parentArray, function (element) { return element.xml == (k.xml || k); }); }, keys); }; // Execute func passing it the parent array and the xmlChild key. // When createParents is true, add the file and parent items they are missing // When createParents is false, stop and return undefined if the file and/or parent items are missing exports.process_munge = function process_munge(obj, createParents, func, keys /* or key1, key2 .... */ ) { if ( !Array.isArray(keys) ) { keys = Array.prototype.slice.call(arguments, 1); } var k = keys[0]; if (keys.length == 1) { return func(obj, k); } else if (keys.length == 2) { if (!obj.parents[k] && !createParents) { return undefined; } obj.parents[k] = obj.parents[k] || []; return exports.process_munge(obj.parents[k], createParents, func, keys.slice(1)); } else if (keys.length == 3){ if (!obj.files[k] && !createParents) { return undefined; } obj.files[k] = obj.files[k] || { parents: {} }; return exports.process_munge(obj.files[k], createParents, func, keys.slice(1)); } else { throw new Error('Invalid key format. Must contain at most 3 elements (file, parent, xmlChild).'); } }; // All values from munge are added to base as // base[file][selector][child] += munge[file][selector][child] // Returns a munge object containing values that exist in munge // but not in base. exports.increment_munge = function increment_munge(base, munge) { var diff = { files: {} }; for (var file in munge.files) { for (var selector in munge.files[file].parents) { for (var xml_child in munge.files[file].parents[selector]) { var val = munge.files[file].parents[selector][xml_child]; // if node not in base, add it to diff and base // else increment it's value in base without adding to diff var newlyAdded = exports.deep_add(base, [file, selector, val]); if (newlyAdded) { exports.deep_add(diff, file, selector, val); } } } } return diff; }; // Update the base munge object as // base[file][selector][child] -= munge[file][selector][child] // nodes that reached zero value are removed from base and added to the returned munge // object. exports.decrement_munge = function decrement_munge(base, munge) { var zeroed = { files: {} }; for (var file in munge.files) { for (var selector in munge.files[file].parents) { for (var xml_child in munge.files[file].parents[selector]) { var val = munge.files[file].parents[selector][xml_child]; // if node not in base, add it to diff and base // else increment it's value in base without adding to diff var removed = exports.deep_remove(base, [file, selector, val]); if (removed) { exports.deep_add(zeroed, file, selector, val); } } } } return zeroed; }; // For better readability where used exports.clone_munge = function clone_munge(munge) { return exports.increment_munge({}, munge); };