var _ = require('lodash'); var placeTypes = require('./placeTypes'); /** * Compare the layer properties if they exist. * Returns false if the objects are the same, and throws * an exception with the message 'different' if not. * * @param {object} item1 * @param {object} item2 * @returns {boolean} * @throws {Error} */ function assertLayerMatch(item1, item2) { if (item1.layer === item2.layer) { return false; } throw new Error('different'); } /** * Compare the parent.*_id properties if they exist. * Returns false if the objects are the same, and throws * an exception with the message 'different' if not. * * @param {object} item1 * @param {object} item2 * @returns {boolean} * @throws {Error} */ function assertParentHierarchyMatch(item1, item2) { // if neither object has parent, assume same if (!item1.hasOwnProperty('parent') && !item2.hasOwnProperty('parent')) { return false; } // if both have parent, do the rest of the checking if (item1.hasOwnProperty('parent') && item2.hasOwnProperty('parent')) { placeTypes.forEach(function (placeType) { // don't consider its own id if (placeType === item1.layer) { return; } propMatch(item1.parent, item2.parent, placeType + '_id'); }); return false; } // if one has parent and the other doesn't consider different throw new Error('different'); } /** * Compare the name.* properties if they exist. * Returns false if the objects are the same, and throws * an exception with the message 'different' if not. * * @param {object} item1 * @param {object} item2 * @returns {boolean} * @throws {Error} */ function assertNameMatch(item1, item2) { if (item1.hasOwnProperty('name') && item2.hasOwnProperty('name')) { for (var lang in item1.name) { if(item2.name.hasOwnProperty(lang) || lang === 'default') { // do not consider absence of an additional name as a difference propMatch(item1.name, item2.name, lang); } } } else { propMatch(item1, item2, 'name'); } } /** * Compare the address_parts properties if they exist. * Returns false if the objects are the same, and throws * an exception with the message 'different' if not. * * @param {object} item1 * @param {object} item2 * @returns {boolean} * @throws {Error} */ function assertAddressMatch(item1, item2) { // if neither record has address, assume same if (!item1.hasOwnProperty('address_parts') && !item2.hasOwnProperty('address_parts')) { return false; } // if both have address, check parts if (item1.hasOwnProperty('address_parts') && item2.hasOwnProperty('address_parts')) { propMatch(item1.address_parts, item2.address_parts, 'number'); propMatch(item1.address_parts, item2.address_parts, 'street'); // only compare zip if both records have it, otherwise just ignore and assume it's the same // since by this time we've already compared parent hierarchies if (item1.address_parts.hasOwnProperty('zip') && item2.address_parts.hasOwnProperty('zip')) { propMatch(item1.address_parts, item2.address_parts, 'zip'); } return false; } // one has address and the other doesn't, different! throw new Error('different'); } /** * Compare the two records and return true if they differ and false if same. * * @param {object} item1 * @param {object} item2 * @returns {boolean} * @throws {Error} */ function isDifferent(item1, item2) { try { assertLayerMatch(item1, item2); assertParentHierarchyMatch(item1, item2); assertNameMatch(item1, item2); assertAddressMatch(item1, item2); } catch (err) { if (err.message === 'different') { return true; } throw err; } return false; } /** * Throw exception if properties are different * * @param {object} item1 * @param {object} item2 * @param {string} prop * @throws {Error} */ function propMatch(item1, item2, prop) { var prop1 = item1[prop]; var prop2 = item2[prop]; // in the case the property is an array (currently only in parent schema) // simply take the 1st item. this will change in the near future to support multiple hierarchies if (_.isArray(prop1)) { prop1 = prop1[0]; } if (_.isArray(prop2)) { prop2 = prop2[0]; } if (normalizeString(prop1) !== normalizeString(prop2)) { throw new Error('different'); } } /** * Remove punctuation and lowercase * * @param {string} str * @returns {string} */ function normalizeString(str) { if (!_.isString(str)) { return str; } if (_.isEmpty(str)) { return ''; } return str.toLowerCase().split(/[ ,-]+/).join(' '); } module.exports.isDifferent = isDifferent;