michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: "use strict" michael@0: michael@0: this.EXPORTED_SYMBOLS = ['ActivitiesServiceFilter']; michael@0: michael@0: this.ActivitiesServiceFilter = { michael@0: match: function(aValues, aFilters) { michael@0: michael@0: function matchValue(aValue, aFilter, aFilterObj) { michael@0: if (aFilter !== null) { michael@0: // Custom functions for the different types. michael@0: switch (typeof(aFilter)) { michael@0: case 'boolean': michael@0: return aValue === aFilter; michael@0: michael@0: case 'number': michael@0: return Number(aValue) === aFilter; michael@0: michael@0: case 'string': michael@0: return String(aValue) === aFilter; michael@0: michael@0: default: // not supported michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: // Pattern. michael@0: if (('pattern' in aFilterObj)) { michael@0: var pattern = String(aFilterObj.pattern); michael@0: michael@0: var patternFlags = ''; michael@0: if (('patternFlags' in aFilterObj)) { michael@0: patternFlags = String(aFilterObj.patternFlags); michael@0: } michael@0: michael@0: var re = new RegExp('^(?:' + pattern + ')$', patternFlags); michael@0: return re.test(aValue); michael@0: } michael@0: michael@0: // Validation of the min/Max. michael@0: if (('min' in aFilterObj) || ('max' in aFilterObj)) { michael@0: // Min value. michael@0: if (('min' in aFilterObj) && michael@0: aFilterObj.min > aValue) { michael@0: return false; michael@0: } michael@0: michael@0: // Max value. michael@0: if (('max' in aFilterObj) && michael@0: aFilterObj.max < aValue) { michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: // this function returns true if the value matches with the filter object michael@0: function matchObject(aValue, aFilterObj) { michael@0: michael@0: // Let's consider anything an array. michael@0: let filters = ('value' in aFilterObj) michael@0: ? (Array.isArray(aFilterObj.value) michael@0: ? aFilterObj.value michael@0: : [aFilterObj.value]) michael@0: : [ null ]; michael@0: let values = Array.isArray(aValue) ? aValue : [aValue]; michael@0: michael@0: for (var filterId = 0; filterId < filters.length; ++filterId) { michael@0: for (var valueId = 0; valueId < values.length; ++valueId) { michael@0: if (matchValue(values[valueId], filters[filterId], aFilterObj)) { michael@0: return true; michael@0: } michael@0: } michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: // Creation of a filter map useful to know what has been michael@0: // matched and what is not. michael@0: let filtersMap = {} michael@0: for (let filter in aFilters) { michael@0: // Convert this filter in an object if needed michael@0: let filterObj = aFilters[filter]; michael@0: michael@0: if (Array.isArray(filterObj) || typeof(filterObj) !== 'object') { michael@0: filterObj = { michael@0: required: false, michael@0: value: filterObj michael@0: } michael@0: } michael@0: michael@0: filtersMap[filter] = { filter: filterObj, michael@0: found: false }; michael@0: } michael@0: michael@0: // For any incoming property. michael@0: for (let prop in aValues) { michael@0: // If this is unknown for the app, let's continue. michael@0: if (!(prop in filtersMap)) { michael@0: continue; michael@0: } michael@0: michael@0: if (Array.isArray(aValues[prop]) && aValues[prop].length == 0) { michael@0: continue; michael@0: } michael@0: michael@0: // Otherwise, let's check the value against the filter. michael@0: if (!matchObject(aValues[prop], filtersMap[prop].filter)) { michael@0: return false; michael@0: } michael@0: michael@0: filtersMap[prop].found = true; michael@0: } michael@0: michael@0: // Required filters: michael@0: for (let filter in filtersMap) { michael@0: if (filtersMap[filter].filter.required && !filtersMap[filter].found) { michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: }