'use strict';
var schemautil = module.exports = {},
util = require('../util');
var isEmpty = function(obj) {
return Object.keys(obj).length === 0;
};
schemautil.extend = function(instance, schema) {
return schemautil.merge(schemautil.instantiate(schema), instance);
};
// instantiate a schema
schemautil.instantiate = function(schema) {
var val;
Iif (schema === undefined) {
return undefined;
} else if ('default' in schema) {
val = schema.default;
return util.isObject(val) ? util.duplicate(val) : val;
} else if (schema.type === 'object') {
var instance = {};
for (var name in schema.properties) {
val = schemautil.instantiate(schema.properties[name]);
if (val !== undefined) {
instance[name] = val;
}
}
return instance;
} else if (schema.type === 'array') {
return [];
}
return undefined;
};
// remove all defaults from an instance
schemautil.subtract = function(instance, defaults) {
var changes = {};
for (var prop in instance) {
var def = defaults[prop];
var ins = instance[prop];
// Note: does not properly subtract arrays
if (!defaults || def !== ins) {
if (typeof ins === 'object' && !util.isArray(ins) && def) {
var c = schemautil.subtract(ins, def);
if (!isEmpty(c))
changes[prop] = c;
} else Eif (!util.isArray(ins) || ins.length > 0) {
changes[prop] = ins;
}
}
}
return changes;
};
schemautil.merge = function(/*dest*, src0, src1, ...*/){
var dest = arguments[0];
for (var i=1 ; i<arguments.length; i++) {
dest = merge(dest, arguments[i]);
}
return dest;
};
// recursively merges src into dest
function merge(dest, src) {
Iif (typeof src !== 'object' || src === null) {
return dest;
}
for (var p in src) {
Iif (!src.hasOwnProperty(p)) {
continue;
}
if (src[p] === undefined) {
continue;
}
if (typeof src[p] !== 'object' || src[p] === null) {
dest[p] = src[p];
} else if (typeof dest[p] !== 'object' || dest[p] === null) {
dest[p] = merge(src[p].constructor === Array ? [] : {}, src[p]);
} else {
merge(dest[p], src[p]);
}
}
return dest;
} |